mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-18 12:41:21 +02:00
Debugger, SourceEditor: Track Line changes during debug. Adjust breakpoints and executionline
git-svn-id: trunk@24569 -
This commit is contained in:
parent
48c111460d
commit
b60616fe5a
@ -201,6 +201,7 @@ type
|
|||||||
FValid: TValidState;
|
FValid: TValidState;
|
||||||
FInitialEnabled: Boolean;
|
FInitialEnabled: Boolean;
|
||||||
protected
|
protected
|
||||||
|
procedure AssignLocationTo(Dest: TPersistent); virtual;
|
||||||
procedure AssignTo(Dest: TPersistent); override;
|
procedure AssignTo(Dest: TPersistent); override;
|
||||||
procedure DoBreakHitCountChange; virtual;
|
procedure DoBreakHitCountChange; virtual;
|
||||||
procedure DoExpressionChange; virtual;
|
procedure DoExpressionChange; virtual;
|
||||||
@ -1924,6 +1925,13 @@ end;
|
|||||||
TBaseBreakPoint
|
TBaseBreakPoint
|
||||||
=========================================================================== }
|
=========================================================================== }
|
||||||
|
|
||||||
|
procedure TBaseBreakPoint.AssignLocationTo(Dest: TPersistent);
|
||||||
|
var
|
||||||
|
DestBreakPoint: TBaseBreakPoint absolute Dest;
|
||||||
|
begin
|
||||||
|
DestBreakPoint.SetLocation(FSource, FLine);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TBaseBreakPoint.AssignTo(Dest: TPersistent);
|
procedure TBaseBreakPoint.AssignTo(Dest: TPersistent);
|
||||||
var
|
var
|
||||||
DestBreakPoint: TBaseBreakPoint absolute Dest;
|
DestBreakPoint: TBaseBreakPoint absolute Dest;
|
||||||
@ -1931,8 +1939,8 @@ begin
|
|||||||
// updatelock is set in source.assignto
|
// updatelock is set in source.assignto
|
||||||
if Dest is TBaseBreakPoint
|
if Dest is TBaseBreakPoint
|
||||||
then begin
|
then begin
|
||||||
|
AssignLocationTo(DestBreakPoint);
|
||||||
DestBreakPoint.SetBreakHitCount(FBreakHitCount);
|
DestBreakPoint.SetBreakHitCount(FBreakHitCount);
|
||||||
DestBreakPoint.SetLocation(FSource, FLine);
|
|
||||||
DestBreakPoint.SetExpression(FExpression);
|
DestBreakPoint.SetExpression(FExpression);
|
||||||
DestBreakPoint.SetEnabled(FEnabled);
|
DestBreakPoint.SetEnabled(FEnabled);
|
||||||
DestBreakPoint.InitialEnabled := FInitialEnabled;
|
DestBreakPoint.InitialEnabled := FInitialEnabled;
|
||||||
|
@ -210,6 +210,7 @@ type
|
|||||||
private
|
private
|
||||||
FMaster: TDBGBreakPoint;
|
FMaster: TDBGBreakPoint;
|
||||||
FSourceMark: TSourceMark;
|
FSourceMark: TSourceMark;
|
||||||
|
FCurrentDebugExeLine: Integer;
|
||||||
procedure OnSourceMarkBeforeFree(Sender: TObject);
|
procedure OnSourceMarkBeforeFree(Sender: TObject);
|
||||||
procedure OnSourceMarkCreatePopupMenu(SenderMark: TSourceMark;
|
procedure OnSourceMarkCreatePopupMenu(SenderMark: TSourceMark;
|
||||||
const AddMenuItem: TAddMenuItemProc);
|
const AddMenuItem: TAddMenuItemProc);
|
||||||
@ -219,6 +220,7 @@ type
|
|||||||
procedure OnDeleteMenuItemClick(Sender: TObject);
|
procedure OnDeleteMenuItemClick(Sender: TObject);
|
||||||
procedure OnViewPropertiesMenuItemClick(Sender: TObject);
|
procedure OnViewPropertiesMenuItemClick(Sender: TObject);
|
||||||
protected
|
protected
|
||||||
|
procedure AssignLocationTo(Dest: TPersistent); override;
|
||||||
procedure AssignTo(Dest: TPersistent); override;
|
procedure AssignTo(Dest: TPersistent); override;
|
||||||
procedure DoChanged; override;
|
procedure DoChanged; override;
|
||||||
function GetHitCount: Integer; override;
|
function GetHitCount: Integer; override;
|
||||||
@ -230,6 +232,7 @@ type
|
|||||||
procedure UpdateSourceMark;
|
procedure UpdateSourceMark;
|
||||||
procedure UpdateSourceMarkImage;
|
procedure UpdateSourceMarkImage;
|
||||||
procedure UpdateSourceMarkLineColor;
|
procedure UpdateSourceMarkLineColor;
|
||||||
|
function DebugExeLine: Integer; // If known, the line in the compiled exe
|
||||||
public
|
public
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
procedure ResetMaster;
|
procedure ResetMaster;
|
||||||
@ -1057,6 +1060,16 @@ begin
|
|||||||
DebugBoss.ShowBreakPointProperties(Self);
|
DebugBoss.ShowBreakPointProperties(Self);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TManagedBreakPoint.AssignLocationTo(Dest: TPersistent);
|
||||||
|
var
|
||||||
|
DestBreakPoint: TBaseBreakPoint absolute Dest;
|
||||||
|
begin
|
||||||
|
if DestBreakPoint is TDBGBreakPoint then
|
||||||
|
DestBreakPoint.SetLocation(Source, DebugExeLine)
|
||||||
|
else
|
||||||
|
inherited;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TManagedBreakPoint.OnSourceMarkBeforeFree(Sender: TObject);
|
procedure TManagedBreakPoint.OnSourceMarkBeforeFree(Sender: TObject);
|
||||||
begin
|
begin
|
||||||
SourceMark:=nil;
|
SourceMark:=nil;
|
||||||
@ -1166,10 +1179,15 @@ end;
|
|||||||
|
|
||||||
procedure TManagedBreakPoint.SetLocation(const ASource: String;
|
procedure TManagedBreakPoint.SetLocation(const ASource: String;
|
||||||
const ALine: Integer);
|
const ALine: Integer);
|
||||||
|
var
|
||||||
|
NewDebugExeLine: Integer;
|
||||||
begin
|
begin
|
||||||
if (Source = ASource) and (Line = ALine) then exit;
|
NewDebugExeLine := DebugExeLine;
|
||||||
|
if (Source = ASource) and (Line = ALine) and (FCurrentDebugExeLine = NewDebugExeLine)
|
||||||
|
then exit;
|
||||||
inherited SetLocation(ASource, ALine);
|
inherited SetLocation(ASource, ALine);
|
||||||
if FMaster<>nil then FMaster.SetLocation(ASource,ALine);
|
FCurrentDebugExeLine := NewDebugExeLine;
|
||||||
|
if FMaster<>nil then FMaster.SetLocation(ASource, DebugExeLine);
|
||||||
if Project1 <> nil
|
if Project1 <> nil
|
||||||
then Project1.Modified := True;
|
then Project1.Modified := True;
|
||||||
end;
|
end;
|
||||||
@ -1225,6 +1243,14 @@ begin
|
|||||||
SourceMark.LineColorAttrib := aha;
|
SourceMark.LineColorAttrib := aha;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TManagedBreakPoint.DebugExeLine: Integer;
|
||||||
|
begin
|
||||||
|
if (FSourceMark <> nil) and (FSourceMark.SourceEditor <> nil) then
|
||||||
|
Result := TSourceEditor(FSourceMark.SourceEditor).SourceToDebugLine(Line)
|
||||||
|
else
|
||||||
|
Result := Line;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TManagedBreakPoint.UpdateSourceMark;
|
procedure TManagedBreakPoint.UpdateSourceMark;
|
||||||
begin
|
begin
|
||||||
UpdateSourceMarkImage;
|
UpdateSourceMarkImage;
|
||||||
@ -1464,6 +1490,7 @@ const
|
|||||||
var
|
var
|
||||||
Editor: TSourceEditor;
|
Editor: TSourceEditor;
|
||||||
MsgResult: TModalResult;
|
MsgResult: TModalResult;
|
||||||
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
if (ADebugger<>FDebugger) or (ADebugger=nil) then
|
if (ADebugger<>FDebugger) or (ADebugger=nil) then
|
||||||
RaiseException('TDebugManager.OnDebuggerChangeState');
|
RaiseException('TDebugManager.OnDebuggerChangeState');
|
||||||
@ -1532,8 +1559,13 @@ begin
|
|||||||
then
|
then
|
||||||
SourceEditorManager.FillExecutionMarks;
|
SourceEditorManager.FillExecutionMarks;
|
||||||
|
|
||||||
if not (FDebugger.State in [dsRun, dsPause]) and (SourceEditorManager <> nil) then
|
if not (FDebugger.State in [dsRun, dsPause]) and (SourceEditorManager <> nil)
|
||||||
|
then begin
|
||||||
SourceEditorManager.ClearExecutionMarks;
|
SourceEditorManager.ClearExecutionMarks;
|
||||||
|
// Refresh DebugExeLine
|
||||||
|
for i := 0 to FBreakPoints.Count - 1 do
|
||||||
|
FBreakPoints[i].SetLocation(FBreakPoints[i].Source, FBreakPoints[i].Line);
|
||||||
|
end;
|
||||||
|
|
||||||
case FDebugger.State of
|
case FDebugger.State of
|
||||||
dsError: begin
|
dsError: begin
|
||||||
@ -1633,21 +1665,23 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
// clear old error and execution lines
|
// clear old error and execution lines
|
||||||
|
Editor := nil;
|
||||||
if SourceEditorManager <> nil
|
if SourceEditorManager <> nil
|
||||||
then begin
|
then begin
|
||||||
|
Editor := SourceEditorManager.GetActiveSE;
|
||||||
SourceEditorManager.ClearExecutionLines;
|
SourceEditorManager.ClearExecutionLines;
|
||||||
SourceEditorManager.ClearErrorLines;
|
SourceEditorManager.ClearErrorLines;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// jump editor to execution line
|
// jump editor to execution line
|
||||||
FocusEditor := (FCurrentBreakPoint = nil) or (FCurrentBreakPoint.AutoContinueTime = 0);
|
FocusEditor := (FCurrentBreakPoint = nil) or (FCurrentBreakPoint.AutoContinueTime = 0);
|
||||||
if MainIDE.DoJumpToCodePos(nil,nil,NewSource,1,SrcLine,-1,true, FocusEditor)<>mrOk
|
i := SrcLine;
|
||||||
|
if Editor <> nil then
|
||||||
|
i := Editor.DebugToSourceLine(i);
|
||||||
|
if MainIDE.DoJumpToCodePos(nil,nil,NewSource,1,i,-1,true, FocusEditor)<>mrOk
|
||||||
then exit;
|
then exit;
|
||||||
|
|
||||||
// mark execution line
|
// mark execution line
|
||||||
if SourceEditorManager <> nil
|
|
||||||
then Editor := SourceEditorManager.GetActiveSE
|
|
||||||
else Editor := nil;
|
|
||||||
|
|
||||||
if Editor <> nil
|
if Editor <> nil
|
||||||
then begin
|
then begin
|
||||||
if not Editor.HasExecutionMarks then
|
if not Editor.HasExecutionMarks then
|
||||||
|
@ -424,6 +424,8 @@ type
|
|||||||
procedure FillExecutionMarks;
|
procedure FillExecutionMarks;
|
||||||
procedure ClearExecutionMarks;
|
procedure ClearExecutionMarks;
|
||||||
procedure LineInfoNotificationChange(const ASender: TObject; const ASource: String);
|
procedure LineInfoNotificationChange(const ASender: TObject; const ASource: String);
|
||||||
|
function SourceToDebugLine(aLinePos: Integer): Integer;
|
||||||
|
function DebugToSourceLine(aLinePos: Integer): Integer;
|
||||||
public
|
public
|
||||||
// properties
|
// properties
|
||||||
property CodeBuffer: TCodeBuffer read FCodeBuffer write SetCodeBuffer;
|
property CodeBuffer: TCodeBuffer read FCodeBuffer write SetCodeBuffer;
|
||||||
@ -3372,6 +3374,7 @@ end;
|
|||||||
|
|
||||||
procedure TSourceEditor.SetExecutionLine(NewLine: integer);
|
procedure TSourceEditor.SetExecutionLine(NewLine: integer);
|
||||||
begin
|
begin
|
||||||
|
NewLine := EditorComponent.IDEGutterMarks.DebugLineToSourceLine(NewLine);
|
||||||
if ExecutionLine=NewLine then exit;
|
if ExecutionLine=NewLine then exit;
|
||||||
if (FSharedValues.ExecutionMark = nil) then begin
|
if (FSharedValues.ExecutionMark = nil) then begin
|
||||||
if NewLine = -1 then
|
if NewLine = -1 then
|
||||||
@ -4353,6 +4356,16 @@ begin
|
|||||||
FillExecutionMarks;
|
FillExecutionMarks;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TSourceEditor.SourceToDebugLine(aLinePos: Integer): Integer;
|
||||||
|
begin
|
||||||
|
Result := FEditor.IDEGutterMarks.SourceLineToDebugLine(aLinePos, True);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSourceEditor.DebugToSourceLine(aLinePos: Integer): Integer;
|
||||||
|
begin
|
||||||
|
Result := FEditor.IDEGutterMarks.DebugLineToSourceLine(aLinePos);
|
||||||
|
end;
|
||||||
|
|
||||||
function TSourceEditor.SharedEditorCount: Integer;
|
function TSourceEditor.SharedEditorCount: Integer;
|
||||||
begin
|
begin
|
||||||
Result := FSharedValues.SharedEditorCount;
|
Result := FSharedValues.SharedEditorCount;
|
||||||
|
@ -37,7 +37,7 @@ interface
|
|||||||
{$I ide.inc}
|
{$I ide.inc}
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, Graphics, SynEdit, SynEditMiscClasses, SynGutter,
|
Classes, SysUtils, LCLProc, Graphics, SynEdit, SynEditMiscClasses, SynGutter,
|
||||||
SynGutterLineNumber, SynGutterCodeFolding, SynGutterMarks, SynGutterChanges,
|
SynGutterLineNumber, SynGutterCodeFolding, SynGutterMarks, SynGutterChanges,
|
||||||
SynEditTextBuffer, SynEditFoldedView, SynTextDrawer, SynEditTextBase;
|
SynEditTextBuffer, SynEditFoldedView, SynTextDrawer, SynEditTextBase;
|
||||||
|
|
||||||
@ -78,8 +78,8 @@ type
|
|||||||
constructor Create;
|
constructor Create;
|
||||||
procedure IncRefCount;
|
procedure IncRefCount;
|
||||||
procedure DecRefCount;
|
procedure DecRefCount;
|
||||||
// Index is the Current line in editor (including source modification)
|
// Index is the Current line-index (0 based) in editor (including source modification)
|
||||||
// Result is the original Line as known by the debugger
|
// Result is the original Line-pos (1 based) as known by the debugger
|
||||||
property SrcLineToMarkLine[SrcIndex: Integer]: Integer
|
property SrcLineToMarkLine[SrcIndex: Integer]: Integer
|
||||||
read GetSrcLineToMarkLine write SetSrcLineToMarkLine; default;
|
read GetSrcLineToMarkLine write SetSrcLineToMarkLine; default;
|
||||||
property RefCount: Integer read FRefCount;
|
property RefCount: Integer read FRefCount;
|
||||||
@ -99,6 +99,8 @@ type
|
|||||||
procedure SetDebugMarks(AFirstLinePos, ALastLinePos: Integer);
|
procedure SetDebugMarks(AFirstLinePos, ALastLinePos: Integer);
|
||||||
procedure ClearDebugMarks;
|
procedure ClearDebugMarks;
|
||||||
function HasDebugMarks: Boolean;
|
function HasDebugMarks: Boolean;
|
||||||
|
function DebugLineToSourceLine(aLinePos: Integer): Integer;
|
||||||
|
function SourceLineToDebugLine(aLinePos: Integer; AdjustOnError: Boolean = False): Integer;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@ -183,7 +185,8 @@ begin
|
|||||||
aGutterOffs := 0;
|
aGutterOffs := 0;
|
||||||
HasAnyMark := PaintMarks(aScreenLine, Canvas, AClip, aGutterOffs);
|
HasAnyMark := PaintMarks(aScreenLine, Canvas, AClip, aGutterOffs);
|
||||||
TxtIdx := FFoldView.TextIndex[aScreenLine];
|
TxtIdx := FFoldView.TextIndex[aScreenLine];
|
||||||
if (not HasAnyMark) and (HasDebugMarks) and (FDebugMarkInfo.SrcLineToMarkLine[TxtIdx] > 0)
|
if (not HasAnyMark) and (HasDebugMarks) and (TxtIdx < FDebugMarkInfo.Count) and
|
||||||
|
(FDebugMarkInfo.SrcLineToMarkLine[TxtIdx] > 0)
|
||||||
then
|
then
|
||||||
DrawDebugMark(aScreenLine);
|
DrawDebugMark(aScreenLine);
|
||||||
end;
|
end;
|
||||||
@ -213,7 +216,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
for i := AFirstLinePos - 1 to ALastLinePos - 1 do
|
for i := AFirstLinePos - 1 to ALastLinePos - 1 do
|
||||||
FDebugMarkInfo[i] := i;
|
FDebugMarkInfo[i] := i + 1;
|
||||||
TSynEdit(SynEdit).InvalidateGutter;
|
TSynEdit(SynEdit).InvalidateGutter;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -245,6 +248,55 @@ begin
|
|||||||
Result := FDebugMarkInfo <> nil;
|
Result := FDebugMarkInfo <> nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TIDESynGutterMarks.DebugLineToSourceLine(aLinePos: Integer): Integer;
|
||||||
|
var
|
||||||
|
i, c: LongInt;
|
||||||
|
begin
|
||||||
|
CheckTextBuffer;
|
||||||
|
if (aLinePos < 1) or (not HasDebugMarks) then exit(aLinePos);
|
||||||
|
Result := aLinePos - 1; // 0 based
|
||||||
|
if (FDebugMarkInfo[Result] = 0) or (FDebugMarkInfo[Result] > aLinePos) then begin
|
||||||
|
i := Result;
|
||||||
|
repeat
|
||||||
|
dec(i);
|
||||||
|
while (i >= 0) and (FDebugMarkInfo[i] = 0) do dec(i);
|
||||||
|
if (i < 0) or (FDebugMarkInfo[i] < aLinePos) then break;
|
||||||
|
Result := i;
|
||||||
|
until FDebugMarkInfo[Result] = aLinePos;
|
||||||
|
if (FDebugMarkInfo[Result] > aLinePos) and // line not found
|
||||||
|
(Result > 0) and (FDebugMarkInfo[Result - 1] = 0)
|
||||||
|
then
|
||||||
|
dec(Result);
|
||||||
|
end;
|
||||||
|
if (FDebugMarkInfo[Result] = 0) or (FDebugMarkInfo[Result] < aLinePos) then begin
|
||||||
|
c := FDebugMarkInfo.Count;
|
||||||
|
i := Result;
|
||||||
|
repeat
|
||||||
|
inc(i);
|
||||||
|
while (i < c) and (FDebugMarkInfo[i] = 0) do inc(i);
|
||||||
|
if (i >= c) or (FDebugMarkInfo[i] > aLinePos) then break;
|
||||||
|
Result := i;
|
||||||
|
until FDebugMarkInfo[Result] = aLinePos;
|
||||||
|
if (FDebugMarkInfo[Result] < aLinePos) and // line not found
|
||||||
|
(Result < c-1) and (FDebugMarkInfo[Result + 1] = 0)
|
||||||
|
then
|
||||||
|
inc(Result);
|
||||||
|
end;
|
||||||
|
inc(Result); // 1 based
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TIDESynGutterMarks.SourceLineToDebugLine(aLinePos: Integer;
|
||||||
|
AdjustOnError: Boolean): Integer;
|
||||||
|
begin
|
||||||
|
CheckTextBuffer;
|
||||||
|
if (aLinePos < 1) or (not HasDebugMarks) then exit(aLinePos);
|
||||||
|
Result := FDebugMarkInfo[aLinePos - 1];
|
||||||
|
while (Result = 0) and AdjustOnError and (aLinePos < FDebugMarkInfo.Count-1) do begin
|
||||||
|
inc(aLinePos);
|
||||||
|
Result := FDebugMarkInfo[aLinePos - 1];
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TIDESynDebugMarkInfo }
|
{ TIDESynDebugMarkInfo }
|
||||||
|
|
||||||
function TIDESynDebugMarkInfo.GetSrcLineToMarkLine(SrcIndex: Integer): Integer;
|
function TIDESynDebugMarkInfo.GetSrcLineToMarkLine(SrcIndex: Integer): Integer;
|
||||||
|
Loading…
Reference in New Issue
Block a user