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