mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-19 01:49:25 +02:00
implemented Refactoring Tool: Find Identfier References
git-svn-id: trunk@6035 -
This commit is contained in:
parent
76c2c59c99
commit
62665cfd40
@ -67,6 +67,7 @@ procedure IndentText(const Source: string; Indent, TabWidth: integer;
|
||||
// identifiers
|
||||
procedure GetIdentStartEndAtPosition(const Source:string; Position:integer;
|
||||
var IdentStart,IdentEnd:integer);
|
||||
function GetIdentStartPosition(const Source:string; Position:integer): integer;
|
||||
function GetIdentLen(Identifier: PChar): integer;
|
||||
function GetIdentifier(Identifier: PChar): string;
|
||||
function FindNextIdentifier(const Source: string; StartPos, MaxPos: integer
|
||||
@ -1287,6 +1288,16 @@ begin
|
||||
inc(IdentEnd);
|
||||
end;
|
||||
|
||||
function GetIdentStartPosition(const Source: string; Position: integer
|
||||
): integer;
|
||||
begin
|
||||
Result:=Position;
|
||||
if (Result<1) or (Result>length(Source)) then exit;
|
||||
while (Result>1)
|
||||
and (IsIdChar[Source[Result-1]]) do
|
||||
dec(Result);
|
||||
end;
|
||||
|
||||
function GetIdentLen(Identifier: PChar): integer;
|
||||
begin
|
||||
Result:=0;
|
||||
|
@ -112,7 +112,7 @@ type
|
||||
function InitResourceTool: boolean;
|
||||
procedure ClearPositions;
|
||||
function GetCodeToolForSource(Code: TCodeBuffer;
|
||||
ExceptionOnError: boolean): TCustomCodeTool;
|
||||
GoToMainCode, ExceptionOnError: boolean): TCustomCodeTool;
|
||||
procedure SetAbortable(const AValue: boolean);
|
||||
procedure SetAddInheritedCodeToOverrideMethod(const AValue: boolean);
|
||||
procedure SetCheckFilesOnDisk(NewValue: boolean);
|
||||
@ -126,7 +126,7 @@ type
|
||||
procedure AfterApplyingChanges;
|
||||
function HandleException(AnException: Exception): boolean;
|
||||
function OnGetCodeToolForBuffer(Sender: TObject;
|
||||
Code: TCodeBuffer): TFindDeclarationTool;
|
||||
Code: TCodeBuffer; GoToMainCode: boolean): TFindDeclarationTool;
|
||||
procedure OnToolSetWriteLock(Lock: boolean);
|
||||
procedure OnToolGetWriteLockInfo(var WriteLockIsSet: boolean;
|
||||
var WriteLockStep: integer);
|
||||
@ -236,6 +236,10 @@ type
|
||||
|
||||
// data function
|
||||
procedure FreeListOfPCodeXYPosition(var List: TList);
|
||||
procedure FreeTreeOfPCodeXYPosition(var Tree: TAVLTree);
|
||||
function CreateTreeOfPCodeXYPosition: TAVLTree;
|
||||
procedure AddListToTreeOfPCodeXYPosition(SrcList: TList; DestTree: TAVLTree;
|
||||
ClearList, CreateCopies: boolean);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
@ -999,6 +1003,55 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TCodeToolManager.FreeTreeOfPCodeXYPosition(var Tree: TAVLTree);
|
||||
var
|
||||
ANode: TAVLTreeNode;
|
||||
CursorPos: PCodeXYPosition;
|
||||
begin
|
||||
if Tree=nil then exit;
|
||||
ANode:=Tree.FindLowest;
|
||||
while ANode<>nil do begin
|
||||
CursorPos:=PCodeXYPosition(ANode.Data);
|
||||
if CursorPos<>nil then
|
||||
Dispose(CursorPos);
|
||||
ANode:=Tree.FindSuccessor(ANode);
|
||||
end;
|
||||
Tree.Free;
|
||||
end;
|
||||
|
||||
function TCodeToolManager.CreateTreeOfPCodeXYPosition: TAVLTree;
|
||||
begin
|
||||
Result:=TAVLTree.Create(@CompareCodeXYPositions);
|
||||
end;
|
||||
|
||||
procedure TCodeToolManager.AddListToTreeOfPCodeXYPosition(SrcList: TList;
|
||||
DestTree: TAVLTree; ClearList, CreateCopies: boolean);
|
||||
var
|
||||
i: Integer;
|
||||
CodePos: PCodeXYPosition;
|
||||
NewCodePos: PCodeXYPosition;
|
||||
begin
|
||||
if SrcList=nil then exit;
|
||||
for i:=SrcList.Count-1 downto 0 do begin
|
||||
CodePos:=PCodeXYPosition(SrcList[i]);
|
||||
if DestTree.Find(CodePos)=nil then begin
|
||||
// new position -> add
|
||||
if CreateCopies and (not ClearList) then begin
|
||||
// list items should be kept and copies should be added to the tree
|
||||
New(NewCodePos);
|
||||
NewCodePos^:=CodePos^;
|
||||
end else
|
||||
NewCodePos:=CodePos;
|
||||
DestTree.Add(NewCodePos);
|
||||
end else if ClearList then begin
|
||||
// position alread exists and items should be deleted
|
||||
Dispose(NewCodePos);
|
||||
end;
|
||||
end;
|
||||
if ClearList then
|
||||
SrcList.Clear;
|
||||
end;
|
||||
|
||||
function TCodeToolManager.Explore(Code: TCodeBuffer;
|
||||
var ACodeTool: TCodeTool; WithStatements: boolean): boolean;
|
||||
begin
|
||||
@ -1032,7 +1085,7 @@ begin
|
||||
FErrorMsg:=Format(ctsNoScannerFound,[MainCode.Filename]);
|
||||
exit;
|
||||
end;
|
||||
FCurCodeTool:=TCodeTool(GetCodeToolForSource(MainCode,true));
|
||||
FCurCodeTool:=TCodeTool(GetCodeToolForSource(MainCode,false,true));
|
||||
FCurCodeTool.ErrorPosition.Code:=nil;
|
||||
{$IFDEF CTDEBUG}
|
||||
DebugLn('[TCodeToolManager.InitCurCodeTool] ',Code.Filename,' ',dbgs(Code.SourceLength));
|
||||
@ -1392,7 +1445,7 @@ begin
|
||||
CursorPos.Y:=NewY;
|
||||
CursorPos.Code:=NewCode;
|
||||
{$IFDEF CTDEBUG}
|
||||
DebugLn('TCodeToolManager.FindReferences B ',dbgs(FCurCodeTool.Scanner<>nil));
|
||||
DebugLn('TCodeToolManager.FindReferences B ',dbgs(FCurCodeTool.Scanner<>nil),' x=',dbgs(CursorPos.X),' y=',dbgs(CursorPos.Y),' ',CursorPos.Code.Filename);
|
||||
{$ENDIF}
|
||||
try
|
||||
Result:=FCurCodeTool.FindReferences(CursorPos,SkipComments,
|
||||
@ -2921,7 +2974,7 @@ begin
|
||||
end;
|
||||
|
||||
function TCodeToolManager.GetCodeToolForSource(Code: TCodeBuffer;
|
||||
ExceptionOnError: boolean): TCustomCodeTool;
|
||||
GoToMainCode, ExceptionOnError: boolean): TCustomCodeTool;
|
||||
// return a codetool for the source
|
||||
begin
|
||||
Result:=nil;
|
||||
@ -2931,6 +2984,8 @@ begin
|
||||
+'internal error: Code=nil');
|
||||
exit;
|
||||
end;
|
||||
if GoToMainCode then
|
||||
Code:=GetMainCode(Code);
|
||||
Result:=FindCodeToolForSource(Code);
|
||||
if Result=nil then begin
|
||||
CreateScanner(Code);
|
||||
@ -2977,14 +3032,14 @@ begin
|
||||
end;
|
||||
|
||||
function TCodeToolManager.OnGetCodeToolForBuffer(Sender: TObject;
|
||||
Code: TCodeBuffer): TFindDeclarationTool;
|
||||
Code: TCodeBuffer; GoToMainCode: boolean): TFindDeclarationTool;
|
||||
begin
|
||||
{$IFDEF CTDEBUG}
|
||||
DebugLn('[TCodeToolManager.OnGetCodeToolForBuffer]'
|
||||
,' Sender=',TCustomCodeTool(Sender).MainFilename
|
||||
,' Code=',Code.Filename);
|
||||
{$ENDIF}
|
||||
Result:=TFindDeclarationTool(GetCodeToolForSource(Code,true));
|
||||
Result:=TFindDeclarationTool(GetCodeToolForSource(Code,GoToMainCode,true));
|
||||
end;
|
||||
|
||||
procedure TCodeToolManager.ActivateWriteLock;
|
||||
|
@ -650,8 +650,8 @@ var
|
||||
{$ENDIF}
|
||||
ProcClassName:=ExtractClassNameOfProcNode(ProcNode);
|
||||
if ProcClassName='' then exit;
|
||||
ProcClassNode:=FindClassNodeInUnit(UpperCaseStr(ProcClassName),
|
||||
true,false,true);
|
||||
ProcClassNode:=FindClassNodeInUnit(ProcClassName,
|
||||
true,false,false,true);
|
||||
if ProcClassNode=nil then exit;
|
||||
ProcClassName:=ExtractClassName(ProcClassNode,false);
|
||||
end;
|
||||
|
@ -412,7 +412,7 @@ type
|
||||
TOnFindUsedUnit = function(SrcTool: TFindDeclarationTool;
|
||||
const TheUnitName, TheUnitInFilename: string): TCodeBuffer of object;
|
||||
TOnGetCodeToolForBuffer = function(Sender: TObject;
|
||||
Code: TCodeBuffer): TFindDeclarationTool of object;
|
||||
Code: TCodeBuffer; GoToMainCode: boolean): TFindDeclarationTool of object;
|
||||
|
||||
TFindDeclarationInput = record
|
||||
Flags: TFindDeclarationFlags;
|
||||
@ -666,7 +666,7 @@ type
|
||||
var ListOfPCodeXYPosition: TList): boolean;
|
||||
function FindReferences(const CursorPos: TCodeXYPosition;
|
||||
SkipComments: boolean; var ListOfPCodeXYPosition: TList): boolean;
|
||||
function CleanPosIsDeclaration(CleanPos: integer;
|
||||
function CleanPosIsDeclarationIdentifier(CleanPos: integer;
|
||||
Node: TCodeTreeNode): boolean;
|
||||
|
||||
function JumpToNode(ANode: TCodeTreeNode;
|
||||
@ -1018,11 +1018,13 @@ begin
|
||||
CursorNode:=BuildSubTreeAndFindDeepestNodeAtPos(Tree.Root,CleanCursorPos,
|
||||
true);
|
||||
if (fsfFindMainDeclaration in SearchSmartFlags)
|
||||
and CleanPosIsDeclaration(CleanCursorPos,CursorNode)
|
||||
and CleanPosIsDeclarationIdentifier(CleanCursorPos,CursorNode)
|
||||
then begin
|
||||
NewTool:=Self;
|
||||
NewNode:=CursorNode;
|
||||
Result:=JumpToNode(CursorNode,NewPos,NewTopLine,false);
|
||||
CleanCursorPos:=GetIdentStartPosition(Src,CleanCursorPos);
|
||||
Result:=JumpToCleanPos(CleanCursorPos,CleanCursorPos,CleanCursorPos,
|
||||
NewPos,NewTopLine,false);
|
||||
exit;
|
||||
end;
|
||||
CleanPosInFront:=CursorNode.StartPos;
|
||||
@ -2882,8 +2884,9 @@ function TFindDeclarationTool.FindReferences(const CursorPos: TCodeXYPosition;
|
||||
var
|
||||
Identifier: string;
|
||||
DeclarationTool: TFindDeclarationTool;
|
||||
CleanDeclCursorPos: integer;
|
||||
DeclarationNode: TCodeTreeNode;
|
||||
CleanDeclCursorPos: integer;
|
||||
AliasDeclarationNode: TCodeTreeNode;
|
||||
StartPos: Integer;
|
||||
Params: TFindDeclarationParams;
|
||||
PosTree: TAVLTree; // tree of PChar positions in Src
|
||||
@ -2891,53 +2894,8 @@ var
|
||||
ReferencePos: TCodeXYPosition;
|
||||
MaxPos: Integer;
|
||||
CursorNode: TCodeTreeNode;
|
||||
Found: Boolean;
|
||||
|
||||
function FindNextIdentifier(var StartPos: integer): boolean;
|
||||
var
|
||||
p: PChar;
|
||||
LastChar: Char;
|
||||
CurChar: Char;
|
||||
MaxP: PChar;
|
||||
begin
|
||||
Result:=false;
|
||||
if SkipComments then begin
|
||||
// search only in tokens
|
||||
MoveCursorToCleanPos(StartPos);
|
||||
repeat
|
||||
ReadNextAtom;
|
||||
if CurPos.StartPos>=MaxPos then exit;
|
||||
if CompareIdentifiers(PChar(Identifier),@Src[CurPos.StartPos])=0 then
|
||||
begin
|
||||
Result:=true;
|
||||
exit;
|
||||
end;
|
||||
until false;
|
||||
end else begin
|
||||
// search in clean source
|
||||
p:=@Src[StartPos];
|
||||
LastChar:=#0;
|
||||
MaxP:=@Src[MaxPos-1];
|
||||
while p<=MaxP do begin
|
||||
CurChar:=p^;
|
||||
if (CurChar=Identifier[1]) and (not IsIdentChar[LastChar]) then begin
|
||||
if CompareIdentifiers(PChar(Identifier),p)=0 then begin
|
||||
//debugln(' FindNextIdentifier ',Identifier,' ',GetIdentifier(p));
|
||||
Result:=true;
|
||||
break;
|
||||
end;
|
||||
end else if CurChar='''' then begin
|
||||
// skip string constants
|
||||
repeat
|
||||
inc(p);
|
||||
until (p^ in ['''',#10,#13]) or (p>MaxP);
|
||||
end;
|
||||
LastChar:=CurChar;
|
||||
inc(p);
|
||||
end;
|
||||
StartPos:=p-PChar(Src)+1;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure AddReference;
|
||||
var
|
||||
p: PChar;
|
||||
@ -2961,20 +2919,197 @@ var
|
||||
//debugln('TFindDeclarationTool.FindReferences.AddCodePosition line=',dbgs(NewCodePos.Y),' col=',dbgs(NewCodePos.X));
|
||||
end;
|
||||
|
||||
begin
|
||||
Result:=false;
|
||||
ListOfPCodeXYPosition:=nil;
|
||||
Params:=nil;
|
||||
PosTree:=nil;
|
||||
procedure ReadIdentifier(IsComment: boolean);
|
||||
var
|
||||
IdentEndPos: LongInt;
|
||||
begin
|
||||
IdentEndPos:=StartPos;
|
||||
while (IdentEndPos<=MaxPos) and (IsIdentChar[Src[IdentEndPos]]) do
|
||||
inc(IdentEndPos);
|
||||
//debugln('ReadIdentifier ',copy(Src,StartPos,IdentEndPos-StartPos));
|
||||
if (IdentEndPos-StartPos=length(Identifier))
|
||||
and (CompareIdentifiers(PChar(Identifier),@Src[StartPos])=0)
|
||||
and (IsComment or (not SkipComments)) then begin
|
||||
debugln('Identifier with same name found at: ',dbgs(StartPos),' ',GetIdentifier(@Src[StartPos]),' CleanDeclCursorPos=',dbgs(CleanDeclCursorPos),' ',dbgs(MaxPos));
|
||||
if CleanPosToCaret(StartPos,ReferencePos) then
|
||||
debugln(' x=',dbgs(ReferencePos.X),' y=',dbgs(ReferencePos.Y),' ',ReferencePos.Code.Filename);
|
||||
|
||||
ActivateGlobalWriteLock;
|
||||
try
|
||||
BuildTree(false);
|
||||
CursorNode:=BuildSubTreeAndFindDeepestNodeAtPos(Tree.Root,StartPos,true);
|
||||
debugln(' CursorNode=',CursorNode.DescAsString,' ',dbgs(CursorNode.SubDesc and ctnsForwardDeclaration));
|
||||
|
||||
// find declaration node and identifier
|
||||
if (DeclarationTool=Self)
|
||||
and ((StartPos=CleanDeclCursorPos) or (CursorNode=AliasDeclarationNode))
|
||||
then
|
||||
// declaration itself found
|
||||
AddReference
|
||||
else if CleanPosIsDeclarationIdentifier(StartPos,CursorNode) then
|
||||
// this identifier is another declaration with the same name
|
||||
else begin
|
||||
// find declaration
|
||||
if Params=nil then
|
||||
Params:=TFindDeclarationParams.Create
|
||||
else
|
||||
Params.Clear;
|
||||
Params.Flags:=[fdfSearchInParentNodes,fdfSearchInAncestors,
|
||||
fdfExceptionOnNotFound];
|
||||
Params.ContextNode:=CursorNode;
|
||||
//debugln(copy(Src,Params.ContextNode.StartPos,200));
|
||||
Params.SetIdentifier(Self,@Src[StartPos],@CheckSrcIdentifier);
|
||||
|
||||
if not IsComment then begin
|
||||
// search identifier
|
||||
Found:=FindDeclarationOfIdentAtCursor(Params);
|
||||
end else begin
|
||||
// search identifier in comment -> if not found, this is no bug
|
||||
// => silently ignore
|
||||
try
|
||||
Found:=FindDeclarationOfIdentAtCursor(Params);
|
||||
except
|
||||
on E: ECodeToolError do ;
|
||||
end;
|
||||
end;
|
||||
|
||||
if Found and (Params.NewNode<>nil) then begin
|
||||
if (Params.NewNode<>nil) and (Params.NewNode.Desc=ctnProcedure)
|
||||
and (Params.NewNode.FirstChild<>nil)
|
||||
and (Params.NewNode.FirstChild.Desc=ctnProcedureHead) then begin
|
||||
// Instead of jumping to the procedure keyword,
|
||||
// jump to the procedure name
|
||||
Params.NewNode:=Params.NewNode.FirstChild;
|
||||
Params.NewCleanPos:=Params.NewNode.StartPos;
|
||||
end;
|
||||
debugln('Context=',Params.NewNode.DescAsString,' ',dbgs(Params.NewNode.StartPos),' ',dbgs(DeclarationNode.StartPos));
|
||||
if (Params.NewNode=DeclarationNode)
|
||||
or (Params.NewNode=AliasDeclarationNode) then
|
||||
AddReference;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
StartPos:=IdentEndPos;
|
||||
end;
|
||||
|
||||
procedure SearchIdentifiers;
|
||||
var
|
||||
CommentLvl: Integer;
|
||||
InStrConst: Boolean;
|
||||
//CommentStart: LongInt;
|
||||
begin
|
||||
StartPos:=1;
|
||||
while StartPos<=MaxPos do begin
|
||||
case Src[StartPos] of
|
||||
|
||||
'{': // pascal comment
|
||||
begin
|
||||
//CommentStart:=StartPos;
|
||||
inc(StartPos);
|
||||
CommentLvl:=1;
|
||||
InStrConst:=false;
|
||||
while StartPos<=MaxPos do begin
|
||||
case Src[StartPos] of
|
||||
'{': if Scanner.NestedComments then inc(CommentLvl);
|
||||
'}':
|
||||
begin
|
||||
dec(CommentLvl);
|
||||
if CommentLvl=0 then break;
|
||||
end;
|
||||
'a'..'z','A'..'Z','_':
|
||||
if not InStrConst then begin
|
||||
ReadIdentifier(true);
|
||||
dec(StartPos);
|
||||
end;
|
||||
'''':
|
||||
InStrConst:=not InStrConst;
|
||||
end;
|
||||
inc(StartPos);
|
||||
end;
|
||||
inc(StartPos);
|
||||
//debugln(StartPos,' ',copy(Src,CommentStart,StartPos-CommentStart));
|
||||
end;
|
||||
|
||||
'/': // Delphi comment
|
||||
if (Src[StartPos+1]<>'/') then begin
|
||||
inc(StartPos);
|
||||
end else begin
|
||||
inc(StartPos,2);
|
||||
InStrConst:=false;
|
||||
while (StartPos<=MaxPos) do begin
|
||||
case Src[StartPos] of
|
||||
#10,#13:
|
||||
break;
|
||||
'a'..'z','A'..'Z','_':
|
||||
if not InStrConst then begin
|
||||
ReadIdentifier(true);
|
||||
dec(StartPos);
|
||||
end;
|
||||
'''':
|
||||
InStrConst:=not InStrConst;
|
||||
end;
|
||||
inc(StartPos);
|
||||
end;
|
||||
inc(StartPos);
|
||||
if (StartPos<=MaxPos) and (Src[StartPos] in [#10,#13])
|
||||
and (Src[StartPos-1]<>Src[StartPos]) then
|
||||
inc(StartPos);
|
||||
end;
|
||||
|
||||
'(': // turbo pascal comment
|
||||
if (Src[StartPos+1]<>'*') then begin
|
||||
inc(StartPos);
|
||||
end else begin
|
||||
inc(StartPos,3);
|
||||
InStrConst:=false;
|
||||
while (StartPos<=MaxPos) do begin
|
||||
case Src[StartPos] of
|
||||
')':
|
||||
if Src[StartPos-1]='*' then break;
|
||||
'a'..'z','A'..'Z','_':
|
||||
if not InStrConst then begin
|
||||
ReadIdentifier(true);
|
||||
dec(StartPos);
|
||||
end;
|
||||
'''':
|
||||
InStrConst:=not InStrConst;
|
||||
end;
|
||||
inc(StartPos);
|
||||
end;
|
||||
inc(StartPos);
|
||||
end;
|
||||
|
||||
'a'..'z','A'..'Z','_':
|
||||
ReadIdentifier(false);
|
||||
|
||||
'''':
|
||||
begin
|
||||
// skip string constant
|
||||
inc(StartPos);
|
||||
while (StartPos<=MaxPos) do begin
|
||||
if (not (Src[StartPos] in ['''',#10,#13])) then
|
||||
inc(StartPos)
|
||||
else begin
|
||||
inc(StartPos);
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
else
|
||||
inc(StartPos);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function FindDeclarationNode: boolean;
|
||||
const
|
||||
JumpToProcAttr = [phpInUpperCase,phpWithoutClassName,phpWithVarModifiers];
|
||||
var
|
||||
ProcNode: TCodeTreeNode;
|
||||
begin
|
||||
Result:=false;
|
||||
|
||||
// find the main declaration node and identifier
|
||||
DeclarationTool:=nil;
|
||||
if Assigned(FOnGetCodeToolForBuffer) then
|
||||
DeclarationTool:=FOnGetCodeToolForBuffer(Self,CursorPos.Code)
|
||||
DeclarationTool:=FOnGetCodeToolForBuffer(Self,CursorPos.Code,true)
|
||||
else if CursorPos.Code=TObject(Scanner.MainCode) then
|
||||
DeclarationTool:=Self;
|
||||
if DeclarationTool=nil then begin
|
||||
@ -2988,52 +3123,72 @@ begin
|
||||
Identifier:=DeclarationTool.ExtractIdentifier(CleanDeclCursorPos);
|
||||
if Identifier='' then exit;
|
||||
|
||||
// search identifiers
|
||||
MaxPos:=Tree.FindLastPosition;
|
||||
StartPos:=1;
|
||||
while FindNextIdentifier(StartPos) do begin
|
||||
//debugln('Identifier with same name found at: ',dbgs(StartPos),' ',GetIdentifier(@Src[StartPos]),' CleanDeclCursorPos=',dbgs(CleanDeclCursorPos),' ',dbgs(MaxPos));
|
||||
//if CleanPosToCaret(StartPos,ReferencePos) then
|
||||
//debugln(' x=',dbgs(ReferencePos.X),' y=',dbgs(ReferencePos.Y),' ',ReferencePos.Code.Filename);
|
||||
// find alias declaration node
|
||||
debugln('FindDeclarationNode DeclarationNode=',DeclarationNode.DescAsString);
|
||||
AliasDeclarationNode:=nil;
|
||||
case DeclarationNode.Desc of
|
||||
|
||||
CursorNode:=BuildSubTreeAndFindDeepestNodeAtPos(Tree.Root,StartPos,true);
|
||||
//debugln(' CursorNode=',CursorNode.DescAsString,' ',dbgs(CursorNode.SubDesc and ctnsForwardDeclaration));
|
||||
|
||||
if (DeclarationTool=Self) and (StartPos=CleanDeclCursorPos) then
|
||||
// declaration itself found
|
||||
AddReference
|
||||
else if CleanPosIsDeclaration(StartPos,CursorNode) then
|
||||
// this identifier is another declaration with the same name
|
||||
else begin
|
||||
// find declaration
|
||||
if Params=nil then
|
||||
Params:=TFindDeclarationParams.Create
|
||||
else
|
||||
Params.Clear;
|
||||
Params.Flags:=[fdfSearchInParentNodes,fdfSearchInAncestors,
|
||||
fdfExceptionOnNotFound];
|
||||
Params.ContextNode:=CursorNode;
|
||||
//debugln(copy(Src,Params.ContextNode.StartPos,200));
|
||||
Params.SetIdentifier(Self,@Src[StartPos],@CheckSrcIdentifier);
|
||||
if FindDeclarationOfIdentAtCursor(Params)
|
||||
and (Params.NewNode<>nil) then begin
|
||||
if (Params.NewNode<>nil) and (Params.NewNode.Desc=ctnProcedure)
|
||||
and (Params.NewNode.FirstChild<>nil)
|
||||
and (Params.NewNode.FirstChild.Desc=ctnProcedureHead) then begin
|
||||
// Instead of jumping to the procedure keyword,
|
||||
// jump to the procedure name
|
||||
Params.NewNode:=Params.NewNode.FirstChild;
|
||||
Params.NewCleanPos:=Params.NewNode.StartPos;
|
||||
ctnProcedure:
|
||||
AliasDeclarationNode:=FindCorrespondingProcNode(DeclarationNode,
|
||||
JumpToProcAttr);
|
||||
ctnProcedureHead:
|
||||
AliasDeclarationNode:=FindCorrespondingProcNode(DeclarationNode.Parent,
|
||||
JumpToProcAttr);
|
||||
ctnVarDefinition:
|
||||
if DeclarationNode.HasParentOfType(ctnProcedureHead) then begin
|
||||
ProcNode:=DeclarationNode.GetNodeOfType(ctnProcedure);
|
||||
// search alias for parameter
|
||||
ProcNode:=FindCorrespondingProcNode(ProcNode,JumpToProcAttr);
|
||||
if ProcNode<>nil then begin
|
||||
BuildSubTreeForProcHead(ProcNode);
|
||||
AliasDeclarationNode:=ProcNode;
|
||||
while (AliasDeclarationNode<>nil) do begin
|
||||
if AliasDeclarationNode.Desc
|
||||
in [ctnProcedure,ctnProcedureHead,ctnParameterList]
|
||||
then
|
||||
AliasDeclarationNode:=AliasDeclarationNode.FirstChild
|
||||
else begin
|
||||
if CompareIdentifiers(PChar(identifier),
|
||||
@Src[AliasDeclarationNode.StartPos])=0 then break;
|
||||
AliasDeclarationNode:=AliasDeclarationNode.NextBrother;
|
||||
end;
|
||||
end;
|
||||
//debugln('Context=',Params.NewNode.DescAsString,' ',dbgs(Params.NewNode.StartPos),' ',dbgs(DeclarationNode.StartPos));
|
||||
if (Params.NewNode=DeclarationNode) then
|
||||
AddReference;
|
||||
end;
|
||||
end;
|
||||
|
||||
inc(StartPos,length(Identifier));
|
||||
end;
|
||||
|
||||
if (AliasDeclarationNode<>nil) and (AliasDeclarationNode.Desc=ctnProcedure)
|
||||
and (AliasDeclarationNode.FirstChild<>nil)
|
||||
and (AliasDeclarationNode.FirstChild.Desc=ctnProcedureHead) then
|
||||
AliasDeclarationNode:=AliasDeclarationNode.FirstChild;
|
||||
if AliasDeclarationNode<>nil then begin
|
||||
debugln('FindDeclarationNode AliasDeclarationNode=',AliasDeclarationNode.DescAsString);
|
||||
end;
|
||||
|
||||
Result:=true;
|
||||
end;
|
||||
|
||||
begin
|
||||
Result:=false;
|
||||
debugln('FindReferences CursorPos=',CursorPos.Code.Filename,' x=',dbgs(CursorPos.X),' y=',dbgs(CursorPos.Y),' SkipComments=',dbgs(SkipComments));
|
||||
|
||||
ListOfPCodeXYPosition:=nil;
|
||||
Params:=nil;
|
||||
PosTree:=nil;
|
||||
|
||||
ActivateGlobalWriteLock;
|
||||
try
|
||||
BuildTree(false);
|
||||
|
||||
// find declaration nodes and identifier
|
||||
if not FindDeclarationNode then exit;
|
||||
|
||||
// search identifiers
|
||||
MaxPos:=Tree.FindLastPosition;
|
||||
if MaxPos>SrcLen then MaxPos:=SrcLen;
|
||||
SearchIdentifiers;
|
||||
|
||||
// create the reference list
|
||||
if PosTree<>nil then begin
|
||||
AVLNode:=PosTree.FindHighest;
|
||||
@ -3054,13 +3209,13 @@ begin
|
||||
end;
|
||||
|
||||
{-------------------------------------------------------------------------------
|
||||
function TFindDeclarationTool.CleanPosIsDeclaration(CleanPos: integer;
|
||||
function TFindDeclarationTool.CleanPosIsDeclarationIdentifier(CleanPos: integer;
|
||||
Node: TCodeTreeNode): boolean;
|
||||
|
||||
Node should be the deepest node at CleanPos, and all sub trees built.
|
||||
See BuildSubTree
|
||||
-------------------------------------------------------------------------------}
|
||||
function TFindDeclarationTool.CleanPosIsDeclaration(CleanPos: integer;
|
||||
function TFindDeclarationTool.CleanPosIsDeclarationIdentifier(CleanPos: integer;
|
||||
Node: TCodeTreeNode): boolean;
|
||||
|
||||
function InNodeIdentifier: boolean;
|
||||
@ -3085,7 +3240,7 @@ begin
|
||||
if Node=nil then exit;
|
||||
case Node.Desc of
|
||||
|
||||
ctnTypeDefinition,ctnVarDefinition,ctnConstDefinition:
|
||||
ctnTypeDefinition,ctnVarDefinition,ctnConstDefinition,ctnEnumIdentifier:
|
||||
begin
|
||||
if NodeIsForwardDeclaration(Node) then exit;
|
||||
Result:=InNodeIdentifier;
|
||||
@ -3096,7 +3251,7 @@ begin
|
||||
|
||||
ctnBeginBlock,ctnClass,ctnProcedure:
|
||||
if (Node.SubDesc and ctnsForwardDeclaration)>0 then
|
||||
RaiseException('TFindDeclarationTool.CleanPosIsDeclaration Node not expanded');
|
||||
RaiseException('TFindDeclarationTool.CleanPosIsDeclarationIdentifier Node not expanded');
|
||||
|
||||
end;
|
||||
end;
|
||||
@ -3835,7 +3990,7 @@ begin
|
||||
' NewCode=',NewCode.Filename);
|
||||
{$ENDIF}
|
||||
if Assigned(FOnGetCodeToolForBuffer) then
|
||||
Result:=FOnGetCodeToolForBuffer(Self,NewCode)
|
||||
Result:=FOnGetCodeToolForBuffer(Self,NewCode,false)
|
||||
else if NewCode=TCodeBuffer(Scanner.MainCode) then
|
||||
Result:=Self;
|
||||
end;
|
||||
@ -4010,7 +4165,7 @@ begin
|
||||
' NewCode=',NewCode.Filename,' IgnoreUsedUnits=',dbgs(fdfIgnoreUsedUnits in Params.Flags));
|
||||
{$ENDIF}
|
||||
if Assigned(FOnGetCodeToolForBuffer) then begin
|
||||
NewCodeTool:=FOnGetCodeToolForBuffer(Self,NewCode);
|
||||
NewCodeTool:=FOnGetCodeToolForBuffer(Self,NewCode,false);
|
||||
if NewCodeTool=nil then begin
|
||||
CurPos.StartPos:=-1;
|
||||
RaiseExceptionInstance(
|
||||
|
@ -37,8 +37,9 @@ uses
|
||||
{$IFDEF MEM_CHECK}
|
||||
MemCheck,
|
||||
{$ENDIF}
|
||||
Classes, SysUtils, CodeToolsStrConsts, CodeTree, CodeAtom, CustomCodeTool,
|
||||
PascalParserTool, KeywordFuncLists, BasicCodeTools, LinkScanner, AVL_Tree;
|
||||
Classes, SysUtils, FileProcs, CodeToolsStrConsts, CodeTree, CodeAtom,
|
||||
CustomCodeTool, PascalParserTool, KeywordFuncLists, BasicCodeTools,
|
||||
LinkScanner, AVL_Tree;
|
||||
|
||||
type
|
||||
TPascalReaderTool = class(TPascalParserTool)
|
||||
@ -84,6 +85,8 @@ type
|
||||
function GetProcNameIdentifier(ProcNode: TCodeTreeNode): PChar;
|
||||
function FindProcNode(StartNode: TCodeTreeNode; const AProcHead: string;
|
||||
Attr: TProcHeadAttributes): TCodeTreeNode;
|
||||
function FindCorrespondingProcNode(ProcNode: TCodeTreeNode;
|
||||
Attr: TProcHeadAttributes): TCodeTreeNode;
|
||||
function FindProcBody(ProcNode: TCodeTreeNode): TCodeTreeNode;
|
||||
procedure MoveCursorToFirstProcSpecifier(ProcNode: TCodeTreeNode);
|
||||
function MoveCursorToProcSpecifier(ProcNode: TCodeTreeNode;
|
||||
@ -100,16 +103,17 @@ type
|
||||
function ExtractClassInheritance(ClassNode: TCodeTreeNode;
|
||||
Attr: TProcHeadAttributes): string;
|
||||
function FindClassNode(StartNode: TCodeTreeNode;
|
||||
const UpperClassName: string;
|
||||
const AClassName: string;
|
||||
IgnoreForwards, IgnoreNonForwards: boolean): TCodeTreeNode;
|
||||
function FindClassSection(ClassNode: TCodeTreeNode;
|
||||
NodeDesc: TCodeTreeNodeDesc): TCodeTreeNode;
|
||||
function FindLastClassSection(ClassNode: TCodeTreeNode;
|
||||
NodeDesc: TCodeTreeNodeDesc): TCodeTreeNode;
|
||||
function FindClassNodeInInterface(const UpperClassName: string;
|
||||
IgnoreForwards, IgnoreNonForwards, ErrorOnNotFound: boolean): TCodeTreeNode;
|
||||
function FindClassNodeInUnit(const UpperClassName: string;
|
||||
function FindClassNodeInInterface(const AClassName: string;
|
||||
IgnoreForwards, IgnoreNonForwards, ErrorOnNotFound: boolean): TCodeTreeNode;
|
||||
function FindClassNodeInUnit(const AClassName: string;
|
||||
IgnoreForwards, IgnoreNonForwards, IgnoreImplementation,
|
||||
ErrorOnNotFound: boolean): TCodeTreeNode;
|
||||
function FindFirstIdentNodeInClass(ClassNode: TCodeTreeNode): TCodeTreeNode;
|
||||
function ClassSectionNodeStartsWithWord(ANode: TCodeTreeNode): boolean;
|
||||
|
||||
@ -534,6 +538,54 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TPascalReaderTool.FindCorrespondingProcNode(ProcNode: TCodeTreeNode;
|
||||
Attr: TProcHeadAttributes): TCodeTreeNode;
|
||||
var
|
||||
ClassNode: TCodeTreeNode;
|
||||
StartNode: TCodeTreeNode;
|
||||
ProcHead: String;
|
||||
begin
|
||||
Result:=nil;
|
||||
// get ctnProcedure
|
||||
//debugln('TPascalReaderTool.FindCorrespondingProcNode A');
|
||||
if (ProcNode=nil) then exit;
|
||||
if ProcNode.Desc=ctnProcedureHead then begin
|
||||
ProcNode:=ProcNode.Parent;
|
||||
if (ProcNode=nil) then exit;
|
||||
end;
|
||||
if ProcNode.Desc<>ctnProcedure then exit;
|
||||
|
||||
// check proc kind
|
||||
//debugln('TPascalReaderTool.FindCorrespondingProcNode B');
|
||||
ClassNode:=ProcNode.GetNodeOfType(ctnClass);
|
||||
if ClassNode<>nil then begin
|
||||
//debugln('TPascalReaderTool.FindCorrespondingProcNode C');
|
||||
// in a class definition -> search method body
|
||||
StartNode:=ClassNode.GetNodeOfType(ctnTypeSection)
|
||||
end else if NodeIsMethodBody(ProcNode) then begin
|
||||
//debugln('TPascalReaderTool.FindCorrespondingProcNode D');
|
||||
// in a method body -> search class
|
||||
StartNode:=FindClassNodeInUnit(ExtractClassNameOfProcNode(ProcNode),true,
|
||||
false,false,true);
|
||||
BuildSubTreeForClass(StartNode);
|
||||
while (StartNode<>nil)
|
||||
and (StartNode.Desc in [ctnClass,ctnClassInterface]+AllClassSections) do
|
||||
StartNode:=StartNode.FirstChild;
|
||||
//debugln('TPascalReaderTool.FindCorrespondingProcNode D2 ',StartNode.DescAsString);
|
||||
end else
|
||||
// else: search on same lvl
|
||||
StartNode:=FindFirstNodeOnSameLvl(ProcNode);
|
||||
if StartNode=nil then exit;
|
||||
|
||||
//debugln('TPascalReaderTool.FindCorrespondingProcNode E');
|
||||
ProcHead:=ExtractProcHead(ProcNode,Attr);
|
||||
Result:=FindProcNode(StartNode,ProcHead,Attr);
|
||||
if Result=ProcNode then begin
|
||||
StartNode:=FindNextNodeOnSameLvl(Result);
|
||||
Result:=FindProcNode(StartNode,ProcHead,Attr);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TPascalReaderTool.FindProcBody(ProcNode: TCodeTreeNode
|
||||
): TCodeTreeNode;
|
||||
begin
|
||||
@ -946,18 +998,18 @@ begin
|
||||
end;
|
||||
|
||||
function TPascalReaderTool.FindClassNode(StartNode: TCodeTreeNode;
|
||||
const UpperClassName: string; IgnoreForwards, IgnoreNonForwards: boolean
|
||||
const AClassName: string; IgnoreForwards, IgnoreNonForwards: boolean
|
||||
): TCodeTreeNode;
|
||||
// search for types on same level,
|
||||
// with type class and classname = SearchedClassName
|
||||
var CurClassName: string;
|
||||
var
|
||||
ANode, CurClassNode: TCodeTreeNode;
|
||||
begin
|
||||
ANode:=StartNode;
|
||||
Result:=nil;
|
||||
while (ANode<>nil) do begin
|
||||
if ANode.Desc=ctnTypeSection then begin
|
||||
Result:=FindClassNode(ANode.FirstChild,UpperClassName,IgnoreForwards,
|
||||
Result:=FindClassNode(ANode.FirstChild,AClassName,IgnoreForwards,
|
||||
IgnoreNonForwards);
|
||||
if Result<>nil then exit;
|
||||
end else if ANode.Desc=ctnTypeDefinition then begin
|
||||
@ -968,10 +1020,8 @@ begin
|
||||
and (not (IgnoreNonForwards
|
||||
and ((CurClassNode.SubDesc and ctnsForwardDeclaration)=0)))
|
||||
then begin
|
||||
MoveCursorToNodeStart(ANode);
|
||||
ReadNextAtom;
|
||||
CurClassName:=GetUpAtom;
|
||||
if UpperClassName=CurClassName then begin
|
||||
if CompareIdentifiers(PChar(AClassName),@Src[ANode.StartPos])=0
|
||||
then begin
|
||||
Result:=CurClassNode;
|
||||
exit;
|
||||
end;
|
||||
@ -1005,12 +1055,12 @@ begin
|
||||
end;
|
||||
|
||||
function TPascalReaderTool.FindClassNodeInInterface(
|
||||
const UpperClassName: string; IgnoreForwards, IgnoreNonForwards,
|
||||
const AClassName: string; IgnoreForwards, IgnoreNonForwards,
|
||||
ErrorOnNotFound: boolean): TCodeTreeNode;
|
||||
|
||||
procedure RaiseClassNotFound;
|
||||
begin
|
||||
RaiseExceptionFmt(ctsClassSNotFound, [UpperClassName]);
|
||||
RaiseExceptionFmt(ctsClassSNotFound, [AClassName]);
|
||||
end;
|
||||
|
||||
begin
|
||||
@ -1019,20 +1069,24 @@ begin
|
||||
if Result.Desc=ctnUnit then begin
|
||||
Result:=Result.NextBrother;
|
||||
end;
|
||||
if Result<>nil then
|
||||
Result:=FindClassNode(Result.FirstChild,UpperClassName,
|
||||
IgnoreForwards, IgnoreNonForwards);
|
||||
if Result<>nil then begin
|
||||
Result:=FindClassNode(Result.FirstChild,AClassName,
|
||||
IgnoreForwards, IgnoreNonForwards);
|
||||
if (Result<>nil) and Result.HasParentOfType(ctnImplementation) then
|
||||
Result:=nil;
|
||||
end;
|
||||
end;
|
||||
if (Result=nil) and ErrorOnNotFound then
|
||||
RaiseClassNotFound;
|
||||
end;
|
||||
|
||||
function TPascalReaderTool.FindClassNodeInUnit(const UpperClassName: string;
|
||||
IgnoreForwards, IgnoreNonForwards, ErrorOnNotFound: boolean): TCodeTreeNode;
|
||||
function TPascalReaderTool.FindClassNodeInUnit(const AClassName: string;
|
||||
IgnoreForwards, IgnoreNonForwards, IgnoreImplementation,
|
||||
ErrorOnNotFound: boolean): TCodeTreeNode;
|
||||
|
||||
procedure RaiseClassNotFound;
|
||||
begin
|
||||
RaiseExceptionFmt(ctsClassSNotFound, [UpperClassName]);
|
||||
RaiseExceptionFmt(ctsClassSNotFound, [AClassName]);
|
||||
end;
|
||||
|
||||
begin
|
||||
@ -1041,9 +1095,13 @@ begin
|
||||
if Result.Desc in [ctnUnit,ctnLibrary,ctnPackage] then begin
|
||||
Result:=Result.NextBrother;
|
||||
end;
|
||||
if Result<>nil then
|
||||
Result:=FindClassNode(Result.FirstChild,UpperClassName,
|
||||
IgnoreForwards, IgnoreNonForwards);
|
||||
if Result<>nil then begin
|
||||
Result:=FindClassNode(Result.FirstChild,AClassName,
|
||||
IgnoreForwards, IgnoreNonForwards);
|
||||
if (Result<>nil) and IgnoreImplementation
|
||||
and Result.HasParentOfType(ctnImplementation) then
|
||||
Result:=nil;
|
||||
end;
|
||||
end;
|
||||
if (Result=nil) and ErrorOnNotFound then
|
||||
RaiseClassNotFound;
|
||||
|
@ -3012,8 +3012,10 @@ begin
|
||||
NearestPos.Code:=nil;
|
||||
// get both codetools
|
||||
if not Assigned(OnGetCodeToolForBuffer) then exit;
|
||||
CursorTool:=TStandardCodeTool(OnGetCodeToolForBuffer(Self,CursorPos.Code));
|
||||
SectionTool:=TStandardCodeTool(OnGetCodeToolForBuffer(Self,SectionPos.Code));
|
||||
CursorTool:=
|
||||
TStandardCodeTool(OnGetCodeToolForBuffer(Self,CursorPos.Code,true));
|
||||
SectionTool:=
|
||||
TStandardCodeTool(OnGetCodeToolForBuffer(Self,SectionPos.Code,true));
|
||||
if (CursorTool=nil) or (SectionTool=nil) then exit;
|
||||
// get all resourcestring identifiers
|
||||
IdentTree:=nil;
|
||||
|
@ -17,7 +17,6 @@ object FindRenameIdentifierDialog: TFindRenameIdentifierDialog
|
||||
Caption = 'CurrentGroupBox'
|
||||
ClientHeight = 55
|
||||
ClientWidth = 432
|
||||
DragCursor = 65524
|
||||
ParentColor = True
|
||||
TabOrder = 0
|
||||
Left = 8
|
||||
@ -38,7 +37,6 @@ object FindRenameIdentifierDialog: TFindRenameIdentifierDialog
|
||||
Caption = 'NewGroupBox'
|
||||
ClientHeight = 36
|
||||
ClientWidth = 432
|
||||
DragCursor = 65524
|
||||
ParentColor = True
|
||||
TabOrder = 1
|
||||
Left = 8
|
||||
@ -60,7 +58,6 @@ object FindRenameIdentifierDialog: TFindRenameIdentifierDialog
|
||||
Anchors = [akTop, akRight]
|
||||
AutoSize = True
|
||||
Caption = 'RenameCheckBox'
|
||||
DragCursor = 65524
|
||||
OnChange = RenameCheckBoxChange
|
||||
TabOrder = 1
|
||||
UseOnChange = True
|
||||
@ -75,7 +72,6 @@ object FindRenameIdentifierDialog: TFindRenameIdentifierDialog
|
||||
Caption = 'ScopeGroupBox'
|
||||
ClientHeight = 187
|
||||
ClientWidth = 433
|
||||
DragCursor = 65524
|
||||
ParentColor = True
|
||||
TabOrder = 2
|
||||
Left = 8
|
||||
@ -87,7 +83,6 @@ object FindRenameIdentifierDialog: TFindRenameIdentifierDialog
|
||||
Anchors = [akTop, akLeft, akRight]
|
||||
AutoSize = True
|
||||
Caption = 'ScopeCommentsCheckBox'
|
||||
DragCursor = 65524
|
||||
TabOrder = 0
|
||||
Left = 6
|
||||
Height = 23
|
||||
@ -99,9 +94,10 @@ object FindRenameIdentifierDialog: TFindRenameIdentifierDialog
|
||||
Caption = 'ScopeRadioGroup'
|
||||
Enabled = False
|
||||
Items.Strings = (
|
||||
'In current Unit'
|
||||
'In current Project/Package'
|
||||
'In all open projects and packages'
|
||||
'in current unit'
|
||||
'in main project'
|
||||
'in project/package owning file'
|
||||
'in all open projects and packages'
|
||||
)
|
||||
ParentColor = True
|
||||
Left = 6
|
||||
@ -114,7 +110,6 @@ object FindRenameIdentifierDialog: TFindRenameIdentifierDialog
|
||||
Caption = 'ExtraFilesGroupBox'
|
||||
ClientHeight = 27
|
||||
ClientWidth = 413
|
||||
DragCursor = 65524
|
||||
Enabled = False
|
||||
ParentColor = True
|
||||
TabOrder = 2
|
||||
|
@ -9,41 +9,39 @@ LazarusResources.Add('TFindRenameIdentifierDialog','FORMDATA',[
|
||||
+#4'Left'#3'#'#1#6'Height'#3#144#1#3'Top'#3#163#0#5'Width'#3#194#1#0#9'TGroup'
|
||||
+'Box'#15'CurrentGroupBox'#7'Anchors'#11#5'akTop'#6'akLeft'#7'akRight'#0#7'Ca'
|
||||
+'ption'#6#15'CurrentGroupBox'#12'ClientHeight'#2'7'#11'ClientWidth'#3#176#1
|
||||
+#10'DragCursor'#4#244#255#0#0#11'ParentColor'#9#8'TabOrder'#2#0#4'Left'#2#8#6
|
||||
+'Height'#2'H'#3'Top'#2#8#5'Width'#3#180#1#0#8'TListBox'#14'CurrentListBox'#5
|
||||
+'Align'#7#8'alClient'#16'ClickOnSelChange'#8#8'TabOrder'#2#0#8'TopIndex'#2
|
||||
+#255#6'Height'#2'7'#5'Width'#3#176#1#0#0#0#9'TGroupBox'#11'NewGroupBox'#7'An'
|
||||
+'chors'#11#5'akTop'#6'akLeft'#7'akRight'#0#7'Caption'#6#11'NewGroupBox'#12'C'
|
||||
+'lientHeight'#2'$'#11'ClientWidth'#3#176#1#10'DragCursor'#4#244#255#0#0#11'P'
|
||||
+'arentColor'#9#8'TabOrder'#2#1#4'Left'#2#8#6'Height'#2'5'#3'Top'#2'['#5'Widt'
|
||||
+'h'#3#180#1#0#5'TEdit'#7'NewEdit'#7'Anchors'#11#5'akTop'#6'akLeft'#7'akRight'
|
||||
+#0#8'TabOrder'#2#0#4'Text'#6#7'NewEdit'#8'TabOrder'#2#0#4'Left'#2#6#6'Height'
|
||||
+#2#23#3'Top'#2#6#5'Width'#3#4#1#0#0#9'TCheckBox'#14'RenameCheckBox'#11'Allow'
|
||||
+'Grayed'#9#7'Anchors'#11#5'akTop'#7'akRight'#0#8'AutoSize'#9#7'Caption'#6#14
|
||||
+'RenameCheckBox'#10'DragCursor'#4#244#255#0#0#8'OnChange'#7#20'RenameCheckBo'
|
||||
+'xChange'#8'TabOrder'#2#1#11'UseOnChange'#9#4'Left'#3#18#1#6'Height'#2#23#3
|
||||
+'Top'#2#6#5'Width'#3#151#0#0#0#0#9'TGroupBox'#13'ScopeGroupBox'#7'Anchors'#11
|
||||
+#5'akTop'#6'akLeft'#7'akRight'#0#7'Caption'#6#13'ScopeGroupBox'#12'ClientHei'
|
||||
+'ght'#3#187#0#11'ClientWidth'#3#177#1#10'DragCursor'#4#244#255#0#0#11'Parent'
|
||||
+'Color'#9#8'TabOrder'#2#2#4'Left'#2#8#6'Height'#3#204#0#3'Top'#3#156#0#5'Wid'
|
||||
+'th'#3#181#1#0#9'TCheckBox'#21'ScopeCommentsCheckBox'#11'AllowGrayed'#9#7'An'
|
||||
+'chors'#11#5'akTop'#6'akLeft'#7'akRight'#0#8'AutoSize'#9#7'Caption'#6#21'Sco'
|
||||
+'peCommentsCheckBox'#10'DragCursor'#4#244#255#0#0#8'TabOrder'#2#0#4'Left'#2#6
|
||||
+#6'Height'#2#23#3'Top'#3#157#0#5'Width'#3#161#1#0#0#11'TRadioGroup'#15'Scope'
|
||||
+'RadioGroup'#7'Anchors'#11#5'akTop'#6'akLeft'#7'akRight'#0#7'Caption'#6#15'S'
|
||||
+'copeRadioGroup'#7'Enabled'#8#13'Items.Strings'#1#6#15'In current Unit'#6#26
|
||||
+'In current Project/Package'#6'!In all open projects and packages'#0#11'Pare'
|
||||
+'ntColor'#9#4'Left'#2#6#6'Height'#2'X'#3'Top'#2#5#5'Width'#3#161#1#0#0#9'TGr'
|
||||
+'oupBox'#18'ExtraFilesGroupBox'#7'Anchors'#11#5'akTop'#6'akLeft'#7'akRight'#0
|
||||
+#7'Caption'#6#18'ExtraFilesGroupBox'#12'ClientHeight'#2#27#11'ClientWidth'#3
|
||||
+#157#1#10'DragCursor'#4#244#255#0#0#7'Enabled'#8#11'ParentColor'#9#8'TabOrde'
|
||||
+'r'#2#2#4'Left'#2#6#6'Height'#2','#3'Top'#2'e'#5'Width'#3#161#1#0#5'TEdit'#14
|
||||
+'ExtraFilesEdit'#7'Anchors'#11#5'akTop'#6'akLeft'#7'akRight'#0#8'TabOrder'#2
|
||||
+#0#4'Text'#6#14'ExtraFilesEdit'#8'TabOrder'#2#0#4'Left'#2#6#6'Height'#2#23#5
|
||||
+'Width'#3#148#1#0#0#0#0#7'TButton'#18'FindOrRenameButton'#7'Anchors'#11#5'ak'
|
||||
+'Top'#7'akRight'#0#7'Caption'#6#18'FindOrRenameButton'#7'OnClick'#7#23'FindO'
|
||||
+'rRenameButtonClick'#8'TabOrder'#2#3#4'Left'#2'X'#6'Height'#2#25#3'Top'#3'p'
|
||||
+#1#5'Width'#3#233#0#0#0#7'TButton'#12'CancelButton'#7'Anchors'#11#5'akTop'#7
|
||||
+'akRight'#0#7'Caption'#6#12'CancelButton'#11'ModalResult'#2#2#8'TabOrder'#2#4
|
||||
+#11'ParentColor'#9#8'TabOrder'#2#0#4'Left'#2#8#6'Height'#2'H'#3'Top'#2#8#5'W'
|
||||
+'idth'#3#180#1#0#8'TListBox'#14'CurrentListBox'#5'Align'#7#8'alClient'#16'Cl'
|
||||
+'ickOnSelChange'#8#8'TabOrder'#2#0#8'TopIndex'#2#255#6'Height'#2'7'#5'Width'
|
||||
+#3#176#1#0#0#0#9'TGroupBox'#11'NewGroupBox'#7'Anchors'#11#5'akTop'#6'akLeft'
|
||||
+#7'akRight'#0#7'Caption'#6#11'NewGroupBox'#12'ClientHeight'#2'$'#11'ClientWi'
|
||||
+'dth'#3#176#1#11'ParentColor'#9#8'TabOrder'#2#1#4'Left'#2#8#6'Height'#2'5'#3
|
||||
+'Top'#2'['#5'Width'#3#180#1#0#5'TEdit'#7'NewEdit'#7'Anchors'#11#5'akTop'#6'a'
|
||||
+'kLeft'#7'akRight'#0#8'TabOrder'#2#0#4'Text'#6#7'NewEdit'#8'TabOrder'#2#0#4
|
||||
+'Left'#2#6#6'Height'#2#23#3'Top'#2#6#5'Width'#3#4#1#0#0#9'TCheckBox'#14'Rena'
|
||||
+'meCheckBox'#11'AllowGrayed'#9#7'Anchors'#11#5'akTop'#7'akRight'#0#8'AutoSiz'
|
||||
+'e'#9#7'Caption'#6#14'RenameCheckBox'#8'OnChange'#7#20'RenameCheckBoxChange'
|
||||
+#8'TabOrder'#2#1#11'UseOnChange'#9#4'Left'#3#18#1#6'Height'#2#23#3'Top'#2#6#5
|
||||
+'Width'#3#151#0#0#0#0#9'TGroupBox'#13'ScopeGroupBox'#7'Anchors'#11#5'akTop'#6
|
||||
+'akLeft'#7'akRight'#0#7'Caption'#6#13'ScopeGroupBox'#12'ClientHeight'#3#187#0
|
||||
+#11'ClientWidth'#3#177#1#11'ParentColor'#9#8'TabOrder'#2#2#4'Left'#2#8#6'Hei'
|
||||
+'ght'#3#204#0#3'Top'#3#156#0#5'Width'#3#181#1#0#9'TCheckBox'#21'ScopeComment'
|
||||
+'sCheckBox'#11'AllowGrayed'#9#7'Anchors'#11#5'akTop'#6'akLeft'#7'akRight'#0#8
|
||||
+'AutoSize'#9#7'Caption'#6#21'ScopeCommentsCheckBox'#8'TabOrder'#2#0#4'Left'#2
|
||||
+#6#6'Height'#2#23#3'Top'#3#157#0#5'Width'#3#161#1#0#0#11'TRadioGroup'#15'Sco'
|
||||
+'peRadioGroup'#7'Anchors'#11#5'akTop'#6'akLeft'#7'akRight'#0#7'Caption'#6#15
|
||||
+'ScopeRadioGroup'#7'Enabled'#8#13'Items.Strings'#1#6#15'in current unit'#6#15
|
||||
+'in main project'#6#30'in project/package owning file'#6'!in all open projec'
|
||||
+'ts and packages'#0#11'ParentColor'#9#4'Left'#2#6#6'Height'#2'X'#3'Top'#2#5#5
|
||||
+'Width'#3#161#1#0#0#9'TGroupBox'#18'ExtraFilesGroupBox'#7'Anchors'#11#5'akTo'
|
||||
+'p'#6'akLeft'#7'akRight'#0#7'Caption'#6#18'ExtraFilesGroupBox'#12'ClientHeig'
|
||||
+'ht'#2#27#11'ClientWidth'#3#157#1#7'Enabled'#8#11'ParentColor'#9#8'TabOrder'
|
||||
+#2#2#4'Left'#2#6#6'Height'#2','#3'Top'#2'e'#5'Width'#3#161#1#0#5'TEdit'#14'E'
|
||||
+'xtraFilesEdit'#7'Anchors'#11#5'akTop'#6'akLeft'#7'akRight'#0#8'TabOrder'#2#0
|
||||
+#4'Text'#6#14'ExtraFilesEdit'#8'TabOrder'#2#0#4'Left'#2#6#6'Height'#2#23#5'W'
|
||||
+'idth'#3#148#1#0#0#0#0#7'TButton'#18'FindOrRenameButton'#7'Anchors'#11#5'akT'
|
||||
+'op'#7'akRight'#0#7'Caption'#6#18'FindOrRenameButton'#7'OnClick'#7#23'FindOr'
|
||||
+'RenameButtonClick'#8'TabOrder'#2#3#4'Left'#2'X'#6'Height'#2#25#3'Top'#3'p'#1
|
||||
+#5'Width'#3#233#0#0#0#7'TButton'#12'CancelButton'#7'Anchors'#11#5'akTop'#7'a'
|
||||
+'kRight'#0#7'Caption'#6#12'CancelButton'#11'ModalResult'#2#2#8'TabOrder'#2#4
|
||||
+#4'Left'#3'P'#1#6'Height'#2#25#3'Top'#3'p'#1#5'Width'#2'Y'#0#0#0
|
||||
]);
|
||||
|
@ -32,7 +32,7 @@ interface
|
||||
uses
|
||||
Classes, SysUtils, LCLProc, LResources, Forms, Controls, Graphics, Dialogs,
|
||||
StdCtrls, Buttons, ExtCtrls,
|
||||
CodeAtom, CodeCache, CodeToolManager,
|
||||
AVL_Tree, CodeAtom, CodeCache, CodeToolManager,
|
||||
LazarusIDEStrConsts, IDEProcs, IDEOptionDefs, MiscOptions, DialogProcs,
|
||||
InputHistory, SearchResultView;
|
||||
|
||||
@ -64,6 +64,8 @@ type
|
||||
public
|
||||
procedure LoadFromConfig;
|
||||
procedure SaveToConfig;
|
||||
procedure LoadFromOptions(Options: TFindRenameIdentifierOptions);
|
||||
procedure SaveToOptions(Options: TFindRenameIdentifierOptions);
|
||||
procedure SetIdentifier(const NewIdentifierFilename: string;
|
||||
const NewIdentifierPosition: TPoint);
|
||||
property IdentifierFilename: string read FIdentifierFilename;
|
||||
@ -73,17 +75,22 @@ type
|
||||
|
||||
|
||||
function ShowFindRenameIdentifierDialog(const Filename: string;
|
||||
const Position: TPoint; AllowRename: boolean): TModalResult;
|
||||
const Position: TPoint; AllowRename: boolean;
|
||||
Options: TFindRenameIdentifierOptions): TModalResult;
|
||||
function GatherIdentifierReferences(Files: TStringList;
|
||||
DeclarationCode: TCodeBuffer; const DeclarationCaretXY: TPoint;
|
||||
SearchInComments: boolean): TModalResult;
|
||||
procedure ShowReferences(DeclarationCode: TCodeBuffer;
|
||||
const DeclarationCaretXY: TPoint; TargetCode: TCodeBuffer;
|
||||
ListOfPCodeXYPosition: TList);
|
||||
TreeOfPCodeXYPosition: TAVLTree; ClearItems: boolean; SearchPageIndex: integer);
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
|
||||
function ShowFindRenameIdentifierDialog(const Filename: string;
|
||||
const Position: TPoint; AllowRename: boolean): TModalResult;
|
||||
const Position: TPoint; AllowRename: boolean;
|
||||
Options: TFindRenameIdentifierOptions): TModalResult;
|
||||
var
|
||||
FindRenameIdentifierDialog: TFindRenameIdentifierDialog;
|
||||
begin
|
||||
@ -93,49 +100,138 @@ begin
|
||||
FindRenameIdentifierDialog.SetIdentifier(Filename,Position);
|
||||
FindRenameIdentifierDialog.AllowRename:=AllowRename;
|
||||
Result:=FindRenameIdentifierDialog.ShowModal;
|
||||
if Result=mrOk then
|
||||
if Options<>nil then
|
||||
FindRenameIdentifierDialog.SaveToOptions(Options);
|
||||
finally
|
||||
FindRenameIdentifierDialog.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
function GatherIdentifierReferences(Files: TStringList;
|
||||
DeclarationCode: TCodeBuffer; const DeclarationCaretXY: TPoint;
|
||||
SearchInComments: boolean): TModalResult;
|
||||
var
|
||||
i: Integer;
|
||||
SearchPageIndex: LongInt;
|
||||
LoadResult: TModalResult;
|
||||
Code: TCodeBuffer;
|
||||
ListOfPCodeXYPosition: TList;
|
||||
TreeOfPCodeXYPosition: TAVLTree;
|
||||
Identifier: string;
|
||||
OldSearchPageIndex: LongInt;
|
||||
begin
|
||||
Result:=mrCancel;
|
||||
ListOfPCodeXYPosition:=nil;
|
||||
TreeOfPCodeXYPosition:=nil;
|
||||
SearchPageIndex:=-1;
|
||||
try
|
||||
// sort files
|
||||
Files.Sort;
|
||||
// remove doubles
|
||||
i:=0;
|
||||
while i<=Files.Count-2 do begin
|
||||
while (i<=Files.Count-2) and (CompareFilenames(Files[i],Files[i+1])=0) do
|
||||
begin
|
||||
Files.Delete(i+1);
|
||||
end;
|
||||
inc(i);
|
||||
end;
|
||||
|
||||
// create a search result page
|
||||
CodeToolBoss.GetIdentifierAt(DeclarationCode,
|
||||
DeclarationCaretXY.X,DeclarationCaretXY.Y,Identifier);
|
||||
|
||||
|
||||
// search in every file
|
||||
for i:=0 to Files.Count-1 do begin
|
||||
LoadResult:=
|
||||
LoadCodeBuffer(Code,Files[i],[lbfCheckIfText,lbfUpdateFromDisk]);
|
||||
if LoadResult=mrAbort then exit;
|
||||
if LoadResult<>mrOk then continue;
|
||||
|
||||
// create search page
|
||||
if SearchPageIndex<0 then begin
|
||||
SearchPageIndex:=SearchResultsView.AddResult(
|
||||
'References of '+Identifier,
|
||||
Identifier,
|
||||
ExtractFilePath(Code.Filename),
|
||||
'*.pas;*.pp;*.inc',
|
||||
[fifWholeWord,fifSearchDirectories]);
|
||||
if SearchPageIndex<0 then exit;
|
||||
SearchResultsView.BeginUpdate(SearchPageIndex);
|
||||
end;
|
||||
|
||||
// search references
|
||||
CodeToolBoss.FreeListOfPCodeXYPosition(ListOfPCodeXYPosition);
|
||||
if not CodeToolBoss.FindReferences(
|
||||
DeclarationCode,DeclarationCaretXY.X,DeclarationCaretXY.Y,
|
||||
Code, not SearchInComments, ListOfPCodeXYPosition) then
|
||||
begin
|
||||
Result:=mrAbort;
|
||||
exit;
|
||||
end;
|
||||
|
||||
// add to tree
|
||||
if ListOfPCodeXYPosition<>nil then begin
|
||||
if TreeOfPCodeXYPosition=nil then
|
||||
TreeOfPCodeXYPosition:=CodeToolBoss.CreateTreeOfPCodeXYPosition;
|
||||
CodeToolBoss.AddListToTreeOfPCodeXYPosition(ListOfPCodeXYPosition,
|
||||
TreeOfPCodeXYPosition,true,false);
|
||||
end;
|
||||
end;
|
||||
|
||||
// show result
|
||||
ShowReferences(DeclarationCode,DeclarationCaretXY,
|
||||
Code,TreeOfPCodeXYPosition,false,SearchPageIndex);
|
||||
OldSearchPageIndex:=SearchPageIndex;
|
||||
SearchPageIndex:=-1;
|
||||
SearchResultsView.EndUpdate(OldSearchPageIndex);
|
||||
SearchResultsView.ShowOnTop;
|
||||
finally
|
||||
if SearchPageIndex>=0 then
|
||||
SearchResultsView.EndUpdate(SearchPageIndex);
|
||||
CodeToolBoss.FreeListOfPCodeXYPosition(ListOfPCodeXYPosition);
|
||||
CodeToolBoss.FreeTreeOfPCodeXYPosition(TreeOfPCodeXYPosition);
|
||||
end;
|
||||
Result:=mrOk;
|
||||
end;
|
||||
|
||||
procedure ShowReferences(DeclarationCode: TCodeBuffer;
|
||||
const DeclarationCaretXY: TPoint; TargetCode: TCodeBuffer;
|
||||
ListOfPCodeXYPosition: TList);
|
||||
TreeOfPCodeXYPosition: TAVLTree; ClearItems: boolean;
|
||||
SearchPageIndex: integer);
|
||||
var
|
||||
Identifier: string;
|
||||
SearchPageIndex: LongInt;
|
||||
i: Integer;
|
||||
CodePos: PCodeXYPosition;
|
||||
CurLine: String;
|
||||
TrimmedLine: String;
|
||||
TrimCnt: Integer;
|
||||
ANode: TAVLTreeNode;
|
||||
begin
|
||||
CodeToolBoss.GetIdentifierAt(DeclarationCode,
|
||||
DeclarationCaretXY.X,DeclarationCaretXY.Y,Identifier);
|
||||
SearchPageIndex:=SearchResultsView.AddResult(
|
||||
'References of '+Identifier,
|
||||
Identifier,
|
||||
ExtractFilePath(TargetCode.Filename),
|
||||
'*.pas;*.pp;*.inc',
|
||||
[fifWholeWord,fifSearchDirectories]);
|
||||
|
||||
SearchResultsView.BeginUpdate(SearchPageIndex);
|
||||
SearchResultsView.Items[SearchPageIndex].Clear;
|
||||
if (ListOfPCodeXYPosition<>nil) then
|
||||
for i:=0 to ListOfPCodeXYPosition.Count-1 do begin
|
||||
CodePos:=PCodeXYPosition(ListOfPCodeXYPosition[i]);
|
||||
if ClearItems then
|
||||
SearchResultsView.Items[SearchPageIndex].Clear;
|
||||
if (TreeOfPCodeXYPosition<>nil) then begin
|
||||
ANode:=TreeOfPCodeXYPosition.FindLowest;
|
||||
while ANode<>nil do begin
|
||||
CodePos:=PCodeXYPosition(ANode.Data);
|
||||
CurLine:=TrimRight(CodePos^.Code.GetLine(CodePos^.Y-1));
|
||||
TrimmedLine:=Trim(CurLine);
|
||||
TrimCnt:=length(CurLine)-length(TrimmedLine);
|
||||
//debugln('ShowReferences x=',dbgs(CodePos^.x),' y=',dbgs(CodePos^.y),' ',CurLine);
|
||||
SearchResultsView.AddMatch(SearchPageIndex,
|
||||
TargetCode.Filename,
|
||||
CodePos^.Code.Filename,
|
||||
Point(CodePos^.X,CodePos^.Y),
|
||||
TrimmedLine,
|
||||
CodePos^.X-TrimCnt, length(Identifier));
|
||||
ANode:=TreeOfPCodeXYPosition.FindSuccessor(ANode);
|
||||
end;
|
||||
end;
|
||||
SearchResultsView.EndUpdate(SearchPageIndex);
|
||||
SearchResultsView.ShowOnTop;
|
||||
end;
|
||||
|
||||
{ TFindRenameIdentifierDialog }
|
||||
@ -156,7 +252,11 @@ begin
|
||||
ScopeCommentsCheckBox.Caption:='Search in comments too';
|
||||
ScopeGroupBox.Caption:='Search where';
|
||||
ScopeRadioGroup.Caption:='Scope';
|
||||
|
||||
ScopeRadioGroup.Items[0]:='in current unit';
|
||||
ScopeRadioGroup.Items[1]:='in main project';
|
||||
ScopeRadioGroup.Items[2]:='in project/package owning current unit';
|
||||
ScopeRadioGroup.Items[3]:='in all open packages and projects';
|
||||
|
||||
LoadFromConfig;
|
||||
end;
|
||||
|
||||
@ -203,29 +303,37 @@ begin
|
||||
end;
|
||||
|
||||
procedure TFindRenameIdentifierDialog.LoadFromConfig;
|
||||
var
|
||||
Options: TFindRenameIdentifierOptions;
|
||||
begin
|
||||
Options:=MiscellaneousOptions.FindRenameIdentifierOptions;
|
||||
LoadFromOptions(MiscellaneousOptions.FindRenameIdentifierOptions);
|
||||
end;
|
||||
|
||||
procedure TFindRenameIdentifierDialog.SaveToConfig;
|
||||
begin
|
||||
SaveToOptions(MiscellaneousOptions.FindRenameIdentifierOptions);
|
||||
end;
|
||||
|
||||
procedure TFindRenameIdentifierDialog.LoadFromOptions(
|
||||
Options: TFindRenameIdentifierOptions);
|
||||
begin
|
||||
RenameCheckBox.Checked:=Options.Rename;
|
||||
ExtraFilesEdit.Text:=StringListToText(Options.ExtraFiles,';',true);
|
||||
NewEdit.Text:=Options.RenameTo;
|
||||
ScopeCommentsCheckBox.Checked:=Options.SearchInComments;
|
||||
case Options.Scope of
|
||||
frCurrentUnit: ScopeRadioGroup.ItemIndex:=0;
|
||||
frCurrentProjectPackage: ScopeRadioGroup.ItemIndex:=1;
|
||||
frProject: ScopeRadioGroup.ItemIndex:=1;
|
||||
frOwnerProjectPackage: ScopeRadioGroup.ItemIndex:=2;
|
||||
else
|
||||
ScopeRadioGroup.ItemIndex:=2;
|
||||
ScopeRadioGroup.ItemIndex:=3;
|
||||
end;
|
||||
UpdateRename;
|
||||
end;
|
||||
|
||||
procedure TFindRenameIdentifierDialog.SaveToConfig;
|
||||
procedure TFindRenameIdentifierDialog.SaveToOptions(
|
||||
Options: TFindRenameIdentifierOptions);
|
||||
var
|
||||
Options: TFindRenameIdentifierOptions;
|
||||
ExtraFileList: TStringList;
|
||||
begin
|
||||
Options:=MiscellaneousOptions.FindRenameIdentifierOptions;
|
||||
Options.Rename:=RenameCheckBox.Checked;
|
||||
ExtraFileList:=SplitString(ExtraFilesEdit.Text,';');
|
||||
Options.ExtraFiles.Assign(ExtraFileList);
|
||||
@ -234,7 +342,8 @@ begin
|
||||
Options.SearchInComments:=ScopeCommentsCheckBox.Checked;
|
||||
case ScopeRadioGroup.ItemIndex of
|
||||
0: Options.Scope:=frCurrentUnit;
|
||||
1: Options.Scope:=frCurrentProjectPackage;
|
||||
1: Options.Scope:=frProject;
|
||||
2: Options.Scope:=frOwnerProjectPackage;
|
||||
else Options.Scope:=frAllOpenProjectsAndPackages;
|
||||
end;
|
||||
end;
|
||||
|
77
ide/main.pp
77
ide/main.pp
@ -63,7 +63,8 @@ uses
|
||||
Forms, Buttons, Menus, FileCtrl, Controls, GraphType, Graphics, ExtCtrls,
|
||||
Dialogs,
|
||||
// codetools
|
||||
Laz_XMLCfg, CodeToolsStructs, CodeToolManager, CodeCache, DefineTemplates,
|
||||
AVL_Tree, Laz_XMLCfg, CodeToolsStructs, CodeToolManager, CodeCache,
|
||||
DefineTemplates,
|
||||
// IDE interface
|
||||
AllIDEIntf, ObjectInspector, PropEdits, IDECommands, SrcEditorIntf,
|
||||
// synedit
|
||||
@ -9250,54 +9251,79 @@ end;
|
||||
-------------------------------------------------------------------------------}
|
||||
procedure TMainIDE.DoFindIdentifierReferences;
|
||||
var
|
||||
ActiveSrcEdit, DeclarationSrcEdit: TSourceEditor;
|
||||
ActiveUnitInfo, DeclarationUnitInfo: TUnitInfo;
|
||||
TargetSrcEdit, DeclarationSrcEdit: TSourceEditor;
|
||||
TargetUnitInfo, DeclarationUnitInfo: TUnitInfo;
|
||||
NewSource: TCodeBuffer;
|
||||
NewX, NewY, NewTopLine: integer;
|
||||
LogCaretXY, DeclarationCaretXY: TPoint;
|
||||
ListOfPCodeXYPosition: TList;
|
||||
Options: TFindRenameIdentifierOptions;
|
||||
OwnerList: TList;
|
||||
ExtraFiles: TStrings;
|
||||
Files: TStringList;
|
||||
begin
|
||||
if not BeginCodeTool(ActiveSrcEdit,ActiveUnitInfo,[]) then exit;
|
||||
if not BeginCodeTool(TargetSrcEdit,TargetUnitInfo,[]) then exit;
|
||||
|
||||
// find the main declaration
|
||||
LogCaretXY:=ActiveSrcEdit.EditorComponent.LogicalCaretXY;
|
||||
if not CodeToolBoss.FindMainDeclaration(ActiveUnitInfo.Source,
|
||||
LogCaretXY:=TargetSrcEdit.EditorComponent.LogicalCaretXY;
|
||||
if not CodeToolBoss.FindMainDeclaration(TargetUnitInfo.Source,
|
||||
LogCaretXY.X,LogCaretXY.Y,
|
||||
NewSource,NewX,NewY,NewTopLine) then
|
||||
begin
|
||||
DoJumpToCodeToolBossError;
|
||||
exit;
|
||||
end;
|
||||
DoJumpToCodePos(ActiveSrcEdit, ActiveUnitInfo,
|
||||
DoJumpToCodePos(TargetSrcEdit, TargetUnitInfo,
|
||||
NewSource, NewX, NewY, NewTopLine, true);
|
||||
GetCurrentUnit(DeclarationSrcEdit,DeclarationUnitInfo);
|
||||
DeclarationCaretXY:=DeclarationSrcEdit.EditorComponent.LogicalCaretXY;
|
||||
|
||||
debugln('TMainIDE.DoFindIdentifierReferences A DeclarationCaretXY=x=',dbgs(DeclarationCaretXY.X),' y=',dbgs(DeclarationCaretXY.Y));
|
||||
|
||||
// let user choose the search scope
|
||||
if ShowFindRenameIdentifierDialog(DeclarationUnitInfo.Source.Filename,
|
||||
LogCaretXY,false)<>mrOk
|
||||
DeclarationCaretXY,false,nil)<>mrOk
|
||||
then exit;
|
||||
|
||||
ListOfPCodeXYPosition:=nil;
|
||||
Files:=nil;
|
||||
OwnerList:=nil;
|
||||
try
|
||||
// search
|
||||
if not CodeToolBoss.FindReferences(
|
||||
DeclarationUnitInfo.Source,DeclarationCaretXY.X,DeclarationCaretXY.Y,
|
||||
ActiveUnitInfo.Source,
|
||||
not MiscellaneousOptions.FindRenameIdentifierOptions.SearchInComments,
|
||||
ListOfPCodeXYPosition) then
|
||||
begin
|
||||
DoJumpToCodeToolBossError;
|
||||
exit;
|
||||
// create the file list
|
||||
Files:=TStringList.Create;
|
||||
Files.Add(TargetUnitInfo.Filename);
|
||||
|
||||
Options:=MiscellaneousOptions.FindRenameIdentifierOptions;
|
||||
case Options.Scope of
|
||||
|
||||
frProject,frOwnerProjectPackage,frAllOpenProjectsAndPackages:
|
||||
begin
|
||||
if Options.Scope=frProject then begin
|
||||
OwnerList:=TList.Create;
|
||||
OwnerList.Add(Project1);
|
||||
end else begin
|
||||
OwnerList:=PkgBoss.GetOwnersOfUnit(TargetUnitInfo.Filename);
|
||||
if Options.Scope=frAllOpenProjectsAndPackages then begin
|
||||
// TODO
|
||||
end;
|
||||
end;
|
||||
ExtraFiles:=PkgBoss.GetSourceFilesOfOwners(OwnerList);
|
||||
try
|
||||
if ExtraFiles<>nil then
|
||||
Files.AddStrings(ExtraFiles);
|
||||
finally
|
||||
ExtraFiles.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
// show result
|
||||
CreateSearchResultWindow;
|
||||
ShowReferences(DeclarationUnitInfo.Source,DeclarationCaretXY,
|
||||
ActiveUnitInfo.Source,ListOfPCodeXYPosition);
|
||||
GatherIdentifierReferences(Files,DeclarationUnitInfo.Source,
|
||||
DeclarationCaretXY,Options.SearchInComments);
|
||||
if CodeToolBoss.ErrorMessage<>'' then
|
||||
DoJumpToCodeToolBossError;
|
||||
|
||||
finally
|
||||
CodeToolBoss.FreeListOfPCodeXYPosition(ListOfPCodeXYPosition);
|
||||
Files.Free;
|
||||
OwnerList.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -10782,6 +10808,9 @@ end.
|
||||
|
||||
{ =============================================================================
|
||||
$Log$
|
||||
Revision 1.774 2004/09/20 20:22:11 mattias
|
||||
implemented Refactoring Tool: Find Identfier References
|
||||
|
||||
Revision 1.773 2004/09/18 01:02:23 mattias
|
||||
started new feature: find identifier references
|
||||
|
||||
|
@ -38,7 +38,8 @@ type
|
||||
|
||||
TFindRenameScope = (
|
||||
frCurrentUnit,
|
||||
frCurrentProjectPackage, // the project/package the current unit beongs to
|
||||
frOwnerProjectPackage, // the project/package the current unit beongs to
|
||||
frProject,
|
||||
frAllOpenProjectsAndPackages
|
||||
);
|
||||
|
||||
@ -97,7 +98,8 @@ const
|
||||
ResourcestringInsertPolicyNames: array[TResourcestringInsertPolicy] of string
|
||||
= ('None', 'Append', 'Alphabetically', 'Context');
|
||||
FindRenameScopeNames: array[TFindRenameScope] of string = (
|
||||
'CurrentUnit', 'CurrentProjectPackage', 'AllOpenProjectsAndPackages'
|
||||
'CurrentUnit', 'Project', 'OwnerProjectPackage',
|
||||
'AllOpenProjectsAndPackages'
|
||||
);
|
||||
|
||||
var MiscellaneousOptions: TMiscellaneousOptions;
|
||||
|
@ -121,7 +121,7 @@ type
|
||||
WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
|
||||
private
|
||||
function PageExists(const APageName: string): boolean;
|
||||
function GetPageIndex(APageName: string): integer;
|
||||
function GetPageIndex(const APageName: string): integer;
|
||||
function GetListBox(APageIndex: integer): TLazSearchResultLB;
|
||||
procedure ListBoxClicked(Sender: TObject);
|
||||
procedure ListBoxDoubleClicked(Sender: TObject);
|
||||
@ -277,10 +277,12 @@ begin
|
||||
if Assigned(CurrentLB) then
|
||||
begin
|
||||
CurrentLB.EndUpdate;
|
||||
CurrentLB.ItemIndex:= 0;
|
||||
CurrentLB.TopIndex:= 0;
|
||||
end;//if
|
||||
end;//EndUpdate
|
||||
if CurrentLB.Items.Count>0 then begin
|
||||
CurrentLB.ItemIndex:= 0;
|
||||
CurrentLB.TopIndex:= 0;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
{Brings the results tab named APageName to front.
|
||||
If APageName does not exist, does nothing}
|
||||
@ -607,7 +609,7 @@ begin
|
||||
end;//if
|
||||
end;
|
||||
|
||||
function TSearchResultsView.GetPageIndex(APageName: string): integer;
|
||||
function TSearchResultsView.GetPageIndex(const APageName: string): integer;
|
||||
var
|
||||
i: integer;
|
||||
begin
|
||||
|
@ -45,6 +45,8 @@ type
|
||||
public
|
||||
function AddUnitDependenciesForComponentClasses(const UnitFilename: string;
|
||||
ComponentClassnames: TStrings): TModalResult; virtual; abstract;
|
||||
function GetOwnersOfUnit(const UnitFilename: string): TList; virtual; abstract;
|
||||
function GetSourceFilesOfOwners(OwnerList: TList): TStrings; virtual; abstract;
|
||||
end;
|
||||
|
||||
var
|
||||
|
@ -125,7 +125,8 @@ end;
|
||||
|
||||
{-------------------------------------------------------------------------------
|
||||
Procedure DragInitControl(Control : TControl; Immediate : Boolean;
|
||||
|
||||
Threshold: Integer);
|
||||
|
||||
Initializes the dragging. If Immediate=True it starts the dragging, otherwise
|
||||
it will be started when the user moves the mouse more than DragThreshold
|
||||
pixel.
|
||||
@ -361,6 +362,9 @@ end;
|
||||
|
||||
{ =============================================================================
|
||||
$Log$
|
||||
Revision 1.6 2004/09/20 20:22:12 mattias
|
||||
implemented Refactoring Tool: Find Identfier References
|
||||
|
||||
Revision 1.5 2004/06/01 09:58:35 mattias
|
||||
implemented setting TCustomPage.PageIndex from Andrew Haines
|
||||
|
||||
|
@ -181,8 +181,9 @@ type
|
||||
function GetMissingDependenciesForUnit(const UnitFilename: string;
|
||||
ComponentClassnames: TStrings;
|
||||
var List: TObjectArray): TModalResult;
|
||||
function GetOwnersOfUnit(const UnitFilename: string): TList;
|
||||
|
||||
function GetOwnersOfUnit(const UnitFilename: string): TList; override;
|
||||
function GetSourceFilesOfOwners(OwnerList: TList): TStrings; override;
|
||||
|
||||
// package graph
|
||||
function AddPackageToGraph(APackage: TLazPackage; Replace: boolean): TModalResult;
|
||||
function DoShowPackageGraph: TModalResult;
|
||||
@ -2794,6 +2795,46 @@ begin
|
||||
FreeThenNil(Result);
|
||||
end;
|
||||
|
||||
function TPkgManager.GetSourceFilesOfOwners(OwnerList: TList): TStrings;
|
||||
|
||||
procedure AddFile(TheOwner: TObject; const Filename: string);
|
||||
begin
|
||||
if Result=nil then Result:=TStringList.Create;
|
||||
Result.AddObject(Filename,TheOwner);
|
||||
end;
|
||||
|
||||
var
|
||||
CurOwner: TObject;
|
||||
CurPackage: TLazPackage;
|
||||
CurPkgFile: TPkgFile;
|
||||
CurProject: TProject;
|
||||
CurUnit: TUnitInfo;
|
||||
i: Integer;
|
||||
j: Integer;
|
||||
begin
|
||||
Result:=nil;
|
||||
if OwnerList=nil then exit;
|
||||
for i:=0 to OwnerList.Count-1 do begin
|
||||
CurOwner:=TObject(OwnerList[i]);
|
||||
if CurOwner is TLazPackage then begin
|
||||
CurPackage:=TLazPackage(CurOwner);
|
||||
for j:=0 to CurPackage.FileCount-1 do begin
|
||||
CurPkgFile:=CurPackage.Files[j];
|
||||
if CurPkgFile.FileType in PkgFileUnitTypes then
|
||||
AddFile(CurOwner,CurPkgFile.Filename);
|
||||
end;
|
||||
end else if CurOwner is TProject then begin
|
||||
CurProject:=TProject(CurOwner);
|
||||
CurUnit:=CurProject.FirstPartOfProject;
|
||||
while CurUnit<>nil do begin
|
||||
if FilenameIsPascalSource(CurUnit.Filename) then
|
||||
AddFile(CurOwner,CurUnit.Filename);
|
||||
CurUnit:=CurUnit.NextPartOfProject;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TPkgManager.DoAddActiveUnitToAPackage: TModalResult;
|
||||
var
|
||||
ActiveSourceEditor: TSourceEditor;
|
||||
|
Loading…
Reference in New Issue
Block a user