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