mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-02 12:00:15 +02:00
IdeDebugger: improve unfolding of watches. Allow Pointer to object/array to be unfolded (and dereference them for this)
This commit is contained in:
parent
9a0e268738
commit
ea1e68ed26
@ -155,6 +155,9 @@ begin
|
||||
end;
|
||||
|
||||
ResData := AWatchAbleResult.ResultData;
|
||||
while (ResData <> nil) and (ResData.ValueKind = rdkPointerVal) do
|
||||
ResData := ResData.DerefData;
|
||||
|
||||
if (ResData <> nil) and
|
||||
(ResData.FieldCount > 0) and
|
||||
(ResData.ValueKind <> rdkConvertRes)
|
||||
@ -180,7 +183,7 @@ procedure TDbgTreeViewWatchDataMgr.DoUpdateArraySubItems(AWatchAble: TObject;
|
||||
ChildCount: LongWord);
|
||||
var
|
||||
NewWatchAble: TObject;
|
||||
i, TotalCount: Integer;
|
||||
i, TotalCount, DerefCount: Integer;
|
||||
ResData: TWatchResultData;
|
||||
ExistingNode, nd: PVirtualNode;
|
||||
Nav: TArrayNavigationBar;
|
||||
@ -188,6 +191,11 @@ var
|
||||
begin
|
||||
ChildCount := 0;
|
||||
ResData := AWatchAbleResult.ResultData;
|
||||
DerefCount := 0;
|
||||
while (ResData <> nil) and (ResData.ValueKind = rdkPointerVal) do begin
|
||||
ResData := ResData.DerefData;
|
||||
inc(DerefCount);
|
||||
end;
|
||||
if (ResData = nil) then
|
||||
exit;
|
||||
|
||||
@ -226,7 +234,7 @@ begin
|
||||
|
||||
Offs := Nav.Index;
|
||||
for i := 0 to ChildCount - 1 do begin
|
||||
NewWatchAble := AWatchAbleResult.ChildrenByNameAsArrayEntry[Offs + i];
|
||||
NewWatchAble := AWatchAbleResult.ChildrenByNameAsArrayEntry[Offs + i, DerefCount];
|
||||
if NewWatchAble = nil then begin
|
||||
dec(ChildCount);
|
||||
continue;
|
||||
@ -265,9 +273,18 @@ var
|
||||
AnchClass: String;
|
||||
NewWatchAble: TObject;
|
||||
ChildInfo: TWatchResultDataFieldInfo;
|
||||
DerefCount: Integer;
|
||||
begin
|
||||
ChildCount := 0;
|
||||
ResData := AWatchAbleResult.ResultData;
|
||||
DerefCount := 0;
|
||||
while (ResData <> nil) and (ResData.ValueKind = rdkPointerVal) do begin
|
||||
ResData := ResData.DerefData;
|
||||
inc(DerefCount);
|
||||
end;
|
||||
if ResData = nil then
|
||||
exit;
|
||||
|
||||
ExistingNode := FTreeView.GetFirstChildNoInit(AVNode);
|
||||
if ExistingNode <> nil then
|
||||
FTreeView.NodeControl[ExistingNode].Free;
|
||||
@ -276,7 +293,7 @@ begin
|
||||
if ResData.StructType <> dstRecord then
|
||||
AnchClass := ResData.TypeName;
|
||||
for ChildInfo in ResData do begin
|
||||
NewWatchAble := AWatchAbleResult.ChildrenByNameAsField[ChildInfo.FieldName, AnchClass];
|
||||
NewWatchAble := AWatchAbleResult.ChildrenByNameAsField[ChildInfo.FieldName, AnchClass, DerefCount];
|
||||
if NewWatchAble = nil then begin
|
||||
continue;
|
||||
end;
|
||||
@ -318,9 +335,9 @@ begin
|
||||
AnchClass := TypInfo.TypeName;
|
||||
for i := 0 to TypInfo.Fields.Count-1 do begin
|
||||
if IsGdbmiArray then
|
||||
NewWatchAble := AWatchAbleResult.ChildrenByNameAsArrayEntry[StrToInt64Def(TypInfo.Fields[i].Name, 0)]
|
||||
NewWatchAble := AWatchAbleResult.ChildrenByNameAsArrayEntry[StrToInt64Def(TypInfo.Fields[i].Name, 0), 0]
|
||||
else
|
||||
NewWatchAble := AWatchAbleResult.ChildrenByNameAsField[TypInfo.Fields[i].Name, AnchClass];
|
||||
NewWatchAble := AWatchAbleResult.ChildrenByNameAsField[TypInfo.Fields[i].Name, AnchClass, 0];
|
||||
if NewWatchAble = nil then begin
|
||||
dec(ChildCount);
|
||||
continue;
|
||||
@ -422,6 +439,7 @@ procedure TDbgTreeViewWatchDataMgr.UpdateWatchData(AWatchAble: TObject;
|
||||
AnIgnoreNodeVisible: Boolean);
|
||||
var
|
||||
TypInfo: TDBGType;
|
||||
ResData: TWatchResultData;
|
||||
HasChildren: Boolean;
|
||||
c: LongWord;
|
||||
begin
|
||||
@ -450,12 +468,15 @@ begin
|
||||
((DebugBoss = nil) or (DebugBoss.State <> dsRun))
|
||||
then begin
|
||||
TypInfo := AWatchAbleResult.TypeInfo;
|
||||
ResData := AWatchAbleResult.ResultData;
|
||||
while (ResData <> nil) and (ResData.ValueKind = rdkPointerVal) do
|
||||
ResData := ResData.DerefData;
|
||||
HasChildren := ( (TypInfo <> nil) and (TypInfo.Fields <> nil) and (TypInfo.Fields.Count > 0) ) or
|
||||
( (AWatchAbleResult.ResultData <> nil) and
|
||||
( ( (AWatchAbleResult.ResultData.FieldCount > 0) and (AWatchAbleResult.ResultData.ValueKind <> rdkConvertRes) )
|
||||
( (ResData <> nil) and
|
||||
( ( (ResData.FieldCount > 0) and (ResData.ValueKind <> rdkConvertRes) )
|
||||
or
|
||||
//( (AWatchAbleResult.ResultData.ValueKind = rdkArray) and (AWatchAbleResult.ResultData.ArrayLength > 0) )
|
||||
(AWatchAbleResult.ResultData.ArrayLength > 0)
|
||||
//( (ResData.ValueKind = rdkArray) and (ResData.ArrayLength > 0) )
|
||||
(ResData.ArrayLength > 0)
|
||||
) );
|
||||
FTreeView.HasChildren[AVNode] := HasChildren;
|
||||
|
||||
|
@ -534,8 +534,8 @@ type
|
||||
|
||||
TIdeWatchValue = class(TWatchValue, IWatchAbleResultIntf)
|
||||
private
|
||||
function GetChildrenByNameAsArrayEntry(AName: Int64): TObject; // TIdeWatch;
|
||||
function GetChildrenByNameAsField(AName, AClassName: String): TObject; // TIdeWatch;
|
||||
function GetChildrenByNameAsArrayEntry(AName: Int64; DerefCount: Integer): TObject; // TIdeWatch;
|
||||
function GetChildrenByNameAsField(AName, AClassName: String; DerefCount: Integer): TObject; // TIdeWatch;
|
||||
function GetWatch: TIdeWatch;
|
||||
function GetEnabled: Boolean;
|
||||
protected
|
||||
@ -566,8 +566,8 @@ type
|
||||
|
||||
function MaybeCopyResult(ASourceWatch: TIdeWatch): boolean;
|
||||
|
||||
property ChildrenByNameAsField[AName, AClassName: String]: TObject read GetChildrenByNameAsField;
|
||||
property ChildrenByNameAsArrayEntry[AName: Int64]: TObject read GetChildrenByNameAsArrayEntry;
|
||||
property ChildrenByNameAsField[AName, AClassName: String; DerefCount: Integer]: TObject read GetChildrenByNameAsField;
|
||||
property ChildrenByNameAsArrayEntry[AName: Int64; DerefCount: Integer]: TObject read GetChildrenByNameAsArrayEntry;
|
||||
end;
|
||||
|
||||
TIdeTempWatchValue = class(TIdeWatchValue)
|
||||
@ -604,8 +604,8 @@ type
|
||||
FParentWatch: TIdeWatch;
|
||||
|
||||
function GetChildWatch(ADispName, AnExpr: String): TIdeWatch;
|
||||
function GetChildrenByNameAsArrayEntry(AName: Int64): TIdeWatch;
|
||||
function GetChildrenByNameAsField(AName, AClassName: String): TIdeWatch;
|
||||
function GetChildrenByNameAsArrayEntry(AName: Int64; DerefCount: Integer): TIdeWatch;
|
||||
function GetChildrenByNameAsField(AName, AClassName: String; DerefCount: Integer): TIdeWatch;
|
||||
function GetTopParentWatch: TIdeWatch;
|
||||
function GetValue(const AThreadId: Integer; const AStackFrame: Integer): TIdeWatchValue;
|
||||
function GetAnyValidParentWatchValue(AThreadId: Integer; AStackFrame: Integer): TIdeWatchValue;
|
||||
@ -636,8 +636,8 @@ type
|
||||
procedure BeginChildUpdate;
|
||||
procedure EndChildUpdate;
|
||||
procedure LimitChildWatchCount(AMaxCnt: Integer; AKeepIndexEntriesBelow: Int64 = low(Int64));
|
||||
property ChildrenByNameAsField[AName, AClassName: String]: TIdeWatch read GetChildrenByNameAsField;
|
||||
property ChildrenByNameAsArrayEntry[AName: Int64]: TIdeWatch read GetChildrenByNameAsArrayEntry;
|
||||
property ChildrenByNameAsField[AName, AClassName: String; DerefCount: Integer]: TIdeWatch read GetChildrenByNameAsField;
|
||||
property ChildrenByNameAsArrayEntry[AName: Int64; DerefCount: Integer]: TIdeWatch read GetChildrenByNameAsArrayEntry;
|
||||
function HasAllValidParents(AThreadId: Integer; AStackFrame: Integer): boolean;
|
||||
property ParentWatch: TIdeWatch read FParentWatch;
|
||||
property TopParentWatch: TIdeWatch read GetTopParentWatch;
|
||||
@ -949,8 +949,8 @@ type
|
||||
function GetDisplayFormat: TWatchDisplayFormat;
|
||||
function GetTypeInfo: TDBGType; deprecated;
|
||||
|
||||
function GetChildrenByNameAsArrayEntry(AName: Int64): TObject;
|
||||
function GetChildrenByNameAsField(AName, AClassName: String): TObject;
|
||||
function GetChildrenByNameAsArrayEntry(AName: Int64; DerefCount: Integer): TObject;
|
||||
function GetChildrenByNameAsField(AName, AClassName: String; DerefCount: Integer): TObject;
|
||||
|
||||
protected
|
||||
function FindParentValue: TIdeLocalsValue; virtual;
|
||||
@ -4378,7 +4378,8 @@ begin
|
||||
Result := ddsEvaluating; // ddsWaitForParent;
|
||||
end;
|
||||
|
||||
function TIdeWatchValue.GetChildrenByNameAsArrayEntry(AName: Int64): TObject;
|
||||
function TIdeWatchValue.GetChildrenByNameAsArrayEntry(AName: Int64;
|
||||
DerefCount: Integer): TObject;
|
||||
begin
|
||||
Result := nil;
|
||||
if FWatch = nil then
|
||||
@ -4389,11 +4390,11 @@ begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
Result := Watch.ChildrenByNameAsArrayEntry[AName];
|
||||
Result := Watch.ChildrenByNameAsArrayEntry[AName, DerefCount];
|
||||
end;
|
||||
|
||||
function TIdeWatchValue.GetChildrenByNameAsField(AName, AClassName: String
|
||||
): TObject;
|
||||
function TIdeWatchValue.GetChildrenByNameAsField(AName, AClassName: String;
|
||||
DerefCount: Integer): TObject;
|
||||
begin
|
||||
Result := nil;
|
||||
if FWatch = nil then
|
||||
@ -4404,7 +4405,7 @@ begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
Result := Watch.ChildrenByNameAsField[AName, AClassName];
|
||||
Result := Watch.ChildrenByNameAsField[AName, AClassName, DerefCount];
|
||||
end;
|
||||
|
||||
function TIdeWatchValue.GetWatch: TIdeWatch;
|
||||
@ -6807,23 +6808,24 @@ begin
|
||||
EndChildUpdate;
|
||||
end;
|
||||
|
||||
function TIdeWatch.GetChildrenByNameAsArrayEntry(AName: Int64): TIdeWatch;
|
||||
function TIdeWatch.GetChildrenByNameAsArrayEntry(AName: Int64;
|
||||
DerefCount: Integer): TIdeWatch;
|
||||
begin
|
||||
Result := GetChildWatch(IntToStr(AName),
|
||||
GetExpressionForArrayElement(Expression, AName)
|
||||
Result := GetChildWatch(StringOfChar('^', DerefCount) + IntToStr(AName),
|
||||
GetExpressionForArrayElement(Expression + StringOfChar('^', DerefCount), AName)
|
||||
);
|
||||
end;
|
||||
|
||||
function TIdeWatch.GetChildrenByNameAsField(AName, AClassName: String
|
||||
): TIdeWatch;
|
||||
function TIdeWatch.GetChildrenByNameAsField(AName, AClassName: String;
|
||||
DerefCount: Integer): TIdeWatch;
|
||||
var
|
||||
Expr: String;
|
||||
begin
|
||||
Expr := Expression;
|
||||
Expr := Expression + StringOfChar('^', DerefCount);
|
||||
if AClassName <> '' then
|
||||
Expr := AClassName + '(' + Expr + ')';
|
||||
Expr := Expr + '.' + AName;
|
||||
Result := GetChildWatch(AName, Expr);
|
||||
Result := GetChildWatch(StringOfChar('^', DerefCount) + AName, Expr);
|
||||
end;
|
||||
|
||||
function TIdeWatch.CreateChildWatches: TIdeWatches;
|
||||
@ -7343,24 +7345,25 @@ begin
|
||||
Result := nil;
|
||||
end;
|
||||
|
||||
function TIdeLocalsValue.GetChildrenByNameAsArrayEntry(AName: Int64): TObject;
|
||||
function TIdeLocalsValue.GetChildrenByNameAsArrayEntry(AName: Int64;
|
||||
DerefCount: Integer): TObject;
|
||||
begin
|
||||
Result := GetSubLocal(IntToStr(AName),
|
||||
GetExpressionForArrayElement(Name, AName)
|
||||
Result := GetSubLocal(StringOfChar('^', DerefCount) + IntToStr(AName),
|
||||
GetExpressionForArrayElement(Name + StringOfChar('^', DerefCount), AName)
|
||||
);
|
||||
end;
|
||||
|
||||
function TIdeLocalsValue.GetChildrenByNameAsField(AName, AClassName: String
|
||||
): TObject;
|
||||
function TIdeLocalsValue.GetChildrenByNameAsField(AName, AClassName: String;
|
||||
DerefCount: Integer): TObject;
|
||||
var
|
||||
Expr: String;
|
||||
begin
|
||||
Expr := Name;
|
||||
Expr := Name + StringOfChar('^', DerefCount);
|
||||
// no defClassAutoCast for locals // if changed also update FindParentValue
|
||||
//if AClassName <> '' then
|
||||
// Expr := AClassName + '(' + Expr + ')';
|
||||
Expr := Expr + '.' + AName;
|
||||
Result := GetSubLocal(AName, Expr);
|
||||
Result := GetSubLocal(StringOfChar('^', DerefCount) + AName, Expr);
|
||||
end;
|
||||
|
||||
function TIdeLocalsValue.FindParentValue: TIdeLocalsValue;
|
||||
|
@ -34,8 +34,8 @@ type
|
||||
end;
|
||||
|
||||
IWatchAbleResultIntf = interface ['wdr']
|
||||
function GetChildrenByNameAsArrayEntry(AName: Int64): TObject;
|
||||
function GetChildrenByNameAsField(AName, AClassName: String): TObject;
|
||||
function GetChildrenByNameAsArrayEntry(AName: Int64; DerefCount: Integer): TObject;
|
||||
function GetChildrenByNameAsField(AName, AClassName: String; DerefCount: Integer): TObject;
|
||||
|
||||
function GetEnabled: Boolean;
|
||||
function GetValidity: TDebuggerDataState;
|
||||
@ -44,8 +44,8 @@ type
|
||||
function GetValue: string;
|
||||
function GetResultData: TWatchResultData;
|
||||
|
||||
property ChildrenByNameAsField[AName, AClassName: String]: TObject read GetChildrenByNameAsField;
|
||||
property ChildrenByNameAsArrayEntry[AName: Int64]: TObject read GetChildrenByNameAsArrayEntry;
|
||||
property ChildrenByNameAsField[AName, AClassName: String; DerefCount: Integer]: TObject read GetChildrenByNameAsField;
|
||||
property ChildrenByNameAsArrayEntry[AName: Int64; DerefCount: Integer]: TObject read GetChildrenByNameAsArrayEntry;
|
||||
|
||||
property Enabled: Boolean read GetEnabled;
|
||||
property Validity: TDebuggerDataState read GetValidity;
|
||||
|
Loading…
Reference in New Issue
Block a user