mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-13 12:39:15 +02:00
codetools: AddWithBlock
git-svn-id: trunk@32244 -
This commit is contained in:
parent
6d24d264ef
commit
be78a06cb3
@ -457,8 +457,9 @@ type
|
||||
function RemoveIdentifierDefinition(Code: TCodeBuffer; X, Y: integer
|
||||
): boolean; // e.g. remove the variable definition at X,Y
|
||||
function RemoveWithBlock(Code: TCodeBuffer; X, Y: integer): boolean;
|
||||
function CheckAddWithBlock(Code: TCodeBuffer; X1, Y1, X2, Y2: integer;
|
||||
var Candidates: TStrings): boolean;
|
||||
function AddWithBlock(Code: TCodeBuffer; X1, Y1, X2, Y2: integer;
|
||||
const WithExpr: string; // if empty: collect Candidates
|
||||
Candidates: TStrings): boolean;
|
||||
function ChangeParamList(Code: TCodeBuffer;
|
||||
Changes: TObjectList; // list of TChangeParamListItem
|
||||
var ProcPos: TCodeXYPosition; // if it is in this unit the proc declaration is changed and this position is cleared
|
||||
@ -2586,14 +2587,14 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TCodeToolManager.CheckAddWithBlock(Code: TCodeBuffer; X1, Y1, X2,
|
||||
Y2: integer; var Candidates: TStrings): boolean;
|
||||
function TCodeToolManager.AddWithBlock(Code: TCodeBuffer; X1, Y1, X2,
|
||||
Y2: integer; const WithExpr: string; Candidates: TStrings): boolean;
|
||||
var
|
||||
StartPos, EndPos: TCodeXYPosition;
|
||||
begin
|
||||
Result:=false;
|
||||
{$IFDEF CTDEBUG}
|
||||
DebugLn('TCodeToolManager.AddWithBlock A ',Code.Filename,' X1=',X1,' Y1=',Y1,' X2=',X2,' Y2=',Y2);
|
||||
DebugLn('TCodeToolManager.AddWithBlock A ',Code.Filename,' X1=',X1,' Y1=',Y1,' X2=',X2,' Y2=',Y2,' WithExpr="',WithExpr,'"');
|
||||
{$ENDIF}
|
||||
if not InitCurCodeTool(Code) then exit;
|
||||
StartPos.X:=X1;
|
||||
@ -2603,7 +2604,8 @@ begin
|
||||
EndPos.Y:=Y2;
|
||||
EndPos.Code:=Code;
|
||||
try
|
||||
Result:=FCurCodeTool.CheckAddWithBlock(StartPos,EndPos,Candidates);
|
||||
Result:=FCurCodeTool.AddWithBlock(StartPos,EndPos,WithExpr,Candidates,
|
||||
SourceChangeCache);
|
||||
except
|
||||
on e: Exception do HandleException(e);
|
||||
end;
|
||||
|
@ -41,28 +41,32 @@ var
|
||||
X2: Integer;
|
||||
Y2: Integer;
|
||||
Candidates: TStrings;
|
||||
WithExpr: String;
|
||||
begin
|
||||
if (ParamCount>=1) and (Paramcount<>5) then begin
|
||||
writeln('Usage:');
|
||||
writeln(' ',ParamStr(0));
|
||||
writeln(' ',ParamStr(0),' <filename> <X> <Y>');
|
||||
writeln(' ',ParamStr(0),' scanexamples/addwith1.pas 1 35 1 40');
|
||||
end;
|
||||
|
||||
CodeToolBoss.SimpleInit(ConfigFilename);
|
||||
|
||||
// load the file
|
||||
Filename:='scanexamples/addwith1.pas';
|
||||
X1:=1;
|
||||
Y1:=35;
|
||||
X2:=1;
|
||||
Y2:=40;
|
||||
if Paramcount=5 then begin
|
||||
WithExpr:='Son1';
|
||||
|
||||
if (ParamCount>=1) and (Paramcount<>6) then begin
|
||||
writeln('Usage:');
|
||||
writeln(' ',ParamStr(0));
|
||||
writeln(' ',ParamStr(0),' <filename> <X1> <Y1> <X2> <Y2> <WithExpression>');
|
||||
writeln(' ',ParamStr(0),' ',Filename,' ',X1,' ',Y1,' ',X2,' ',Y2,' ',WithExpr);
|
||||
end;
|
||||
|
||||
CodeToolBoss.SimpleInit(ConfigFilename);
|
||||
|
||||
// load the file
|
||||
if Paramcount=6 then begin
|
||||
Filename:=ParamStrUTF8(1);
|
||||
X1:=StrToIntDef(ParamStrUTF8(2),1);
|
||||
Y1:=StrToIntDef(ParamStrUTF8(3),1);
|
||||
X2:=StrToIntDef(ParamStrUTF8(4),1);
|
||||
Y2:=StrToIntDef(ParamStrUTF8(5),1);
|
||||
WithExpr:=ParamStrUTF8(6);
|
||||
end;
|
||||
|
||||
Filename:=ExpandFileName(SetDirSeparators(Filename));
|
||||
@ -71,9 +75,12 @@ begin
|
||||
raise Exception.Create('loading failed: '+Filename);
|
||||
|
||||
// parse the unit and remove the with variable
|
||||
Candidates:=nil;
|
||||
if not CodeToolBoss.CheckAddWithBlock(Code,X1,Y1,X2,Y2,Candidates) then
|
||||
raise Exception.Create('CheckAddWithBlock failed');
|
||||
Candidates:=TStringList.Create;
|
||||
if not CodeToolBoss.AddWithBlock(Code,X1,Y1,X2,Y2,'',Candidates) then
|
||||
raise Exception.Create('Finding candidates for "With" block failed');
|
||||
Candidates.Free;
|
||||
if not CodeToolBoss.AddWithBlock(Code,X1,Y1,X2,Y2,WithExpr,nil) then
|
||||
raise Exception.Create('Adding "With" block for "'+WithExpr+'" failed');
|
||||
|
||||
// write the new source:
|
||||
writeln('-----------------------------------');
|
||||
|
@ -110,8 +110,9 @@ type
|
||||
|
||||
function RemoveWithBlock(const CursorPos: TCodeXYPosition;
|
||||
SourceChangeCache: TSourceChangeCache): boolean;
|
||||
function CheckAddWithBlock(const StartPos, EndPos: TCodeXYPosition;
|
||||
var Candidates: TStrings): boolean;
|
||||
function AddWithBlock(const StartPos, EndPos: TCodeXYPosition;
|
||||
const WithExpr: string; // if empty: collect Candidates
|
||||
Candidates: TStrings; SourceChangeCache: TSourceChangeCache): boolean;
|
||||
|
||||
procedure CalcMemSize(Stats: TCTMemStats); override;
|
||||
end;
|
||||
@ -1386,25 +1387,36 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TExtractProcTool.CheckAddWithBlock(const StartPos,
|
||||
EndPos: TCodeXYPosition; var Candidates: TStrings): boolean;
|
||||
function TExtractProcTool.AddWithBlock(const StartPos, EndPos: TCodeXYPosition;
|
||||
const WithExpr: string; Candidates: TStrings;
|
||||
SourceChangeCache: TSourceChangeCache): boolean;
|
||||
var
|
||||
CleanStartPos: integer;
|
||||
CleanEndPos: integer;
|
||||
StartNode: TCodeTreeNode;
|
||||
|
||||
procedure Add(const Identifier: string);
|
||||
function Add(IdentifierStart, IdentifierEnd: integer;
|
||||
const Identifier: string): boolean;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
if Candidates=nil then
|
||||
Candidates:=TStringList.Create;
|
||||
i:=Candidates.IndexOf(Identifier);
|
||||
if i<0 then
|
||||
Candidates.AddObject(Identifier,TObject(Pointer(1)))
|
||||
else
|
||||
Candidates.Objects[i]:=TObject(PtrUInt(Candidates.Objects[i])+1);
|
||||
//debugln(['TExtractProcTool.CheckAddWithBlock.Add ',Identifier]);
|
||||
Result:=true;
|
||||
if WithExpr<>'' then begin
|
||||
if CompareText(Identifier,WithExpr)=0 then begin
|
||||
if not SourceChangeCache.Replace(gtNone,gtNone,
|
||||
IdentifierStart,IdentifierEnd,'')
|
||||
then
|
||||
exit(false);
|
||||
end;
|
||||
end else begin
|
||||
if Candidates=nil then exit;
|
||||
i:=Candidates.IndexOf(Identifier);
|
||||
if i<0 then
|
||||
Candidates.AddObject(Identifier,TObject(Pointer(1)))
|
||||
else
|
||||
Candidates.Objects[i]:=TObject(PtrUInt(Candidates.Objects[i])+1);
|
||||
//debugln(['TExtractProcTool.AddWithBlock.Add ',Identifier]);
|
||||
end;
|
||||
end;
|
||||
|
||||
function ReadBlock(Code: PAnsiString): boolean;
|
||||
@ -1412,13 +1424,14 @@ var
|
||||
LastPos: TAtomPosition;
|
||||
Identifier: String;
|
||||
StartFlag: TCommonAtomFlag;
|
||||
IdentifierStart: Integer;
|
||||
begin
|
||||
Result:=false;
|
||||
StartFlag:=CurPos.Flag;
|
||||
while true do begin
|
||||
if Code<>nil then
|
||||
Code^:=Code^+GetAtom;
|
||||
//debugln(['TExtractProcTool.CheckAddWithBlock Atom=',GetAtom]);
|
||||
//debugln(['TExtractProcTool.AddWithBlock Atom=',GetAtom]);
|
||||
if (CurPos.EndPos>CleanEndPos) or (CurPos.StartPos>SrcLen)
|
||||
or (CurPos.StartPos>StartNode.EndPos) then
|
||||
break;
|
||||
@ -1442,16 +1455,17 @@ var
|
||||
or LastUpAtomIs(0,'INHERITED'))
|
||||
then begin
|
||||
// start of identifier
|
||||
//debugln(['TExtractProcTool.CheckAddWithBlock identifier start ',GetAtom]);
|
||||
//debugln(['TExtractProcTool.AddWithBlock identifier start ',GetAtom]);
|
||||
Identifier:=GetAtom;
|
||||
IdentifierStart:=CurPos.StartPos;
|
||||
repeat
|
||||
ReadNextAtom;
|
||||
//debugln(['TExtractProcTool.CheckAddWithBlock identifier next ',GetAtom]);
|
||||
//debugln(['TExtractProcTool.AddWithBlock identifier next ',GetAtom]);
|
||||
if CurPos.Flag in [cafRoundBracketOpen,cafEdgedBracketOpen] then
|
||||
begin
|
||||
if not ReadBlock(@Identifier) then exit;
|
||||
end else if (CurPos.Flag=cafPoint) then begin
|
||||
Add(Identifier);
|
||||
if not Add(IdentifierStart,CurPos.EndPos,Identifier) then exit;
|
||||
Identifier:=Identifier+GetAtom;
|
||||
end else if AtomIsChar('^') then begin
|
||||
Identifier:=Identifier+GetAtom;
|
||||
@ -1471,14 +1485,44 @@ var
|
||||
Result:=true;
|
||||
end;
|
||||
|
||||
var
|
||||
Code: String;
|
||||
Indent: Integer;
|
||||
begin
|
||||
Result:=false;
|
||||
if not CheckIfRangeOnSameLevel(StartPos,EndPos,CleanStartPos,CleanEndPos,
|
||||
StartNode) then exit;
|
||||
//debugln(['TExtractProcTool.AddWithBlock ',SrcLen,' ',CleanStartPos,' ',CleanEndPos]);
|
||||
MoveCursorToNodeStart(StartNode);
|
||||
if WithExpr<>'' then
|
||||
SourceChangeCache.MainScanner:=Scanner;
|
||||
ReadNextAtom;
|
||||
if not ReadBlock(nil) then exit;
|
||||
|
||||
// ToDo: check if identifiers are variables
|
||||
|
||||
if WithExpr<>'' then begin
|
||||
// add 'with expr do begin'
|
||||
Indent:=GetLineIndentWithTabs(Src,CleanStartPos,
|
||||
SourceChangeCache.BeautifyCodeOptions.TabWidth);
|
||||
Code:='with '+WithExpr+' do begin';
|
||||
Code:=SourceChangeCache.BeautifyCodeOptions.BeautifyStatement(Code,Indent);
|
||||
//debugln(['TExtractProcTool.AddWithBlock Header=',Code]);
|
||||
if not SourceChangeCache.Replace(gtNewLine,gtNewLine,
|
||||
CleanStartPos,CleanStartPos,Code) then exit;
|
||||
// add 'end;'
|
||||
Code:='end;';
|
||||
Code:=SourceChangeCache.BeautifyCodeOptions.BeautifyStatement(Code,Indent);
|
||||
//debugln(['TExtractProcTool.AddWithBlock Footer=',Code]);
|
||||
if not SourceChangeCache.Replace(gtNewLine,gtNewLine,
|
||||
CleanEndPos,CleanEndPos,Code) then exit;
|
||||
// indent all between
|
||||
//debugln(['TExtractProcTool.AddWithBlock Indent...']);
|
||||
if not SourceChangeCache.IndentBlock(CleanStartPos,CleanEndPos,
|
||||
SourceChangeCache.BeautifyCodeOptions.Indent) then exit;
|
||||
//debugln(['TExtractProcTool.AddWithBlock Apply']);
|
||||
if not SourceChangeCache.Apply then exit;
|
||||
end;
|
||||
Result:=true;
|
||||
end;
|
||||
|
||||
|
@ -701,6 +701,7 @@ begin
|
||||
|
||||
p:=FromPos;
|
||||
while p<ToPos do begin
|
||||
//debugln(['TSourceChangeCache.IndentBlock ',p]);
|
||||
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);
|
||||
@ -730,7 +731,7 @@ begin
|
||||
NewIndent:=OldIndent+IndentDiff;
|
||||
if NewIndent<0 then NewIndent:=0;
|
||||
if OldIndent=NewIndent then exit(true);
|
||||
//debugln(['TSourceChangeCache.IndentLine change indent OldIndent=',OldIndent,' NewIndent=',NewIndent]);
|
||||
//debugln(['TSourceChangeCache.IndentLine change indent at ',LineStartPos,' OldIndent=',OldIndent,' NewIndent=',NewIndent]);
|
||||
|
||||
p:=LineStartPos;
|
||||
// use as much of the old space as possible
|
||||
@ -746,6 +747,7 @@ begin
|
||||
if NextIndent>NewIndent then break;
|
||||
Indent:=NextIndent;
|
||||
end;
|
||||
else break;
|
||||
end;
|
||||
inc(p);
|
||||
end;
|
||||
@ -753,7 +755,7 @@ begin
|
||||
StartPos:=p;
|
||||
while (p<=SrcLen) and (Src[p] in [' ',#9]) do inc(p);
|
||||
IndentStr:=GetIndentStr(NewIndent-Indent);
|
||||
|
||||
//debugln(['TSourceChangeCache.IndentLine Replace ',StartPos,'..',p,' IndentStr="',dbgstr(IndentStr),'"']);
|
||||
Result:=Replace(gtNone,gtNone,StartPos,p,IndentStr);
|
||||
end;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user