mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-13 12:59:19 +02: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;
|
||||
function FindLineEndOrCodeInFrontOfPosition(const Source: string;
|
||||
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;
|
||||
Position, MaxPosition: integer; NestedComments: boolean;
|
||||
StopAtDirectives: boolean = true; SkipEmptyLines: boolean = false;
|
||||
@ -2463,11 +2464,14 @@ begin
|
||||
end;
|
||||
|
||||
function FindLineEndOrCodeInFrontOfPosition(const Source: string;
|
||||
Position, MinPosition: integer; NestedComments: boolean;
|
||||
StopAtDirectives: boolean; SkipSemicolonComma: boolean): integer;
|
||||
Position, MinPosition: integer; NestedComments: boolean;
|
||||
StopAtDirectives: boolean; SkipSemicolonComma: boolean;
|
||||
SkipEmptyLines: boolean): integer;
|
||||
{ search backward for a line end or code
|
||||
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 directly in front are skipped too
|
||||
if SkipEmptyLines=true then empty lines are skipped too.
|
||||
Result is Position of Start of Line End
|
||||
|
||||
examples: Position points at char 'a'
|
||||
@ -2585,6 +2589,28 @@ begin
|
||||
if IsEmpty then begin
|
||||
// the line is empty => return start of line end
|
||||
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;
|
||||
end;
|
||||
TestPos:=LineStartPos;
|
||||
|
@ -231,7 +231,7 @@ type
|
||||
function FindLineEndOrCodeAfterPosition(StartPos: integer;
|
||||
SkipEmptyLines: boolean = false; IncludeLineEnd: boolean = false): integer;
|
||||
function FindLineEndOrCodeInFrontOfPosition(StartPos: integer;
|
||||
StopAtDirectives: boolean = true): integer;
|
||||
StopAtDirectives: boolean = true; SkipEmptyLines: boolean = false): integer;
|
||||
|
||||
function UpdateNeeded(OnlyInterfaceNeeded: boolean): boolean;
|
||||
procedure BeginParsing(DeleteNodes, OnlyInterfaceNeeded: boolean); virtual;
|
||||
@ -2601,7 +2601,7 @@ begin
|
||||
end;
|
||||
|
||||
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.
|
||||
It will skip any space or comments (not directives) till next
|
||||
line end or compiler directive or code or include file end.
|
||||
@ -2612,7 +2612,8 @@ begin
|
||||
LinkIndex:=Scanner.LinkIndexAtCleanPos(StartPos);
|
||||
LinkStart:=Scanner.Links[LinkIndex].CleanedPos;
|
||||
Result:=BasicCodeTools.FindLineEndOrCodeInFrontOfPosition(Src,
|
||||
StartPos,LinkStart,Scanner.NestedComments,StopAtDirectives,false);
|
||||
StartPos,LinkStart,Scanner.NestedComments,StopAtDirectives,false,
|
||||
SkipEmptyLines);
|
||||
end;
|
||||
|
||||
procedure TCustomCodeTool.ClearIgnoreErrorAfter;
|
||||
|
@ -1,19 +1,18 @@
|
||||
<?xml version="1.0"?>
|
||||
<CONFIG>
|
||||
<ProjectOptions>
|
||||
<Version Value="7"/>
|
||||
<Version Value="9"/>
|
||||
<General>
|
||||
<Flags>
|
||||
<LRSInOutputDirectory Value="False"/>
|
||||
</Flags>
|
||||
<SessionStorage Value="InProjectDir"/>
|
||||
<MainUnit Value="0"/>
|
||||
<TargetFileExt Value=""/>
|
||||
<Title Value="finddeclaration"/>
|
||||
</General>
|
||||
<VersionInfo>
|
||||
<StringTable Comments="" CompanyName="" FileDescription="" FileVersion="0.0.0.0" InternalName="" LegalCopyright="" LegalTrademarks="" OriginalFilename="" ProductName="" ProductVersion="0.0.0.0"/>
|
||||
</VersionInfo>
|
||||
<BuildModes Count="1">
|
||||
<Item1 Name="default" Default="True"/>
|
||||
</BuildModes>
|
||||
<PublishOptions>
|
||||
<Version Value="2"/>
|
||||
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
|
||||
@ -50,7 +49,7 @@
|
||||
<CompilerOptions>
|
||||
<Version Value="9"/>
|
||||
<SearchPaths>
|
||||
<OtherUnitFiles Value="scanexamples/"/>
|
||||
<OtherUnitFiles Value="scanexamples"/>
|
||||
</SearchPaths>
|
||||
<Parsing>
|
||||
<SyntaxOptions>
|
||||
|
@ -1086,8 +1086,10 @@ begin
|
||||
// first unit in uses section
|
||||
if AtomIsChar(';') then begin
|
||||
// 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,
|
||||
UsesNode.StartPos,UsesNode.EndPos,'') then exit;
|
||||
StartPos,UsesNode.EndPos,'') then exit;
|
||||
end else begin
|
||||
// not last unit -> delete with comma behind
|
||||
EndPos:=FindLineEndOrCodeAfterPosition(CurPos.EndPos);
|
||||
|
@ -27,10 +27,14 @@
|
||||
<LaunchingApplication PathPlusParams="/usr/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
|
||||
</local>
|
||||
</RunParams>
|
||||
<RequiredPackages Count="1">
|
||||
<RequiredPackages Count="2">
|
||||
<Item1>
|
||||
<PackageName Value="LCL"/>
|
||||
<PackageName Value="CodeTools"/>
|
||||
<MinVersion Major="1" Release="1" Valid="True"/>
|
||||
</Item1>
|
||||
<Item2>
|
||||
<PackageName Value="LCL"/>
|
||||
</Item2>
|
||||
</RequiredPackages>
|
||||
<Units Count="2">
|
||||
<Unit0>
|
||||
|
@ -6,7 +6,7 @@ interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, LCLProc,
|
||||
contnrs;
|
||||
contnrs, XMLRead;
|
||||
|
||||
type
|
||||
|
||||
@ -41,16 +41,12 @@ type
|
||||
procedure FixFPDocFragment(var Fragment: string; Fix: boolean;
|
||||
out ErrorList: TObjectList);
|
||||
{ - Fix all tags to lowercase to reduce svn commits
|
||||
- remove unneeded spaces
|
||||
< b => <b
|
||||
b > => b>
|
||||
a b => a b
|
||||
- auto close comments
|
||||
- remove #0 from comments
|
||||
- auto close unclosed tags
|
||||
- fix & without ;
|
||||
- convert special characters to &x;
|
||||
- fix &name; lower case
|
||||
- fix unclosed attribute values
|
||||
- auto close unclosed tags
|
||||
}
|
||||
type
|
||||
TStackItemTyp = (
|
||||
@ -292,6 +288,125 @@ var
|
||||
HandleSpecialChar;
|
||||
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
|
||||
ErrorList:=nil;
|
||||
if Fragment='' then exit;
|
||||
@ -314,16 +429,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
'<':
|
||||
begin
|
||||
// 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;
|
||||
ParseLowerThan;
|
||||
'>':
|
||||
// invalid character => convert or skip
|
||||
HandleSpecialChar;
|
||||
@ -346,8 +452,8 @@ end;
|
||||
|
||||
procedure TForm1.FormCreate(Sender: TObject);
|
||||
begin
|
||||
TestComment;
|
||||
TestInvalidCharacters;
|
||||
//TestComment;
|
||||
//TestInvalidCharacters;
|
||||
end;
|
||||
|
||||
procedure TForm1.TestComment;
|
||||
|
Loading…
Reference in New Issue
Block a user