mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-11-23 21:19:35 +01:00
codetools: RemoveUnitFromUsesSection: when removing the last unit remove empty lines in front too, bug #18055
git-svn-id: trunk@28498 -
This commit is contained in:
parent
23252ff1fe
commit
94948dde5e
@ -109,7 +109,8 @@ function IsFirstNonSpaceCharInLine(const Source: string;
|
|||||||
Position: integer): boolean;
|
Position: integer): boolean;
|
||||||
function FindLineEndOrCodeInFrontOfPosition(const Source: string;
|
function FindLineEndOrCodeInFrontOfPosition(const Source: string;
|
||||||
Position, MinPosition: integer; NestedComments: boolean;
|
Position, MinPosition: integer; NestedComments: boolean;
|
||||||
StopAtDirectives: boolean = true; SkipSemicolonComma: boolean = true): integer;
|
StopAtDirectives: boolean = true; SkipSemicolonComma: boolean = true;
|
||||||
|
SkipEmptyLines: boolean = false): integer;
|
||||||
function FindLineEndOrCodeAfterPosition(const Source: string;
|
function FindLineEndOrCodeAfterPosition(const Source: string;
|
||||||
Position, MaxPosition: integer; NestedComments: boolean;
|
Position, MaxPosition: integer; NestedComments: boolean;
|
||||||
StopAtDirectives: boolean = true; SkipEmptyLines: boolean = false;
|
StopAtDirectives: boolean = true; SkipEmptyLines: boolean = false;
|
||||||
@ -2464,10 +2465,13 @@ end;
|
|||||||
|
|
||||||
function FindLineEndOrCodeInFrontOfPosition(const Source: string;
|
function FindLineEndOrCodeInFrontOfPosition(const Source: string;
|
||||||
Position, MinPosition: integer; NestedComments: boolean;
|
Position, MinPosition: integer; NestedComments: boolean;
|
||||||
StopAtDirectives: boolean; SkipSemicolonComma: boolean): integer;
|
StopAtDirectives: boolean; SkipSemicolonComma: boolean;
|
||||||
|
SkipEmptyLines: boolean): integer;
|
||||||
{ search backward for a line end or code
|
{ search backward for a line end or code
|
||||||
ignore line ends in comments or at the end of comment lines
|
ignore line ends in comments or at the end of comment lines
|
||||||
(comment lines are lines without code and at least one comment)
|
(comment lines are lines without code and at least one comment)
|
||||||
|
comment lines directly in front are skipped too
|
||||||
|
if SkipEmptyLines=true then empty lines are skipped too.
|
||||||
Result is Position of Start of Line End
|
Result is Position of Start of Line End
|
||||||
|
|
||||||
examples: Position points at char 'a'
|
examples: Position points at char 'a'
|
||||||
@ -2585,6 +2589,28 @@ begin
|
|||||||
if IsEmpty then begin
|
if IsEmpty then begin
|
||||||
// the line is empty => return start of line end
|
// the line is empty => return start of line end
|
||||||
Result:=LineEndPos;
|
Result:=LineEndPos;
|
||||||
|
if SkipEmptyLines then begin
|
||||||
|
// skip all empty lines
|
||||||
|
LineStartPos:=Result;
|
||||||
|
while (LineStartPos>SrcStart) do begin
|
||||||
|
case Source[LineStartPos-1] of
|
||||||
|
#10,#13:
|
||||||
|
begin
|
||||||
|
// empty line
|
||||||
|
LineEndPos:=LineStartPos-1;
|
||||||
|
if (LineEndPos>SrcStart) and (Source[LineEndPos-1] in [#10,#13])
|
||||||
|
and (Source[LineEndPos]<>Source[LineEndPos-1]) then
|
||||||
|
dec(LineEndPos);
|
||||||
|
Result:=LineEndPos;
|
||||||
|
end;
|
||||||
|
' ',#9: ;
|
||||||
|
else
|
||||||
|
// not empty
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
dec(LineStartPos);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
TestPos:=LineStartPos;
|
TestPos:=LineStartPos;
|
||||||
|
|||||||
@ -231,7 +231,7 @@ type
|
|||||||
function FindLineEndOrCodeAfterPosition(StartPos: integer;
|
function FindLineEndOrCodeAfterPosition(StartPos: integer;
|
||||||
SkipEmptyLines: boolean = false; IncludeLineEnd: boolean = false): integer;
|
SkipEmptyLines: boolean = false; IncludeLineEnd: boolean = false): integer;
|
||||||
function FindLineEndOrCodeInFrontOfPosition(StartPos: integer;
|
function FindLineEndOrCodeInFrontOfPosition(StartPos: integer;
|
||||||
StopAtDirectives: boolean = true): integer;
|
StopAtDirectives: boolean = true; SkipEmptyLines: boolean = false): integer;
|
||||||
|
|
||||||
function UpdateNeeded(OnlyInterfaceNeeded: boolean): boolean;
|
function UpdateNeeded(OnlyInterfaceNeeded: boolean): boolean;
|
||||||
procedure BeginParsing(DeleteNodes, OnlyInterfaceNeeded: boolean); virtual;
|
procedure BeginParsing(DeleteNodes, OnlyInterfaceNeeded: boolean); virtual;
|
||||||
@ -2601,7 +2601,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
function TCustomCodeTool.FindLineEndOrCodeInFrontOfPosition(StartPos: integer;
|
function TCustomCodeTool.FindLineEndOrCodeInFrontOfPosition(StartPos: integer;
|
||||||
StopAtDirectives: boolean): integer;
|
StopAtDirectives: boolean; SkipEmptyLines: boolean): integer;
|
||||||
{ Searches a nice position in the cleaned source in front of StartPos.
|
{ Searches a nice position in the cleaned source in front of StartPos.
|
||||||
It will skip any space or comments (not directives) till next
|
It will skip any space or comments (not directives) till next
|
||||||
line end or compiler directive or code or include file end.
|
line end or compiler directive or code or include file end.
|
||||||
@ -2612,7 +2612,8 @@ begin
|
|||||||
LinkIndex:=Scanner.LinkIndexAtCleanPos(StartPos);
|
LinkIndex:=Scanner.LinkIndexAtCleanPos(StartPos);
|
||||||
LinkStart:=Scanner.Links[LinkIndex].CleanedPos;
|
LinkStart:=Scanner.Links[LinkIndex].CleanedPos;
|
||||||
Result:=BasicCodeTools.FindLineEndOrCodeInFrontOfPosition(Src,
|
Result:=BasicCodeTools.FindLineEndOrCodeInFrontOfPosition(Src,
|
||||||
StartPos,LinkStart,Scanner.NestedComments,StopAtDirectives,false);
|
StartPos,LinkStart,Scanner.NestedComments,StopAtDirectives,false,
|
||||||
|
SkipEmptyLines);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCustomCodeTool.ClearIgnoreErrorAfter;
|
procedure TCustomCodeTool.ClearIgnoreErrorAfter;
|
||||||
|
|||||||
@ -1,19 +1,18 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<CONFIG>
|
<CONFIG>
|
||||||
<ProjectOptions>
|
<ProjectOptions>
|
||||||
<Version Value="7"/>
|
<Version Value="9"/>
|
||||||
<General>
|
<General>
|
||||||
<Flags>
|
<Flags>
|
||||||
<LRSInOutputDirectory Value="False"/>
|
<LRSInOutputDirectory Value="False"/>
|
||||||
</Flags>
|
</Flags>
|
||||||
<SessionStorage Value="InProjectDir"/>
|
<SessionStorage Value="InProjectDir"/>
|
||||||
<MainUnit Value="0"/>
|
<MainUnit Value="0"/>
|
||||||
<TargetFileExt Value=""/>
|
|
||||||
<Title Value="finddeclaration"/>
|
<Title Value="finddeclaration"/>
|
||||||
</General>
|
</General>
|
||||||
<VersionInfo>
|
<BuildModes Count="1">
|
||||||
<StringTable Comments="" CompanyName="" FileDescription="" FileVersion="0.0.0.0" InternalName="" LegalCopyright="" LegalTrademarks="" OriginalFilename="" ProductName="" ProductVersion="0.0.0.0"/>
|
<Item1 Name="default" Default="True"/>
|
||||||
</VersionInfo>
|
</BuildModes>
|
||||||
<PublishOptions>
|
<PublishOptions>
|
||||||
<Version Value="2"/>
|
<Version Value="2"/>
|
||||||
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
|
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
|
||||||
@ -50,7 +49,7 @@
|
|||||||
<CompilerOptions>
|
<CompilerOptions>
|
||||||
<Version Value="9"/>
|
<Version Value="9"/>
|
||||||
<SearchPaths>
|
<SearchPaths>
|
||||||
<OtherUnitFiles Value="scanexamples/"/>
|
<OtherUnitFiles Value="scanexamples"/>
|
||||||
</SearchPaths>
|
</SearchPaths>
|
||||||
<Parsing>
|
<Parsing>
|
||||||
<SyntaxOptions>
|
<SyntaxOptions>
|
||||||
|
|||||||
@ -1086,8 +1086,10 @@ begin
|
|||||||
// first unit in uses section
|
// first unit in uses section
|
||||||
if AtomIsChar(';') then begin
|
if AtomIsChar(';') then begin
|
||||||
// last unit in uses section -> delete whole uses section
|
// last unit in uses section -> delete whole uses section
|
||||||
|
StartPos:=FindLineEndOrCodeInFrontOfPosition(UsesNode.StartPos,true,true);
|
||||||
|
debugln(['TStandardCodeTool.RemoveUnitFromUsesSection AAA1 "',dbgstr(copy(Src,StartPos,UsesNode.EndPos-StartPos)),'"']);
|
||||||
if not SourceChangeCache.Replace(gtNone,gtNone,
|
if not SourceChangeCache.Replace(gtNone,gtNone,
|
||||||
UsesNode.StartPos,UsesNode.EndPos,'') then exit;
|
StartPos,UsesNode.EndPos,'') then exit;
|
||||||
end else begin
|
end else begin
|
||||||
// not last unit -> delete with comma behind
|
// not last unit -> delete with comma behind
|
||||||
EndPos:=FindLineEndOrCodeAfterPosition(CurPos.EndPos);
|
EndPos:=FindLineEndOrCodeAfterPosition(CurPos.EndPos);
|
||||||
|
|||||||
@ -27,10 +27,14 @@
|
|||||||
<LaunchingApplication PathPlusParams="/usr/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
|
<LaunchingApplication PathPlusParams="/usr/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
|
||||||
</local>
|
</local>
|
||||||
</RunParams>
|
</RunParams>
|
||||||
<RequiredPackages Count="1">
|
<RequiredPackages Count="2">
|
||||||
<Item1>
|
<Item1>
|
||||||
<PackageName Value="LCL"/>
|
<PackageName Value="CodeTools"/>
|
||||||
|
<MinVersion Major="1" Release="1" Valid="True"/>
|
||||||
</Item1>
|
</Item1>
|
||||||
|
<Item2>
|
||||||
|
<PackageName Value="LCL"/>
|
||||||
|
</Item2>
|
||||||
</RequiredPackages>
|
</RequiredPackages>
|
||||||
<Units Count="2">
|
<Units Count="2">
|
||||||
<Unit0>
|
<Unit0>
|
||||||
|
|||||||
@ -6,7 +6,7 @@ interface
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, LCLProc,
|
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, LCLProc,
|
||||||
contnrs;
|
contnrs, XMLRead;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
@ -41,16 +41,12 @@ type
|
|||||||
procedure FixFPDocFragment(var Fragment: string; Fix: boolean;
|
procedure FixFPDocFragment(var Fragment: string; Fix: boolean;
|
||||||
out ErrorList: TObjectList);
|
out ErrorList: TObjectList);
|
||||||
{ - Fix all tags to lowercase to reduce svn commits
|
{ - Fix all tags to lowercase to reduce svn commits
|
||||||
- remove unneeded spaces
|
|
||||||
< b => <b
|
|
||||||
b > => b>
|
|
||||||
a b => a b
|
|
||||||
- auto close comments
|
- auto close comments
|
||||||
- remove #0 from comments
|
- remove #0 from comments
|
||||||
- auto close unclosed tags
|
|
||||||
- fix & without ;
|
|
||||||
- convert special characters to &x;
|
- convert special characters to &x;
|
||||||
|
- fix &name; lower case
|
||||||
- fix unclosed attribute values
|
- fix unclosed attribute values
|
||||||
|
- auto close unclosed tags
|
||||||
}
|
}
|
||||||
type
|
type
|
||||||
TStackItemTyp = (
|
TStackItemTyp = (
|
||||||
@ -292,6 +288,125 @@ var
|
|||||||
HandleSpecialChar;
|
HandleSpecialChar;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure LowerCaseName;
|
||||||
|
var
|
||||||
|
Start: PChar;
|
||||||
|
NeedLowercase: PChar;
|
||||||
|
begin
|
||||||
|
Start:=p;
|
||||||
|
NeedLowercase:=nil;
|
||||||
|
repeat
|
||||||
|
case p^ of
|
||||||
|
'a'..'z': inc(p);
|
||||||
|
'A'..'Z':
|
||||||
|
begin
|
||||||
|
inc(p);
|
||||||
|
if NeedLowercase=nil then
|
||||||
|
NeedLowercase:=p;
|
||||||
|
end;
|
||||||
|
else break;
|
||||||
|
end;
|
||||||
|
until false;
|
||||||
|
if NeedLowercase<>nil then begin
|
||||||
|
if Fix then begin
|
||||||
|
Replace(Rel(Start),p-Start,lowercase(copy(Fragment,Rel(Start),p-Start)));
|
||||||
|
end else begin
|
||||||
|
// all current tags must be lower case
|
||||||
|
Error(NeedLowercase,'tags must be lower case');
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure ParseAttribute;
|
||||||
|
begin
|
||||||
|
// attribute name
|
||||||
|
LowerCaseName;
|
||||||
|
while p^ in [' ',#9,#10,#13] do inc(p); // skip space
|
||||||
|
if p^<>'=' then begin
|
||||||
|
// missing value
|
||||||
|
if Fix then begin
|
||||||
|
Replace(Rel(p),0,'=');
|
||||||
|
end else begin
|
||||||
|
Error(p,'expected =');
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
if p^='=' then begin
|
||||||
|
inc(p);
|
||||||
|
while p^ in [' ',#9,#10,#13] do inc(p); // skip space
|
||||||
|
if p^<>'"' then begin
|
||||||
|
// missing quotes
|
||||||
|
if Fix then begin
|
||||||
|
Replace(Rel(p),0,'"');
|
||||||
|
end else begin
|
||||||
|
Error(p,'expected "');
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
if p^='"' then begin
|
||||||
|
// read value
|
||||||
|
inc(p);
|
||||||
|
repeat
|
||||||
|
case p^ of
|
||||||
|
'>',#0..#8,#11,#12,#14..#31,#127:
|
||||||
|
// the > is not allowed in the quotes, probably the ending quot is missing
|
||||||
|
if Fix then begin
|
||||||
|
Replace(Rel(p),0,'"');
|
||||||
|
end else begin
|
||||||
|
Error(p,'expected ending "');
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
'&':
|
||||||
|
ParseAmpersand;
|
||||||
|
'"':
|
||||||
|
begin
|
||||||
|
inc(p);
|
||||||
|
break;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
inc(p);
|
||||||
|
end;
|
||||||
|
until false;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure ParseLowerThan;
|
||||||
|
begin
|
||||||
|
// comment, tag or 'lower than'
|
||||||
|
if (p[1]='!') and (p[2]='-') and (p[3]='-') then begin
|
||||||
|
// comment
|
||||||
|
ParseComment;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
if p[1] in ['a'..'z','A'..'Z'] then begin
|
||||||
|
// open tag
|
||||||
|
Push(sitTag);
|
||||||
|
TopItem^.StartPos:=Rel(p);
|
||||||
|
inc(p);
|
||||||
|
TopItem^.NameStartPos:=Rel(p);
|
||||||
|
LowerCaseName;
|
||||||
|
TopItem^.NameEndPos:=Rel(p);
|
||||||
|
while p^ in [' ',#9,#10,#13] do inc(p); // skip space
|
||||||
|
case p^ of
|
||||||
|
'a'..'z','A'..'Z':
|
||||||
|
ParseAttribute;
|
||||||
|
'/':
|
||||||
|
begin
|
||||||
|
// ToDo: close tag
|
||||||
|
RaiseGDBException('ToDo');
|
||||||
|
end;
|
||||||
|
'>':
|
||||||
|
begin
|
||||||
|
// ToDo:
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end else if p[1]='/' then begin
|
||||||
|
// ToDo: close tag
|
||||||
|
RaiseGDBException('ToDo');
|
||||||
|
end;
|
||||||
|
// invalid character => convert or skip
|
||||||
|
HandleSpecialChar;
|
||||||
|
end;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
ErrorList:=nil;
|
ErrorList:=nil;
|
||||||
if Fragment='' then exit;
|
if Fragment='' then exit;
|
||||||
@ -314,16 +429,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
'<':
|
'<':
|
||||||
begin
|
ParseLowerThan;
|
||||||
// comment, tag or 'lower than'
|
|
||||||
if (p[1]='!') and (p[2]='-') and (p[3]='-') then
|
|
||||||
// comment
|
|
||||||
ParseComment
|
|
||||||
else begin
|
|
||||||
// invalid character => convert or skip
|
|
||||||
HandleSpecialChar;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
'>':
|
'>':
|
||||||
// invalid character => convert or skip
|
// invalid character => convert or skip
|
||||||
HandleSpecialChar;
|
HandleSpecialChar;
|
||||||
@ -346,8 +452,8 @@ end;
|
|||||||
|
|
||||||
procedure TForm1.FormCreate(Sender: TObject);
|
procedure TForm1.FormCreate(Sender: TObject);
|
||||||
begin
|
begin
|
||||||
TestComment;
|
//TestComment;
|
||||||
TestInvalidCharacters;
|
//TestInvalidCharacters;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TForm1.TestComment;
|
procedure TForm1.TestComment;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user