Debugger, SourceEditor: Track Line changes during debug. Adjust breakpoints and executionline

git-svn-id: trunk@24569 -
This commit is contained in:
martin 2010-04-10 22:41:44 +00:00
parent 48c111460d
commit b60616fe5a
4 changed files with 121 additions and 14 deletions

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;