mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-10 22:16:17 +02:00
IDE: codeexplorer: show source editor node in implementation
git-svn-id: trunk@29981 -
This commit is contained in:
parent
cd8d49e9e6
commit
4f26caa11d
@ -2398,9 +2398,9 @@ function TCustomCodeTool.CaretToCleanPos(const Caret: TCodeXYPosition;
|
||||
out CleanPos: integer): integer;
|
||||
begin
|
||||
CleanPos:=0;
|
||||
//DebugLn('TCustomCodeTool.CaretToCleanPos A ',Caret.Code.Filename,' ',Caret.Code.SourceLength);
|
||||
//DebugLn(['TCustomCodeTool.CaretToCleanPos A ',Caret.Code.Filename,' ',Caret.Y,',',Caret.X,' ',Caret.Code.SourceLength]);
|
||||
Caret.Code.LineColToPosition(Caret.Y,Caret.X,CleanPos);
|
||||
//DebugLn('TCustomCodeTool.CaretToCleanPos B ',CleanPos,',',Caret.Y,',',Caret.X);
|
||||
//DebugLn(['TCustomCodeTool.CaretToCleanPos B ',CleanPos,',',Caret.Y,',',Caret.X,' ',dbgstr(copy(Caret.Code.Source,CleanPos-20,20)),'|',dbgstr(copy(Caret.Code.Source,CleanPos,20))]);
|
||||
if (CleanPos>=1) then
|
||||
Result:=Scanner.CursorToCleanPos(CleanPos,Caret.Code,CleanPos)
|
||||
else
|
||||
|
@ -419,6 +419,7 @@ type
|
||||
function LinkIndexAtCursorPos(ACursorPos: integer; ACode: Pointer): integer;
|
||||
function LinkSize(Index: integer): integer;
|
||||
function LinkCleanedEndPos(Index: integer): integer;
|
||||
function LinkSourceLog(Index: integer): TSourceLog;
|
||||
function FindFirstSiblingLink(LinkIndex: integer): integer;
|
||||
function FindParentLink(LinkIndex: integer): integer;
|
||||
function LinkIndexNearCursorPos(ACursorPos: integer; ACode: Pointer;
|
||||
@ -794,6 +795,14 @@ begin
|
||||
Result:=FLinks[Index].CleanedPos+LinkSize(Index);
|
||||
end;
|
||||
|
||||
function TLinkScanner.LinkSourceLog(Index: integer): TSourceLog;
|
||||
begin
|
||||
if Assigned(OnGetSource) then
|
||||
Result:=OnGetSource(Self,FLinks[Index].Code)
|
||||
else
|
||||
Result:=nil;
|
||||
end;
|
||||
|
||||
function TLinkScanner.FindFirstSiblingLink(LinkIndex: integer): integer;
|
||||
{ find link at the start of the code
|
||||
e.g. The resulting link SrcPos is always 1
|
||||
@ -3560,27 +3569,28 @@ function TLinkScanner.CursorToCleanPos(ACursorPos: integer; ACode: pointer;
|
||||
var
|
||||
i, j, SkippedCleanPos: integer;
|
||||
SkippedPos: boolean;
|
||||
Link: PSourceLink;
|
||||
begin
|
||||
i:=0;
|
||||
SkippedPos:=false;
|
||||
SkippedCleanPos:=-1;
|
||||
ACleanPos:=0;
|
||||
while i<LinkCount do begin
|
||||
//DebugLn('[TLinkScanner.CursorToCleanPos] A ACursorPos=',ACursorPos,', Code=',Links[i].Code=ACode,', Links[i].SrcPos=',Links[i].SrcPos,', Links[i].CleanedPos=',Links[i].CleanedPos);
|
||||
if (FLinks[i].Code=ACode) and (FLinks[i].SrcPos<=ACursorPos) then begin
|
||||
Link:=@FLinks[i];
|
||||
//DebugLn(['[TLinkScanner.CursorToCleanPos] A ACursorPos=',ACursorPos,', Code=',Link^.Code=ACode,', Link^.SrcPos=',Link^.SrcPos,', Link^.CleanedPos=',Link^.CleanedPos]);
|
||||
if (Link^.Code=ACode) and (Link^.SrcPos<=ACursorPos) then begin
|
||||
// link in same code found
|
||||
ACleanPos:=ACursorPos-FLinks[i].SrcPos+FLinks[i].CleanedPos;
|
||||
//DebugLn('[TLinkScanner.CursorToCleanPos] B ACleanPos=',ACleanPos);
|
||||
ACleanPos:=ACursorPos-Link^.SrcPos+Link^.CleanedPos;
|
||||
//DebugLn(['[TLinkScanner.CursorToCleanPos] Same code ACursorPos=',ACursorPos,', Code=',Link^.Code=ACode,', Link^.SrcPos=',Link^.SrcPos,', Link^.CleanedPos=',Link^.CleanedPos,' EndCleanPos=',Link^.CleanedPos+LinkSize(i)]);
|
||||
if i+1<LinkCount then begin
|
||||
// link has successor
|
||||
//DebugLn(['[TLinkScanner.CursorToCleanPos] C Links[i+1].CleanedPos=',Links[i+1].CleanedPos]);
|
||||
if ACleanPos<FLinks[i+1].CleanedPos then begin
|
||||
// link covers the cursor position
|
||||
//debugln(['TLinkScanner.CursorToCleanPos Found LinkStartInSrc="',dbgstr(copy(LinkSourceLog(i).Source,Link^.SrcPos,40)),'" LinkStartInCleanSrc="',dbgstr(copy(FCleanedSrc,Link^.CleanedPos,40)),'" CursorSrc="',dbgstr(copy(LinkSourceLog(i).Source,ACursorPos-20,20)),'|',dbgstr(copy(LinkSourceLog(i).Source,ACursorPos,20)),'" CleanCursorSrc="',dbgstr(copy(FCleanedSrc,ACleanPos-20,20)),'|',dbgstr(copy(FCleanedSrc,ACleanPos,20)),'"']);
|
||||
Result:=0; // valid position
|
||||
exit;
|
||||
end;
|
||||
// set found cleanpos to end of link
|
||||
ACleanPos:=FLinks[i].CleanedPos+LinkSize(i);
|
||||
// link does not cover the cursor position
|
||||
// find the next link in the same code
|
||||
j:=i+1;
|
||||
@ -3592,13 +3602,14 @@ begin
|
||||
// but because include files can be parsed multiple times,
|
||||
// search must continue
|
||||
SkippedPos:=true;
|
||||
SkippedCleanPos:=ACleanPos;
|
||||
// set found cleanpos to end of link
|
||||
SkippedCleanPos:=Link^.CleanedPos+LinkSize(i);
|
||||
end;
|
||||
// if this is an double included file,
|
||||
// this position can be in clean code -> search next
|
||||
end;
|
||||
// search next
|
||||
i:=j-1;
|
||||
i:=j;
|
||||
end else begin
|
||||
// in last link
|
||||
//DebugLn(['[TLinkScanner.CursorToCleanPos] E ACleanPos=',ACleanPos,' CleanedLen=',CleanedLen]);
|
||||
@ -3608,8 +3619,8 @@ begin
|
||||
end;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
inc(i);
|
||||
end else
|
||||
inc(i);
|
||||
end;
|
||||
if SkippedPos then begin
|
||||
Result:=-1;
|
||||
|
@ -147,6 +147,7 @@ type
|
||||
procedure IdleTimer1Timer(Sender: TObject);
|
||||
procedure JumpToMenuItemClick(Sender: TObject);
|
||||
procedure JumpToImplementationMenuItemClick(Sender: TObject);
|
||||
procedure ShowSrcEditPosMenuItemClick(Sender: TObject);
|
||||
procedure MainNotebookPageChanged(Sender: TObject);
|
||||
procedure ModeSpeedButtonClick(Sender: TObject);
|
||||
procedure OptionsSpeedButtonClick(Sender: TObject);
|
||||
@ -275,6 +276,7 @@ var
|
||||
CodeExplorerView: TCodeExplorerView = nil;
|
||||
CEJumpToIDEMenuCommand: TIDEMenuCommand;
|
||||
CEJumpToImplementationIDEMenuCommand: TIDEMenuCommand;
|
||||
CEShowSrcEditPosIDEMenuCommand: TIDEMenuCommand;
|
||||
CERefreshIDEMenuCommand: TIDEMenuCommand;
|
||||
CERenameIDEMenuCommand: TIDEMenuCommand;
|
||||
|
||||
@ -294,7 +296,7 @@ type
|
||||
|
||||
TViewNodeData = class
|
||||
public
|
||||
CTNode: TCodeTreeNode; // only valid during update, other times it is nil
|
||||
CTNode: TCodeTreeNode; // only valid during update, at other times it is nil
|
||||
Desc: TCodeTreeNodeDesc;
|
||||
SubDesc: TCodeTreeNodeSubDesc;
|
||||
StartPos, EndPos: integer;
|
||||
@ -366,6 +368,8 @@ begin
|
||||
);
|
||||
CEJumpToImplementationIDEMenuCommand:=RegisterIDEMenuCommand(Path,
|
||||
'Jump to implementation', lisMenuJumpToImplementation);
|
||||
CEShowSrcEditPosIDEMenuCommand:=RegisterIDEMenuCommand(Path, 'Show position of source editor',
|
||||
lisShowPositionOfSourceEditor);
|
||||
CERefreshIDEMenuCommand:=RegisterIDEMenuCommand(Path, 'Refresh',
|
||||
dlgUnitDepRefresh);
|
||||
CERenameIDEMenuCommand:=RegisterIDEMenuCommand(Path, 'Rename', lisFRIRename);
|
||||
@ -487,6 +491,7 @@ begin
|
||||
|
||||
CEJumpToIDEMenuCommand.OnClick:=@JumpToMenuItemClick;
|
||||
CEJumpToImplementationIDEMenuCommand.OnClick:=@JumpToImplementationMenuItemClick;
|
||||
CEShowSrcEditPosIDEMenuCommand.OnClick:=@ShowSrcEditPosMenuItemClick;
|
||||
CERefreshIDEMenuCommand.OnClick:=@RefreshMenuItemClick;
|
||||
CERenameIDEMenuCommand.OnClick:=@RenameMenuItemClick;
|
||||
|
||||
@ -576,6 +581,11 @@ begin
|
||||
JumpToSelection(true);
|
||||
end;
|
||||
|
||||
procedure TCodeExplorerView.ShowSrcEditPosMenuItemClick(Sender: TObject);
|
||||
begin
|
||||
SelectSourceEditorNode;
|
||||
end;
|
||||
|
||||
procedure TCodeExplorerView.MainNotebookPageChanged(Sender: TObject);
|
||||
begin
|
||||
Refresh(true);
|
||||
@ -654,7 +664,7 @@ begin
|
||||
end;
|
||||
CERenameIDEMenuCommand.Visible:=CanRename;
|
||||
CEJumpToImplementationIDEMenuCommand.Visible:=HasImplementation;
|
||||
DebugLn(['TCodeExplorerView.TreePopupmenuPopup ',CERenameIDEMenuCommand.Visible]);
|
||||
//DebugLn(['TCodeExplorerView.TreePopupmenuPopup ',CERenameIDEMenuCommand.Visible]);
|
||||
end;
|
||||
|
||||
procedure TCodeExplorerView.OnUserInput(Sender: TObject; Msg: Cardinal);
|
||||
@ -2101,9 +2111,13 @@ begin
|
||||
if CurrentPage=cepCode then begin
|
||||
if FLastCodeValid and (fLastCodeTool<>nil) then begin
|
||||
CodePos:=CodeXYPosition(X,Y,CodeBuf);
|
||||
CodeBuf.LineColToPosition(Y,X,CleanPos);
|
||||
//debugln(['TCodeExplorerView.SelectCodePosition Code ',ExtractFileName(CodeBuf.Filename),' y=',y,' x=',x,' CleanPos=',CleanPos,' ',dbgstr(copy(CodeBuf.Source,CleanPos-20,20)),'|',dbgstr(copy(CodeBuf.Source,CleanPos,20))]);
|
||||
if fLastCodeTool.CaretToCleanPos(CodePos,CleanPos)<>0 then exit;
|
||||
//debugln(['TCodeExplorerView.SelectCodePosition CleanSrc ',ExtractFileName(CodeBuf.Filename),' y=',y,' x=',x,' Tool=',ExtractFileName(fLastCodeTool.MainFilename),' ',dbgstr(copy(fLastCodeTool.Src,CleanPos-20,20)),'|',dbgstr(copy(fLastCodeTool.Src,CleanPos,20))]);
|
||||
TVNode:=FindCodeTVNodeAtCleanPos(CleanPos);
|
||||
if TVNode=nil then exit;
|
||||
//debugln(['TCodeExplorerView.SelectCodePosition ',TVNode.Text]);
|
||||
CodeTreeview.BeginUpdate;
|
||||
CodeTreeview.Options:=CodeTreeview.Options-[tvoAllowMultiselect];
|
||||
if not TVNode.IsVisible then begin
|
||||
@ -2115,6 +2129,7 @@ begin
|
||||
CodeTreeview.Selected:=TVNode;
|
||||
//debugln(['TCodeExplorerView.SelectCodePosition ',TVNode.Text]);
|
||||
end;
|
||||
//debugln(['TCodeExplorerView.SelectCodePosition TVNode=',TVNode.Text,' Selected=',CodeTreeview.Selected=TVNode]);
|
||||
CodeTreeview.EndUpdate;
|
||||
Result:=true;
|
||||
end;
|
||||
@ -2125,6 +2140,28 @@ function TCodeExplorerView.FindCodeTVNodeAtCleanPos(CleanPos: integer): TTreeNod
|
||||
// find TTreeNode in CodeTreeView containing the codetools clean position
|
||||
// if there are several nodes, the one with the shortest range (EndPos-StartPos)
|
||||
// is returned.
|
||||
var
|
||||
Best: TTreeNode;
|
||||
BestStartPos, BestEndPos: integer;
|
||||
|
||||
procedure Check(TVNode: TTreeNode; NodeData: TViewNodeData);
|
||||
begin
|
||||
if NodeData=nil then exit;
|
||||
if (NodeData.StartPos>CleanPos) or (NodeData.EndPos<CleanPos) then exit;
|
||||
//debugln(['FindCodeTVNodeAtCleanPos.Check TVNode="',TVNode.Text,'" NodeData="',dbgstr(copy(fLastCodeTool.Src,NodeData.StartPos,40)),'"']);
|
||||
if (Best<>nil) then begin
|
||||
if (BestEndPos=CleanPos) and (NodeData.EndPos>CleanPos) then begin
|
||||
// for example a,|b then b is better
|
||||
end else if BestEndPos-BestStartPos<NodeData.EndPos-NodeData.StartPos then begin
|
||||
// smaller range is better
|
||||
end else
|
||||
exit;
|
||||
end;
|
||||
Best:=TVNode;
|
||||
BestStartPos:=NodeData.StartPos;
|
||||
BestEndPos:=NodeData.EndPos;
|
||||
end;
|
||||
|
||||
var
|
||||
AVLNode: TAvgLvlTreeNode;
|
||||
Node: TTreeNode;
|
||||
@ -2133,23 +2170,21 @@ begin
|
||||
Result:=nil;
|
||||
if (fLastCodeTool=nil) or (not FLastCodeValid) or (CodeTreeview=nil)
|
||||
or (fCodeSortedForStartPos=nil) then exit;
|
||||
// find nearest node in tree
|
||||
|
||||
// find nearest node in tree
|
||||
Best:=nil;
|
||||
BestStartPos:=0;
|
||||
BestEndPos:=0;
|
||||
AVLNode:=fCodeSortedForStartPos.FindLowest;
|
||||
while AVLNode<>nil do begin
|
||||
Node:=TTreeNode(AVLNode.Data);
|
||||
NodeData:=TViewNodeData(Node.Data);
|
||||
//debugln(['TCodeExplorerView.FindCodeTVNodeAtCleanPos Node ',NodeData.StartPos,'-',NodeData.EndPos,' ',Node.Text,' ',CleanPos]);
|
||||
if NodeData.StartPos>CleanPos then exit;
|
||||
if NodeData.EndPos>=CleanPos then begin
|
||||
if (Result=nil)
|
||||
or (NodeData.EndPos-NodeData.StartPos
|
||||
< TViewNodeData(Result.Data).EndPos-TViewNodeData(Result.Data).StartPos)
|
||||
then
|
||||
Result:=Node;
|
||||
end;
|
||||
Check(Node,NodeData);
|
||||
Check(Node,NodeData.ImplementationNode);
|
||||
AVLNode:=fCodeSortedForStartPos.FindSuccessor(AVLNode);
|
||||
end;
|
||||
Result:=Best;
|
||||
end;
|
||||
|
||||
procedure TCodeExplorerView.BuildCodeSortedForStartPos;
|
||||
|
@ -5200,6 +5200,7 @@ resourcestring
|
||||
+'of class "%s"has created the error:%s"%s"';
|
||||
lisShowSetupDialogForMostImportantSettings = 'Show setup dialog for most '
|
||||
+'important settings';
|
||||
lisShowPositionOfSourceEditor = 'Show position of source editor';
|
||||
|
||||
implementation
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user