From 00f3d3b39738f96419f35accfdc861d54b6f9a18 Mon Sep 17 00:00:00 2001 From: mattias Date: Sat, 27 Jul 2024 09:21:00 +0200 Subject: [PATCH] codetools: added tree of PCodeToolPos --- components/codetools/basiccodetools.pas | 19 ++++ components/codetools/codetoolmanager.pas | 126 ++++++++++++++++++++++- 2 files changed, 143 insertions(+), 2 deletions(-) diff --git a/components/codetools/basiccodetools.pas b/components/codetools/basiccodetools.pas index 942b319d67..37fe97f2b6 100644 --- a/components/codetools/basiccodetools.pas +++ b/components/codetools/basiccodetools.pas @@ -195,6 +195,7 @@ function IsDottedIdentifier(const Identifier: string): boolean; function CompareDottedIdentifiers(Identifier1, Identifier2: PChar): integer; function CompareDottedIdentifiersCaseSens(Identifier1, Identifier2: PChar): integer; function ChompDottedIdentifier(const Identifier: string): string; +function SkipDottedIdentifierPart(var Identifier: PChar): boolean; // space and special chars function TrimCodeSpace(const ACode: string): string; @@ -5342,6 +5343,24 @@ begin Result:=LeftStr(Identifier,p-1); end; +function SkipDottedIdentifierPart(var Identifier: PChar): boolean; +var + c: Char; +begin + c:=Identifier^; + if (c='&') and (IsIdentStartChar[Identifier[1]]) then + inc(Identifier,2) + else if IsIdentStartChar[c] then + inc(Identifier) + else + exit(false); + while IsIdentChar[Identifier^] do + inc(Identifier); + if Identifier^='.' then + inc(Identifier); + Result:=true; +end; + function TrimCodeSpace(const ACode: string): string; // turn all lineends and special chars to space // space is combined to one char diff --git a/components/codetools/codetoolmanager.pas b/components/codetools/codetoolmanager.pas index f10922da2a..c5434158c2 100644 --- a/components/codetools/codetoolmanager.pas +++ b/components/codetools/codetoolmanager.pas @@ -57,6 +57,12 @@ uses type TCodeToolManager = class; TCodeTool = TEventsCodeTool; + TCodeToolPos = record + Tool: TCodeTool; + CleanPos: integer; + end; + PCodeToolPos = ^TCodeToolPos; + TDirectivesTool = TCompilerDirectivesTree; TOnBeforeApplyCTChanges = procedure(Manager: TCodeToolManager; @@ -408,6 +414,9 @@ type function CreateTreeOfPCodeXYPosition: TAVLTree; procedure AddListToTreeOfPCodeXYPosition(SrcList: TFPList; DestTree: TAVLTree; ClearList, CreateCopies: boolean); + function CreateTreeOfPCodeToolPos: TAVLTree; + procedure FreeTreeOfPCodeToolPos(var Tree: TAVLTree); + procedure RemoveDuplicatesInTreeOfPCodeToolPos(Tree: TAVLTree); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -576,6 +585,8 @@ type var ProcPos: TCodeXYPosition; // if it is in this unit the proc declaration is changed and this position is cleared TreeOfPCodeXYPosition: TAVLTree // positions in this unit are processed and removed from the tree ): boolean; + procedure ConvertTreeOf_CodeXYPosToToolCleanPos(TreeOfPCodeXYPosition: TAVLTree; + out TreeOfPCodeToolPos: TAVLTree); // resourcestring sections function GatherResourceStringSections( @@ -936,7 +947,7 @@ var CodeToolBoss: TCodeToolManager; function CreateDefinesForFPCMode(const Name: string; CompilerMode: TCompilerMode): TDefineTemplate; - +function ComparePCodeToolPos(ToolPos1, ToolPos2: PCodeToolPos): integer; implementation @@ -1005,6 +1016,18 @@ begin NewMode,NewMode,'1',da_Define)); end; +function ComparePCodeToolPos(ToolPos1, ToolPos2: PCodeToolPos): integer; +begin + Result:=ComparePointer(ToolPos1^.Tool,ToolPos2^.Tool); + if Result<>0 then exit; + if ToolPos1^.CleanPosToolPos2^.CleanPos then + Result:=-1 + else + Result:=0; +end; + { ECodeToolManagerError } constructor ECodeToolManagerError.Create(TheID: int64; const Msg: string); @@ -1865,6 +1888,50 @@ begin CodeCache.AddListToTreeOfPCodeXYPosition(SrcList,DestTree,ClearList,CreateCopies); end; +function TCodeToolManager.CreateTreeOfPCodeToolPos: TAVLTree; +begin + Result:=TAVLTree.Create(TListSortCompare(@ComparePCodeToolPos)); +end; + +procedure TCodeToolManager.FreeTreeOfPCodeToolPos(var Tree: TAVLTree); +var + ANode: TAVLTreeNode; + ToolPos: PCodeToolPos; +begin + if Tree=nil then exit; + ANode:=Tree.FindLowest; + while ANode<>nil do begin + ToolPos:=PCodeToolPos(ANode.Data); + if ToolPos<>nil then + Dispose(ToolPos); + ANode:=Tree.FindSuccessor(ANode); + end; + Tree.Free; + Tree:=nil; +end; + +procedure TCodeToolManager.RemoveDuplicatesInTreeOfPCodeToolPos(Tree: TAVLTree); +var + ANode, DelNode: TAVLTreeNode; + ToolPos, LastToolPos: PCodeToolPos; +begin + if Tree=nil then exit; + ANode:=Tree.FindLowest; + LastToolPos:=nil; + while ANode<>nil do begin + ToolPos:=PCodeToolPos(ANode.Data); + if (LastToolPos<>nil) and (ComparePCodeToolPos(ToolPos,LastToolPos)=0) then begin + DelNode:=ANode; + ANode:=Tree.FindSuccessor(ANode); + Dispose(ToolPos); + Tree.Delete(DelNode); + end else begin + LastToolPos:=ToolPos; + ANode:=Tree.FindSuccessor(ANode); + end; + end; +end; + function TCodeToolManager.Explore(Code: TCodeBuffer; out ACodeTool: TCodeTool; WithStatements: boolean; OnlyInterface: boolean ): boolean; @@ -2935,7 +3002,7 @@ begin {$IFDEF CTDEBUG} DebugLn('TCodeToolManager.RenameIdentifier A Old=',OldIdentifier,' New=',NewIdentifier,' ',dbgs(TreeOfPCodeXYPosition<>nil)); {$ENDIF} - if TreeOfPCodeXYPosition=nil then + if (TreeOfPCodeXYPosition=nil) or (TreeOfPCodeXYPosition.Count=0) then exit(true); if not LazIsValidIdent(NewIdentifier,True,True) then exit; @@ -3011,6 +3078,7 @@ begin if (ANode = nil) or (PCodeXYPosition(ANode.Data)^.Code <> LastCodePos^.Code) or (PCodeXYPosition(ANode.Data)^.Y <> LastCodePos^.Y) then begin + // todo: check if this is needed, the tree is sorted, so it should not be needed if (SameLineCount > 0) then begin for i := 1 to SameLineCount do begin ANode2 := TreeOfPCodeXYPosition.FindPrecessor(ANode2); @@ -3020,6 +3088,7 @@ begin SameLineCount := 0; end; end; + // apply DebugLn('TCodeToolManager.RenameIdentifier Apply'); if not SourceChangeCache.Apply then exit; @@ -3128,6 +3197,59 @@ begin end; end; +procedure TCodeToolManager.ConvertTreeOf_CodeXYPosToToolCleanPos(TreeOfPCodeXYPosition: TAVLTree; + out TreeOfPCodeToolPos: TAVLTree); +var + ANode: TAVLTreeNode; + CurCodePos: PCodeXYPosition; + Code, MainCode, LastCode, LastMainCode: TCodeBuffer; + ToolPos: PCodeToolPos; + Tool, LastTool: TCodeTool; + CleanPos: integer; +begin + TreeOfPCodeToolPos:=nil; + // the tree is sorted for descending line code positions + LastCode:=nil; + LastMainCode:=nil; + LastTool:=nil; + ANode:=TreeOfPCodeXYPosition.FindLowest; + while ANode<>nil do begin + CurCodePos:=PCodeXYPosition(ANode.Data); + ANode:=TreeOfPCodeXYPosition.FindSuccessor(ANode); + Code:=CurCodePos^.Code; + if Code=LastCode then + begin + MainCode:=LastMainCode; + Tool:=LastTool; + end else begin + MainCode:=GetMainCode(Code); + if MainCode=nil then continue; + if MainCode=LastMainCode then begin + Tool:=LastTool; + end else begin + Tool:=TCodeTool(GetCodeToolForSource(MainCode,false,false)); + if Tool=nil then continue; + end; + end; + + LastCode:=Code; + LastMainCode:=MainCode; + LastTool:=Tool; + + if Tool.CaretToCleanPos(CurCodePos^,CleanPos)<>0 then continue; + + New(ToolPos); + ToolPos^.Tool:=Tool; + ToolPos^.CleanPos:=CleanPos; + if TreeOfPCodeToolPos=nil then + TreeOfPCodeToolPos:=CreateTreeOfPCodeToolPos; + TreeOfPCodeToolPos.Add(ToolPos); + end; + + // remove duplicates + RemoveDuplicatesInTreeOfPCodeToolPos(TreeOfPCodeToolPos); +end; + function TCodeToolManager.GatherResourceStringSections(Code: TCodeBuffer; X, Y: integer; CodePositions: TCodeXYPositions): boolean; var