65
65
function FindJumpPointInProcNode(ProcNode: TCodeTreeNode;
66
66
out NewPos: TCodeXYPosition; out NewTopLine: integer): boolean;
67
67
function GatherProcNodes(StartNode: TCodeTreeNode;
68
Attr: TProcHeadAttributes; const UpperClassName: string): TAVLTree;
68
Attr: TProcHeadAttributes; const FilterClassName: string): TAVLTree;
69
69
function FindFirstDifferenceNode(SearchForNodes, SearchInNodes: TAVLTree;
70
70
var DiffTxtPos: integer): TAVLTreeNode;
71
71
function JumpToMethod(const ProcHead: string; Attr: TProcHeadAttributes;
115
115
OldAVLNode1:=AVLNode1;
116
116
AVLNode1:=Tree1.FindSuccessor(AVLNode1);
117
117
if not KeepTree1 then begin
118
NodeExtMemManager.DisposeNode(TCodeTreeNodeExtension(OldAVLNode1.Data));
119
Tree1.Delete(OldAVLNode1);
118
Tree1.FreeAndDelete(OldAVLNode1);
121
120
OldAVLNode2:=AVLNode2;
122
121
AVLNode2:=Tree2.FindSuccessor(AVLNode2);
123
NodeExtMemManager.DisposeNode(TCodeTreeNodeExtension(OldAVLNode2.Data));
124
Tree2.Delete(OldAVLNode2);
122
Tree2.FreeAndDelete(OldAVLNode2);
336
335
DebugLn('TMethodJumpingCodeTool.FindJumpPoint A CursorPos=',dbgs(CursorPos.X),',',dbgs(CursorPos.Y));
338
BuildTreeAndGetCleanPos(trAll,CursorPos,CleanCursorPos,[]);
337
BuildTreeAndGetCleanPos(CursorPos,CleanCursorPos);
339
338
GetLineInfo(CleanCursorPos,LineStart,LineEnd,FirstAtomStart,LastAtomEnd);
340
339
if CleanCursorPos<FirstAtomStart then CleanCursorPos:=FirstAtomStart;
341
340
if CleanCursorPos>=LastAtomEnd then CleanCursorPos:=LastAtomEnd-1;
348
347
// find CodeTreeNode at cursor
349
348
CursorNode:=FindDeepestNodeAtPos(CleanCursorPos,true);
351
DebugLn('TMethodJumpingCodeTool.FindJumpPoint C ',NodeDescriptionAsString(CursorNode.Desc));
350
DebugLn('TMethodJumpingCodeTool.FindJumpPoint CursorNode=',CursorNode.DescAsString);
353
352
// first test if in a class
354
ClassNode:=CursorNode.GetNodeOfTypes([ctnClass,ctnObject,
355
ctnObjCClass,ctnObjCCategory,ctnCPPClass]);
353
ClassNode:=CursorNode.GetNodeOfTypes([ctnClass,ctnClassInterface,
354
ctnDispinterface,ctnObject,ctnRecordType,
355
ctnObjCClass,ctnObjCCategory,ctnObjCProtocol,
356
357
if ClassNode<>nil then begin
357
// cursor is in class/object definition
358
// search in all implemented class procedures for the body
358
// cursor is in class/object/interface definition
359
// Interfaces have no method bodies, but if the class was refactored it has
360
// and then jumping is a nide feature
361
// => search in all implemented class procedures for the body
360
DebugLn('TMethodJumpingCodeTool.FindJumpPoint D ',NodeDescriptionAsString(ClassNode.Desc));
363
DebugLn('TMethodJumpingCodeTool.FindJumpPoint ClasNode=',ClassNode.DescAsString);
362
365
if (ClassNode.SubDesc and ctnsForwardDeclaration)>0 then exit;
363
366
// parse class and build CodeTreeNodes for all properties/methods
365
368
DebugLn('TMethodJumpingCodeTool.FindJumpPoint E ',dbgs(CleanCursorPos),', |',copy(Src,CleanCursorPos,8));
367
BuildSubTreeForClass(ClassNode);
368
TypeSectionNode:=ClassNode.GetNodeOfType(ctnTypeSection);
370
TypeSectionNode:=ClassNode.GetTopMostNodeOfType(ctnTypeSection);
369
371
// search the method node under the cursor
370
372
CursorNode:=FindDeepestNodeAtPos(CleanCursorPos,true).
371
373
GetNodeOfType(ctnProcedure);
401
399
// gather the method bodies
402
400
SearchInNodes:=GatherProcNodes(TypeSectionNode,
403
401
[phpInUpperCase,phpIgnoreForwards,phpOnlyWithClassname],
404
ExtractClassName(ClassNode,true));
402
ExtractClassName(ClassNode,true,true));
406
404
// remove all corresponding methods
407
405
RemoveCorrespondingProcNodes(SearchInNodes,SearchForNodes,false);
520
NodeExtMemManager.DisposeAVLTree(SearchForNodes);
521
NodeExtMemManager.DisposeAVLTree(SearchInNodes);
518
DisposeAVLTree(SearchForNodes);
519
DisposeAVLTree(SearchInNodes);
524
522
// procedure is not forward, search on same proc level
526
DebugLn('TMethodJumpingCodeTool.FindJumpPoint 4A');
524
DebugLn('TMethodJumpingCodeTool.FindJumpPoint proc body');
528
SearchedClassname:=ExtractClassNameOfProcNode(ProcNode);
526
SearchedClassname:=ExtractClassNameOfProcNode(ProcNode,true);
529
527
StartNode:=FindFirstNodeOnSameLvl(ProcNode);
531
DebugLn('TMethodJumpingCodeTool.FindJumpPoint 4B ',dbgs(StartNode<>nil),' ',SearchedClassName);
529
DebugLn('TMethodJumpingCodeTool.FindJumpPoint body to decl: ',dbgs(StartNode<>nil),' Class="',SearchedClassName,'"');
533
531
if StartNode=nil then exit;
534
532
if SearchedClassname<>'' then begin
535
533
// search class node
536
ClassNode:=FindClassNode(StartNode,UpperCaseStr(SearchedClassName),
534
ClassNode:=FindClassNode(StartNode,SearchedClassName,true,false);
539
DebugLn('TMethodJumpingCodeTool.FindJumpPoint 4C ',dbgs(ClassNode<>nil));
536
DebugLn('TMethodJumpingCodeTool.FindJumpPoint class found: ',dbgs(ClassNode<>nil));
541
if ClassNode=nil then exit;
542
BuildSubTreeForClass(ClassNode);
538
if ClassNode=nil then begin
539
MoveCursorToProcName(ProcNode,false);
540
RaiseException('class not found "'+SearchedClassname+'"');
543
542
// search first class grand child node
544
543
StartNode:=ClassNode.FirstChild;
545
544
while (StartNode<>nil) and (StartNode.FirstChild=nil) do
548
547
DebugLn('TMethodJumpingCodeTool.FindJumpPoint 4D ',dbgs(StartNode<>nil));
550
if StartNode=nil then exit;
551
StartNode:=StartNode.FirstChild;
549
if StartNode=nil then begin
550
ProcName:=ExtractProcName(ProcNode,[]);
551
MoveCursorToNodeStart(ClassNode);
552
RaiseException('method "'+ProcName+'" has no declaration');
552
554
// search method with same name and param list
553
555
Result:=FindBestProcNode(ProcNode,[phpWithoutClassName,phpInUpperCase],
554
556
StartNode,[phpInUpperCase],false);
564
566
DebugLn('TMethodJumpingCodeTool.FindJumpPoint 4F ');
566
568
// gather method bodies
567
TypeSectionNode:=ClassNode.Parent;
568
if (TypeSectionNode<>nil) and (TypeSectionNode.Parent<>nil)
569
and (TypeSectionNode.Parent.Desc=ctnTypeSection) then
570
TypeSectionNode:=TypeSectionNode.Parent;
569
TypeSectionNode:=ClassNode.GetTopMostNodeOfType(ctnTypeSection);
571
570
SearchForNodes:=GatherProcNodes(TypeSectionNode,
572
571
[phpInUpperCase,phpIgnoreForwards,phpOnlyWithClassname],
573
ExtractClassName(ClassNode,true));
572
ExtractClassName(ClassNode,true,true));
575
574
// remove corresponding methods
576
575
RemoveCorrespondingProcNodes(SearchForNodes,SearchInNodes,false);
578
577
DebugLn('TMethodJumpingCodeTool.FindJumpPoint 4G DiffNodes=',dbgs(SearchInNodes.Count));
580
if SearchInNodes.Count=0 then exit;
579
if SearchInNodes.Count=0 then begin
580
ProcName:=ExtractProcName(ProcNode,[]);
581
MoveCursorToNodeStart(ClassNode);
582
RaiseException('method "'+ProcName+'" has no declaration');
581
584
// search for a method with same name but different param list
582
585
ProcNode:=FindProcNodeInTreeWithName(SearchInNodes,
583
586
ExtractProcName(ProcNode,[phpWithoutClassName,phpInUpperCase]));
771
774
function TMethodJumpingCodeTool.GatherProcNodes(StartNode: TCodeTreeNode;
772
Attr: TProcHeadAttributes; const UpperClassName: string): TAVLTree;
773
// create a tree of TCodeTreeNodeExtension
775
Attr: TProcHeadAttributes; const FilterClassName: string): TAVLTree;
776
// create a tree of TCodeTreeNodeExtension sorted with CompareCodeTreeNodeExt
777
// Node.Desc = ctnProcedure
778
// Node.Txt = ExtractProcHead(Node,Attr)
774
779
var CurProcName: string;
775
780
ANode: TCodeTreeNode;
776
781
NewNodeExt: TCodeTreeNodeExtension;
778
783
CurClassName: String;
785
//debugln(['TMethodJumpingCodeTool.GatherProcNodes START']);
780
786
Result:=TAVLTree.Create(@CompareCodeTreeNodeExt);
787
if (StartNode=nil) or (StartNode.Parent=nil) then exit;
781
788
ANode:=StartNode;
782
789
while (ANode<>nil) do begin
790
//debugln(['TMethodJumpingCodeTool.GatherProcNodes ',ANode.DescAsString]);
783
791
if ANode.Desc=ctnProcedure then begin
784
792
if (not ((phpIgnoreForwards in Attr)
785
793
and ((ANode.SubDesc and ctnsForwardDeclaration)>0)))
786
794
and (not ((phpIgnoreProcsWithBody in Attr)
787
795
and (FindProcBody(ANode)<>nil))) then
789
//DebugLn('[TMethodJumpingCodeTool.GatherProcNodes] B');
797
//DebugLn('[TMethodJumpingCodeTool.GatherProcNodes] Proc found');
791
799
if (phpOnlyWithClassname in Attr) then begin
792
CurClassName:=ExtractClassNameOfProcNode(ANode);
793
//DebugLn('[TMethodJumpingCodeTool.GatherProcNodes] B2 "',CurClassName,'" =? ',UpperClassName);
800
CurClassName:=ExtractClassNameOfProcNode(ANode,true);
801
//DebugLn('[TMethodJumpingCodeTool.GatherProcNodes] Proc Class="',CurClassName,'" =? ',FilterClassName,'=Filter');
795
if CompareIdentifiers(PChar(UpperClassName),PChar(CurClassName))<>0 then
803
if CompareText(FilterClassName,CurClassName)<>0 then
798
806
if cmp and (phpIgnoreMethods in Attr) then begin
799
if (ANode.GetNodeOfTypes([ctnClass,ctnObject,
807
if (ANode.GetNodeOfTypes([ctnClass,ctnObject,ctnRecordType,
800
808
ctnObjCClass,ctnObjCCategory,ctnCPPClass])<>nil)
801
or (ExtractClassNameOfProcNode(ANode)<>'')
809
or (ExtractClassNameOfProcNode(ANode,true)<>'')
805
813
if cmp then begin
806
//DebugLn('[TMethodJumpingCodeTool.GatherProcNodes] C');
814
//DebugLn('[TMethodJumpingCodeTool.GatherProcNodes] Proc with right class');
807
815
CurProcName:=ExtractProcHead(ANode,Attr);
808
//DebugLn(['[TMethodJumpingCodeTool.GatherProcNodes] D "',CurProcName,'" ',phpInUpperCase in Attr]);
816
//DebugLn(['[TMethodJumpingCodeTool.GatherProcNodes] Proc with right class, name="',CurProcName,'" phpInUpperCase=',phpInUpperCase in Attr]);
809
817
if (CurProcName<>'') then begin
810
NewNodeExt:=NodeExtMemManager.NewNode;
818
NewNodeExt:=TCodeTreeNodeExtension.Create;
811
819
with NewNodeExt do begin
813
821
Txt:=CurProcName;
821
ANode:=FindNextNodeOnSameLvl(ANode);
829
if (ANode.FirstChild<>nil)
830
and (ANode.Desc in (AllClassSections+[ctnImplementation])) then
831
ANode:=ANode.FirstChild
833
while ANode.NextBrother=nil do begin
835
if ANode=nil then break;
836
if not (ANode.Desc in (AllClassSections+[ctnImplementation])) then
839
if ANode=nil then break;
840
ANode:=ANode.NextBrother;
843
//debugln(['TMethodJumpingCodeTool.GatherProcNodes END']);
825
846
function TMethodJumpingCodeTool.FindFirstDifferenceNode(
935
956
if (PathIndex>SubProcPath.Count) or (StartNode=nil) then exit;
936
957
ProcHead:=SubProcPath[PathIndex];
937
958
ProcNode:=FindProcNode(StartNode,ProcHead,Attr);
938
DebugLn('TMethodJumpingCodeTool.SearchSubProcPath A ProcHead="',ProcHead,'" Found=',dbgs(ProcNode<>nil));
959
//DebugLn('TMethodJumpingCodeTool.SearchSubProcPath A ProcHead="',ProcHead,'" Found=',dbgs(ProcNode<>nil));
939
960
if ProcNode=nil then exit;
940
961
if PathIndex=SubProcPath.Count-1 then begin
941
962
Result:=ProcNode;