mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-18 18:39:28 +02:00
Debugger: Inspect-Win, use Watch object to get data / Display arrays with FpDebug
This commit is contained in:
parent
363d0ac778
commit
54bca1219b
@ -28,17 +28,18 @@ unit InspectDlg;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils,
|
Classes, SysUtils, Math,
|
||||||
// LCL
|
// LCL
|
||||||
LCLProc, LCLType, Grids, StdCtrls, Menus, Forms, Controls, Graphics, ComCtrls,
|
LCLProc, LCLType, Grids, StdCtrls, Menus, Forms, Controls, Graphics, ComCtrls,
|
||||||
// IdeIntf
|
// IdeIntf
|
||||||
IDEWindowIntf, IDEImagesIntf, ObjectInspector, PropEdits,
|
IDEWindowIntf, IDEImagesIntf, ObjectInspector, PropEdits,
|
||||||
// DebuggerIntf
|
// DebuggerIntf
|
||||||
DbgIntfDebuggerBase, DbgIntfBaseTypes, LazDebuggerIntf,
|
DbgIntfDebuggerBase, DbgIntfBaseTypes, LazClasses, LazDebuggerIntf,
|
||||||
LazDebuggerIntfBaseTypes,
|
LazDebuggerIntfBaseTypes,
|
||||||
// IDE
|
// IDE
|
||||||
LazarusIDEStrConsts, BaseDebugManager, InputHistory, IDEProcs,
|
LazarusIDEStrConsts, BaseDebugManager, InputHistory, IDEProcs, Debugger,
|
||||||
Debugger, DebuggerDlg, DebuggerStrConst, EnvironmentOpts;
|
IdeDebuggerWatchResPrinter, IdeDebuggerWatchResult, DebuggerDlg,
|
||||||
|
DebuggerStrConst, EnvironmentOpts;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
@ -94,25 +95,29 @@ type
|
|||||||
//FDataGrid,
|
//FDataGrid,
|
||||||
//FPropertiesGrid,
|
//FPropertiesGrid,
|
||||||
//FMethodsGrid: TOIDBGGrid;
|
//FMethodsGrid: TOIDBGGrid;
|
||||||
FExpression: ansistring;
|
FExpression, FAlternateExpression: ansistring;
|
||||||
|
FWatchPrinter: TWatchResultPrinter;
|
||||||
|
FInspectWatches: TCurrentWatches;
|
||||||
|
FCurrentWatchValue: TIdeWatchValue;
|
||||||
FHumanReadable: ansistring;
|
FHumanReadable: ansistring;
|
||||||
FDBGInfo: TDBGType;
|
|
||||||
FGridData: TStringGrid;
|
FGridData: TStringGrid;
|
||||||
FGridMethods: TStringGrid;
|
FGridMethods: TStringGrid;
|
||||||
FUpdateLock, FUpdateNeeded, FExpressionWasEvaluated: Boolean;
|
FExpressionWasEvaluated: Boolean;
|
||||||
FTestUpdateLock: Boolean;
|
|
||||||
FRowClicked: Integer;
|
|
||||||
FHistory: TStringList;
|
FHistory: TStringList;
|
||||||
FHistoryIndex: Integer;
|
FHistoryIndex: Integer;
|
||||||
FPowerImgIdx, FPowerImgIdxGrey: Integer;
|
FPowerImgIdx, FPowerImgIdxGrey: Integer;
|
||||||
|
|
||||||
procedure EvaluateCallback(Sender: TObject; ASuccess: Boolean;
|
procedure DoDebuggerState(ADebugger: TDebuggerIntf; AnOldState: TDBGState);
|
||||||
ResultText: String; ResultDBGType: TDBGType);
|
procedure DoWatchUpdated(const ASender: TIdeWatches; const AWatch: TIdeWatch);
|
||||||
procedure EvaluateTestCallback(Sender: TObject; ASuccess: Boolean;
|
|
||||||
{%H-}ResultText: String; ResultDBGType: TDBGType);
|
|
||||||
procedure Localize;
|
procedure Localize;
|
||||||
function ShortenedExpression: String;
|
function ShortenedExpression: String;
|
||||||
procedure ContextChanged(Sender: TObject);
|
procedure ContextChanged(Sender: TObject);
|
||||||
|
procedure InspectResDataSimple;
|
||||||
|
procedure InspectResDataPointer;
|
||||||
|
procedure InspectResDataEnum;
|
||||||
|
procedure InspectResDataSet;
|
||||||
|
procedure InspectResDataArray;
|
||||||
|
procedure InspectResDataStruct;
|
||||||
procedure InspectClass;
|
procedure InspectClass;
|
||||||
procedure InspectRecord;
|
procedure InspectRecord;
|
||||||
procedure InspectVariant;
|
procedure InspectVariant;
|
||||||
@ -209,6 +214,196 @@ begin
|
|||||||
UpdateData;
|
UpdateData;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TIDEInspectDlg.InspectResDataSimple;
|
||||||
|
var
|
||||||
|
Res: TWatchResultData;
|
||||||
|
v: String;
|
||||||
|
begin
|
||||||
|
Res := FCurrentWatchValue.ResultData;
|
||||||
|
|
||||||
|
DataPage.TabVisible:=true;
|
||||||
|
PropertiesPage.TabVisible:=false;
|
||||||
|
MethodsPage.TabVisible:=false;
|
||||||
|
PageControl.ActivePage := DataPage;
|
||||||
|
FGridData.Columns[0].Visible := False;
|
||||||
|
FGridData.Columns[2].Visible := btnColType.Down;
|
||||||
|
FGridData.Columns[4].Visible := False;
|
||||||
|
btnUseInstance.Enabled := False;
|
||||||
|
btnColClass.Enabled := False;
|
||||||
|
btnColType.Enabled := True;
|
||||||
|
btnColVisibility.Enabled := False;
|
||||||
|
|
||||||
|
v := FWatchPrinter.PrintWatchValue(Res, wdfDefault);
|
||||||
|
StatusBar1.SimpleText:=ShortenedExpression+' : '+Res.TypeName + ' = ' + v;
|
||||||
|
|
||||||
|
GridDataSetup;
|
||||||
|
FGridData.Cells[1,1]:=FExpression;
|
||||||
|
FGridData.Cells[2,1]:=Res.TypeName;
|
||||||
|
FGridData.Cells[3,1]:=v;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TIDEInspectDlg.InspectResDataPointer;
|
||||||
|
var
|
||||||
|
Res: TWatchResultData;
|
||||||
|
v: String;
|
||||||
|
begin
|
||||||
|
Res := FCurrentWatchValue.ResultData;
|
||||||
|
DataPage.TabVisible:=true;
|
||||||
|
PropertiesPage.TabVisible:=false;
|
||||||
|
MethodsPage.TabVisible:=false;
|
||||||
|
PageControl.ActivePage := DataPage;
|
||||||
|
FGridData.Columns[0].Visible := False;
|
||||||
|
FGridData.Columns[2].Visible := btnColType.Down;
|
||||||
|
FGridData.Columns[4].Visible := False;
|
||||||
|
btnUseInstance.Enabled := False;
|
||||||
|
btnColClass.Enabled := False;
|
||||||
|
btnColType.Enabled := True;
|
||||||
|
btnColVisibility.Enabled := False;
|
||||||
|
|
||||||
|
v := FWatchPrinter.PrintWatchValue(Res, wdfDefault);
|
||||||
|
StatusBar1.SimpleText:=ShortenedExpression+' : '+Res.TypeName + ' = ' + v;
|
||||||
|
|
||||||
|
GridDataSetup;
|
||||||
|
v := FWatchPrinter.PrintWatchValue(Res, wdfPointer);
|
||||||
|
FGridData.Cells[1,1]:=FExpression;
|
||||||
|
FGridData.Cells[2,1]:=Res.TypeName;
|
||||||
|
FGridData.Cells[3,1]:=v;
|
||||||
|
|
||||||
|
Res := Res.DerefData;
|
||||||
|
if Res <> nil then begin
|
||||||
|
FGridData.RowCount := 3;
|
||||||
|
FGridData.Cells[1,2]:=Format(lisInspectPointerTo, ['']);
|
||||||
|
FGridData.Cells[2,2]:=Res.TypeName;
|
||||||
|
FGridData.Cells[3,2]:=FWatchPrinter.PrintWatchValue(Res, wdfDefault);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TIDEInspectDlg.InspectResDataEnum;
|
||||||
|
var
|
||||||
|
Res: TWatchResultData;
|
||||||
|
v: String;
|
||||||
|
begin
|
||||||
|
Res := FCurrentWatchValue.ResultData;
|
||||||
|
|
||||||
|
DataPage.TabVisible:=true;
|
||||||
|
PropertiesPage.TabVisible:=false;
|
||||||
|
MethodsPage.TabVisible:=false;
|
||||||
|
PageControl.ActivePage := DataPage;
|
||||||
|
FGridData.Columns[0].Visible := False; // anchestor
|
||||||
|
FGridData.Columns[2].Visible := btnColType.Down; // typename
|
||||||
|
FGridData.Columns[4].Visible := False;
|
||||||
|
btnUseInstance.Enabled := False;
|
||||||
|
btnColClass.Enabled := False;
|
||||||
|
btnColType.Enabled := True;
|
||||||
|
btnColVisibility.Enabled := False;
|
||||||
|
|
||||||
|
v := FWatchPrinter.PrintWatchValue(Res, wdfDefault);
|
||||||
|
StatusBar1.SimpleText:=ShortenedExpression+' : '+Res.TypeName + ' = ' + v;
|
||||||
|
|
||||||
|
GridDataSetup;
|
||||||
|
FGridData.Cells[1,1]:=FExpression;
|
||||||
|
FGridData.Cells[2,1]:=Res.TypeName;
|
||||||
|
// TODO: show declaration (all elements)
|
||||||
|
FGridData.Cells[3,1]:=v;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TIDEInspectDlg.InspectResDataSet;
|
||||||
|
begin
|
||||||
|
InspectEnum;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TIDEInspectDlg.InspectResDataArray;
|
||||||
|
var
|
||||||
|
Res, Entry: TWatchResultData;
|
||||||
|
v: String;
|
||||||
|
b: Int64;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
Res := FCurrentWatchValue.ResultData;
|
||||||
|
|
||||||
|
DataPage.TabVisible:=true;
|
||||||
|
PropertiesPage.TabVisible:=false;
|
||||||
|
MethodsPage.TabVisible:=false;
|
||||||
|
PageControl.ActivePage := DataPage;
|
||||||
|
FGridData.Columns[0].Visible := False;
|
||||||
|
FGridData.Columns[2].Visible := btnColType.Down;
|
||||||
|
FGridData.Columns[4].Visible := False;
|
||||||
|
btnUseInstance.Enabled := False;
|
||||||
|
btnColClass.Enabled := False;
|
||||||
|
btnColType.Enabled := True;
|
||||||
|
btnColVisibility.Enabled := False;
|
||||||
|
|
||||||
|
StatusBar1.SimpleText:=ShortenedExpression+' : '+Res.TypeName + ' = Len:' + IntToStr(Res.Count);
|
||||||
|
|
||||||
|
GridDataSetup;
|
||||||
|
if Res.Count > 0 then begin
|
||||||
|
FGridData.RowCount:=Res.Count+1;
|
||||||
|
b := Res.LowBound;
|
||||||
|
for i := 0 to Res.Count-1 do begin
|
||||||
|
Res.SetSelectedIndex(i);
|
||||||
|
Entry := Res.SelectedEntry;
|
||||||
|
FGridData.Cells[1,i+1] := IntToStr(b+i);
|
||||||
|
FGridData.Cells[2,i+1] := Entry.TypeName;
|
||||||
|
FGridData.Cells[3,i+1] := FWatchPrinter.PrintWatchValue(Entry, wdfDefault);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TIDEInspectDlg.InspectResDataStruct;
|
||||||
|
const
|
||||||
|
FieldLocationNames: array[TLzDbgFieldVisibility] of string = //(dfvUnknown, dfvPrivate, dfvProtected, dfvPublic, dfvPublished);
|
||||||
|
('', 'Private', 'Protected', 'Public', 'Published');
|
||||||
|
var
|
||||||
|
Res: TWatchResultData;
|
||||||
|
cnt, i: Integer;
|
||||||
|
FldInfo: TWatchResultDataFieldInfo;
|
||||||
|
AnchType: String;
|
||||||
|
begin
|
||||||
|
Res := FCurrentWatchValue.ResultData;
|
||||||
|
|
||||||
|
DataPage.TabVisible :=true;
|
||||||
|
PropertiesPage.TabVisible :=false;
|
||||||
|
MethodsPage.TabVisible := False; // TODO
|
||||||
|
//if not (PageControl.ActivePage = MethodsPage) then
|
||||||
|
PageControl.ActivePage := DataPage;
|
||||||
|
|
||||||
|
FGridData.Columns[0].Visible := (Res.StructType in [dstClass, dstObject]) and btnColClass.Down; // anchestor
|
||||||
|
FGridData.Columns[2].Visible := btnColType.Down; // typename
|
||||||
|
FGridData.Columns[4].Visible := (Res.StructType in [dstClass, dstObject]) and btnColVisibility.Down; // class-visibility
|
||||||
|
btnUseInstance.Enabled := Res.StructType in [dstClass];
|
||||||
|
btnColClass.Enabled := Res.StructType in [dstClass, dstObject];
|
||||||
|
btnColType.Enabled := True;
|
||||||
|
btnColVisibility.Enabled := Res.StructType in [dstClass, dstObject];
|
||||||
|
|
||||||
|
AnchType := '';
|
||||||
|
if Res.Anchestor <> nil then
|
||||||
|
AnchType := Res.Anchestor.TypeName;
|
||||||
|
StatusBar1.SimpleText:=Format(lisInspectClassInherit, [ShortenedExpression, Res.TypeName, AnchType]);
|
||||||
|
|
||||||
|
GridDataSetup;
|
||||||
|
cnt := Res.FieldCount; // TODO: filter method vs field
|
||||||
|
FGridData.RowCount := max(cnt+1, 2);
|
||||||
|
for i := 1 to cnt do begin
|
||||||
|
FldInfo := Res.Fields[i-1];
|
||||||
|
|
||||||
|
FGridData.Cells[1,i] := FldInfo.FieldName;
|
||||||
|
if FldInfo.Field <> nil
|
||||||
|
then FGridData.Cells[2,i] := FldInfo.Field.TypeName
|
||||||
|
else FGridData.Cells[2,i] := '';
|
||||||
|
if FldInfo.Field <> nil
|
||||||
|
then FGridData.Cells[3,i] := FWatchPrinter.PrintWatchValue(FldInfo.Field, wdfDefault)
|
||||||
|
else FGridData.Cells[3,i] := '<error>';
|
||||||
|
if FldInfo.Owner <> nil
|
||||||
|
then FGridData.Cells[0,i] := FldInfo.Owner.TypeName
|
||||||
|
else FGridData.Cells[0,i] := '';
|
||||||
|
FGridData.Cells[4,i] := FieldLocationNames[FldInfo.FieldVisibility];
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
//GridMethodsSetup;
|
||||||
|
//ShowMethodsFields;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TIDEInspectDlg.DataGridMouseDown(Sender: TObject; Button: TMouseButton;
|
procedure TIDEInspectDlg.DataGridMouseDown(Sender: TObject; Button: TMouseButton;
|
||||||
Shift: TShiftState; X, Y: Integer);
|
Shift: TShiftState; X, Y: Integer);
|
||||||
begin
|
begin
|
||||||
@ -219,78 +414,85 @@ end;
|
|||||||
|
|
||||||
procedure TIDEInspectDlg.FormShow(Sender: TObject);
|
procedure TIDEInspectDlg.FormShow(Sender: TObject);
|
||||||
begin
|
begin
|
||||||
|
ReleaseRefAndNil(FCurrentWatchValue);
|
||||||
|
FInspectWatches.Clear;
|
||||||
UpdateData;
|
UpdateData;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TIDEInspectDlg.EvaluateTestCallback(Sender: TObject;
|
|
||||||
ASuccess: Boolean; ResultText: String; ResultDBGType: TDBGType);
|
|
||||||
begin
|
|
||||||
FTestUpdateLock := False;
|
|
||||||
if ASuccess and (ResultDBGType <> nil) then begin
|
|
||||||
if pos('Cannot access memory at address', ResultDBGType.Value.AsString) = 1 then begin
|
|
||||||
FreeAndNil(ResultDBGType);
|
|
||||||
Execute(FGridData.Cells[2, FRowClicked] + '(' + FExpression + ')[0]');
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
FreeAndNil(ResultDBGType);
|
|
||||||
end;
|
|
||||||
Execute('(' + FExpression + ')^');
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TIDEInspectDlg.DataGridDoubleClick(Sender: TObject);
|
procedure TIDEInspectDlg.DataGridDoubleClick(Sender: TObject);
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
s: String;
|
s, t: String;
|
||||||
TestOpts: TWatcheEvaluateFlags;
|
|
||||||
begin
|
begin
|
||||||
if FTestUpdateLock then
|
if (FCurrentWatchValue = nil) or (FExpression = '') then exit;
|
||||||
exit;
|
|
||||||
|
|
||||||
if (FDBGInfo = nil) or (FExpression = '') then exit;
|
if FCurrentWatchValue.TypeInfo <> nil then begin
|
||||||
|
|
||||||
if (FDBGInfo.Kind in [skClass, skRecord, skObject]) then begin
|
if (FCurrentWatchValue.TypeInfo.Kind in [skClass, skRecord, skObject]) then begin
|
||||||
i := FGridData.Row;
|
|
||||||
if (i < 1) or (i >= FGridData.RowCount) then exit;
|
|
||||||
s := FGridData.Cells[1, i];
|
|
||||||
|
|
||||||
if btnUseInstance.Down and (FDBGInfo.Kind = skClass) then
|
|
||||||
Execute(FGridData.Cells[0, i] + '(' + FExpression + ').' + s)
|
|
||||||
else
|
|
||||||
Execute(FExpression + '.' + s);
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if (FDBGInfo.Kind in [skPointer]) then begin
|
|
||||||
FTestUpdateLock := true;
|
|
||||||
try
|
|
||||||
|
|
||||||
FRowClicked := FGridData.Row;
|
|
||||||
if (FRowClicked < 1) or (FRowClicked >= FGridData.RowCount) then exit;
|
|
||||||
s := FGridData.Cells[1, FRowClicked];
|
|
||||||
|
|
||||||
//TestOpts := [defFullTypeInfo];
|
|
||||||
TestOpts := [];
|
|
||||||
if btnUseInstance.Down then
|
|
||||||
include(TestOpts, defClassAutoCast);
|
|
||||||
|
|
||||||
if not DebugBoss.Evaluate('(' + FExpression + ')^', @EvaluateTestCallback, TestOpts) then
|
|
||||||
EvaluateTestCallback(nil, False, '', nil);
|
|
||||||
except
|
|
||||||
FTestUpdateLock := False;
|
|
||||||
end;
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if (FDBGInfo.Kind in [skSimple]) and (FDBGInfo.Attributes*[saArray,saDynArray] <> []) then begin
|
|
||||||
if FDBGInfo.Len < 1 then exit;
|
|
||||||
if FDBGInfo.Fields.Count > 0 then begin
|
|
||||||
i := FGridData.Row;
|
i := FGridData.Row;
|
||||||
if (i < 1) or (i >= FGridData.RowCount) then exit;
|
if (i < 1) or (i >= FGridData.RowCount) then exit;
|
||||||
s := FGridData.Cells[1, i];
|
s := FGridData.Cells[1, i];
|
||||||
Execute(FExpression + '[' + s + ']');
|
|
||||||
end
|
if btnUseInstance.Down and (FCurrentWatchValue.TypeInfo.Kind = skClass) then
|
||||||
else begin
|
Execute(FGridData.Cells[0, i] + '(' + FExpression + ').' + s)
|
||||||
//
|
else
|
||||||
|
Execute(FExpression + '.' + s);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if (FCurrentWatchValue.TypeInfo.Kind in [skPointer]) then begin
|
||||||
|
i := FGridData.Row;
|
||||||
|
if (i < 1) or (i >= FGridData.RowCount) then exit;
|
||||||
|
s := FGridData.Cells[1, i];
|
||||||
|
t := FGridData.Cells[2, i];
|
||||||
|
Execute('(' + FExpression + ')^');
|
||||||
|
if not FExpressionWasEvaluated then
|
||||||
|
FAlternateExpression := t + '(' + FExpression + ')[0]';
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if (FCurrentWatchValue.TypeInfo.Kind in [skSimple]) and (FCurrentWatchValue.TypeInfo.Attributes*[saArray,saDynArray] <> []) then begin
|
||||||
|
if FCurrentWatchValue.TypeInfo.Len < 1 then exit;
|
||||||
|
if FCurrentWatchValue.TypeInfo.Fields.Count > 0 then begin
|
||||||
|
i := FGridData.Row;
|
||||||
|
if (i < 1) or (i >= FGridData.RowCount) then exit;
|
||||||
|
s := FGridData.Cells[1, i];
|
||||||
|
Execute(FExpression + '[' + s + ']');
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
//
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if FCurrentWatchValue.ResultData <> nil then begin
|
||||||
|
case FCurrentWatchValue.ResultData.ValueKind of
|
||||||
|
rdkPointerVal: begin
|
||||||
|
i := FGridData.Row;
|
||||||
|
if (i < 1) or (i >= FGridData.RowCount) then exit;
|
||||||
|
s := FGridData.Cells[1, i];
|
||||||
|
t := FGridData.Cells[2, i];
|
||||||
|
Execute('(' + FExpression + ')^');
|
||||||
|
if not FExpressionWasEvaluated then
|
||||||
|
FAlternateExpression := t + '(' + FExpression + ')[0]';
|
||||||
|
end;
|
||||||
|
rdkArray: begin
|
||||||
|
i := FGridData.Row;
|
||||||
|
if (i < 1) or (i >= FGridData.RowCount) then exit;
|
||||||
|
s := FGridData.Cells[1, i];
|
||||||
|
Execute(FExpression + '[' + s + ']');
|
||||||
|
end;
|
||||||
|
rdkStruct: begin
|
||||||
|
i := FGridData.Row;
|
||||||
|
if (i < 1) or (i >= FGridData.RowCount) then exit;
|
||||||
|
s := FGridData.Cells[1, i];
|
||||||
|
|
||||||
|
if btnUseInstance.Down and (FCurrentWatchValue.ResultData.StructType in [dstClass, dstObject]) then
|
||||||
|
Execute(FGridData.Cells[0, i] + '(' + FExpression + ').' + s)
|
||||||
|
else
|
||||||
|
Execute(FExpression + '.' + s);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -298,9 +500,13 @@ end;
|
|||||||
|
|
||||||
procedure TIDEInspectDlg.btnColClassClick(Sender: TObject);
|
procedure TIDEInspectDlg.btnColClassClick(Sender: TObject);
|
||||||
begin
|
begin
|
||||||
if (FDBGInfo = nil) then exit;
|
if (FCurrentWatchValue = nil) then exit;
|
||||||
|
|
||||||
if (FDBGInfo.Kind = skClass) then begin
|
if ( (FCurrentWatchValue.TypeInfo = nil) and
|
||||||
|
(FCurrentWatchValue.TypeInfo.Kind = skClass)
|
||||||
|
) or
|
||||||
|
( FCurrentWatchValue.ResultData.StructType in [dstClass, dstObject] )
|
||||||
|
then begin
|
||||||
FGridData.Columns[0].Visible := btnColClass.Down;
|
FGridData.Columns[0].Visible := btnColClass.Down;
|
||||||
FGridData.Columns[4].Visible := btnColVisibility.Down;
|
FGridData.Columns[4].Visible := btnColVisibility.Down;
|
||||||
end;
|
end;
|
||||||
@ -318,6 +524,8 @@ begin
|
|||||||
if btnPower.Down
|
if btnPower.Down
|
||||||
then begin
|
then begin
|
||||||
btnPower.ImageIndex := FPowerImgIdx;
|
btnPower.ImageIndex := FPowerImgIdx;
|
||||||
|
ReleaseRefAndNil(FCurrentWatchValue);
|
||||||
|
FInspectWatches.Clear;
|
||||||
UpdateData;
|
UpdateData;
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
@ -400,10 +608,11 @@ begin
|
|||||||
btnColVisibility.Enabled := True;
|
btnColVisibility.Enabled := True;
|
||||||
|
|
||||||
|
|
||||||
if not Assigned(FDBGInfo) then exit;
|
if not Assigned(FCurrentWatchValue) then exit;
|
||||||
if not Assigned(FDBGInfo.Fields) then exit;
|
if not Assigned(FCurrentWatchValue.TypeInfo) then exit;
|
||||||
StatusBar1.SimpleText:=Format(lisInspectClassInherit, [ShortenedExpression, FDBGInfo.
|
if not Assigned(FCurrentWatchValue.TypeInfo.Fields) then exit;
|
||||||
TypeName, FDBGInfo.Ancestor]);
|
StatusBar1.SimpleText:=Format(lisInspectClassInherit, [ShortenedExpression, FCurrentWatchValue.TypeInfo.
|
||||||
|
TypeName, FCurrentWatchValue.TypeInfo.Ancestor]);
|
||||||
GridDataSetup;
|
GridDataSetup;
|
||||||
ShowDataFields;
|
ShowDataFields;
|
||||||
//FGridData.AutoSizeColumn(1);
|
//FGridData.AutoSizeColumn(1);
|
||||||
@ -428,12 +637,13 @@ begin
|
|||||||
btnColType.Enabled := True;
|
btnColType.Enabled := True;
|
||||||
btnColVisibility.Enabled := False;
|
btnColVisibility.Enabled := False;
|
||||||
|
|
||||||
if not Assigned(FDBGInfo) then exit;
|
if not Assigned(FCurrentWatchValue) then exit;
|
||||||
|
if not Assigned(FCurrentWatchValue.TypeInfo) then exit;
|
||||||
StatusBar1.SimpleText:=ShortenedExpression+' : Variant';
|
StatusBar1.SimpleText:=ShortenedExpression+' : Variant';
|
||||||
GridDataSetup;
|
GridDataSetup;
|
||||||
FGridData.Cells[1,1]:=FExpression;
|
FGridData.Cells[1,1]:=FExpression;
|
||||||
FGridData.Cells[2,1]:='Variant';
|
FGridData.Cells[2,1]:='Variant';
|
||||||
FGridData.Cells[3,1]:=FDBGInfo.Value.AsString;
|
FGridData.Cells[3,1]:=FCurrentWatchValue.TypeInfo.Value.AsString;
|
||||||
//FGridData.AutoSizeColumn(1);
|
//FGridData.AutoSizeColumn(1);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -451,9 +661,10 @@ begin
|
|||||||
btnColType.Enabled := True;
|
btnColType.Enabled := True;
|
||||||
btnColVisibility.Enabled := False;
|
btnColVisibility.Enabled := False;
|
||||||
|
|
||||||
if not Assigned(FDBGInfo) then exit;
|
if not Assigned(FCurrentWatchValue) then exit;
|
||||||
if not Assigned(FDBGInfo.Fields) then exit;
|
if not Assigned(FCurrentWatchValue.TypeInfo) then exit;
|
||||||
StatusBar1.SimpleText:=ShortenedExpression+' : '+FDBGInfo.TypeName;
|
if not Assigned(FCurrentWatchValue.TypeInfo.Fields) then exit;
|
||||||
|
StatusBar1.SimpleText:=ShortenedExpression+' : '+FCurrentWatchValue.TypeInfo.TypeName;
|
||||||
GridDataSetup;
|
GridDataSetup;
|
||||||
ShowDataFields;
|
ShowDataFields;
|
||||||
//FGridData.AutoSizeColumn(2);
|
//FGridData.AutoSizeColumn(2);
|
||||||
@ -476,19 +687,20 @@ begin
|
|||||||
btnColType.Enabled := True;
|
btnColType.Enabled := True;
|
||||||
btnColVisibility.Enabled := False;
|
btnColVisibility.Enabled := False;
|
||||||
|
|
||||||
if not Assigned(FDBGInfo) then exit;
|
if not Assigned(FCurrentWatchValue) then exit;
|
||||||
|
if not Assigned(FCurrentWatchValue.TypeInfo) then exit;
|
||||||
GridDataSetup;
|
GridDataSetup;
|
||||||
|
|
||||||
if FDBGInfo.Attributes*[saArray,saDynArray] <> [] then begin
|
if FCurrentWatchValue.TypeInfo.Attributes*[saArray,saDynArray] <> [] then begin
|
||||||
if FDBGInfo.Len >= 0 then
|
if FCurrentWatchValue.TypeInfo.Len >= 0 then
|
||||||
StatusBar1.SimpleText:=ShortenedExpression+' : '+FDBGInfo.TypeName + ' = Len:' + IntToStr(FDBGInfo.Len) + ' ' + FDBGInfo.Value.AsString
|
StatusBar1.SimpleText:=ShortenedExpression+' : '+FCurrentWatchValue.TypeInfo.TypeName + ' = Len:' + IntToStr(FCurrentWatchValue.TypeInfo.Len) + ' ' + FCurrentWatchValue.TypeInfo.Value.AsString
|
||||||
else
|
else
|
||||||
StatusBar1.SimpleText:=ShortenedExpression+' : '+FDBGInfo.TypeName + ' = ' + FDBGInfo.Value.AsString;
|
StatusBar1.SimpleText:=ShortenedExpression+' : '+FCurrentWatchValue.TypeInfo.TypeName + ' = ' + FCurrentWatchValue.TypeInfo.Value.AsString;
|
||||||
|
|
||||||
if FDBGInfo.Fields.Count > 0 then begin
|
if FCurrentWatchValue.TypeInfo.Fields.Count > 0 then begin
|
||||||
FGridData.RowCount:=FDBGInfo.Fields.Count+1;
|
FGridData.RowCount:=FCurrentWatchValue.TypeInfo.Fields.Count+1;
|
||||||
for j := 0 to FDBGInfo.Fields.Count-1 do begin
|
for j := 0 to FCurrentWatchValue.TypeInfo.Fields.Count-1 do begin
|
||||||
fld := FDBGInfo.Fields[j];
|
fld := FCurrentWatchValue.TypeInfo.Fields[j];
|
||||||
FGridData.Cells[1,j+1]:=fld.Name; // index
|
FGridData.Cells[1,j+1]:=fld.Name; // index
|
||||||
FGridData.Cells[2,j+1]:=fld.DBGType.TypeName;
|
FGridData.Cells[2,j+1]:=fld.DBGType.TypeName;
|
||||||
FGridData.Cells[3,j+1]:=fld.DBGType.Value.AsString;
|
FGridData.Cells[3,j+1]:=fld.DBGType.Value.AsString;
|
||||||
@ -497,11 +709,11 @@ begin
|
|||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
StatusBar1.SimpleText:=ShortenedExpression+' : '+FDBGInfo.TypeName + ' = ' + FDBGInfo.Value.AsString;
|
StatusBar1.SimpleText:=ShortenedExpression+' : '+FCurrentWatchValue.TypeInfo.TypeName + ' = ' + FCurrentWatchValue.TypeInfo.Value.AsString;
|
||||||
|
|
||||||
FGridData.Cells[1,1]:=FExpression;
|
FGridData.Cells[1,1]:=FExpression;
|
||||||
FGridData.Cells[2,1]:=FDBGInfo.TypeName;
|
FGridData.Cells[2,1]:=FCurrentWatchValue.TypeInfo.TypeName;
|
||||||
FGridData.Cells[3,1]:=FDBGInfo.Value.AsString;
|
FGridData.Cells[3,1]:=FCurrentWatchValue.TypeInfo.Value.AsString;
|
||||||
//FGridData.AutoSizeColumn(2);
|
//FGridData.AutoSizeColumn(2);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -519,15 +731,16 @@ begin
|
|||||||
btnColType.Enabled := True;
|
btnColType.Enabled := True;
|
||||||
btnColVisibility.Enabled := False;
|
btnColVisibility.Enabled := False;
|
||||||
|
|
||||||
if not Assigned(FDBGInfo) then exit;
|
if not Assigned(FCurrentWatchValue) then exit;
|
||||||
StatusBar1.SimpleText:=ShortenedExpression+' : '+FDBGInfo.TypeName + ' = ' + FDBGInfo.Value.AsString;
|
if not Assigned(FCurrentWatchValue.TypeInfo) then exit;
|
||||||
|
StatusBar1.SimpleText:=ShortenedExpression+' : '+FCurrentWatchValue.TypeInfo.TypeName + ' = ' + FCurrentWatchValue.TypeInfo.Value.AsString;
|
||||||
GridDataSetup;
|
GridDataSetup;
|
||||||
FGridData.Cells[1,1]:=FExpression;
|
FGridData.Cells[1,1]:=FExpression;
|
||||||
FGridData.Cells[2,1]:=FDBGInfo.TypeName;
|
FGridData.Cells[2,1]:=FCurrentWatchValue.TypeInfo.TypeName;
|
||||||
if (FDBGInfo.TypeName <> '') and (FDBGInfo.TypeDeclaration <> '')
|
if (FCurrentWatchValue.TypeInfo.TypeName <> '') and (FCurrentWatchValue.TypeInfo.TypeDeclaration <> '')
|
||||||
then FGridData.Cells[2,1] := FGridData.Cells[2,1] + ' = ';
|
then FGridData.Cells[2,1] := FGridData.Cells[2,1] + ' = ';
|
||||||
FGridData.Cells[2,1] := FGridData.Cells[2,1] + FDBGInfo.TypeDeclaration;
|
FGridData.Cells[2,1] := FGridData.Cells[2,1] + FCurrentWatchValue.TypeInfo.TypeDeclaration;
|
||||||
FGridData.Cells[3,1]:=FDBGInfo.Value.AsString;
|
FGridData.Cells[3,1]:=FCurrentWatchValue.TypeInfo.Value.AsString;
|
||||||
//FGridData.AutoSizeColumn(2);
|
//FGridData.AutoSizeColumn(2);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -545,15 +758,16 @@ begin
|
|||||||
btnColType.Enabled := True;
|
btnColType.Enabled := True;
|
||||||
btnColVisibility.Enabled := False;
|
btnColVisibility.Enabled := False;
|
||||||
|
|
||||||
if not Assigned(FDBGInfo) then exit;
|
if not Assigned(FCurrentWatchValue) then exit;
|
||||||
StatusBar1.SimpleText:=ShortenedExpression+' : '+FDBGInfo.TypeName + ' = ' + FDBGInfo.Value.AsString;
|
if not Assigned(FCurrentWatchValue.TypeInfo) then exit;
|
||||||
|
StatusBar1.SimpleText:=ShortenedExpression+' : '+FCurrentWatchValue.TypeInfo.TypeName + ' = ' + FCurrentWatchValue.TypeInfo.Value.AsString;
|
||||||
GridDataSetup;
|
GridDataSetup;
|
||||||
FGridData.Cells[1,1]:=FExpression;
|
FGridData.Cells[1,1]:=FExpression;
|
||||||
FGridData.Cells[2,1]:=FDBGInfo.TypeName;
|
FGridData.Cells[2,1]:=FCurrentWatchValue.TypeInfo.TypeName;
|
||||||
if (FDBGInfo.TypeName <> '') and (FDBGInfo.TypeDeclaration <> '')
|
if (FCurrentWatchValue.TypeInfo.TypeName <> '') and (FCurrentWatchValue.TypeInfo.TypeDeclaration <> '')
|
||||||
then FGridData.Cells[2,1] := FGridData.Cells[2,1] + ' = ';
|
then FGridData.Cells[2,1] := FGridData.Cells[2,1] + ' = ';
|
||||||
FGridData.Cells[2,1] := FGridData.Cells[2,1] + FDBGInfo.TypeDeclaration;
|
FGridData.Cells[2,1] := FGridData.Cells[2,1] + FCurrentWatchValue.TypeInfo.TypeDeclaration;
|
||||||
FGridData.Cells[3,1]:=FDBGInfo.Value.AsString;
|
FGridData.Cells[3,1]:=FCurrentWatchValue.TypeInfo.Value.AsString;
|
||||||
//FGridData.AutoSizeColumn(2);
|
//FGridData.AutoSizeColumn(2);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -571,16 +785,17 @@ begin
|
|||||||
btnColType.Enabled := True;
|
btnColType.Enabled := True;
|
||||||
btnColVisibility.Enabled := False;
|
btnColVisibility.Enabled := False;
|
||||||
|
|
||||||
if not Assigned(FDBGInfo) then exit;
|
if not Assigned(FCurrentWatchValue) then exit;
|
||||||
StatusBar1.SimpleText:=ShortenedExpression+' : '+FDBGInfo.TypeName + ' = ' + FDBGInfo.Value.AsString;
|
if not Assigned(FCurrentWatchValue.TypeInfo) then exit;
|
||||||
|
StatusBar1.SimpleText:=ShortenedExpression+' : '+FCurrentWatchValue.TypeInfo.TypeName + ' = ' + FCurrentWatchValue.TypeInfo.Value.AsString;
|
||||||
GridDataSetup;
|
GridDataSetup;
|
||||||
FGridData.Cells[1,1]:=FExpression;
|
FGridData.Cells[1,1]:=FExpression;
|
||||||
if (FDBGInfo.TypeName <> '') and (FDBGInfo.TypeName[1] = '^')
|
if (FCurrentWatchValue.TypeInfo.TypeName <> '') and (FCurrentWatchValue.TypeInfo.TypeName[1] = '^')
|
||||||
then FGridData.Cells[2, 1]:=Format(lisInspectPointerTo, [copy(FDBGInfo.
|
then FGridData.Cells[2, 1]:=Format(lisInspectPointerTo, [copy(FCurrentWatchValue.TypeInfo.
|
||||||
TypeName, 2, length(FDBGInfo.TypeName))])
|
TypeName, 2, length(FCurrentWatchValue.TypeInfo.TypeName))])
|
||||||
else FGridData.Cells[2,1]:=FDBGInfo.TypeName;
|
else FGridData.Cells[2,1]:=FCurrentWatchValue.TypeInfo.TypeName;
|
||||||
{$PUSH}{$RANGECHECKS OFF}
|
{$PUSH}{$RANGECHECKS OFF}
|
||||||
FGridData.Cells[3,1]:=format('$%x',[{%H-}PtrUInt(FDBGInfo.Value.AsPointer)]);
|
FGridData.Cells[3,1]:=format('$%x',[{%H-}PtrUInt(FCurrentWatchValue.TypeInfo.Value.AsPointer)]);
|
||||||
{$POP}
|
{$POP}
|
||||||
//FGridData.AutoSizeColumn(2);
|
//FGridData.AutoSizeColumn(2);
|
||||||
end;
|
end;
|
||||||
@ -661,8 +876,8 @@ var
|
|||||||
fld: TDBGField;
|
fld: TDBGField;
|
||||||
begin
|
begin
|
||||||
k:=0;
|
k:=0;
|
||||||
for j := 0 to FDBGInfo.Fields.Count-1 do begin
|
for j := 0 to FCurrentWatchValue.TypeInfo.Fields.Count-1 do begin
|
||||||
case FDBGInfo.Fields[j].DBGType.Kind of
|
case FCurrentWatchValue.TypeInfo.Fields[j].DBGType.Kind of
|
||||||
skSimple,skRecord,skVariant,skPointer: inc(k);
|
skSimple,skRecord,skVariant,skPointer: inc(k);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -670,8 +885,8 @@ begin
|
|||||||
if k<2 Then k:=2;
|
if k<2 Then k:=2;
|
||||||
FGridData.RowCount:=k;
|
FGridData.RowCount:=k;
|
||||||
k:=0;
|
k:=0;
|
||||||
for j := 0 to FDBGInfo.Fields.Count-1 do begin
|
for j := 0 to FCurrentWatchValue.TypeInfo.Fields.Count-1 do begin
|
||||||
fld := FDBGInfo.Fields[j];
|
fld := FCurrentWatchValue.TypeInfo.Fields[j];
|
||||||
case fld.DBGType.Kind of
|
case fld.DBGType.Kind of
|
||||||
skSimple:
|
skSimple:
|
||||||
begin
|
begin
|
||||||
@ -734,8 +949,8 @@ var
|
|||||||
j,k: SizeInt;
|
j,k: SizeInt;
|
||||||
begin
|
begin
|
||||||
k:=0;
|
k:=0;
|
||||||
for j := 0 to FDBGInfo.Fields.Count-1 do begin
|
for j := 0 to FCurrentWatchValue.TypeInfo.Fields.Count-1 do begin
|
||||||
case FDBGInfo.Fields[j].DBGType.Kind of
|
case FCurrentWatchValue.TypeInfo.Fields[j].DBGType.Kind of
|
||||||
skProcedure,skFunction,skProcedureRef, skFunctionRef: inc(k);
|
skProcedure,skFunction,skProcedureRef, skFunctionRef: inc(k);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -743,13 +958,13 @@ begin
|
|||||||
if k<2 Then k:=2;
|
if k<2 Then k:=2;
|
||||||
FGridMethods.RowCount:=k;
|
FGridMethods.RowCount:=k;
|
||||||
k:=0;
|
k:=0;
|
||||||
for j := 0 to FDBGInfo.Fields.Count-1 do begin
|
for j := 0 to FCurrentWatchValue.TypeInfo.Fields.Count-1 do begin
|
||||||
case FDBGInfo.Fields[j].DBGType.Kind of
|
case FCurrentWatchValue.TypeInfo.Fields[j].DBGType.Kind of
|
||||||
skProcedure, skProcedureRef:
|
skProcedure, skProcedureRef:
|
||||||
begin
|
begin
|
||||||
inc(k);
|
inc(k);
|
||||||
FGridMethods.Cells[0,k]:=FDBGInfo.Fields[j].Name;
|
FGridMethods.Cells[0,k]:=FCurrentWatchValue.TypeInfo.Fields[j].Name;
|
||||||
if ffDestructor in FDBGInfo.Fields[j].Flags then begin
|
if ffDestructor in FCurrentWatchValue.TypeInfo.Fields[j].Flags then begin
|
||||||
FGridMethods.Cells[1,k]:='Destructor';
|
FGridMethods.Cells[1,k]:='Destructor';
|
||||||
end else begin
|
end else begin
|
||||||
FGridMethods.Cells[1,k]:='Procedure';
|
FGridMethods.Cells[1,k]:='Procedure';
|
||||||
@ -760,14 +975,14 @@ begin
|
|||||||
skFunction, skFunctionRef:
|
skFunction, skFunctionRef:
|
||||||
begin
|
begin
|
||||||
inc(k);
|
inc(k);
|
||||||
FGridMethods.Cells[0,k]:=FDBGInfo.Fields[j].Name;
|
FGridMethods.Cells[0,k]:=FCurrentWatchValue.TypeInfo.Fields[j].Name;
|
||||||
if ffConstructor in FDBGInfo.Fields[j].Flags then begin
|
if ffConstructor in FCurrentWatchValue.TypeInfo.Fields[j].Flags then begin
|
||||||
FGridMethods.Cells[1,k]:='Constructor';
|
FGridMethods.Cells[1,k]:='Constructor';
|
||||||
end else begin
|
end else begin
|
||||||
FGridMethods.Cells[1,k]:='Function';
|
FGridMethods.Cells[1,k]:='Function';
|
||||||
end;
|
end;
|
||||||
if Assigned(FDBGInfo.Fields[j].DBGType.Result) then begin
|
if Assigned(FCurrentWatchValue.TypeInfo.Fields[j].DBGType.Result) then begin
|
||||||
FGridMethods.Cells[2,k]:=FDBGInfo.Fields[j].DBGType.Result.TypeName;
|
FGridMethods.Cells[2,k]:=FCurrentWatchValue.TypeInfo.Fields[j].DBGType.Result.TypeName;
|
||||||
end else begin
|
end else begin
|
||||||
FGridMethods.Cells[2,k]:='';
|
FGridMethods.Cells[2,k]:='';
|
||||||
end;
|
end;
|
||||||
@ -824,16 +1039,21 @@ constructor TIDEInspectDlg.Create(AOwner: TComponent);
|
|||||||
begin
|
begin
|
||||||
inherited Create(AOwner);
|
inherited Create(AOwner);
|
||||||
|
|
||||||
FUpdateLock := False;
|
|
||||||
FUpdateNeeded := False;
|
|
||||||
Localize;
|
Localize;
|
||||||
|
|
||||||
|
|
||||||
ThreadsMonitor := DebugBoss.Threads;
|
ThreadsMonitor := DebugBoss.Threads;
|
||||||
CallStackMonitor := DebugBoss.CallStack;
|
CallStackMonitor := DebugBoss.CallStack;
|
||||||
|
WatchesMonitor := DebugBoss.Watches;
|
||||||
|
WatchesNotification.OnUpdate := @DoWatchUpdated;
|
||||||
|
|
||||||
|
FWatchPrinter := TWatchResultPrinter.Create;
|
||||||
|
FInspectWatches := TCurrentWatches.Create(WatchesMonitor);
|
||||||
|
|
||||||
ThreadsNotification.OnCurrent := @ContextChanged;
|
ThreadsNotification.OnCurrent := @ContextChanged;
|
||||||
CallstackNotification.OnCurrent := @ContextChanged;
|
CallstackNotification.OnCurrent := @ContextChanged;
|
||||||
|
|
||||||
|
DebugBoss.RegisterStateChangeHandler(@DoDebuggerState);
|
||||||
|
|
||||||
FHistory := TStringList.Create;
|
FHistory := TStringList.Create;
|
||||||
|
|
||||||
FGridData:=TStringGrid.Create(DataPage);
|
FGridData:=TStringGrid.Create(DataPage);
|
||||||
@ -877,12 +1097,16 @@ end;
|
|||||||
|
|
||||||
destructor TIDEInspectDlg.Destroy;
|
destructor TIDEInspectDlg.Destroy;
|
||||||
begin
|
begin
|
||||||
FreeAndNil(FDBGInfo);
|
DebugBoss.UnregisterStateChangeHandler(@DoDebuggerState);
|
||||||
|
ReleaseRefAndNil(FCurrentWatchValue);
|
||||||
FreeAndNil(FHistory);
|
FreeAndNil(FHistory);
|
||||||
|
FreeAndNil(FWatchPrinter);
|
||||||
//FreeAndNil(FDataGridHook);
|
//FreeAndNil(FDataGridHook);
|
||||||
//FreeAndNil(FPropertiesGridHook);
|
//FreeAndNil(FPropertiesGridHook);
|
||||||
//FreeAndNil(FMethodsGridHook);
|
//FreeAndNil(FMethodsGridHook);
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
|
|
||||||
|
FreeAndNil(FInspectWatches);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TIDEInspectDlg.InternalExecute(const AExpression: ansistring);
|
procedure TIDEInspectDlg.InternalExecute(const AExpression: ansistring);
|
||||||
@ -931,98 +1155,175 @@ begin
|
|||||||
UpdateData;
|
UpdateData;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TIDEInspectDlg.EvaluateCallback(Sender: TObject; ASuccess: Boolean;
|
|
||||||
ResultText: String; ResultDBGType: TDBGType);
|
procedure TIDEInspectDlg.DoWatchUpdated(const ASender: TIdeWatches;
|
||||||
|
const AWatch: TIdeWatch);
|
||||||
begin
|
begin
|
||||||
FUpdateLock := False;
|
if (FCurrentWatchValue = nil) or
|
||||||
if FUpdateNeeded then begin
|
not (FCurrentWatchValue.Validity in [ddsError, ddsInvalid, ddsValid])
|
||||||
Clear;
|
then
|
||||||
UpdateData;
|
exit;
|
||||||
|
if (AWatch <> FCurrentWatchValue.Watch) or
|
||||||
|
(ASender <> FInspectWatches)
|
||||||
|
then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
if (FCurrentWatchValue.Validity in [ddsError, ddsInvalid]) and
|
||||||
|
(FAlternateExpression <> '')
|
||||||
|
then begin
|
||||||
|
if (FHistoryIndex = FHistory.Count - 1) and
|
||||||
|
(FHistory[FHistoryIndex] = FExpression)
|
||||||
|
then begin
|
||||||
|
FHistory.Delete(FHistoryIndex);
|
||||||
|
dec(FHistoryIndex);
|
||||||
|
end;
|
||||||
|
Execute(FAlternateExpression);
|
||||||
|
FAlternateExpression := '';
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
FAlternateExpression := '';
|
||||||
FExpressionWasEvaluated := True;
|
FExpressionWasEvaluated := True;
|
||||||
|
FHumanReadable := FWatchPrinter.PrintWatchValue(FCurrentWatchValue.ResultData, wdfStructure);
|
||||||
|
|
||||||
FHumanReadable := ResultText;
|
if FCurrentWatchValue.Validity = ddsValid then begin
|
||||||
FDBGInfo := ResultDBGType;
|
if FCurrentWatchValue.TypeInfo <> nil then begin
|
||||||
|
case FCurrentWatchValue.TypeInfo.Kind of
|
||||||
if not ASuccess or not assigned(FDBGInfo) then
|
skClass, skObject, skInterface: InspectClass();
|
||||||
begin
|
skRecord: InspectRecord();
|
||||||
FreeAndNil(FDBGInfo);
|
skVariant: InspectVariant();
|
||||||
Clear;
|
skEnum: InspectEnum;
|
||||||
StatusBar1.SimpleText:=Format(lisInspectUnavailableError, [ShortenedExpression, FHumanReadable]);
|
skSet: InspectSet;
|
||||||
ErrorLabel.Caption :=Format(lisInspectUnavailableError, [ShortenedExpression, FHumanReadable]);
|
skProcedure, skProcedureRef: InspectSimple;
|
||||||
PageControl.ActivePage := ErrorPage;
|
skFunction, skFunctionRef: InspectSimple;
|
||||||
Exit;
|
skSimple,
|
||||||
end;
|
skInteger,
|
||||||
case FDBGInfo.Kind of
|
skCardinal, skBoolean, skChar, skFloat: InspectSimple();
|
||||||
skClass, skObject, skInterface: InspectClass();
|
skArray: InspectSimple();
|
||||||
skRecord: InspectRecord();
|
skPointer: InspectPointer();
|
||||||
skVariant: InspectVariant();
|
skString, skAnsiString, skWideString: InspectSimple;
|
||||||
skEnum: InspectEnum;
|
// skDecomposable: ;
|
||||||
skSet: InspectSet;
|
else begin
|
||||||
skProcedure, skProcedureRef: InspectSimple;
|
Clear;
|
||||||
skFunction, skFunctionRef: InspectSimple;
|
StatusBar1.SimpleText:=Format(lisInspectUnavailableError, [ShortenedExpression, FHumanReadable]);
|
||||||
skSimple,
|
ErrorLabel.Caption :=Format(lisInspectUnavailableError, [ShortenedExpression, FHumanReadable]);
|
||||||
skInteger,
|
PageControl.ActivePage := ErrorPage;
|
||||||
skCardinal, skBoolean, skChar, skFloat: InspectSimple();
|
end;
|
||||||
skArray: InspectSimple();
|
|
||||||
skPointer: InspectPointer();
|
|
||||||
skString, skAnsiString, skWideString: InspectSimple;
|
|
||||||
// skDecomposable: ;
|
|
||||||
else begin
|
|
||||||
Clear;
|
|
||||||
StatusBar1.SimpleText:=Format(lisInspectUnavailableError, [ShortenedExpression, FHumanReadable]);
|
|
||||||
ErrorLabel.Caption :=Format(lisInspectUnavailableError, [ShortenedExpression, FHumanReadable]);
|
|
||||||
PageControl.ActivePage := ErrorPage;
|
|
||||||
end;
|
end;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
// resultdata
|
||||||
|
case FCurrentWatchValue.ResultData.ValueKind of
|
||||||
|
//rdkError: ;
|
||||||
|
rdkPrePrinted,
|
||||||
|
rdkString,
|
||||||
|
rdkWideString,
|
||||||
|
rdkChar,
|
||||||
|
rdkSignedNumVal,
|
||||||
|
rdkUnsignedNumVal,
|
||||||
|
rdkFloatVal,
|
||||||
|
rdkBool,
|
||||||
|
rdkPCharOrString: InspectResDataSimple;
|
||||||
|
rdkPointerVal: InspectResDataPointer;
|
||||||
|
rdkEnum: InspectResDataEnum;
|
||||||
|
rdkEnumVal: InspectResDataEnum;
|
||||||
|
rdkSet: InspectResDataSet;
|
||||||
|
rdkArray: InspectResDataArray;
|
||||||
|
rdkStruct: InspectResDataStruct;
|
||||||
|
else begin
|
||||||
|
Clear;
|
||||||
|
StatusBar1.SimpleText:=Format(lisInspectUnavailableError, [ShortenedExpression, FHumanReadable]);
|
||||||
|
ErrorLabel.Caption :=Format(lisInspectUnavailableError, [ShortenedExpression, FHumanReadable]);
|
||||||
|
PageControl.ActivePage := ErrorPage;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
exit
|
||||||
|
end;
|
||||||
|
|
||||||
|
Clear;
|
||||||
|
StatusBar1.SimpleText:=Format(lisInspectUnavailableError, [ShortenedExpression, FHumanReadable]);
|
||||||
|
ErrorLabel.Caption :=Format(lisInspectUnavailableError, [ShortenedExpression, FHumanReadable]);
|
||||||
|
PageControl.ActivePage := ErrorPage;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TIDEInspectDlg.DoDebuggerState(ADebugger: TDebuggerIntf;
|
||||||
|
AnOldState: TDBGState);
|
||||||
|
begin
|
||||||
|
if (ADebugger.State = dsPause) and (AnOldState <> dsPause) then begin
|
||||||
|
ReleaseRefAndNil(FCurrentWatchValue);
|
||||||
|
FInspectWatches.Clear;
|
||||||
|
UpdateData;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TIDEInspectDlg.UpdateData;
|
procedure TIDEInspectDlg.UpdateData;
|
||||||
var
|
var
|
||||||
Opts: TWatcheEvaluateFlags;
|
Opts: TWatcheEvaluateFlags;
|
||||||
|
AWatch: TCurrentWatch;
|
||||||
|
tid, idx: Integer;
|
||||||
|
stack: TIdeCallStack;
|
||||||
|
expr: String;
|
||||||
begin
|
begin
|
||||||
FExpressionWasEvaluated := False;
|
FExpressionWasEvaluated := False;
|
||||||
if DebugBoss.State in [dsRun, dsStop, dsIdle] then begin
|
FAlternateExpression := '';
|
||||||
// No request can be running
|
|
||||||
FUpdateLock := False;
|
|
||||||
FTestUpdateLock := False;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if FUpdateLock then begin
|
expr := trim(FExpression);
|
||||||
FUpdateNeeded := True;
|
if expr = '' then begin
|
||||||
exit;
|
ReleaseRefAndNil(FCurrentWatchValue);
|
||||||
end;
|
|
||||||
|
|
||||||
if FExpression = '' then begin
|
|
||||||
Clear;
|
Clear;
|
||||||
StatusBar1.SimpleText := '';
|
StatusBar1.SimpleText := '';
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
FUpdateLock := True;
|
InputHistories.HistoryLists.Add(ClassName, FExpression,rltCaseSensitive);
|
||||||
FUpdateNeeded := False;
|
if EdInspect.Items.IndexOf(FExpression) = -1
|
||||||
try
|
then EdInspect.Items.Insert(0, FExpression);
|
||||||
FreeAndNil(FDBGInfo);
|
|
||||||
|
|
||||||
InputHistories.HistoryLists.Add(ClassName, FExpression,rltCaseSensitive);
|
|
||||||
if EdInspect.Items.IndexOf(FExpression) = -1
|
|
||||||
then EdInspect.Items.Insert(0, FExpression);
|
|
||||||
|
|
||||||
Opts := [defFullTypeInfo];
|
if (CallStackMonitor = nil) or (ThreadsMonitor = nil) or
|
||||||
if btnUseInstance.Down then
|
(DebugBoss.State <> dsPause)
|
||||||
include(Opts, defClassAutoCast);
|
then
|
||||||
|
exit;
|
||||||
|
|
||||||
if not DebugBoss.Evaluate(FExpression, @EvaluateCallback, Opts) then
|
tid := ThreadsMonitor.CurrentThreads.CurrentThreadId;
|
||||||
EvaluateCallback(nil, False, '', nil);
|
stack := CallStackMonitor.CurrentCallStackList.EntriesForThreads[tid];
|
||||||
|
idx := 0;
|
||||||
|
if stack <> nil then
|
||||||
|
idx := stack.CurrentIndex;
|
||||||
|
|
||||||
except
|
Opts := [defFullTypeInfo];
|
||||||
FUpdateLock := False;
|
if btnUseInstance.Down then
|
||||||
|
include(Opts, defClassAutoCast);
|
||||||
|
|
||||||
|
if (FCurrentWatchValue <> nil) and
|
||||||
|
(FCurrentWatchValue.Expression = expr) and
|
||||||
|
(FCurrentWatchValue.EvaluateFlags = Opts) and
|
||||||
|
(FCurrentWatchValue.ThreadId = tid) and
|
||||||
|
(FCurrentWatchValue.StackFrame = idx)
|
||||||
|
then begin
|
||||||
|
FCurrentWatchValue.Value;
|
||||||
|
DoWatchUpdated(nil, FCurrentWatchValue.Watch);
|
||||||
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if FUpdateNeeded then
|
ReleaseRefAndNil(FCurrentWatchValue);
|
||||||
UpdateData;
|
|
||||||
|
FInspectWatches.BeginUpdate;
|
||||||
|
AWatch := FInspectWatches.Find(expr);
|
||||||
|
if AWatch = nil then begin
|
||||||
|
FInspectWatches.Clear;
|
||||||
|
AWatch := FInspectWatches.Add(expr);
|
||||||
|
end;
|
||||||
|
AWatch.EvaluateFlags := Opts;
|
||||||
|
AWatch.Enabled := True;
|
||||||
|
FInspectWatches.EndUpdate;
|
||||||
|
FCurrentWatchValue := AWatch.Values[tid, idx];
|
||||||
|
if FCurrentWatchValue <> nil then begin
|
||||||
|
FCurrentWatchValue.AddReference;
|
||||||
|
FCurrentWatchValue.Value;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
|
@ -91,6 +91,8 @@ const
|
|||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
|
TDebuggerStateChangeNotification = procedure(ADebugger: TDebuggerIntf; AnOldState: TDBGState) of object;
|
||||||
|
|
||||||
{ TBaseDebugManager }
|
{ TBaseDebugManager }
|
||||||
|
|
||||||
TDebugManagerState = (
|
TDebugManagerState = (
|
||||||
@ -222,6 +224,9 @@ type
|
|||||||
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;
|
||||||
|
|
||||||
|
procedure RegisterStateChangeHandler(AHandler: TDebuggerStateChangeNotification); virtual; abstract;
|
||||||
|
procedure UnregisterStateChangeHandler(AHandler: TDebuggerStateChangeNotification); virtual; abstract;
|
||||||
public
|
public
|
||||||
property Commands: TDBGCommands read GetCommands; // All current available commands of the debugger
|
property Commands: TDBGCommands read GetCommands; // All current available commands of the debugger
|
||||||
property Destroying: boolean read FDestroying;
|
property Destroying: boolean read FDestroying;
|
||||||
|
@ -45,6 +45,7 @@ uses
|
|||||||
LCLType, LCLIntf, Forms, Controls, Dialogs, ExtCtrls,
|
LCLType, LCLIntf, Forms, Controls, Dialogs, ExtCtrls,
|
||||||
// LazUtils
|
// LazUtils
|
||||||
LazFileUtils, LazFileCache, LazLoggerBase, Laz2_XMLCfg, LazUTF8, LazTracer,
|
LazFileUtils, LazFileCache, LazLoggerBase, Laz2_XMLCfg, LazUTF8, LazTracer,
|
||||||
|
LazMethodList,
|
||||||
// codetools
|
// codetools
|
||||||
CodeCache, CodeToolManager, PascalParserTool, CodeTree,
|
CodeCache, CodeToolManager, PascalParserTool, CodeTree,
|
||||||
// IDEIntf
|
// IDEIntf
|
||||||
@ -142,6 +143,7 @@ type
|
|||||||
FCurrentBreakpoint: TIDEBreakpoint;
|
FCurrentBreakpoint: TIDEBreakpoint;
|
||||||
FAutoContinueTimer: TTimer;
|
FAutoContinueTimer: TTimer;
|
||||||
FIsInitializingDebugger: Boolean;
|
FIsInitializingDebugger: Boolean;
|
||||||
|
FStateNotificationList: TMethodList;
|
||||||
|
|
||||||
// When a source file is not found, the user can choose one
|
// When a source file is not found, the user can choose one
|
||||||
// here are all choices stored
|
// here are all choices stored
|
||||||
@ -283,6 +285,9 @@ type
|
|||||||
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;
|
||||||
|
|
||||||
|
procedure RegisterStateChangeHandler(AHandler: TDebuggerStateChangeNotification); override;
|
||||||
|
procedure UnregisterStateChangeHandler(AHandler: TDebuggerStateChangeNotification); override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function DBGDateTimeFormatter(const aValue: string): string;
|
function DBGDateTimeFormatter(const aValue: string): string;
|
||||||
@ -1344,6 +1349,9 @@ begin
|
|||||||
|
|
||||||
UnlockDialogs;
|
UnlockDialogs;
|
||||||
|
|
||||||
|
for i := 0 to FStateNotificationList.Count-1 do
|
||||||
|
TDebuggerStateChangeNotification(FStateNotificationList[i])(ADebugger, OldState);
|
||||||
|
|
||||||
if FDebugger.State = dsInternalPause
|
if FDebugger.State = dsInternalPause
|
||||||
then exit;
|
then exit;
|
||||||
|
|
||||||
@ -1743,6 +1751,18 @@ begin
|
|||||||
then TAssemblerDlg(FDialogs[ddtAssembler]).SetLocation(FDebugger, FCurrentLocation.Address, AnAddr);
|
then TAssemblerDlg(FDialogs[ddtAssembler]).SetLocation(FDebugger, FCurrentLocation.Address, AnAddr);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TDebugManager.RegisterStateChangeHandler(
|
||||||
|
AHandler: TDebuggerStateChangeNotification);
|
||||||
|
begin
|
||||||
|
FStateNotificationList.Add(TMethod(AHandler));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TDebugManager.UnregisterStateChangeHandler(
|
||||||
|
AHandler: TDebuggerStateChangeNotification);
|
||||||
|
begin
|
||||||
|
FStateNotificationList.Remove(TMethod(AHandler));
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TDebugManager.DestroyDebugDialog(const ADialogType: TDebugDialogType);
|
procedure TDebugManager.DestroyDebugDialog(const ADialogType: TDebugDialogType);
|
||||||
begin
|
begin
|
||||||
if FDialogs[ADialogType] = nil then Exit;
|
if FDialogs[ADialogType] = nil then Exit;
|
||||||
@ -1917,6 +1937,7 @@ begin
|
|||||||
FSnapshots.Locals := FLocals;
|
FSnapshots.Locals := FLocals;
|
||||||
FSnapshots.UnitInfoProvider := FUnitInfoProvider;
|
FSnapshots.UnitInfoProvider := FUnitInfoProvider;
|
||||||
|
|
||||||
|
FStateNotificationList := TMethodList.Create;
|
||||||
FUserSourceFiles := TStringList.Create;
|
FUserSourceFiles := TStringList.Create;
|
||||||
|
|
||||||
FAutoContinueTimer := TTimer.Create(Self);
|
FAutoContinueTimer := TTimer.Create(Self);
|
||||||
@ -1975,6 +1996,7 @@ begin
|
|||||||
FreeAndNil(FUserSourceFiles);
|
FreeAndNil(FUserSourceFiles);
|
||||||
FreeAndNil(FHiddenDebugOutputLog);
|
FreeAndNil(FHiddenDebugOutputLog);
|
||||||
FreeAndNil(FUnitInfoProvider);
|
FreeAndNil(FUnitInfoProvider);
|
||||||
|
FreeAndNil(FStateNotificationList);
|
||||||
|
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
Loading…
Reference in New Issue
Block a user