mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-29 12:30:36 +02:00
codetools: added tests for RenameIdentifier, simplified RenameIdentifier
This commit is contained in:
parent
1393bae4a7
commit
e1482c3582
@ -2990,11 +2990,10 @@ function TCodeToolManager.RenameIdentifier(TreeOfPCodeXYPosition: TAVLTree;
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
ANode, ANode2: TAVLTreeNode;
|
ANode: TAVLTreeNode;
|
||||||
CurCodePos, LastCodePos: PCodeXYPosition;
|
CurCodePos: PCodeXYPosition;
|
||||||
IdentStartPos: integer;
|
IdentStartPos: integer;
|
||||||
IdentLen, IdentLenDiff: Integer;
|
IdentLen: Integer;
|
||||||
SameLineCount: Integer;
|
|
||||||
i: Integer;
|
i: Integer;
|
||||||
Code: TCodeBuffer;
|
Code: TCodeBuffer;
|
||||||
begin
|
begin
|
||||||
@ -3009,10 +3008,7 @@ begin
|
|||||||
ClearCurCodeTool;
|
ClearCurCodeTool;
|
||||||
SourceChangeCache.Clear;
|
SourceChangeCache.Clear;
|
||||||
CurCodePos := nil;
|
CurCodePos := nil;
|
||||||
LastCodePos := nil;
|
|
||||||
SameLineCount := 0;
|
|
||||||
IdentLen:=length(OldIdentifier);
|
IdentLen:=length(OldIdentifier);
|
||||||
IdentLenDiff := length(NewIdentifier) - IdentLen;
|
|
||||||
if DeclarationCode = nil then
|
if DeclarationCode = nil then
|
||||||
DeclarationCaretXY := nil;
|
DeclarationCaretXY := nil;
|
||||||
if DeclarationCaretXY = nil then
|
if DeclarationCaretXY = nil then
|
||||||
@ -3056,37 +3052,11 @@ begin
|
|||||||
DebugLn('TCodeToolManager.RenameIdentifier Change ');
|
DebugLn('TCodeToolManager.RenameIdentifier Change ');
|
||||||
SourceChangeCache.ReplaceEx(gtNone,gtNone,1,1,Code,
|
SourceChangeCache.ReplaceEx(gtNone,gtNone,1,1,Code,
|
||||||
IdentStartPos,IdentStartPos+IdentLen,NewIdentifier);
|
IdentStartPos,IdentStartPos+IdentLen,NewIdentifier);
|
||||||
|
|
||||||
if (DeclarationCode = Code) and (CurCodePos^.Y = DeclarationCaretXY^.Y) and
|
|
||||||
(CurCodePos^.X < DeclarationCaretXY^.X)
|
|
||||||
then
|
|
||||||
DeclarationCaretXY^.X := DeclarationCaretXY^.X + IdentLenDiff;
|
|
||||||
|
|
||||||
if (LastCodePos <> nil) and (CurCodePos^.Y = LastCodePos^.Y) and
|
|
||||||
(CurCodePos^.Code = LastCodePos^.Code)
|
|
||||||
then
|
|
||||||
inc(SameLineCount);
|
|
||||||
|
|
||||||
end else begin
|
end else begin
|
||||||
DebugLn('TCodeToolManager.RenameIdentifier KEPT ',GetIdent(@Code.Source[IdentStartPos]));
|
DebugLn('TCodeToolManager.RenameIdentifier KEPT ',GetIdent(@Code.Source[IdentStartPos]));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
LastCodePos := CurCodePos;
|
|
||||||
ANode2 := ANode;
|
|
||||||
ANode:=TreeOfPCodeXYPosition.FindSuccessor(ANode);
|
ANode:=TreeOfPCodeXYPosition.FindSuccessor(ANode);
|
||||||
|
|
||||||
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);
|
|
||||||
PCodeXYPosition(ANode2.Data)^.X := PCodeXYPosition(ANode2.Data)^.X + i * IdentLenDiff;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
SameLineCount := 0;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// apply
|
// apply
|
||||||
|
@ -5,18 +5,157 @@ unit TestChangeDeclaration;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, CodeToolManager, CodeCache, PascalParserTool,
|
Classes, SysUtils,
|
||||||
LazLogger, LazFileUtils, fpcunit, testregistry,
|
LazLogger, LazFileUtils, fpcunit, testregistry, AVL_Tree,
|
||||||
|
CodeToolManager, CodeCache, PascalParserTool, BasicCodeTools, CTUnitGraph,
|
||||||
TestFinddeclaration, TestStdCodetools;
|
TestFinddeclaration, TestStdCodetools;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
|
{ TTestChangeDeclaration }
|
||||||
|
|
||||||
TTestChangeDeclaration = class(TCustomTestCTStdCodetools)
|
TTestChangeDeclaration = class(TCustomTestCTStdCodetools)
|
||||||
|
protected
|
||||||
|
FDefFilename: string;
|
||||||
|
procedure SetUp; override;
|
||||||
|
procedure TestRenameIdentifier(DeclCode: TCodeBuffer; SearchInCodeBufs: TFPList); overload;
|
||||||
|
procedure TestRenameIdentifier(DeclCode: TCodeBuffer; Module1: TCodeBuffer = nil); overload;
|
||||||
published
|
published
|
||||||
procedure TestCTAddProcedureModifier;
|
procedure TestCTAddProcedureModifier;
|
||||||
|
procedure TestCTRenameIdentifier_MultiInLine;
|
||||||
|
procedure TestCTRenameIdentifier_MultiInLine_Amp;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
|
procedure TTestChangeDeclaration.SetUp;
|
||||||
|
begin
|
||||||
|
inherited SetUp;
|
||||||
|
FDefFilename:='TestChangeDeclaration.pas';
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestChangeDeclaration.TestRenameIdentifier(DeclCode: TCodeBuffer;
|
||||||
|
SearchInCodeBufs: TFPList);
|
||||||
|
var
|
||||||
|
p, DeclPos, l: SizeInt;
|
||||||
|
NewIdentifier, OldIdentifier, Src, CurIdentifier: String;
|
||||||
|
SearchInCode: TCodeBuffer;
|
||||||
|
i, j: integer;
|
||||||
|
DeclXY: TPoint;
|
||||||
|
TreeOfPCodeXYPosition: TAVLTree;
|
||||||
|
ListOfPCodeXYPosition: TFPList;
|
||||||
|
Cache: TFindIdentifierReferenceCache;
|
||||||
|
RefXYPos: TCodeXYPosition;
|
||||||
|
begin
|
||||||
|
Cache:=nil;
|
||||||
|
ListOfPCodeXYPosition:=nil;
|
||||||
|
TreeOfPCodeXYPosition:=nil;
|
||||||
|
try
|
||||||
|
// parse %rename directive
|
||||||
|
Src:=DeclCode.Source;
|
||||||
|
DeclPos:=Pos('{%rename:',Src);
|
||||||
|
if DeclPos<1 then
|
||||||
|
Fail('missing declaration marker');
|
||||||
|
inc(DeclPos,length('{%rename:'));
|
||||||
|
NewIdentifier:=GetIdentifier(@Src[DeclPos]);
|
||||||
|
if NewIdentifier='' then
|
||||||
|
Fail('missing rename-to identifier');
|
||||||
|
while Src[DeclPos]<>'}' do inc(DeclPos);
|
||||||
|
inc(DeclPos);
|
||||||
|
OldIdentifier:=GetIdentifier(@Src[DeclPos]);
|
||||||
|
if OldIdentifier='' then
|
||||||
|
Fail('missing rename-from identifier');
|
||||||
|
|
||||||
|
DeclCode.AbsoluteToLineCol(DeclPos,DeclXY.Y,DeclXY.X);
|
||||||
|
|
||||||
|
// find all references
|
||||||
|
if SearchInCodeBufs=nil then
|
||||||
|
SearchInCodeBufs:=TFPList.Create;
|
||||||
|
if SearchInCodeBufs.IndexOf(DeclCode)<0 then
|
||||||
|
SearchInCodeBufs.Add(DeclCode);
|
||||||
|
for i:=0 to SearchInCodeBufs.Count-1 do begin
|
||||||
|
SearchInCode:=TCodeBuffer(SearchInCodeBufs[i]);
|
||||||
|
if not CodeToolBoss.FindReferences(DeclCode,DeclXY.X,DeclXY.Y,SearchInCode,false,ListOfPCodeXYPosition,Cache) then
|
||||||
|
Fail('FindReferences failed at '+DeclCode.Filename+'('+dbgs(DeclXY.Y)+','+dbgs(DeclXY.X)+')');
|
||||||
|
|
||||||
|
// check that all %R directives were found
|
||||||
|
p:=1;
|
||||||
|
Src:=SearchInCode.Source;
|
||||||
|
l:=length(Src);
|
||||||
|
while p<=l do begin
|
||||||
|
if (Src[p]='{') and (Src[p+1]='%') and (Src[p+2]='R') and (Src[p+3]='}') then begin
|
||||||
|
inc(p,4);
|
||||||
|
RefXYPos.Code:=SearchInCode;
|
||||||
|
SearchInCode.AbsoluteToLineCol(p,RefXYPos.Y,RefXYPos.X);
|
||||||
|
j:=IndexOfCodePosition(ListOfPCodeXYPosition,@RefXYPos);
|
||||||
|
if j<0 then begin
|
||||||
|
if ListOfPCodeXYPosition=nil then
|
||||||
|
debugln(['TTestChangeDeclaration.TestRenameIdentifier ListOfPCodeXYPosition empty'])
|
||||||
|
else begin
|
||||||
|
debugln(['TTestChangeDeclaration.TestRenameIdentifier ListOfPCodeXYPosition: Count=',ListOfPCodeXYPosition.Count]);
|
||||||
|
for j:=0 to ListOfPCodeXYPosition.Count-1 do begin
|
||||||
|
debugln([' ',i,':',dbgs(PCodeXYPosition(ListOfPCodeXYPosition[j])^)]);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
Fail('missing reference: '+dbgs(RefXYPos));
|
||||||
|
end;
|
||||||
|
end else
|
||||||
|
inc(p);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// add to tree
|
||||||
|
if ListOfPCodeXYPosition<>nil then begin
|
||||||
|
if TreeOfPCodeXYPosition=nil then
|
||||||
|
TreeOfPCodeXYPosition:=CodeToolBoss.CreateTreeOfPCodeXYPosition;
|
||||||
|
CodeToolBoss.AddListToTreeOfPCodeXYPosition(ListOfPCodeXYPosition,
|
||||||
|
TreeOfPCodeXYPosition,true,false); // this empties ListOfPCodeXYPosition
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if (TreeOfPCodeXYPosition=nil) or (TreeOfPCodeXYPosition.Count=0) then
|
||||||
|
Fail('TreeOfPCodeXYPosition empty');
|
||||||
|
|
||||||
|
// rename references
|
||||||
|
if not CodeToolBoss.RenameIdentifier(TreeOfPCodeXYPosition,OldIdentifier,NewIdentifier,DeclCode,@DeclXY,false) then
|
||||||
|
Fail('RenameIdentifier failed');
|
||||||
|
|
||||||
|
// check all {%R} directives were replaced
|
||||||
|
for i:=0 to SearchInCodeBufs.Count-1 do begin
|
||||||
|
SearchInCode:=TCodeBuffer(SearchInCodeBufs[i]);
|
||||||
|
// check that all %R directives were found
|
||||||
|
p:=1;
|
||||||
|
Src:=SearchInCode.Source;
|
||||||
|
l:=length(Src);
|
||||||
|
while p<=l do begin
|
||||||
|
if (Src[p]='{') and (Src[p+1]='%') and (Src[p+2]='R') and (Src[p+3]='}') then begin
|
||||||
|
inc(p,4);
|
||||||
|
CurIdentifier:=copy(Src,p,length(NewIdentifier));
|
||||||
|
if CurIdentifier<>NewIdentifier then
|
||||||
|
Fail('reference differ: expected "'+NewIdentifier+'", but found "'+CurIdentifier+'"');
|
||||||
|
end else
|
||||||
|
inc(p);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
finally
|
||||||
|
CodeToolBoss.FreeListOfPCodeXYPosition(ListOfPCodeXYPosition);
|
||||||
|
CodeToolBoss.FreeTreeOfPCodeXYPosition(TreeOfPCodeXYPosition);
|
||||||
|
Cache.Free;
|
||||||
|
SearchInCodeBufs.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestChangeDeclaration.TestRenameIdentifier(DeclCode: TCodeBuffer; Module1: TCodeBuffer);
|
||||||
|
var
|
||||||
|
SearchInModules: TFPList;
|
||||||
|
begin
|
||||||
|
SearchInModules:=TFPList.Create;
|
||||||
|
if Module1<>nil then
|
||||||
|
SearchInModules.Add(Module1);
|
||||||
|
TestRenameIdentifier(DeclCode,SearchInModules);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TTestChangeDeclaration.TestCTAddProcedureModifier;
|
procedure TTestChangeDeclaration.TestCTAddProcedureModifier;
|
||||||
|
|
||||||
procedure Test(ProcCode, aModifier, Expected: string);
|
procedure Test(ProcCode, aModifier, Expected: string);
|
||||||
@ -24,12 +163,12 @@ procedure TTestChangeDeclaration.TestCTAddProcedureModifier;
|
|||||||
Code: TCodeBuffer;
|
Code: TCodeBuffer;
|
||||||
Src, ProcHead: String;
|
Src, ProcHead: String;
|
||||||
begin
|
begin
|
||||||
Src:='unit TestChangeDeclaration;'+sLineBreak
|
Src:='unit '+FDefFilename+';'+sLineBreak
|
||||||
+'interface'+sLineBreak
|
+'interface'+sLineBreak
|
||||||
+ProcCode+sLineBreak
|
+ProcCode+sLineBreak
|
||||||
+'implementation'+sLineBreak
|
+'implementation'+sLineBreak
|
||||||
+'end.';
|
+'end.';
|
||||||
Code:=CodeToolBoss.CreateFile('TestChangeDeclaration.pas');
|
Code:=CodeToolBoss.CreateFile(FDefFilename);
|
||||||
Code.Source:=Src;
|
Code.Source:=Src;
|
||||||
if not CodeToolBoss.AddProcModifier(Code,3,3,aModifier) then
|
if not CodeToolBoss.AddProcModifier(Code,3,3,aModifier) then
|
||||||
begin
|
begin
|
||||||
@ -65,6 +204,40 @@ begin
|
|||||||
'overload','procedure DoIt; external name ''doit''; overload;');
|
'overload','procedure DoIt; external name ''doit''; overload;');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestChangeDeclaration.TestCTRenameIdentifier_MultiInLine;
|
||||||
|
var
|
||||||
|
DeclCode: TCodeBuffer;
|
||||||
|
begin
|
||||||
|
DeclCode:=CodeToolBoss.CreateFile(FDefFilename);
|
||||||
|
DeclCode.Source:='unit '+FDefFilename+';'+sLineBreak
|
||||||
|
+'interface'+sLineBreak
|
||||||
|
+'type'+sLineBreak
|
||||||
|
+' {%rename:TWhale}TFoo = word;'+sLineBreak
|
||||||
|
+' TBar = low({%R}TFoo)..high({%R}TFoo);'
|
||||||
|
+'implementation'+sLineBreak
|
||||||
|
+'type'+sLineBreak
|
||||||
|
+' TBird = low({%R}TFoo)..high({%R}TFoo);'
|
||||||
|
+'end.';
|
||||||
|
TestRenameIdentifier(DeclCode);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestChangeDeclaration.TestCTRenameIdentifier_MultiInLine_Amp;
|
||||||
|
var
|
||||||
|
DeclCode: TCodeBuffer;
|
||||||
|
begin
|
||||||
|
DeclCode:=CodeToolBoss.CreateFile(FDefFilename);
|
||||||
|
DeclCode.Source:='unit '+FDefFilename+';'+sLineBreak
|
||||||
|
+'interface'+sLineBreak
|
||||||
|
+'type'+sLineBreak
|
||||||
|
+' {%rename:&Type}TFoo = word;'+sLineBreak
|
||||||
|
+' TBar = low({%R}TFoo)..high({%R}TFoo);'
|
||||||
|
+'implementation'+sLineBreak
|
||||||
|
+'type'+sLineBreak
|
||||||
|
+' TBird = low({%R}TFoo)..high({%R}TFoo);'
|
||||||
|
+'end.';
|
||||||
|
TestRenameIdentifier(DeclCode);
|
||||||
|
end;
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
RegisterTests([TTestChangeDeclaration]);
|
RegisterTests([TTestChangeDeclaration]);
|
||||||
end.
|
end.
|
||||||
|
Loading…
Reference in New Issue
Block a user