mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-12-10 00:17:18 +01:00
codetools: RemoveWithBlock: unindent
git-svn-id: trunk@30614 -
This commit is contained in:
parent
56884905ce
commit
934a90187a
@ -63,9 +63,10 @@ begin
|
||||
if Code=nil then
|
||||
raise Exception.Create('loading failed: '+Filename);
|
||||
|
||||
// parse the unit
|
||||
// parse the unit and remove the with variable
|
||||
if not CodeToolBoss.RemoveWithBlock(Code,X,Y) then
|
||||
raise Exception.Create('RemoveWithBlock failed');
|
||||
|
||||
// write the new source:
|
||||
writeln('-----------------------------------');
|
||||
writeln('New source:');
|
||||
|
||||
@ -39,6 +39,7 @@ begin
|
||||
Name:='name of TSon1';
|
||||
with Son2 do begin
|
||||
Name:='name of TSon2';
|
||||
//
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -37,7 +37,7 @@ unit ExtractProcTool;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
{$define CTDEBUG}
|
||||
{ $define CTDEBUG}
|
||||
|
||||
interface
|
||||
|
||||
@ -1166,7 +1166,9 @@ var
|
||||
p:=Pointer(PtrUInt(CleanPos));
|
||||
if WithIdentifiers=nil then WithIdentifiers:=TAVLTree.Create;
|
||||
if WithIdentifiers.Find(p)<>nil then exit;
|
||||
{$IFDEF CTDEBUG}
|
||||
debugln(['AddIdentifier ',GetIdentifier(@Src[CleanPos])]);
|
||||
{$ENDIF}
|
||||
WithIdentifiers.Add(p);
|
||||
end;
|
||||
|
||||
@ -1189,7 +1191,9 @@ var
|
||||
Cache:=PWithVarCache(WithVarCache[i]);
|
||||
end else begin
|
||||
// resolve type of With variable
|
||||
{$IFDEF CTDEBUG}
|
||||
debugln(['IdentifierDefinedByWith NEW WithVar']);
|
||||
{$ENDIF}
|
||||
New(Cache);
|
||||
WithVarCache.Add(Cache);
|
||||
Cache^.WithVarNode:=WithVarNode;
|
||||
@ -1208,7 +1212,9 @@ var
|
||||
MoveCursorToCleanPos(Cache^.WithVarNode.StartPos);
|
||||
RaiseException(ctsExprTypeMustBeClassOrRecord);
|
||||
end;
|
||||
{$IFDEF CTDEBUG}
|
||||
debugln(['IdentifierDefinedByWith WithVarExpr=',ExprTypeToString(Cache^.WithVarExpr)]);
|
||||
{$ENDIF}
|
||||
finally
|
||||
Params.Free;
|
||||
end;
|
||||
@ -1223,7 +1229,9 @@ var
|
||||
Params.Flags:=[fdfSearchInAncestors];
|
||||
Params.ContextNode:=Cache^.WithVarExpr.Context.Node;
|
||||
Result:=Cache^.WithVarExpr.Context.Tool.FindIdentifierInContext(Params);
|
||||
{$IFDEF CTDEBUG}
|
||||
debugln(['IdentifierDefinedByWith Identifier=',GetIdentifier(@Src[CleanPos]),' FoundInWith=',Result,' WithVar="',dbgstr(Src,WithVarNode.StartPos,10),'"']);
|
||||
{$ENDIF}
|
||||
finally
|
||||
Params.Free;
|
||||
end;
|
||||
@ -1287,6 +1295,8 @@ var
|
||||
DoKeywordEndPos: Integer;
|
||||
EndKeywordStartPos: LongInt;
|
||||
EndKeywordEndPos: LongInt;
|
||||
IndentWith: LongInt;
|
||||
IndentInnerWith: LongInt;
|
||||
begin
|
||||
SourceChangeCache.MainScanner:=Scanner;
|
||||
|
||||
@ -1325,15 +1335,28 @@ var
|
||||
break;
|
||||
end;
|
||||
until (CurPos.StartPos>SrcLen) or (CurPos.StartPos>StatementNode.EndPos);
|
||||
IndentWith:=GetLineIndentWithTabs(Src,WithKeywordStartPos,
|
||||
SourceChangeCache.BeautifyCodeOptions.TabWidth);
|
||||
WithKeywordStartPos:=FindLineEndOrCodeInFrontOfPosition(WithKeywordStartPos);
|
||||
DoKeywordEndPos:=FindLineEndOrCodeAfterPosition(DoKeywordEndPos);
|
||||
if not SourceChangeCache.Replace(gtSpace,gtNone,WithKeywordStartPos,DoKeywordEndPos,'')
|
||||
then exit(false);
|
||||
if EndKeywordStartPos>0 then begin
|
||||
EndKeywordStartPos:=FindLineEndOrCodeInFrontOfPosition(EndKeywordStartPos);
|
||||
EndKeywordStartPos:=GetLineStartPosition(Src,EndKeywordStartPos);
|
||||
while (EndKeywordStartPos>1) and (Src[EndKeywordStartPos-1] in [#10,#13]) do
|
||||
dec(EndKeywordStartPos);
|
||||
EndKeywordEndPos:=FindLineEndOrCodeAfterPosition(EndKeywordEndPos);
|
||||
if not SourceChangeCache.Replace(gtSpace,gtNone,EndKeywordStartPos,EndKeywordEndPos,'')
|
||||
then exit(false);
|
||||
|
||||
// unindent
|
||||
StartPos:=FindLineEndOrCodeAfterPosition(DoKeywordEndPos,true,true);
|
||||
IndentInnerWith:=GetLineIndentWithTabs(Src,StartPos,
|
||||
SourceChangeCache.BeautifyCodeOptions.TabWidth);
|
||||
if IndentWith<IndentInnerWith then
|
||||
if not SourceChangeCache.IndentBlock(DoKeywordEndPos,EndKeywordStartPos,
|
||||
IndentWith-IndentInnerWith)
|
||||
then exit(false);
|
||||
end;
|
||||
end else begin
|
||||
// remove only variable
|
||||
@ -1411,7 +1434,9 @@ begin
|
||||
MoveCursorToAtomPos(LastAtom);
|
||||
end;
|
||||
until (CurPos.StartPos>SrcLen) or (CurPos.StartPos>=StatementNode.EndPos);
|
||||
{$IFDEF CTDEBUG}
|
||||
debugln(['TExtractProcTool.RemoveWithBlock Statement=',copy(Src,StatementNode.StartPos,StatementNode.EndPos-StatementNode.StartPos)]);
|
||||
{$ENDIF}
|
||||
|
||||
// replace
|
||||
Result:=Replace;
|
||||
|
||||
@ -57,7 +57,7 @@ interface
|
||||
{ $DEFINE ShowTriedParentContexts}
|
||||
{ $DEFINE ShowTriedIdentifiers}
|
||||
{ $DEFINE ShowTriedUnits}
|
||||
{$DEFINE ShowExprEval}
|
||||
{ $DEFINE ShowExprEval}
|
||||
{ $DEFINE ShowFoundIdentifier}
|
||||
{ $DEFINE ShowInterfaceCache}
|
||||
{ $DEFINE ShowNodeCache}
|
||||
|
||||
@ -230,6 +230,8 @@ type
|
||||
function ReplaceEx(FrontGap, AfterGap: TGapTyp; FromPos, ToPos: integer;
|
||||
DirectCode: TCodeBuffer; FromDirectPos, ToDirectPos: integer;
|
||||
const Text: string): boolean;
|
||||
function IndentBlock(FromPos, ToPos, IndentDiff: integer): boolean;
|
||||
function IndentLine(LineStartPos, IndentDiff: integer): boolean;
|
||||
function Apply: boolean;
|
||||
function FindEntryInRange(FromPos, ToPos: integer): TSourceChangeCacheEntry;
|
||||
function FindEntryAtPos(APos: integer): TSourceChangeCacheEntry;
|
||||
@ -657,6 +659,100 @@ begin
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
function TSourceChangeCache.IndentBlock(FromPos, ToPos, IndentDiff: integer): boolean;
|
||||
// (un)indent all lines in FromPos..ToPos
|
||||
// If FromPos starts in the middle of a line the first line is not changed
|
||||
// If ToPos is in the indentation the last line is not changed
|
||||
var
|
||||
p: LongInt;
|
||||
begin
|
||||
if ToPos<1 then ToPos:=1;
|
||||
if (IndentDiff=0) or (FromPos>=ToPos) then exit;
|
||||
if MainScanner=nil then begin
|
||||
debugln(['TSourceChangeCache.IndentBlock need MainScanner']);
|
||||
exit(false);
|
||||
end;
|
||||
Src:=MainScanner.CleanedSrc;
|
||||
SrcLen:=length(Src);
|
||||
if FromPos>SrcLen then exit(true);
|
||||
if ToPos>SrcLen then ToPos:=SrcLen+1;
|
||||
// skip empty lines at start
|
||||
while (FromPos<ToPos) and (Src[FromPos] in [#10,#13]) do inc(FromPos);
|
||||
if (FromPos>1) and (not (Src[FromPos-1] in [#10,#13])) then begin
|
||||
// FromPos is in the middle of a line => start in next line
|
||||
while (FromPos<ToPos) and (not (Src[FromPos] in [#10,#13])) do inc(FromPos);
|
||||
if FromPos>=ToPos then exit(true);
|
||||
end;
|
||||
if (ToPos<=SrcLen) and (Src[ToPos] in [' ',#9]) then begin
|
||||
p:=ToPos;
|
||||
while (p>=ToPos) and (Src[p] in [' ',#9]) do dec(p);
|
||||
if (p=1) or (Src[p] in [#10,#13]) then begin
|
||||
// ToPos in IndentDiff of last line => end in previous line
|
||||
while (p>ToPos) and (Src[p-1] in [#10,#13]) do dec(p);
|
||||
ToPos:=p;
|
||||
if FromPos>=ToPos then exit(true);
|
||||
end;
|
||||
end;
|
||||
//debugln(['TSourceChangeCache.IndentBlock Indent=',IndentDiff,' Src="',dbgstr(Src,FromPos,ToPos-FromPos),'"']);
|
||||
|
||||
p:=FromPos;
|
||||
while p<ToPos do begin
|
||||
if not IndentLine(p,IndentDiff) then exit(false);
|
||||
// go to next line
|
||||
while (p<ToPos) and (not (Src[p] in [#10,#13])) do inc(p);
|
||||
// skip empty lines
|
||||
while (p<ToPos) and (Src[p] in [#10,#13]) do inc(p);
|
||||
end;
|
||||
|
||||
Result:=true;
|
||||
end;
|
||||
|
||||
function TSourceChangeCache.IndentLine(LineStartPos, IndentDiff: integer
|
||||
): boolean;
|
||||
var
|
||||
OldIndent: LongInt;
|
||||
NewIndent: Integer;
|
||||
p: LongInt;
|
||||
Indent: Integer;
|
||||
StartPos: LongInt;
|
||||
IndentStr: String;
|
||||
NextIndent: Integer;
|
||||
begin
|
||||
if (IndentDiff=0) or (LineStartPos<1) then exit(true);
|
||||
Src:=MainScanner.CleanedSrc;
|
||||
SrcLen:=length(Src);
|
||||
if LineStartPos>SrcLen then exit(true);
|
||||
OldIndent:=GetLineIndentWithTabs(Src,LineStartPos,BeautifyCodeOptions.TabWidth);
|
||||
NewIndent:=OldIndent+IndentDiff;
|
||||
if NewIndent<0 then NewIndent:=0;
|
||||
if OldIndent=NewIndent then exit(true);
|
||||
//debugln(['TSourceChangeCache.IndentLine change indent OldIndent=',OldIndent,' NewIndent=',NewIndent]);
|
||||
|
||||
p:=LineStartPos;
|
||||
// use as much of the old space as possible
|
||||
Indent:=0;
|
||||
while (p<=SrcLen) and (Indent<NewIndent) do begin
|
||||
case Src[p] of
|
||||
' ':
|
||||
inc(Indent);
|
||||
#9:
|
||||
begin
|
||||
NextIndent:=Indent+BeautifyCodeOptions.TabWidth;
|
||||
NextIndent:=NextIndent-(NextIndent mod BeautifyCodeOptions.TabWidth);
|
||||
if NextIndent>NewIndent then break;
|
||||
Indent:=NextIndent;
|
||||
end;
|
||||
end;
|
||||
inc(p);
|
||||
end;
|
||||
|
||||
StartPos:=p;
|
||||
while (p<=SrcLen) and (Src[p] in [' ',#9]) do inc(p);
|
||||
IndentStr:=GetIndentStr(NewIndent-Indent);
|
||||
|
||||
Result:=Replace(gtNone,gtNone,StartPos,p,IndentStr);
|
||||
end;
|
||||
|
||||
function TSourceChangeCache.Replace(FrontGap, AfterGap: TGapTyp;
|
||||
FromPos, ToPos: integer; const Text: string): boolean;
|
||||
begin
|
||||
|
||||
Loading…
Reference in New Issue
Block a user