codetools: AddWithBlock

git-svn-id: trunk@32244 -
This commit is contained in:
mattias 2011-09-09 22:32:47 +00:00
parent 6d24d264ef
commit be78a06cb3
4 changed files with 94 additions and 39 deletions

View File

@ -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;

View File

@ -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('-----------------------------------');

View File

@ -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;

View File

@ -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;