mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-02 10:00:48 +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));
|
inc(p,GetIdentLen(StartP));
|
||||||
exit;
|
exit;
|
||||||
end;
|
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);
|
Expr:=ReadDottedIdentifier(Src,p,Scanner.NestedComments);
|
||||||
//debugln([' CheckIdentifier At ',CleanPosToStr(p),' Expr="',Expr,'"']);
|
//debugln([' CheckIdentifier At ',CleanPosToStr(p),' Expr="',Expr,'"']);
|
||||||
@ -7490,15 +7495,16 @@ var
|
|||||||
if Node.Desc=ctnSrcName then begin
|
if Node.Desc=ctnSrcName then begin
|
||||||
if IsSelf then
|
if IsSelf then
|
||||||
AddPos(StartPos);
|
AddPos(StartPos);
|
||||||
end else begin
|
end else if Node.Desc in [ctnUseUnitClearName,ctnUseUnitNamespace] then begin
|
||||||
// todo: found uses node
|
if Node.StartPos=LocalSrcNamePos then
|
||||||
|
AddPos(StartPos);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function CheckComment(var StartPos: integer; MaxPos: integer): boolean;
|
function CheckComment(var StartPos: integer; MaxPos: integer): boolean;
|
||||||
var
|
var
|
||||||
c: Char;
|
c: Char;
|
||||||
CommentLvl: Integer;
|
AtomStart, CommentLvl: Integer;
|
||||||
InStrConst, LastTokenWasPoint, IsDirective: Boolean;
|
InStrConst, LastTokenWasPoint, IsDirective: Boolean;
|
||||||
begin
|
begin
|
||||||
Result:=true;
|
Result:=true;
|
||||||
@ -7541,6 +7547,7 @@ var
|
|||||||
begin
|
begin
|
||||||
if (c='{') and Scanner.NestedComments then inc(CommentLvl);
|
if (c='{') and Scanner.NestedComments then inc(CommentLvl);
|
||||||
LastTokenWasPoint:=false;
|
LastTokenWasPoint:=false;
|
||||||
|
inc(StartPos);
|
||||||
end;
|
end;
|
||||||
'}':
|
'}':
|
||||||
begin
|
begin
|
||||||
@ -7552,6 +7559,7 @@ var
|
|||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
inc(StartPos);
|
||||||
end;
|
end;
|
||||||
')':
|
')':
|
||||||
begin
|
begin
|
||||||
@ -7560,6 +7568,7 @@ var
|
|||||||
inc(StartPos);
|
inc(StartPos);
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
inc(StartPos);
|
||||||
end;
|
end;
|
||||||
'a'..'z','A'..'Z','_','&':
|
'a'..'z','A'..'Z','_','&':
|
||||||
begin
|
begin
|
||||||
@ -7567,12 +7576,17 @@ var
|
|||||||
and (not LastTokenWasPoint) then
|
and (not LastTokenWasPoint) then
|
||||||
if not CheckIdentifier(StartPos) then exit(false);
|
if not CheckIdentifier(StartPos) then exit(false);
|
||||||
LastTokenWasPoint:=false;
|
LastTokenWasPoint:=false;
|
||||||
|
inc(StartPos,GetIdentLen(@Src[StartPos]));
|
||||||
end;
|
end;
|
||||||
'''':
|
'''':
|
||||||
begin
|
begin
|
||||||
InStrConst:=not InStrConst;
|
InStrConst:=not InStrConst;
|
||||||
LastTokenWasPoint:=false;
|
LastTokenWasPoint:=false;
|
||||||
|
inc(StartPos);
|
||||||
end;
|
end;
|
||||||
|
'$','0'..'9':
|
||||||
|
// skip number, could contain letters
|
||||||
|
ReadRawNextPascalAtom(Src,StartPos,AtomStart,Scanner.NestedComments);
|
||||||
#10,#13:
|
#10,#13:
|
||||||
begin
|
begin
|
||||||
InStrConst:=false;
|
InStrConst:=false;
|
||||||
@ -7583,19 +7597,24 @@ var
|
|||||||
inc(StartPos);
|
inc(StartPos);
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
inc(StartPos);
|
||||||
end;
|
end;
|
||||||
' ',#9: ;
|
' ',#9: inc(StartPos);
|
||||||
'.': LastTokenWasPoint:=true;
|
'.':
|
||||||
|
begin
|
||||||
|
LastTokenWasPoint:=true;
|
||||||
|
inc(StartPos);
|
||||||
|
end
|
||||||
else
|
else
|
||||||
LastTokenWasPoint:=false;
|
LastTokenWasPoint:=false;
|
||||||
end;
|
|
||||||
inc(StartPos);
|
inc(StartPos);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
function CheckSource(MinPos, MaxPos: integer): boolean;
|
function CheckSource(MinPos, MaxPos: integer): boolean;
|
||||||
var
|
var
|
||||||
StartPos: Integer;
|
StartPos, AtomStart: Integer;
|
||||||
LastTokenWasPoint, LastCommentTokenWasPoint: Boolean;
|
LastTokenWasPoint, LastCommentTokenWasPoint: Boolean;
|
||||||
begin
|
begin
|
||||||
Result:=true;
|
Result:=true;
|
||||||
@ -7647,8 +7666,10 @@ var
|
|||||||
|
|
||||||
'a'..'z','A'..'Z','_','&':
|
'a'..'z','A'..'Z','_','&':
|
||||||
begin
|
begin
|
||||||
if not LastTokenWasPoint then
|
if LastTokenWasPoint then
|
||||||
if not CheckIdentifier(StartPos) then exit;
|
inc(StartPos,GetIdentLen(@Src[StartPos]))
|
||||||
|
else if not CheckIdentifier(StartPos) then
|
||||||
|
exit;
|
||||||
LastTokenWasPoint:=false;
|
LastTokenWasPoint:=false;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -7658,6 +7679,9 @@ var
|
|||||||
inc(StartPos);
|
inc(StartPos);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
'$','0'..'9':
|
||||||
|
// skip number, could contain letters
|
||||||
|
ReadRawNextPascalAtom(Src,StartPos,AtomStart,Scanner.NestedComments);
|
||||||
else
|
else
|
||||||
LastTokenWasPoint:=false;
|
LastTokenWasPoint:=false;
|
||||||
inc(StartPos);
|
inc(StartPos);
|
||||||
|
@ -2382,6 +2382,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
Node:=Node.Parent;
|
Node:=Node.Parent;
|
||||||
until Node=nil;
|
until Node=nil;
|
||||||
|
if Result='' then
|
||||||
|
Result:='['+StartNode.DescAsString+']';
|
||||||
|
|
||||||
if RestoreCurPos then
|
if RestoreCurPos then
|
||||||
MoveCursorToAtomPos(OldPos);
|
MoveCursorToAtomPos(OldPos);
|
||||||
|
@ -819,9 +819,9 @@ begin
|
|||||||
repeat
|
repeat
|
||||||
StartPos:=p;
|
StartPos:=p;
|
||||||
if KeepComments then
|
if KeepComments then
|
||||||
p:=FindNextComment(CurSrc,FromPos,ToPos-1)
|
p:=FindNextComment(CurSrc,p,ToPos-1)
|
||||||
else
|
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>ToPos then p:=ToPos;
|
||||||
if p>StartPos then
|
if p>StartPos then
|
||||||
if not DeleteRange(Scanner,StartPos,p,false,false) then exit;
|
if not DeleteRange(Scanner,StartPos,p,false,false) then exit;
|
||||||
|
@ -24,6 +24,7 @@ type
|
|||||||
protected
|
protected
|
||||||
procedure RenameReferences(NewIdentifier: string; const Flags: TFindRefsFlags = []);
|
procedure RenameReferences(NewIdentifier: string; const Flags: TFindRefsFlags = []);
|
||||||
procedure RenameSourceName(NewName, NewFilename: string);
|
procedure RenameSourceName(NewName, NewFilename: string);
|
||||||
|
procedure RenameUsedUnitRefs(UsedUnit: TCodeBuffer; NewName, NewFilename: string);
|
||||||
procedure CheckDiff(CurCode: TCodeBuffer; const ExpLines: array of string);
|
procedure CheckDiff(CurCode: TCodeBuffer; const ExpLines: array of string);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -61,21 +62,16 @@ type
|
|||||||
procedure TestRenameProgramName_MakeDotted;
|
procedure TestRenameProgramName_MakeDotted;
|
||||||
procedure TestRenameProgramName_DottedAppendThird;
|
procedure TestRenameProgramName_DottedAppendThird;
|
||||||
procedure TestRenameProgramName_DottedPrependThird;
|
procedure TestRenameProgramName_DottedPrependThird;
|
||||||
|
procedure TestRenameProgramName_DottedShortenStart;
|
||||||
|
procedure TestRenameProgramName_DottedShortenMiddle;
|
||||||
procedure TestRenameProgramName_DottedShortenEnd;
|
procedure TestRenameProgramName_DottedShortenEnd;
|
||||||
// todo: skip multiline string literals
|
// todo: tskip multiline string literals
|
||||||
|
|
||||||
// rename uses
|
// rename uses
|
||||||
// todo: rename unit &Type to &End
|
procedure TestRenameUsedUnit_Amp;
|
||||||
// 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
|
|
||||||
// todo: search in an include file should not stop searching in other files
|
// 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: 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 with -FN, unit Foo.Bar to Foo.Red, uses Bar;
|
||||||
// todo: rename a.b->c.d must not change { a.}b
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@ -180,16 +176,39 @@ begin
|
|||||||
ListOfSrcNameRefs:=nil;
|
ListOfSrcNameRefs:=nil;
|
||||||
Files:=TStringList.Create;
|
Files:=TStringList.Create;
|
||||||
try
|
try
|
||||||
|
// search pascal source references in Code
|
||||||
Files.Add(Code.Filename);
|
Files.Add(Code.Filename);
|
||||||
|
|
||||||
// search pascal source references
|
|
||||||
if not CodeToolBoss.FindSourceNameReferences(Code.Filename,Files,false,ListOfSrcNameRefs) then
|
if not CodeToolBoss.FindSourceNameReferences(Code.Filename,Files,false,ListOfSrcNameRefs) then
|
||||||
begin
|
begin
|
||||||
Fail('CodeToolBoss.FindSourceNameReferences failed File='+Code.Filename);
|
Fail('CodeToolBoss.FindSourceNameReferences failed File='+Code.Filename);
|
||||||
end;
|
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)
|
if not CodeToolBoss.RenameSourceNameReferences(Code.Filename,NewFilename,NewName,ListOfSrcNameRefs)
|
||||||
then
|
then
|
||||||
Fail('CodeToolBoss.RenameSourceNameReferences failed');
|
Fail('CodeToolBoss.RenameSourceNameReferences failed');
|
||||||
@ -1338,6 +1357,56 @@ begin
|
|||||||
'']);
|
'']);
|
||||||
end;
|
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;
|
procedure TTestRefactoring.TestRenameProgramName_DottedShortenEnd;
|
||||||
begin
|
begin
|
||||||
Add([
|
Add([
|
||||||
@ -1361,6 +1430,51 @@ begin
|
|||||||
'']);
|
'']);
|
||||||
end;
|
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
|
initialization
|
||||||
RegisterTests([TTestRefactoring]);
|
RegisterTests([TTestRefactoring]);
|
||||||
end.
|
end.
|
||||||
|
Loading…
Reference in New Issue
Block a user