mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-06 13:39:17 +02:00
codetools: find sourcename refs to used unit
This commit is contained in:
parent
3276690fec
commit
370938ca90
@ -7402,6 +7402,11 @@ var
|
||||
inc(p,GetIdentLen(StartP));
|
||||
exit;
|
||||
end;
|
||||
if (StartP^<>'&') and WordIsKeyWordFuncList.DoIdentifier(StartP) then begin
|
||||
// do not check keyword identifier references without ampersand
|
||||
inc(p,GetIdentLen(StartP));
|
||||
exit;
|
||||
end;
|
||||
|
||||
Expr:=ReadDottedIdentifier(Src,p,Scanner.NestedComments);
|
||||
//debugln([' CheckIdentifier At ',CleanPosToStr(p),' Expr="',Expr,'"']);
|
||||
@ -7490,15 +7495,16 @@ var
|
||||
if Node.Desc=ctnSrcName then begin
|
||||
if IsSelf then
|
||||
AddPos(StartPos);
|
||||
end else begin
|
||||
// todo: found uses node
|
||||
end else if Node.Desc in [ctnUseUnitClearName,ctnUseUnitNamespace] then begin
|
||||
if Node.StartPos=LocalSrcNamePos then
|
||||
AddPos(StartPos);
|
||||
end;
|
||||
end;
|
||||
|
||||
function CheckComment(var StartPos: integer; MaxPos: integer): boolean;
|
||||
var
|
||||
c: Char;
|
||||
CommentLvl: Integer;
|
||||
AtomStart, CommentLvl: Integer;
|
||||
InStrConst, LastTokenWasPoint, IsDirective: Boolean;
|
||||
begin
|
||||
Result:=true;
|
||||
@ -7541,6 +7547,7 @@ var
|
||||
begin
|
||||
if (c='{') and Scanner.NestedComments then inc(CommentLvl);
|
||||
LastTokenWasPoint:=false;
|
||||
inc(StartPos);
|
||||
end;
|
||||
'}':
|
||||
begin
|
||||
@ -7552,6 +7559,7 @@ var
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
inc(StartPos);
|
||||
end;
|
||||
')':
|
||||
begin
|
||||
@ -7560,6 +7568,7 @@ var
|
||||
inc(StartPos);
|
||||
exit;
|
||||
end;
|
||||
inc(StartPos);
|
||||
end;
|
||||
'a'..'z','A'..'Z','_','&':
|
||||
begin
|
||||
@ -7567,12 +7576,17 @@ var
|
||||
and (not LastTokenWasPoint) then
|
||||
if not CheckIdentifier(StartPos) then exit(false);
|
||||
LastTokenWasPoint:=false;
|
||||
inc(StartPos,GetIdentLen(@Src[StartPos]));
|
||||
end;
|
||||
'''':
|
||||
begin
|
||||
InStrConst:=not InStrConst;
|
||||
LastTokenWasPoint:=false;
|
||||
inc(StartPos);
|
||||
end;
|
||||
'$','0'..'9':
|
||||
// skip number, could contain letters
|
||||
ReadRawNextPascalAtom(Src,StartPos,AtomStart,Scanner.NestedComments);
|
||||
#10,#13:
|
||||
begin
|
||||
InStrConst:=false;
|
||||
@ -7583,19 +7597,24 @@ var
|
||||
inc(StartPos);
|
||||
exit;
|
||||
end;
|
||||
inc(StartPos);
|
||||
end;
|
||||
' ',#9: ;
|
||||
'.': LastTokenWasPoint:=true;
|
||||
' ',#9: inc(StartPos);
|
||||
'.':
|
||||
begin
|
||||
LastTokenWasPoint:=true;
|
||||
inc(StartPos);
|
||||
end
|
||||
else
|
||||
LastTokenWasPoint:=false;
|
||||
inc(StartPos);
|
||||
end;
|
||||
inc(StartPos);
|
||||
end;
|
||||
end;
|
||||
|
||||
function CheckSource(MinPos, MaxPos: integer): boolean;
|
||||
var
|
||||
StartPos: Integer;
|
||||
StartPos, AtomStart: Integer;
|
||||
LastTokenWasPoint, LastCommentTokenWasPoint: Boolean;
|
||||
begin
|
||||
Result:=true;
|
||||
@ -7647,8 +7666,10 @@ var
|
||||
|
||||
'a'..'z','A'..'Z','_','&':
|
||||
begin
|
||||
if not LastTokenWasPoint then
|
||||
if not CheckIdentifier(StartPos) then exit;
|
||||
if LastTokenWasPoint then
|
||||
inc(StartPos,GetIdentLen(@Src[StartPos]))
|
||||
else if not CheckIdentifier(StartPos) then
|
||||
exit;
|
||||
LastTokenWasPoint:=false;
|
||||
end;
|
||||
|
||||
@ -7658,6 +7679,9 @@ var
|
||||
inc(StartPos);
|
||||
end;
|
||||
|
||||
'$','0'..'9':
|
||||
// skip number, could contain letters
|
||||
ReadRawNextPascalAtom(Src,StartPos,AtomStart,Scanner.NestedComments);
|
||||
else
|
||||
LastTokenWasPoint:=false;
|
||||
inc(StartPos);
|
||||
|
@ -2382,6 +2382,8 @@ begin
|
||||
end;
|
||||
Node:=Node.Parent;
|
||||
until Node=nil;
|
||||
if Result='' then
|
||||
Result:='['+StartNode.DescAsString+']';
|
||||
|
||||
if RestoreCurPos then
|
||||
MoveCursorToAtomPos(OldPos);
|
||||
|
@ -819,9 +819,9 @@ begin
|
||||
repeat
|
||||
StartPos:=p;
|
||||
if KeepComments then
|
||||
p:=FindNextComment(CurSrc,FromPos,ToPos-1)
|
||||
p:=FindNextComment(CurSrc,p,ToPos-1)
|
||||
else
|
||||
p:=FindNextCompilerDirective(CurSrc,FromPos,Scanner.NestedComments,ToPos-1);
|
||||
p:=FindNextCompilerDirective(CurSrc,p,Scanner.NestedComments,ToPos-1);
|
||||
if p>ToPos then p:=ToPos;
|
||||
if p>StartPos then
|
||||
if not DeleteRange(Scanner,StartPos,p,false,false) then exit;
|
||||
|
@ -24,6 +24,7 @@ type
|
||||
protected
|
||||
procedure RenameReferences(NewIdentifier: string; const Flags: TFindRefsFlags = []);
|
||||
procedure RenameSourceName(NewName, NewFilename: string);
|
||||
procedure RenameUsedUnitRefs(UsedUnit: TCodeBuffer; NewName, NewFilename: string);
|
||||
procedure CheckDiff(CurCode: TCodeBuffer; const ExpLines: array of string);
|
||||
end;
|
||||
|
||||
@ -61,21 +62,16 @@ type
|
||||
procedure TestRenameProgramName_MakeDotted;
|
||||
procedure TestRenameProgramName_DottedAppendThird;
|
||||
procedure TestRenameProgramName_DottedPrependThird;
|
||||
procedure TestRenameProgramName_DottedShortenStart;
|
||||
procedure TestRenameProgramName_DottedShortenMiddle;
|
||||
procedure TestRenameProgramName_DottedShortenEnd;
|
||||
// todo: skip multiline string literals
|
||||
// todo: tskip multiline string literals
|
||||
|
||||
// rename uses
|
||||
// todo: rename unit &Type to &End
|
||||
// todo: rename unit Foo.Bar to Foo.Red
|
||||
// todo: rename unit Foo.Bar to Red.Bar
|
||||
// todo: rename unit Foo to Foo.Bar
|
||||
// todo: rename unit Foo.Bar to Foo
|
||||
// todo: rename unit Foo.Bar to Bar
|
||||
procedure TestRenameUsedUnit_Amp;
|
||||
// todo: search in an include file should not stop searching in other files
|
||||
// todo: missing used unit should not stop searching in other files
|
||||
// todo: rename with ifdefs
|
||||
// todo: rename with -FN, unit Foo.Bar to Foo.Red, uses Bar;
|
||||
// todo: rename a.b->c.d must not change { a.}b
|
||||
end;
|
||||
|
||||
implementation
|
||||
@ -180,16 +176,39 @@ begin
|
||||
ListOfSrcNameRefs:=nil;
|
||||
Files:=TStringList.Create;
|
||||
try
|
||||
// search pascal source references in Code
|
||||
Files.Add(Code.Filename);
|
||||
|
||||
// search pascal source references
|
||||
if not CodeToolBoss.FindSourceNameReferences(Code.Filename,Files,false,ListOfSrcNameRefs) then
|
||||
begin
|
||||
Fail('CodeToolBoss.FindSourceNameReferences failed File='+Code.Filename);
|
||||
end;
|
||||
// rename
|
||||
if not CodeToolBoss.RenameSourceNameReferences(Code.Filename,NewFilename,NewName,ListOfSrcNameRefs)
|
||||
then
|
||||
Fail('CodeToolBoss.RenameSourceNameReferences failed');
|
||||
finally
|
||||
ListOfSrcNameRefs.Free;
|
||||
Files.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
// todo: check for conflicts
|
||||
|
||||
procedure TCustomTestRefactoring.RenameUsedUnitRefs(UsedUnit: TCodeBuffer; NewName,
|
||||
NewFilename: string);
|
||||
var
|
||||
Files: TStringList;
|
||||
ListOfSrcNameRefs: TObjectList;
|
||||
begin
|
||||
// create the file list
|
||||
ListOfSrcNameRefs:=nil;
|
||||
Files:=TStringList.Create;
|
||||
try
|
||||
// search pascal source references in Code
|
||||
Files.Add(Code.Filename);
|
||||
if not CodeToolBoss.FindSourceNameReferences(UsedUnit.Filename,Files,false,ListOfSrcNameRefs) then
|
||||
begin
|
||||
Fail('CodeToolBoss.FindSourceNameReferences failed File='+Code.Filename);
|
||||
end;
|
||||
// rename
|
||||
if not CodeToolBoss.RenameSourceNameReferences(Code.Filename,NewFilename,NewName,ListOfSrcNameRefs)
|
||||
then
|
||||
Fail('CodeToolBoss.RenameSourceNameReferences failed');
|
||||
@ -1338,6 +1357,56 @@ begin
|
||||
'']);
|
||||
end;
|
||||
|
||||
procedure TTestRefactoring.TestRenameProgramName_DottedShortenStart;
|
||||
begin
|
||||
Add([
|
||||
'program &Type . Foo . Bar;',
|
||||
'{$mode objfpc}{$H+}',
|
||||
'type TRed = word;',
|
||||
'var c: &Type . Foo . Bar . TRed;',
|
||||
'begin',
|
||||
' &TYpe.foo.bar.c:=&Type . &foo . bar . &c;',
|
||||
' {$IFDEF FPC}&Type.{$ENDIF}foo.bar:={$IFDEF FPC}&Type.Foo.{$ENDIF}bar;',
|
||||
'end.',
|
||||
'']);
|
||||
RenameSourceName('Foo.Bar','foo.bar.pas');
|
||||
CheckDiff(Code,[
|
||||
'program Foo . Bar;',
|
||||
'{$mode objfpc}{$H+}',
|
||||
'type TRed = word;',
|
||||
'var c: Foo . Bar . TRed;',
|
||||
'begin',
|
||||
' Foo.Bar.c:=Foo . Bar . &c;',
|
||||
' {$IFDEF FPC}{$ENDIF}Foo.Bar:={$IFDEF FPC}Foo.{$ENDIF}Bar;',
|
||||
'end.',
|
||||
'']);
|
||||
end;
|
||||
|
||||
procedure TTestRefactoring.TestRenameProgramName_DottedShortenMiddle;
|
||||
begin
|
||||
Add([
|
||||
'program &Type . Foo . Bar;',
|
||||
'{$mode objfpc}{$H+}',
|
||||
'type TRed = word;',
|
||||
'var c: &Type . Foo . Bar . TRed;',
|
||||
'begin',
|
||||
' &TYpe.foo.bar.c:=&Type . &foo . bar . &c;',
|
||||
' {$ifdef fpc}&type.{$endif}foo{$ifdef fpc}.bar{$endif};',
|
||||
'end.',
|
||||
'']);
|
||||
RenameSourceName('&Type.Bar','type.bar.pas');
|
||||
CheckDiff(Code,[
|
||||
'program &Type .Bar;',
|
||||
'{$mode objfpc}{$H+}',
|
||||
'type TRed = word;',
|
||||
'var c: &Type .Bar . TRed;',
|
||||
'begin',
|
||||
' &Type.Bar.c:=&Type .Bar . &c;',
|
||||
' {$ifdef fpc}&Type.{$endif}{$ifdef fpc}Bar{$endif};',
|
||||
'end.',
|
||||
'']);
|
||||
end;
|
||||
|
||||
procedure TTestRefactoring.TestRenameProgramName_DottedShortenEnd;
|
||||
begin
|
||||
Add([
|
||||
@ -1361,6 +1430,51 @@ begin
|
||||
'']);
|
||||
end;
|
||||
|
||||
procedure TTestRefactoring.TestRenameUsedUnit_Amp;
|
||||
var
|
||||
UsedUnit: TCodeBuffer;
|
||||
begin
|
||||
UsedUnit:=nil;
|
||||
try
|
||||
UsedUnit:=CodeToolBoss.CreateFile('type.pp');
|
||||
UsedUnit.Source:='unit &Type;'+LineEnding
|
||||
+'interface'+LineEnding
|
||||
+'type'+LineEnding
|
||||
+' TAnt = word;'+LineEnding
|
||||
+' Ant: TAnt;'+LineEnding
|
||||
+'implementation'+LineEnding
|
||||
+'end.';
|
||||
|
||||
Add([
|
||||
'unit test1;',
|
||||
'{$mode objfpc}{$H+}',
|
||||
'interface',
|
||||
'uses &Type;',
|
||||
'var c: &Type . TAnt;',
|
||||
'implementation',
|
||||
'initialization',
|
||||
' &type.ant:=&Type . &ant;',
|
||||
'end.',
|
||||
'']);
|
||||
RenameUsedUnitRefs(UsedUnit,'&End','end.pas');
|
||||
CheckDiff(Code,[
|
||||
'unit test1;',
|
||||
'{$mode objfpc}{$H+}',
|
||||
'interface',
|
||||
'uses &End;',
|
||||
'var c: &End . TAnt;',
|
||||
'implementation',
|
||||
'initialization',
|
||||
' &End.ant:=&End . &ant;',
|
||||
'end.',
|
||||
'']);
|
||||
|
||||
finally
|
||||
if UsedUnit<>nil then
|
||||
UsedUnit.IsDeleted:=true;
|
||||
end;
|
||||
end;
|
||||
|
||||
initialization
|
||||
RegisterTests([TTestRefactoring]);
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user