mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-11 14:49:28 +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;
|
||||
|
||||
var
|
||||
ANode, ANode2: TAVLTreeNode;
|
||||
CurCodePos, LastCodePos: PCodeXYPosition;
|
||||
ANode: TAVLTreeNode;
|
||||
CurCodePos: PCodeXYPosition;
|
||||
IdentStartPos: integer;
|
||||
IdentLen, IdentLenDiff: Integer;
|
||||
SameLineCount: Integer;
|
||||
IdentLen: Integer;
|
||||
i: Integer;
|
||||
Code: TCodeBuffer;
|
||||
begin
|
||||
@ -3009,10 +3008,7 @@ begin
|
||||
ClearCurCodeTool;
|
||||
SourceChangeCache.Clear;
|
||||
CurCodePos := nil;
|
||||
LastCodePos := nil;
|
||||
SameLineCount := 0;
|
||||
IdentLen:=length(OldIdentifier);
|
||||
IdentLenDiff := length(NewIdentifier) - IdentLen;
|
||||
if DeclarationCode = nil then
|
||||
DeclarationCaretXY := nil;
|
||||
if DeclarationCaretXY = nil then
|
||||
@ -3056,37 +3052,11 @@ begin
|
||||
DebugLn('TCodeToolManager.RenameIdentifier Change ');
|
||||
SourceChangeCache.ReplaceEx(gtNone,gtNone,1,1,Code,
|
||||
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
|
||||
DebugLn('TCodeToolManager.RenameIdentifier KEPT ',GetIdent(@Code.Source[IdentStartPos]));
|
||||
end;
|
||||
|
||||
LastCodePos := CurCodePos;
|
||||
ANode2 := 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;
|
||||
|
||||
// apply
|
||||
|
@ -5,18 +5,157 @@ unit TestChangeDeclaration;
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, CodeToolManager, CodeCache, PascalParserTool,
|
||||
LazLogger, LazFileUtils, fpcunit, testregistry,
|
||||
Classes, SysUtils,
|
||||
LazLogger, LazFileUtils, fpcunit, testregistry, AVL_Tree,
|
||||
CodeToolManager, CodeCache, PascalParserTool, BasicCodeTools, CTUnitGraph,
|
||||
TestFinddeclaration, TestStdCodetools;
|
||||
|
||||
type
|
||||
|
||||
{ TTestChangeDeclaration }
|
||||
|
||||
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
|
||||
procedure TestCTAddProcedureModifier;
|
||||
procedure TestCTRenameIdentifier_MultiInLine;
|
||||
procedure TestCTRenameIdentifier_MultiInLine_Amp;
|
||||
end;
|
||||
|
||||
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 Test(ProcCode, aModifier, Expected: string);
|
||||
@ -24,12 +163,12 @@ procedure TTestChangeDeclaration.TestCTAddProcedureModifier;
|
||||
Code: TCodeBuffer;
|
||||
Src, ProcHead: String;
|
||||
begin
|
||||
Src:='unit TestChangeDeclaration;'+sLineBreak
|
||||
Src:='unit '+FDefFilename+';'+sLineBreak
|
||||
+'interface'+sLineBreak
|
||||
+ProcCode+sLineBreak
|
||||
+'implementation'+sLineBreak
|
||||
+'end.';
|
||||
Code:=CodeToolBoss.CreateFile('TestChangeDeclaration.pas');
|
||||
Code:=CodeToolBoss.CreateFile(FDefFilename);
|
||||
Code.Source:=Src;
|
||||
if not CodeToolBoss.AddProcModifier(Code,3,3,aModifier) then
|
||||
begin
|
||||
@ -65,6 +204,40 @@ begin
|
||||
'overload','procedure DoIt; external name ''doit''; overload;');
|
||||
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
|
||||
RegisterTests([TTestChangeDeclaration]);
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user