mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-18 21:59:14 +02:00
Debugger: Allow to expand/unfold locals values
This commit is contained in:
parent
26f4160df9
commit
ad9eaf0474
@ -1805,6 +1805,8 @@ type
|
|||||||
class function GetDebuggerClass(const AIndex: Integer): TDebuggerClass;static;
|
class function GetDebuggerClass(const AIndex: Integer): TDebuggerClass;static;
|
||||||
class function GetDebuggerClassByName(const AIndex: String): TDebuggerClass; static;
|
class function GetDebuggerClassByName(const AIndex: String): TDebuggerClass; static;
|
||||||
function FindDebuggerClass(const Astring: String): TDebuggerClass;
|
function FindDebuggerClass(const Astring: String): TDebuggerClass;
|
||||||
|
public
|
||||||
|
procedure RequestWatchData(AWatchValue: TWatchValueIntf); virtual; abstract;
|
||||||
public
|
public
|
||||||
class function DebuggerCount: Integer;
|
class function DebuggerCount: Integer;
|
||||||
|
|
||||||
|
@ -24,10 +24,10 @@ type
|
|||||||
FOwner: TDbgEntityValuesList;
|
FOwner: TDbgEntityValuesList;
|
||||||
FFlags: set of (devImmutable);
|
FFlags: set of (devImmutable);
|
||||||
function GetImmutable: Boolean;
|
function GetImmutable: Boolean;
|
||||||
function GetStackFrame: Integer;
|
|
||||||
function GetThreadId: Integer;
|
|
||||||
procedure SetImmutable(AValue: Boolean);
|
procedure SetImmutable(AValue: Boolean);
|
||||||
protected
|
protected
|
||||||
|
function GetStackFrame: Integer;
|
||||||
|
function GetThreadId: Integer;
|
||||||
procedure DoAssign({%H-}AnOther: TDbgEntityValue); virtual;
|
procedure DoAssign({%H-}AnOther: TDbgEntityValue); virtual;
|
||||||
property Owner: TDbgEntityValuesList read FOwner;
|
property Owner: TDbgEntityValuesList read FOwner;
|
||||||
public
|
public
|
||||||
@ -63,7 +63,7 @@ type
|
|||||||
constructor Create(AThreadId, AStackFrame: Integer);
|
constructor Create(AThreadId, AStackFrame: Integer);
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
procedure Assign(AnOther: TDbgEntityValuesList); // assert other has same thread/stack
|
procedure Assign(AnOther: TDbgEntityValuesList); // assert other has same thread/stack
|
||||||
procedure Add(AnEntry: TDbgEntityValue);
|
procedure Add(AnEntry: TDbgEntityValue); virtual;
|
||||||
procedure Clear;
|
procedure Clear;
|
||||||
function Count: Integer;
|
function Count: Integer;
|
||||||
property Entries[AnIndex: Integer]: TDbgEntityValue read GetEntry;
|
property Entries[AnIndex: Integer]: TDbgEntityValue read GetEntry;
|
||||||
|
@ -198,6 +198,7 @@ type
|
|||||||
function ShowBreakPointProperties(const ABreakpoint: TIDEBreakPoint): TModalresult; virtual; abstract;
|
function ShowBreakPointProperties(const ABreakpoint: TIDEBreakPoint): TModalresult; virtual; abstract;
|
||||||
function ShowWatchProperties(const AWatch: TCurrentWatch; AWatchExpression: String = ''): TModalresult; virtual; abstract;
|
function ShowWatchProperties(const AWatch: TCurrentWatch; AWatchExpression: String = ''): TModalresult; virtual; abstract;
|
||||||
|
|
||||||
|
procedure RequestWatchData(AWatchValue: TWatchValueIntf); override;
|
||||||
// Dialog routines
|
// Dialog routines
|
||||||
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;
|
||||||
@ -247,6 +248,15 @@ var
|
|||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
|
{ TBaseDebugManager }
|
||||||
|
|
||||||
|
procedure TBaseDebugManager.RequestWatchData(AWatchValue: TWatchValueIntf);
|
||||||
|
begin
|
||||||
|
if (Watches <> nil) and (Watches.Supplier <> nil)
|
||||||
|
then
|
||||||
|
Watches.Supplier.RequestData(AWatchValue);
|
||||||
|
end;
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
RegisterIDEOptionsGroup(GroupDebugger, TDebuggerOptions);
|
RegisterIDEOptionsGroup(GroupDebugger, TDebuggerOptions);
|
||||||
DebugBoss := nil;
|
DebugBoss := nil;
|
||||||
|
@ -43,7 +43,7 @@ type
|
|||||||
constructor Create(ATreeView: TDbgTreeView);
|
constructor Create(ATreeView: TDbgTreeView);
|
||||||
//destructor Destroy; override;
|
//destructor Destroy; override;
|
||||||
|
|
||||||
procedure AddWatchData(AWatchAble: TObject; AWatchAbleResult: TWatchAbleResultIntf = nil);
|
function AddWatchData(AWatchAble: TObject; AWatchAbleResult: TWatchAbleResultIntf = nil; AVNode: PVirtualNode = nil): PVirtualNode;
|
||||||
procedure UpdateWatchData(AWatchAble: TObject; AVNode: PVirtualNode; AWatchAbleResult: TWatchAbleResultIntf = nil);
|
procedure UpdateWatchData(AWatchAble: TObject; AVNode: PVirtualNode; AWatchAbleResult: TWatchAbleResultIntf = nil);
|
||||||
|
|
||||||
property CancelUpdate: Boolean read FCancelUpdate write FCancelUpdate;
|
property CancelUpdate: Boolean read FCancelUpdate write FCancelUpdate;
|
||||||
@ -365,19 +365,26 @@ begin
|
|||||||
FTreeView.OnInitChildren := @TreeViewInitChildren;
|
FTreeView.OnInitChildren := @TreeViewInitChildren;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TDbgTreeViewWatchDataMgr.AddWatchData(AWatchAble: TObject;
|
function TDbgTreeViewWatchDataMgr.AddWatchData(AWatchAble: TObject;
|
||||||
AWatchAbleResult: TWatchAbleResultIntf);
|
AWatchAbleResult: TWatchAbleResultIntf; AVNode: PVirtualNode): PVirtualNode;
|
||||||
var
|
|
||||||
AVNode: PVirtualNode;
|
|
||||||
begin
|
begin
|
||||||
if AWatchAble = nil then
|
if AWatchAble = nil then
|
||||||
exit;
|
exit;
|
||||||
AVNode := FTreeView.FindNodeForItem(AWatchAble);
|
|
||||||
if AVNode = nil then begin
|
if (AVNode <> nil) then begin
|
||||||
AVNode := FTreeView.AddChild(nil, AWatchAble);
|
FTreeView.NodeItem[AVNode] := AWatchAble;
|
||||||
FTreeView.SelectNode(AVNode);
|
FTreeView.SelectNode(AVNode);
|
||||||
(AWatchAble as TFreeNotifyingIntf).AddFreeNotification(@DoWatchAbleFreed);
|
(AWatchAble as TFreeNotifyingIntf).AddFreeNotification(@DoWatchAbleFreed);
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
AVNode := FTreeView.FindNodeForItem(AWatchAble);
|
||||||
|
if AVNode = nil then begin
|
||||||
|
AVNode := FTreeView.AddChild(nil, AWatchAble);
|
||||||
|
FTreeView.SelectNode(AVNode);
|
||||||
|
(AWatchAble as TFreeNotifyingIntf).AddFreeNotification(@DoWatchAbleFreed);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
Result := AVNode;
|
||||||
|
|
||||||
UpdateWatchData(AWatchAble, AVNode, AWatchAbleResult);
|
UpdateWatchData(AWatchAble, AVNode, AWatchAbleResult);
|
||||||
end;
|
end;
|
||||||
|
@ -590,7 +590,7 @@ type
|
|||||||
|
|
||||||
{ TIdeWatch }
|
{ TIdeWatch }
|
||||||
|
|
||||||
TIdeWatch = class(TWatch, TWatchAbleDataIntf)
|
TIdeWatch = class(TWatch, TWatchAbleDataIntf, TFreeNotifyingIntf)
|
||||||
private
|
private
|
||||||
FChildWatches: TIdeWatches;
|
FChildWatches: TIdeWatches;
|
||||||
FDisplayName: String;
|
FDisplayName: String;
|
||||||
@ -922,6 +922,40 @@ type
|
|||||||
property OnChange;
|
property OnChange;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
TSubLocals = class;
|
||||||
|
|
||||||
|
{ TIdeLocalsValue }
|
||||||
|
|
||||||
|
TIdeLocalsValue = class(TLocalsValue, TWatchAbleResultIntf, TWatchAbleDataIntf, TFreeNotifyingIntf)
|
||||||
|
private
|
||||||
|
FSubLocals: TSubLocals;
|
||||||
|
FDisplayName: String;
|
||||||
|
private
|
||||||
|
// TWatchAble
|
||||||
|
procedure LimitChildWatchCount(AMaxCnt: Integer; AKeepIndexEntriesBelow: Int64 = low(Int64)); virtual;
|
||||||
|
procedure ClearDisplayData; // Clear any cached display-data / keep only what's needed for the snapshot
|
||||||
|
|
||||||
|
function GetDisplayName: String;
|
||||||
|
function GetExpression: String;
|
||||||
|
function GetEnabled: Boolean;
|
||||||
|
function GetValidity: TDebuggerDataState; virtual;
|
||||||
|
function GetDisplayFormat: TWatchDisplayFormat;
|
||||||
|
function GetTypeInfo: TDBGType; deprecated;
|
||||||
|
|
||||||
|
function GetChildrenByNameAsArrayEntry(AName: Int64): TObject;
|
||||||
|
function GetChildrenByNameAsField(AName, AClassName: String): TObject;
|
||||||
|
|
||||||
|
private
|
||||||
|
procedure CreateSubLocals; virtual;
|
||||||
|
function GetSubLocal(ADispName, AnExpr: String): TIdeLocalsValue;
|
||||||
|
protected
|
||||||
|
procedure SetDisplayName(AValue: String); virtual;
|
||||||
|
procedure DoAssign(AnOther: TDbgEntityValue); override;
|
||||||
|
public
|
||||||
|
destructor Destroy; override;
|
||||||
|
property DisplayName: String read GetDisplayName write SetDisplayName;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TIDELocals }
|
{ TIDELocals }
|
||||||
|
|
||||||
TIDELocals = class(TLocals)
|
TIDELocals = class(TLocals)
|
||||||
@ -930,19 +964,84 @@ type
|
|||||||
APath: string);
|
APath: string);
|
||||||
procedure SaveDataToXMLConfig(const AConfig: TXMLConfig;
|
procedure SaveDataToXMLConfig(const AConfig: TXMLConfig;
|
||||||
APath: string);
|
APath: string);
|
||||||
|
function CreateEntry: TDbgEntityValue; override;
|
||||||
public
|
public
|
||||||
constructor CreateFromXMLConfig(const AConfig: TXMLConfig; APath: string);
|
constructor CreateFromXMLConfig(const AConfig: TXMLConfig; APath: string);
|
||||||
procedure SetDataValidity({%H-}AValidity: TDebuggerDataState); override;
|
procedure SetDataValidity({%H-}AValidity: TDebuggerDataState); override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ THistoryLocalValue }
|
||||||
|
|
||||||
|
THistoryLocalValue = class(TIdeLocalsValue)
|
||||||
|
protected
|
||||||
|
FSnapShot: TIdeLocalsValue;
|
||||||
|
procedure SetSnapShot(const AValue: TIdeLocalsValue); virtual;
|
||||||
|
procedure CreateSubLocals; override;
|
||||||
|
procedure SetDisplayName(AValue: String); override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ THistoryLocals }
|
||||||
|
|
||||||
|
THistoryLocals = class(TIDELocals)
|
||||||
|
protected
|
||||||
|
FSnapShot: TIDELocals;
|
||||||
|
procedure SetSnapShot(const AValue: TIDELocals); virtual;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TSubLocalsValue }
|
||||||
|
|
||||||
|
TSubLocalsValue = class(specialize TDbgDataRequestTemplateBase<THistoryLocalValue, TWatchValueIntf>, TWatchValueIntf)
|
||||||
|
private
|
||||||
|
FValidity: TDebuggerDataState;
|
||||||
|
FCurrentResData: TCurrentResData;
|
||||||
|
private
|
||||||
|
FOnChange: TNotifyEvent;
|
||||||
|
// TWatchValueIntf
|
||||||
|
function GetEvaluateFlags: TWatcheEvaluateFlags;
|
||||||
|
function GetDbgValConverter: TLazDbgValueConvertSelectorIntf;
|
||||||
|
function GetFirstIndexOffs: Int64;
|
||||||
|
function GetRepeatCount: Integer;
|
||||||
|
function GetValidity: TDebuggerDataState; override;
|
||||||
|
procedure SetTypeInfo(AValue: TDBGTypeBase);
|
||||||
|
procedure SetValidity(AValue: TDebuggerDataState);
|
||||||
|
procedure SetValue(AValue: String);
|
||||||
|
|
||||||
|
function ResData: TLzDbgWatchDataIntf; // new ResData for debugger to fill in
|
||||||
|
procedure DoBeginUpdating; override;
|
||||||
|
procedure DoEndUpdating; override;
|
||||||
|
procedure RequestData;
|
||||||
|
|
||||||
|
protected
|
||||||
|
function GetResultData: TWatchResultData; override;
|
||||||
|
function GetValue: String; override;
|
||||||
|
public
|
||||||
|
destructor Destroy; override;
|
||||||
|
property OnChange: TNotifyEvent read FOnChange write FOnChange;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TSubLocals }
|
||||||
|
|
||||||
|
TSubLocals = class(THistoryLocals)
|
||||||
|
private
|
||||||
|
FOwnerLocals: TIDELocals;
|
||||||
|
protected
|
||||||
|
function CreateEntry: TDbgEntityValue; override;
|
||||||
|
function Add(const AName: String): TIdeLocalsValue; overload;
|
||||||
|
procedure SetSnapShot(const AValue: TIDELocals); override;
|
||||||
|
function TopOwner: TIDELocals;
|
||||||
|
public
|
||||||
|
constructor Create(AThreadId, AStackFrame: Integer; AOwnerLocals: TIDELocals);
|
||||||
|
end;
|
||||||
|
|
||||||
|
TCurrentLocalValue = class(THistoryLocalValue)
|
||||||
|
end;
|
||||||
|
|
||||||
{ TCurrentLocals }
|
{ TCurrentLocals }
|
||||||
|
|
||||||
TCurrentLocals = class(specialize TDbgDataRequestTemplateBase<TIDELocals, TLocalsListIntf>, TLocalsListIntf)
|
TCurrentLocals = class(specialize TDbgDataRequestTemplateBase<THistoryLocals, TLocalsListIntf>, TLocalsListIntf)
|
||||||
private
|
private
|
||||||
FMonitor: TIdeLocalsMonitor;
|
FMonitor: TIdeLocalsMonitor;
|
||||||
FSnapShot: TIDELocals;
|
|
||||||
FDataValidity: TDebuggerDataState;
|
FDataValidity: TDebuggerDataState;
|
||||||
procedure SetSnapShot(const AValue: TIDELocals);
|
|
||||||
private
|
private
|
||||||
(* TLocalsListIntf *)
|
(* TLocalsListIntf *)
|
||||||
FCurrentResName: String;
|
FCurrentResName: String;
|
||||||
@ -955,14 +1054,19 @@ type
|
|||||||
procedure DoEndUpdating; override;
|
procedure DoEndUpdating; override;
|
||||||
procedure SetValidity(AValue: TDebuggerDataState);
|
procedure SetValidity(AValue: TDebuggerDataState);
|
||||||
function Add(AName: String): TLzDbgWatchDataIntf; overload;
|
function Add(AName: String): TLzDbgWatchDataIntf; overload;
|
||||||
procedure FinishCurrentRes;
|
|
||||||
protected
|
protected
|
||||||
|
procedure FinishCurrentRes(AnInUpdate: Boolean = False);
|
||||||
|
function CreateEntry: TDbgEntityValue; override;
|
||||||
|
procedure SetSnapShot(const AValue: TIDELocals); override;
|
||||||
property SnapShot: TIDELocals read FSnapShot write SetSnapShot;
|
property SnapShot: TIDELocals read FSnapShot write SetSnapShot;
|
||||||
public
|
public
|
||||||
constructor Create(AMonitor: TIdeLocalsMonitor; AThreadId, AStackFrame: Integer);
|
constructor Create(AMonitor: TIdeLocalsMonitor; AThreadId, AStackFrame: Integer);
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
function Count: Integer; override;
|
function Count: Integer; override;
|
||||||
|
procedure Add(AnEntry: TDbgEntityValue); override;
|
||||||
|
function Add(const AName: String; AValue: TWatchResultData): TLocalsValue; override; overload;
|
||||||
procedure SetDataValidity(AValidity: TDebuggerDataState); override;
|
procedure SetDataValidity(AValidity: TDebuggerDataState); override;
|
||||||
|
property Validity: TDebuggerDataState read FDataValidity;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TLocalsList }
|
{ TLocalsList }
|
||||||
@ -7055,6 +7159,115 @@ end;
|
|||||||
(******************************************************************************)
|
(******************************************************************************)
|
||||||
(******************************************************************************)
|
(******************************************************************************)
|
||||||
|
|
||||||
|
{ TIdeLocalsValue }
|
||||||
|
|
||||||
|
procedure TIdeLocalsValue.LimitChildWatchCount(AMaxCnt: Integer;
|
||||||
|
AKeepIndexEntriesBelow: Int64);
|
||||||
|
begin
|
||||||
|
//
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TIdeLocalsValue.ClearDisplayData;
|
||||||
|
begin
|
||||||
|
//
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TIdeLocalsValue.GetDisplayName: String;
|
||||||
|
begin
|
||||||
|
Result := FDisplayName;
|
||||||
|
if Result = '' then
|
||||||
|
Result := Name;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TIdeLocalsValue.GetExpression: String;
|
||||||
|
begin
|
||||||
|
Result := Name;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TIdeLocalsValue.GetEnabled: Boolean;
|
||||||
|
begin
|
||||||
|
Result := True;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TIdeLocalsValue.GetValidity: TDebuggerDataState;
|
||||||
|
begin
|
||||||
|
if ResultData <> nil then
|
||||||
|
Result := ddsValid
|
||||||
|
else
|
||||||
|
Result := ddsRequested;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TIdeLocalsValue.GetDisplayFormat: TWatchDisplayFormat;
|
||||||
|
begin
|
||||||
|
Result := wdfDefault;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TIdeLocalsValue.GetTypeInfo: TDBGType;
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TIdeLocalsValue.GetChildrenByNameAsArrayEntry(AName: Int64): TObject;
|
||||||
|
begin
|
||||||
|
Result := GetSubLocal(IntToStr(AName),
|
||||||
|
GetExpressionForArrayElement(Name, AName)
|
||||||
|
);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TIdeLocalsValue.GetChildrenByNameAsField(AName, AClassName: String
|
||||||
|
): TObject;
|
||||||
|
var
|
||||||
|
Expr: String;
|
||||||
|
begin
|
||||||
|
Expr := Name;
|
||||||
|
if AClassName <> '' then
|
||||||
|
Expr := AClassName + '(' + Expr + ')';
|
||||||
|
Expr := Expr + '.' + AName;
|
||||||
|
Result := GetSubLocal(AName, Expr);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TIdeLocalsValue.CreateSubLocals;
|
||||||
|
begin
|
||||||
|
if FSubLocals = nil then
|
||||||
|
FSubLocals := TSubLocals.Create(ThreadId, StackFrame, TIDELocals(Owner));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TIdeLocalsValue.GetSubLocal(ADispName, AnExpr: String
|
||||||
|
): TIdeLocalsValue;
|
||||||
|
begin
|
||||||
|
if FSubLocals = nil then begin
|
||||||
|
CreateSubLocals;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
Result := TIdeLocalsValue(FSubLocals.Find(AnExpr));
|
||||||
|
if Result <> nil then
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Result := FSubLocals.Add(AnExpr);
|
||||||
|
Result.DisplayName := ADispName;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TIdeLocalsValue.SetDisplayName(AValue: String);
|
||||||
|
begin
|
||||||
|
FDisplayName := AValue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TIdeLocalsValue.DoAssign(AnOther: TDbgEntityValue);
|
||||||
|
begin
|
||||||
|
inherited DoAssign(AnOther);
|
||||||
|
if AnOther is TIdeLocalsValue then begin
|
||||||
|
FDisplayName := TIdeLocalsValue(AnOther).FDisplayName;
|
||||||
|
// skip SubLocals
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TIdeLocalsValue.Destroy;
|
||||||
|
begin
|
||||||
|
inherited Destroy;
|
||||||
|
FSubLocals.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
{ =========================================================================== }
|
{ =========================================================================== }
|
||||||
{ TLocals }
|
{ TLocals }
|
||||||
{ =========================================================================== }
|
{ =========================================================================== }
|
||||||
@ -7092,6 +7305,11 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TIDELocals.CreateEntry: TDbgEntityValue;
|
||||||
|
begin
|
||||||
|
Result := TIdeLocalsValue.Create;
|
||||||
|
end;
|
||||||
|
|
||||||
constructor TIDELocals.CreateFromXMLConfig(const AConfig: TXMLConfig; APath: string);
|
constructor TIDELocals.CreateFromXMLConfig(const AConfig: TXMLConfig; APath: string);
|
||||||
var
|
var
|
||||||
LoadThreadId, LoadStackFrame: Integer;
|
LoadThreadId, LoadStackFrame: Integer;
|
||||||
@ -7102,17 +7320,247 @@ begin
|
|||||||
LoadDataFromXMLConfig(AConfig, APath);
|
LoadDataFromXMLConfig(AConfig, APath);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ THistoryLocalValue }
|
||||||
|
|
||||||
|
procedure THistoryLocalValue.SetSnapShot(const AValue: TIdeLocalsValue);
|
||||||
|
begin
|
||||||
|
FSnapShot := AValue;
|
||||||
|
FSnapShot.Assign(Self);
|
||||||
|
|
||||||
|
if FSubLocals <> nil then begin
|
||||||
|
FSnapShot.CreateSubLocals;
|
||||||
|
FSubLocals.SetSnapShot(FSnapShot.FSubLocals);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure THistoryLocalValue.CreateSubLocals;
|
||||||
|
begin
|
||||||
|
inherited CreateSubLocals;
|
||||||
|
if FSnapShot <> nil then begin
|
||||||
|
FSnapShot.CreateSubLocals;
|
||||||
|
FSubLocals.SetSnapShot(FSnapShot.FSubLocals);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure THistoryLocalValue.SetDisplayName(AValue: String);
|
||||||
|
begin
|
||||||
|
inherited SetDisplayName(AValue);
|
||||||
|
if FSnapShot <> nil then
|
||||||
|
FSnapShot.DisplayName := AValue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ THistoryLocals }
|
||||||
|
|
||||||
|
procedure THistoryLocals.SetSnapShot(const AValue: TIDELocals);
|
||||||
|
begin
|
||||||
|
FSnapShot := AValue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TSubLocalsValue }
|
||||||
|
|
||||||
|
function TSubLocalsValue.ResData: TLzDbgWatchDataIntf;
|
||||||
|
begin
|
||||||
|
if FCurrentResData = nil then
|
||||||
|
FCurrentResData := TCurrentResData.Create;
|
||||||
|
Result := FCurrentResData;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSubLocalsValue.DoBeginUpdating;
|
||||||
|
begin
|
||||||
|
AddReference;
|
||||||
|
FValidity := ddsEvaluating;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSubLocalsValue.DoEndUpdating;
|
||||||
|
begin
|
||||||
|
FCurrentResData := FCurrentResData.RootResultData;
|
||||||
|
// TODO: maybe create an error entry, if only FNewResultData is missing
|
||||||
|
if (FCurrentResData <> nil) then begin
|
||||||
|
if (FCurrentResData.FNewResultData = nil) then begin
|
||||||
|
FreeAndNil(FCurrentResData);
|
||||||
|
FValidity := ddsInvalid;
|
||||||
|
ReleaseReference;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
FCurrentResData.Done;
|
||||||
|
FValue := FCurrentResData.FNewResultData;
|
||||||
|
FreeAndNil(FCurrentResData);
|
||||||
|
|
||||||
|
if FValidity = ddsEvaluating then
|
||||||
|
FValidity := ddsValid;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
FValidity := ddsInvalid;
|
||||||
|
|
||||||
|
if FSnapShot <> nil then begin
|
||||||
|
TSubLocalsValue(FSnapShot).FValidity := FValidity;
|
||||||
|
TSubLocalsValue(FSnapShot).FValue := FValue.CreateCopy;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if FOnChange <> nil then
|
||||||
|
FOnChange(Self);
|
||||||
|
|
||||||
|
ReleaseReference;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSubLocalsValue.RequestData;
|
||||||
|
begin
|
||||||
|
if(DebugBossManager <> nil) and
|
||||||
|
(FValidity = ddsUnknown) and
|
||||||
|
(TSubLocals(Owner).TopOwner is TCurrentLocals) and
|
||||||
|
(inherited GetResultData = nil)
|
||||||
|
then begin
|
||||||
|
FValidity := ddsRequested;
|
||||||
|
DebugBossManager.RequestWatchData(Self);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSubLocalsValue.GetResultData: TWatchResultData;
|
||||||
|
begin
|
||||||
|
RequestData;
|
||||||
|
Result := inherited GetResultData;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSubLocalsValue.GetValue: String;
|
||||||
|
begin
|
||||||
|
RequestData;
|
||||||
|
case FValidity of
|
||||||
|
ddsRequested, ddsEvaluating: Result := '<evaluating>';
|
||||||
|
ddsValid: Result := inherited GetValue;
|
||||||
|
ddsInvalid: Result := '<invalid>';
|
||||||
|
ddsError: Result := '<Error: '+ (inherited GetValue) +'>';
|
||||||
|
else Result := '<not evaluated>';
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TSubLocalsValue.Destroy;
|
||||||
|
begin
|
||||||
|
inherited Destroy;
|
||||||
|
DoDestroy;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSubLocalsValue.GetEvaluateFlags: TWatcheEvaluateFlags;
|
||||||
|
begin
|
||||||
|
Result := [];
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSubLocalsValue.GetDbgValConverter: TLazDbgValueConvertSelectorIntf;
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSubLocalsValue.GetFirstIndexOffs: Int64;
|
||||||
|
begin
|
||||||
|
Result := 0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSubLocalsValue.GetRepeatCount: Integer;
|
||||||
|
begin
|
||||||
|
Result := 0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSubLocalsValue.GetValidity: TDebuggerDataState;
|
||||||
|
begin
|
||||||
|
RequestData;
|
||||||
|
Result := FValidity;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSubLocalsValue.SetTypeInfo(AValue: TDBGTypeBase);
|
||||||
|
begin
|
||||||
|
//assert(False, 'TSubLocalsValue.SetTypeInfo: False');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSubLocalsValue.SetValidity(AValue: TDebuggerDataState);
|
||||||
|
begin
|
||||||
|
FValidity := AValue;
|
||||||
|
if not IsUpdating then begin
|
||||||
|
AddReference;
|
||||||
|
DoEndUpdating;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSubLocalsValue.SetValue(AValue: String);
|
||||||
|
begin
|
||||||
|
FValue.Free;
|
||||||
|
FValue := TWatchResultDataPrePrinted.Create(AValue);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TSubLocals }
|
||||||
|
|
||||||
|
function TSubLocals.CreateEntry: TDbgEntityValue;
|
||||||
|
begin
|
||||||
|
Result := TSubLocalsValue.Create;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSubLocals.Add(const AName: String): TIdeLocalsValue;
|
||||||
|
var
|
||||||
|
V: TSubLocalsValue;
|
||||||
|
begin
|
||||||
|
Result := TIdeLocalsValue(CreateEntry);
|
||||||
|
Result.FName := AName;
|
||||||
|
Add(Result);
|
||||||
|
|
||||||
|
if FSnapShot <> nil then begin
|
||||||
|
V := TSubLocalsValue(FSnapShot.Add('', nil));
|
||||||
|
assert(V is TSubLocalsValue, 'TSubLocals.Add: V is TSubLocalsValue');
|
||||||
|
assert(Result is TSubLocalsValue, 'TSubLocals.Add: Result is TSubLocalsValue');
|
||||||
|
TSubLocalsValue(Result).SetSnapShot(V);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSubLocals.SetSnapShot(const AValue: TIDELocals);
|
||||||
|
var
|
||||||
|
V: TSubLocalsValue;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
assert((FSnapShot=nil) or (AValue=nil), 'TSubLocals.SetSnapShot: (FSnapShot=nil) or (AValue=nil)');
|
||||||
|
inherited SetSnapShot(AValue);
|
||||||
|
|
||||||
|
if FSnapShot <> nil then begin
|
||||||
|
assert(FSnapShot is TSubLocals, 'TSubLocals.SetSnapShot: FSnapShot is TSubLocals');
|
||||||
|
FSnapShot.Clear;
|
||||||
|
for i := 0 to Count - 1 do begin
|
||||||
|
V := TSubLocalsValue(FSnapShot.Add('', nil));
|
||||||
|
TSubLocalsValue(Entries[i]).SetSnapShot(V);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSubLocals.TopOwner: TIDELocals;
|
||||||
|
begin
|
||||||
|
Result := FOwnerLocals;
|
||||||
|
while (Result <> nil) and (Result is TSubLocals) do
|
||||||
|
Result := TSubLocals(Result).FOwnerLocals;
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TSubLocals.Create(AThreadId, AStackFrame: Integer;
|
||||||
|
AOwnerLocals: TIDELocals);
|
||||||
|
begin
|
||||||
|
inherited Create(AThreadId, AStackFrame);
|
||||||
|
FOwnerLocals := AOwnerLocals;
|
||||||
|
end;
|
||||||
|
|
||||||
{ =========================================================================== }
|
{ =========================================================================== }
|
||||||
{ TCurrentLocals }
|
{ TCurrentLocals }
|
||||||
{ =========================================================================== }
|
{ =========================================================================== }
|
||||||
|
|
||||||
procedure TCurrentLocals.SetSnapShot(const AValue: TIDELocals);
|
procedure TCurrentLocals.SetSnapShot(const AValue: TIDELocals);
|
||||||
|
var
|
||||||
|
V: TIdeLocalsValue;
|
||||||
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
assert((FSnapShot=nil) or (AValue=nil), 'TCurrentLocals already have snapshot');
|
assert((FSnapShot=nil) or (AValue=nil), 'TCurrentLocals already have snapshot');
|
||||||
if FSnapShot = AValue then exit;
|
if FSnapShot = AValue then exit;
|
||||||
FSnapShot := AValue;
|
inherited SetSnapShot(AValue);
|
||||||
if FSnapShot <> nil
|
|
||||||
then FSnapShot.Assign(Self);
|
if FSnapShot <> nil then begin
|
||||||
|
FSnapShot.Clear;
|
||||||
|
for i := 0 to Count - 1 do begin
|
||||||
|
V := TIdeLocalsValue(FSnapShot.Add('', nil));
|
||||||
|
TCurrentLocalValue(Entries[i]).SetSnapShot(V);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TCurrentLocals.GetStackFrame: Integer;
|
function TCurrentLocals.GetStackFrame: Integer;
|
||||||
@ -7140,7 +7588,7 @@ procedure TCurrentLocals.DoEndUpdating;
|
|||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
FinishCurrentRes;
|
FinishCurrentRes(True);
|
||||||
|
|
||||||
for i := 0 to FCurrentResList.Count - 1 do
|
for i := 0 to FCurrentResList.Count - 1 do
|
||||||
Add(TLocalsValue(FCurrentResList[i]));
|
Add(TLocalsValue(FCurrentResList[i]));
|
||||||
@ -7173,7 +7621,7 @@ begin
|
|||||||
Result := FCurrentResData;
|
Result := FCurrentResData;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCurrentLocals.FinishCurrentRes;
|
procedure TCurrentLocals.FinishCurrentRes(AnInUpdate: Boolean);
|
||||||
var
|
var
|
||||||
v: TLocalsValue;
|
v: TLocalsValue;
|
||||||
begin
|
begin
|
||||||
@ -7191,7 +7639,7 @@ begin
|
|||||||
v := TLocalsValue(CreateEntry);
|
v := TLocalsValue(CreateEntry);
|
||||||
v.Init(FCurrentResName, FCurrentResData.FNewResultData);
|
v.Init(FCurrentResName, FCurrentResData.FNewResultData);
|
||||||
|
|
||||||
if IsUpdating then
|
if IsUpdating or AnInUpdate then
|
||||||
FCurrentResList.Add(v)
|
FCurrentResList.Add(v)
|
||||||
else
|
else
|
||||||
Add(v);
|
Add(v);
|
||||||
@ -7199,6 +7647,11 @@ begin
|
|||||||
FreeAndNil(FCurrentResData);
|
FreeAndNil(FCurrentResData);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TCurrentLocals.CreateEntry: TDbgEntityValue;
|
||||||
|
begin
|
||||||
|
Result := TCurrentLocalValue.Create;
|
||||||
|
end;
|
||||||
|
|
||||||
constructor TCurrentLocals.Create(AMonitor: TIdeLocalsMonitor; AThreadId, AStackFrame: Integer);
|
constructor TCurrentLocals.Create(AMonitor: TIdeLocalsMonitor; AThreadId, AStackFrame: Integer);
|
||||||
begin
|
begin
|
||||||
FMonitor := AMonitor;
|
FMonitor := AMonitor;
|
||||||
@ -7209,6 +7662,7 @@ end;
|
|||||||
destructor TCurrentLocals.Destroy;
|
destructor TCurrentLocals.Destroy;
|
||||||
begin
|
begin
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
|
DoDestroy;
|
||||||
|
|
||||||
FCurrentResData := FCurrentResData.RootResultData;
|
FCurrentResData := FCurrentResData.RootResultData;
|
||||||
if (FCurrentResData <> nil) {and (FResultData = nil)} then
|
if (FCurrentResData <> nil) {and (FResultData = nil)} then
|
||||||
@ -7240,6 +7694,30 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TCurrentLocals.Add(AnEntry: TDbgEntityValue);
|
||||||
|
var
|
||||||
|
V: TIdeLocalsValue;
|
||||||
|
begin
|
||||||
|
inherited Add(AnEntry);
|
||||||
|
assert(AnEntry is TCurrentLocalValue, 'TCurrentLocals.Add: AnEntry is TCurrentLocalValue');
|
||||||
|
if FSnapShot <> nil then begin
|
||||||
|
V := TIdeLocalsValue(FSnapShot.Add('', nil));
|
||||||
|
TCurrentLocalValue(AnEntry).SetSnapShot(V);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TCurrentLocals.Add(const AName: String; AValue: TWatchResultData
|
||||||
|
): TLocalsValue;
|
||||||
|
var
|
||||||
|
V: TIdeLocalsValue;
|
||||||
|
begin
|
||||||
|
Result := inherited Add(AName, AValue);
|
||||||
|
if FSnapShot <> nil then begin
|
||||||
|
V := TIdeLocalsValue(FSnapShot.Add('', nil));
|
||||||
|
TCurrentLocalValue(Result).SetSnapShot(V);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TCurrentLocals.SetDataValidity(AValidity: TDebuggerDataState);
|
procedure TCurrentLocals.SetDataValidity(AValidity: TDebuggerDataState);
|
||||||
begin
|
begin
|
||||||
if FDataValidity = AValidity then exit;
|
if FDataValidity = AValidity then exit;
|
||||||
|
@ -56,8 +56,10 @@ type
|
|||||||
|
|
||||||
procedure SelectNode(Node: PVirtualNode; ASetFocus: boolean = True);
|
procedure SelectNode(Node: PVirtualNode; ASetFocus: boolean = True);
|
||||||
function FindNodeForItem(AnItem: TObject): PVirtualNode;
|
function FindNodeForItem(AnItem: TObject): PVirtualNode;
|
||||||
function FindNodeForText(AText: String; AColumn: integer): PVirtualNode;
|
function FindNodeForText(AText: String; AColumn: integer; ATopLvlOnly: Boolean = False): PVirtualNode;
|
||||||
procedure DeleteNodeEx(Node: PVirtualNode; FreeItem: Boolean; Reindex: Boolean = True);
|
procedure DeleteNodeEx(Node: PVirtualNode; FreeItem: Boolean; Reindex: Boolean = True);
|
||||||
|
// LazMoveTo: Don't mess with children
|
||||||
|
procedure LazMoveTo(Source, Target: PVirtualNode; Mode: TVTNodeAttachMode);
|
||||||
|
|
||||||
property NodeItem[Node: PVirtualNode]: TObject read GetNodeItem write SetNodeItem;
|
property NodeItem[Node: PVirtualNode]: TObject read GetNodeItem write SetNodeItem;
|
||||||
property NodeText[Node: PVirtualNode; AColumn: integer]: String read GetNodeText write SetNodeText;
|
property NodeText[Node: PVirtualNode; AColumn: integer]: String read GetNodeText write SetNodeText;
|
||||||
@ -351,14 +353,19 @@ begin
|
|||||||
Result := nil;
|
Result := nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDbgTreeView.FindNodeForText(AText: String; AColumn: integer
|
function TDbgTreeView.FindNodeForText(AText: String; AColumn: integer;
|
||||||
): PVirtualNode;
|
ATopLvlOnly: Boolean): PVirtualNode;
|
||||||
var
|
var
|
||||||
VNode: PVirtualNode;
|
VNode: PVirtualNode;
|
||||||
begin
|
begin
|
||||||
for VNode in NoInitNodes do begin
|
VNode := GetFirstNoInit;
|
||||||
|
while VNode <> nil do begin
|
||||||
if GetNodeText(VNode, AColumn) = AText then
|
if GetNodeText(VNode, AColumn) = AText then
|
||||||
exit(VNode);
|
exit(VNode);
|
||||||
|
if ATopLvlOnly then
|
||||||
|
VNode := GetNextSiblingNoInit(VNode)
|
||||||
|
else
|
||||||
|
VNode := GetNextNoInit(VNode);
|
||||||
end;
|
end;
|
||||||
Result := nil;
|
Result := nil;
|
||||||
end;
|
end;
|
||||||
@ -377,6 +384,46 @@ begin
|
|||||||
Item.Free;
|
Item.Free;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TDbgTreeView.LazMoveTo(Source, Target: PVirtualNode; Mode: TVTNodeAttachMode);
|
||||||
|
var
|
||||||
|
NewNode: PVirtualNode;
|
||||||
|
begin
|
||||||
|
if Target = nil then
|
||||||
|
begin
|
||||||
|
Target := RootNode;
|
||||||
|
Mode := amAddChildFirst;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if Target = RootNode then
|
||||||
|
begin
|
||||||
|
case Mode of
|
||||||
|
amInsertBefore:
|
||||||
|
Mode := amAddChildFirst;
|
||||||
|
amInsertAfter:
|
||||||
|
Mode := amAddChildLast;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if (Source <> Target) and HasAsParent(Target, Source) then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
// Disconnect from old location.
|
||||||
|
InternalDisconnectNode(Source, True);
|
||||||
|
// Connect to new location.
|
||||||
|
InternalConnectNode(Source, Target, Self, Mode);
|
||||||
|
DoNodeMoved(Source);
|
||||||
|
|
||||||
|
|
||||||
|
InvalidateCache;
|
||||||
|
if (UpdateCount = 0) then
|
||||||
|
begin
|
||||||
|
ValidateCache;
|
||||||
|
UpdateScrollBars(True);
|
||||||
|
Invalidate;
|
||||||
|
end;
|
||||||
|
StructureChange(Source, crNodeMoved);
|
||||||
|
end;
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
RegisterClass(TDbgTreeView);
|
RegisterClass(TDbgTreeView);
|
||||||
|
|
||||||
|
@ -235,18 +235,20 @@ type
|
|||||||
|
|
||||||
{ TLocalsValue }
|
{ TLocalsValue }
|
||||||
|
|
||||||
TLocalsValue = class(TDbgEntityValue)
|
TLocalsValue = class(TDbgEntityValue)
|
||||||
private
|
protected
|
||||||
FName: String;
|
FName: String;
|
||||||
FValue: TWatchResultData;
|
FValue: TWatchResultData;
|
||||||
protected
|
function GetValue: String; virtual;
|
||||||
procedure DoAssign(AnOther: TDbgEntityValue); override;
|
function GetResultData: TWatchResultData; virtual;
|
||||||
public
|
procedure DoAssign(AnOther: TDbgEntityValue); override;
|
||||||
destructor Destroy; override;
|
public
|
||||||
procedure Init(AName: String; AValue: TWatchResultData);
|
destructor Destroy; override;
|
||||||
property Name: String read FName;
|
procedure Init(AName: String; AValue: TWatchResultData);
|
||||||
property Value: TWatchResultData read FValue;
|
property Name: String read FName;
|
||||||
end;
|
property Value: String read GetValue;
|
||||||
|
property ResultData: TWatchResultData read GetResultData;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TLocals }
|
{ TLocals }
|
||||||
|
|
||||||
@ -254,17 +256,18 @@ type
|
|||||||
private
|
private
|
||||||
function GetEntry(AnIndex: Integer): TLocalsValue;
|
function GetEntry(AnIndex: Integer): TLocalsValue;
|
||||||
function GetName(const AnIndex: Integer): String;
|
function GetName(const AnIndex: Integer): String;
|
||||||
function GetValue(const AnIndex: Integer): TWatchResultData;
|
function GetResultData(const AnIndex: Integer): TWatchResultData;
|
||||||
protected
|
protected
|
||||||
function CreateEntry: TDbgEntityValue; override;
|
function CreateEntry: TDbgEntityValue; override;
|
||||||
public
|
public
|
||||||
procedure Add(const AName: String; AValue: TWatchResultData); overload; deprecated;
|
function Add(const AName: String; AValue: TWatchResultData): TLocalsValue; virtual; overload;
|
||||||
procedure SetDataValidity({%H-}AValidity: TDebuggerDataState); virtual;
|
procedure SetDataValidity({%H-}AValidity: TDebuggerDataState); virtual;
|
||||||
public
|
public
|
||||||
function Count: Integer;reintroduce; virtual;
|
function Count: Integer;reintroduce; virtual;
|
||||||
|
function Find(AName: String): TLocalsValue;
|
||||||
property Entries[AnIndex: Integer]: TLocalsValue read GetEntry;
|
property Entries[AnIndex: Integer]: TLocalsValue read GetEntry;
|
||||||
property Names[const AnIndex: Integer]: String read GetName;
|
property Names[const AnIndex: Integer]: String read GetName;
|
||||||
property Values[const AnIndex: Integer]: TWatchResultData read GetValue;
|
property Values[const AnIndex: Integer]: TWatchResultData read GetResultData;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TLocalsList }
|
{ TLocalsList }
|
||||||
@ -972,6 +975,18 @@ end;
|
|||||||
|
|
||||||
{ TLocalsValue }
|
{ TLocalsValue }
|
||||||
|
|
||||||
|
function TLocalsValue.GetValue: String;
|
||||||
|
begin
|
||||||
|
Result := '';
|
||||||
|
if FValue <> nil then
|
||||||
|
Result := FValue.AsString;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TLocalsValue.GetResultData: TWatchResultData;
|
||||||
|
begin
|
||||||
|
Result := FValue;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TLocalsValue.DoAssign(AnOther: TDbgEntityValue);
|
procedure TLocalsValue.DoAssign(AnOther: TDbgEntityValue);
|
||||||
begin
|
begin
|
||||||
inherited DoAssign(AnOther);
|
inherited DoAssign(AnOther);
|
||||||
@ -1016,9 +1031,9 @@ begin
|
|||||||
Result := Entries[AnIndex].Name;
|
Result := Entries[AnIndex].Name;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TLocals.GetValue(const AnIndex: Integer): TWatchResultData;
|
function TLocals.GetResultData(const AnIndex: Integer): TWatchResultData;
|
||||||
begin
|
begin
|
||||||
Result := Entries[AnIndex].Value;
|
Result := Entries[AnIndex].ResultData;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TLocals.CreateEntry: TDbgEntityValue;
|
function TLocals.CreateEntry: TDbgEntityValue;
|
||||||
@ -1026,15 +1041,14 @@ begin
|
|||||||
Result := TLocalsValue.Create;
|
Result := TLocalsValue.Create;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TLocals.Add(const AName: String; AValue: TWatchResultData);
|
function TLocals.Add(const AName: String; AValue: TWatchResultData
|
||||||
var
|
): TLocalsValue;
|
||||||
v: TLocalsValue;
|
|
||||||
begin
|
begin
|
||||||
assert(not Immutable, 'TLocalsBase.Add Immutable');
|
assert(not Immutable, 'TLocalsBase.Add Immutable');
|
||||||
v := TLocalsValue(CreateEntry);
|
Result := TLocalsValue(CreateEntry);
|
||||||
v.FName := AName;
|
Result.FName := AName;
|
||||||
v.FValue := AValue;
|
Result.FValue := AValue;
|
||||||
inherited Add(v);
|
inherited Add(Result);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TLocals.SetDataValidity(AValidity: TDebuggerDataState);
|
procedure TLocals.SetDataValidity(AValidity: TDebuggerDataState);
|
||||||
@ -1047,6 +1061,20 @@ begin
|
|||||||
Result := inherited Count;
|
Result := inherited Count;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TLocals.Find(AName: String): TLocalsValue;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
i := Count - 1;
|
||||||
|
while i >= 0 do begin
|
||||||
|
Result := Entries[i];
|
||||||
|
if Result.Name = AName then
|
||||||
|
exit;
|
||||||
|
dec(i);
|
||||||
|
end;
|
||||||
|
Result := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TLocalsMonitor }
|
{ TLocalsMonitor }
|
||||||
|
|
||||||
procedure TLocalsMonitor.DoStateChange(const AOldState, ANewState: TDBGState);
|
procedure TLocalsMonitor.DoStateChange(const AOldState, ANewState: TDBGState);
|
||||||
|
@ -26,7 +26,7 @@ function ClearMultiline(const AValue: ansistring): ansistring;
|
|||||||
The Index "11" returns Foo[11]
|
The Index "11" returns Foo[11]
|
||||||
*)
|
*)
|
||||||
function GetExpressionForArrayElement(AnArrayExpression: AnsiString; AnIndex: String): AnsiString; overload;
|
function GetExpressionForArrayElement(AnArrayExpression: AnsiString; AnIndex: String): AnsiString; overload;
|
||||||
function GetExpressionForArrayElement(AnArrayExpression: AnsiString; AnIndex: Integer): AnsiString; overload;
|
function GetExpressionForArrayElement(AnArrayExpression: AnsiString; AnIndex: Int64): AnsiString; overload;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
@ -349,7 +349,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
function GetExpressionForArrayElement(AnArrayExpression: AnsiString;
|
function GetExpressionForArrayElement(AnArrayExpression: AnsiString;
|
||||||
AnIndex: Integer): AnsiString;
|
AnIndex: Int64): AnsiString;
|
||||||
begin
|
begin
|
||||||
Result := GetExpressionForArrayElement(AnArrayExpression, IntToStr(AnIndex));
|
Result := GetExpressionForArrayElement(AnArrayExpression, IntToStr(AnIndex));
|
||||||
end;
|
end;
|
||||||
|
@ -45,13 +45,17 @@ uses
|
|||||||
IDEWindowIntf,
|
IDEWindowIntf,
|
||||||
// DebuggerIntf
|
// DebuggerIntf
|
||||||
DbgIntfDebuggerBase, laz.VirtualTrees, LazDebuggerIntf,
|
DbgIntfDebuggerBase, laz.VirtualTrees, LazDebuggerIntf,
|
||||||
|
LazDebuggerIntfBaseTypes,
|
||||||
// IDE Debugger
|
// IDE Debugger
|
||||||
IdeDebuggerStringConstants, BaseDebugManager, EnvironmentOpts, Debugger,
|
IdeDebuggerStringConstants, BaseDebugManager, EnvironmentOpts, Debugger,
|
||||||
DebuggerDlg, IdeDebuggerWatchResPrinter, IdeDebuggerUtils, DebuggerTreeView,
|
DebuggerDlg, IdeDebuggerWatchResPrinter, IdeDebuggerUtils, DebuggerTreeView,
|
||||||
IdeDebuggerWatchResult, IdeDebuggerBase, Controls, ActiveX;
|
IdeDebuggerWatchResult, IdeDebuggerBase, DbgTreeViewWatchData, Controls,
|
||||||
|
ActiveX;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
|
TDbgTreeViewLocalsValueMgr = class;
|
||||||
|
|
||||||
{ TLocalsDlg }
|
{ TLocalsDlg }
|
||||||
|
|
||||||
TLocalsDlg = class(TDebuggerDlg)
|
TLocalsDlg = class(TDebuggerDlg)
|
||||||
@ -95,16 +99,18 @@ type
|
|||||||
const HitInfo: THitInfo);
|
const HitInfo: THitInfo);
|
||||||
private
|
private
|
||||||
FWatchPrinter: TWatchResultPrinter;
|
FWatchPrinter: TWatchResultPrinter;
|
||||||
|
FLocolsTreeMgr: TDbgTreeViewLocalsValueMgr;
|
||||||
|
|
||||||
FUpdateFlags: set of (ufNeedUpdating);
|
FUpdateFlags: set of (ufNeedUpdating);
|
||||||
function GetSelected: TLocalsValue; // The focused Selected Node
|
function GetSelected: TLocalsValue; // The focused Selected Node
|
||||||
procedure CopyRAWValueEvaluateCallback(Sender: TObject; ASuccess: Boolean;
|
procedure CopyRAWValueEvaluateCallback(Sender: TObject; ASuccess: Boolean;
|
||||||
ResultText: String; ResultDBGType: TDBGType);
|
ResultText: String; ResultDBGType: TDBGType);
|
||||||
procedure CopyValueEvaluateCallback(Sender: TObject; ASuccess: Boolean;
|
procedure CopyValueEvaluateCallback(Sender: TObject; ASuccess: Boolean;
|
||||||
ResultText: String; ResultDBGType: TDBGType);
|
ResultText: String; ResultDBGType: TDBGType);
|
||||||
procedure DoLocalValueFreed(Sender: TObject);
|
|
||||||
|
|
||||||
procedure ClearTree(OnlyClearNodeData: boolean = False);
|
procedure ClearTree(OnlyClearNodeData: boolean = False);
|
||||||
procedure LocalsChanged(Sender: TObject);
|
procedure LocalsChanged(Sender: TObject);
|
||||||
|
procedure SubLocalChanged(Sender: TObject);
|
||||||
function GetThreadId: Integer;
|
function GetThreadId: Integer;
|
||||||
function GetSelectedThreads(Snap: TSnapshot): TIdeThreads;
|
function GetSelectedThreads(Snap: TSnapshot): TIdeThreads;
|
||||||
function GetStackframe: Integer;
|
function GetStackframe: Integer;
|
||||||
@ -123,6 +129,23 @@ type
|
|||||||
property SnapshotManager;
|
property SnapshotManager;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TDbgTreeViewLocalsValueMgr }
|
||||||
|
|
||||||
|
TDbgTreeViewLocalsValueMgr = class(TDbgTreeViewWatchDataMgr)
|
||||||
|
private
|
||||||
|
FLocalsDlg: TLocalsDlg;
|
||||||
|
protected
|
||||||
|
function WatchAbleResultFromNode(AVNode: PVirtualNode): TWatchAbleResultIntf; override;
|
||||||
|
function WatchAbleResultFromObject(AWatchAble: TObject): TWatchAbleResultIntf; override;
|
||||||
|
|
||||||
|
procedure UpdateColumnsText(AWatchAble: TObject; AWatchAbleResult: TWatchAbleResultIntf; AVNode: PVirtualNode); override;
|
||||||
|
procedure ConfigureNewSubItem(AWatchAble: TObject); override;
|
||||||
|
//procedure UpdateSubItems(AWatchAble: TObject; AWatchAbleResult: TWatchAbleResultIntf;
|
||||||
|
// AVNode: PVirtualNode; out ChildCount: LongWord); override;
|
||||||
|
//procedure UpdateSubItemsLocked(AWatchAble: TObject; AWatchAbleResult: TWatchAbleResultIntf;
|
||||||
|
// AVNode: PVirtualNode; out ChildCount: LongWord); override;
|
||||||
|
end;
|
||||||
|
|
||||||
function ValueToRAW(const AValue: string): string;
|
function ValueToRAW(const AValue: string): string;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@ -289,6 +312,8 @@ begin
|
|||||||
CallstackNotification.OnCurrent := @LocalsChanged;
|
CallstackNotification.OnCurrent := @LocalsChanged;
|
||||||
SnapshotNotification.OnCurrent := @LocalsChanged;
|
SnapshotNotification.OnCurrent := @LocalsChanged;
|
||||||
FWatchPrinter := TWatchResultPrinter.Create;
|
FWatchPrinter := TWatchResultPrinter.Create;
|
||||||
|
FLocolsTreeMgr := TDbgTreeViewLocalsValueMgr.Create(vtLocals);
|
||||||
|
FLocolsTreeMgr.FLocalsDlg := Self;
|
||||||
|
|
||||||
Caption:= lisLocals;
|
Caption:= lisLocals;
|
||||||
vtLocals.Header.Columns[0].Text:= lisName;
|
vtLocals.Header.Columns[0].Text:= lisName;
|
||||||
@ -310,6 +335,7 @@ begin
|
|||||||
ClearTree;
|
ClearTree;
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
FWatchPrinter.free;
|
FWatchPrinter.free;
|
||||||
|
FLocolsTreeMgr.Free;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TLocalsDlg.actInspectUpdate(Sender: TObject);
|
procedure TLocalsDlg.actInspectUpdate(Sender: TObject);
|
||||||
@ -326,7 +352,7 @@ begin
|
|||||||
if LVal = nil then
|
if LVal = nil then
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
ResVal := LVal.Value;
|
ResVal := LVal.ResultData;
|
||||||
if ResVal = nil then
|
if ResVal = nil then
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
@ -347,7 +373,7 @@ begin
|
|||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
Clipboard.Open;
|
Clipboard.Open;
|
||||||
Clipboard.AsText := ClearMultiline(FWatchPrinter.PrintWatchValue(LVal.Value, wdfDefault));
|
Clipboard.AsText := ClearMultiline(FWatchPrinter.PrintWatchValue(ResVal, wdfDefault));
|
||||||
Clipboard.Close;
|
Clipboard.Close;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -357,7 +383,7 @@ begin
|
|||||||
if not DebugBoss.Evaluate(LVal.Name, @CopyRAWValueEvaluateCallback, []) then
|
if not DebugBoss.Evaluate(LVal.Name, @CopyRAWValueEvaluateCallback, []) then
|
||||||
begin
|
begin
|
||||||
Clipboard.Open;
|
Clipboard.Open;
|
||||||
Clipboard.AsText := ValueToRAW(ClearMultiline(FWatchPrinter.PrintWatchValue(LVal.Value, wdfDefault)));
|
Clipboard.AsText := ValueToRAW(ClearMultiline(FWatchPrinter.PrintWatchValue(ResVal, wdfDefault)));
|
||||||
Clipboard.Close;
|
Clipboard.Close;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -459,7 +485,7 @@ begin
|
|||||||
for VNode in vtLocals.NoInitNodes do begin
|
for VNode in vtLocals.NoInitNodes do begin
|
||||||
LVal := TLocalsValue((vtLocals.NodeItem[VNode]));
|
LVal := TLocalsValue((vtLocals.NodeItem[VNode]));
|
||||||
if LVal <> nil then
|
if LVal <> nil then
|
||||||
AStringList.Values[LVal.Name] := ClearMultiline(FWatchPrinter.PrintWatchValue(LVal.Value, wdfDefault));
|
AStringList.Values[LVal.Name] := ClearMultiline(FWatchPrinter.PrintWatchValue(LVal.ResultData, wdfDefault));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Clipboard.Open;
|
Clipboard.Open;
|
||||||
@ -482,13 +508,13 @@ begin
|
|||||||
if LVal = nil then
|
if LVal = nil then
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
ResVal := LVal.Value;
|
ResVal := LVal.ResultData;
|
||||||
if ResVal = nil then
|
if ResVal = nil then
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
if (ResVal.ValueKind <> rdkPrePrinted) then begin
|
if (ResVal.ValueKind <> rdkPrePrinted) then begin
|
||||||
Clipboard.Open;
|
Clipboard.Open;
|
||||||
Clipboard.AsText := ClearMultiline(FWatchPrinter.PrintWatchValue(LVal.Value, wdfDefault));
|
Clipboard.AsText := ClearMultiline(FWatchPrinter.PrintWatchValue(ResVal, wdfDefault));
|
||||||
Clipboard.Close;
|
Clipboard.Close;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
@ -496,7 +522,7 @@ begin
|
|||||||
if not DebugBoss.Evaluate(LVal.Name, @CopyValueEvaluateCallback, []) then
|
if not DebugBoss.Evaluate(LVal.Name, @CopyValueEvaluateCallback, []) then
|
||||||
begin
|
begin
|
||||||
Clipboard.Open;
|
Clipboard.Open;
|
||||||
Clipboard.AsText := ClearMultiline(FWatchPrinter.PrintWatchValue(LVal.Value, wdfDefault));
|
Clipboard.AsText := ClearMultiline(FWatchPrinter.PrintWatchValue(ResVal, wdfDefault));
|
||||||
Clipboard.Close;
|
Clipboard.Close;
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
@ -507,10 +533,10 @@ var
|
|||||||
Locals: TIDELocals;
|
Locals: TIDELocals;
|
||||||
Snap: TSnapshot;
|
Snap: TSnapshot;
|
||||||
s: String;
|
s: String;
|
||||||
LVal: TLocalsValue;
|
LVal: TIdeLocalsValue;
|
||||||
VNode, VN2: PVirtualNode;
|
VNode, VN2: PVirtualNode;
|
||||||
begin
|
begin
|
||||||
if (ThreadsMonitor = nil) or (CallStackMonitor = nil) or (LocalsMonitor=nil) then begin
|
if (DebugBoss = nil) or (ThreadsMonitor = nil) or (CallStackMonitor = nil) or (LocalsMonitor=nil) then begin
|
||||||
ClearTree;
|
ClearTree;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
@ -529,6 +555,19 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
Snap := GetSelectedSnapshot;
|
Snap := GetSelectedSnapshot;
|
||||||
|
|
||||||
|
if (Snap = nil) then begin
|
||||||
|
if (DebugBoss.State in [dsInit, dsIdle, dsStop]) then begin
|
||||||
|
ClearTree;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if not (DebugBoss.State in [dsPause, dsInternalPause]) then begin
|
||||||
|
ClearTree(True);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
if (Snap <> nil)
|
if (Snap <> nil)
|
||||||
then begin
|
then begin
|
||||||
Locals := LocalsMonitor.Snapshots[Snap][GetThreadId, GetStackframe];
|
Locals := LocalsMonitor.Snapshots[Snap][GetThreadId, GetStackframe];
|
||||||
@ -539,32 +578,29 @@ begin
|
|||||||
Caption:= lisLocals;
|
Caption:= lisLocals;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if Locals = nil
|
if (Locals = nil) then begin
|
||||||
then begin
|
|
||||||
ClearTree;
|
ClearTree;
|
||||||
VNode:= vtLocals.AddChild(nil, nil);
|
Exit;
|
||||||
vtLocals.NodeText[VNode, 1] := lisLocalsNotEvaluated;
|
end;
|
||||||
|
|
||||||
|
if (Locals is TCurrentLocals) and (TCurrentLocals(Locals).Validity in [ddsUnknown, ddsRequested, ddsEvaluating])
|
||||||
|
then begin
|
||||||
|
Locals.Count; // trigger
|
||||||
|
ClearTree(True);
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
BeginUpdate;
|
BeginUpdate;
|
||||||
try
|
try
|
||||||
ClearTree(True);
|
ClearTree(True);
|
||||||
|
VN2 := nil;
|
||||||
for n := 0 to Locals.Count - 1 do begin
|
for n := 0 to Locals.Count - 1 do begin
|
||||||
LVal := Locals.Entries[n];
|
LVal := TIdeLocalsValue(Locals.Entries[n]);
|
||||||
LVal.AddFreeNotification(@DoLocalValueFreed);
|
VNode := vtLocals.FindNodeForText(LVal.DisplayName, 0, True);
|
||||||
|
if (VNode <> nil) and (VNode^.PrevSibling <> VN2) then
|
||||||
VNode := vtLocals.FindNodeForText(LVal.Name, 0);
|
vtLocals.LazMoveTo(VNode, VN2, amInsertAfter);
|
||||||
if (VNode = nil) then begin
|
VNode := FLocolsTreeMgr.AddWatchData(LVal, LVal, VNode);
|
||||||
VNode := vtLocals.AddChild(nil, LVal);
|
VN2 := VNode;
|
||||||
LVal.AddFreeNotification(@DoLocalValueFreed);
|
|
||||||
end
|
|
||||||
else
|
|
||||||
vtLocals.NodeItem[VNode] := LVal;
|
|
||||||
|
|
||||||
s := ClearMultiline(FWatchPrinter.PrintWatchValue(LVal.Value, wdfDefault));
|
|
||||||
vtLocals.NodeText[VNode, 0] := LVal.Name;
|
|
||||||
vtLocals.NodeText[VNode, 1] := s;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -578,12 +614,21 @@ begin
|
|||||||
else
|
else
|
||||||
VNode := vtLocals.GetNextVisibleNoInit(VNode);
|
VNode := vtLocals.GetNextVisibleNoInit(VNode);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
finally
|
finally
|
||||||
EndUpdate;
|
EndUpdate;
|
||||||
|
vtLocals.Invalidate;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TLocalsDlg.SubLocalChanged(Sender: TObject);
|
||||||
|
var
|
||||||
|
VNode: PVirtualNode;
|
||||||
|
begin
|
||||||
|
VNode := vtLocals.FindNodeForItem(Sender);
|
||||||
|
if VNode <> nil then
|
||||||
|
FLocolsTreeMgr.UpdateWatchData(TSubLocalsValue(Sender), VNode);
|
||||||
|
end;
|
||||||
|
|
||||||
function TLocalsDlg.GetThreadId: Integer;
|
function TLocalsDlg.GetThreadId: Integer;
|
||||||
var
|
var
|
||||||
Threads: TIdeThreads;
|
Threads: TIdeThreads;
|
||||||
@ -682,9 +727,9 @@ begin
|
|||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
LVal := GetSelected;
|
LVal := GetSelected;
|
||||||
if (LVal <> nil) and (LVal.Value <> nil) then begin
|
if (LVal <> nil) and (LVal.ResultData <> nil) then begin
|
||||||
Clipboard.Open;
|
Clipboard.Open;
|
||||||
Clipboard.AsText := ValueToRAW(ClearMultiline(FWatchPrinter.PrintWatchValue(LVal.Value, wdfDefault)));
|
Clipboard.AsText := ValueToRAW(ClearMultiline(FWatchPrinter.PrintWatchValue(LVal.ResultData, wdfDefault)));
|
||||||
Clipboard.Close;
|
Clipboard.Close;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -702,9 +747,9 @@ begin
|
|||||||
Clipboard.AsText := ExtractValue(ResultText, ResultDBGType.TypeName)
|
Clipboard.AsText := ExtractValue(ResultText, ResultDBGType.TypeName)
|
||||||
else begin
|
else begin
|
||||||
LVal := GetSelected;
|
LVal := GetSelected;
|
||||||
if (LVal <> nil) and (LVal.Value <> nil) then begin
|
if (LVal <> nil) and (LVal.ResultData <> nil) then begin
|
||||||
Clipboard.Open;
|
Clipboard.Open;
|
||||||
Clipboard.AsText := ClearMultiline(FWatchPrinter.PrintWatchValue(LVal.Value, wdfDefault));
|
Clipboard.AsText := ClearMultiline(FWatchPrinter.PrintWatchValue(LVal.ResultData, wdfDefault));
|
||||||
Clipboard.Close;
|
Clipboard.Close;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -712,35 +757,55 @@ begin
|
|||||||
FreeAndNil(ResultDBGType);
|
FreeAndNil(ResultDBGType);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TLocalsDlg.DoLocalValueFreed(Sender: TObject);
|
|
||||||
var
|
|
||||||
nd: PVirtualNode;
|
|
||||||
begin
|
|
||||||
nd := vtLocals.FindNodeForItem(Sender);
|
|
||||||
if nd = nil then
|
|
||||||
exit;
|
|
||||||
|
|
||||||
//vtLocals.OnItemRemoved := nil;
|
|
||||||
vtLocals.NodeItem[nd] := nil;
|
|
||||||
//vtLocals.OnItemRemoved := @DoItemRemovedFromView;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TLocalsDlg.ClearTree(OnlyClearNodeData: boolean);
|
procedure TLocalsDlg.ClearTree(OnlyClearNodeData: boolean);
|
||||||
var
|
var
|
||||||
LVal: TLocalsValue;
|
LVal: TLocalsValue;
|
||||||
VNode: PVirtualNode;
|
VNode: PVirtualNode;
|
||||||
begin
|
begin
|
||||||
for VNode in vtLocals.NoInitNodes do begin
|
for VNode in vtLocals.NoInitNodes do begin
|
||||||
LVal := TLocalsValue(vtLocals.NodeItem[VNode]);
|
|
||||||
if LVal <> nil then
|
|
||||||
LVal.RemoveFreeNotification(@DoLocalValueFreed);
|
|
||||||
vtLocals.NodeItem[VNode] := nil;
|
vtLocals.NodeItem[VNode] := nil;
|
||||||
|
if OnlyClearNodeData then
|
||||||
|
vtLocals.NodeText[VNode, 1] := '<not evaluated>';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if not OnlyClearNodeData then
|
if not OnlyClearNodeData then
|
||||||
vtLocals.Clear;
|
vtLocals.Clear;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TDbgTreeViewLocalsValueMgr }
|
||||||
|
|
||||||
|
function TDbgTreeViewLocalsValueMgr.WatchAbleResultFromNode(AVNode: PVirtualNode
|
||||||
|
): TWatchAbleResultIntf;
|
||||||
|
begin
|
||||||
|
Result := TIdeLocalsValue(TreeView.NodeItem[AVNode]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TDbgTreeViewLocalsValueMgr.WatchAbleResultFromObject(
|
||||||
|
AWatchAble: TObject): TWatchAbleResultIntf;
|
||||||
|
begin
|
||||||
|
Result := TIdeLocalsValue(AWatchAble);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TDbgTreeViewLocalsValueMgr.UpdateColumnsText(AWatchAble: TObject;
|
||||||
|
AWatchAbleResult: TWatchAbleResultIntf; AVNode: PVirtualNode);
|
||||||
|
var
|
||||||
|
s: String;
|
||||||
|
ResData: TWatchResultData;
|
||||||
|
begin
|
||||||
|
ResData := AWatchAbleResult.ResultData;
|
||||||
|
if ResData = nil then
|
||||||
|
s := AWatchAbleResult.Value
|
||||||
|
else
|
||||||
|
s := ClearMultiline(FLocalsDlg.FWatchPrinter.PrintWatchValue(ResData, wdfDefault));
|
||||||
|
TreeView.NodeText[AVNode, 0] := TIdeLocalsValue(AWatchAble).DisplayName;
|
||||||
|
TreeView.NodeText[AVNode, 1] := s;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TDbgTreeViewLocalsValueMgr.ConfigureNewSubItem(AWatchAble: TObject);
|
||||||
|
begin
|
||||||
|
TSubLocalsValue(AWatchAble).OnChange := @FLocalsDlg.SubLocalChanged;
|
||||||
|
end;
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
|
|
||||||
LocalsDlgWindowCreator := IDEWindowCreators.Add(DebugDialogNames[ddtLocals]);
|
LocalsDlgWindowCreator := IDEWindowCreators.Add(DebugDialogNames[ddtLocals]);
|
||||||
|
Loading…
Reference in New Issue
Block a user