{ Test all with: ./runtests --format=plain --suite=TTestCodetoolsCompleteBlock Test specific with: ./runtests --format=plain --suite=TestCompleteBlockClassStart ./runtests --format=plain --suite=TestCompleteBlockBegin ./runtests --format=plain --suite=TestCompleteBlockRepeat ./runtests --format=plain --suite=TestCompleteBlockCase ./runtests --format=plain --suite=TestCompleteBlockTry ./runtests --format=plain --suite=TestCompleteBlockAsm ./runtests --format=plain --suite=TestCompleteBlockIf } unit TestCompleteBlock; {$mode objfpc}{$H+} interface uses Classes, SysUtils, fpcunit, testregistry, FileProcs, CodeToolManager, CodeCache, CustomCodeTool; type { TTestCodetoolsCompleteBlock } TTestCodetoolsCompleteBlock = class(TTestCase) private function CreateFullSrc(Src: string; out Cursor: integer): string; procedure TestCompleteBlocks; public procedure CompleteBlock(Src, ExpectedSrc: string; OnlyIfCursorBlockIndented: boolean = false); procedure CompleteBlock(Src: string; OnlyIfCursorBlockIndented: boolean = false); procedure CompleteBlockFail(Src: string; OnlyIfCursorBlockIndented: boolean = false); published procedure TestCompleteBlockClassStart; procedure TestCompleteBlockBegin; procedure TestCompleteBlockRepeat; procedure TestCompleteBlockCase; procedure TestCompleteBlockTry; procedure TestCompleteBlockAsm; procedure TestCompleteBlockIf; end; implementation { TTestCodetoolsCompleteBlock } procedure TTestCodetoolsCompleteBlock.TestCompleteBlocks; procedure CompareComplete(a,b,c: string); begin writeln('CompareComplete ',a,',',b,',',c); end; begin CompareComplete('ifbeginelse1.inc','6 28 ifbeginelse fpcunit', 'ifbeginelse1_result.inc'); CompareComplete('whilebegin1.inc','5 10 whilebegin fpcunit', 'whilebegin1_result.inc'); CompareComplete('beginwithoutindent1.inc','4 21 beginwithoutindent fpcunit', 'beginwithoutindent1_result1.inc'); CompareComplete('beginwithoutindent1.inc','5 6 beginwithoutindent fpcunit', 'beginwithoutindent1_result2.inc'); CompareComplete('casecolon1.inc','5 5 casecolon fpcunit', 'casecolon1_result.inc'); CompareComplete('caseelseend1.inc','5 7 caseelseend fpcunit', 'caseelseend1_result.inc'); CompareComplete('caseend1.inc','4 12 caseend fpcunit', 'caseend1_result.inc'); CompareComplete('class1.inc','3 19 class fpcunit', 'class1_result.inc'); CompareComplete('ifbegin1.inc','4 21 ifbegin fpcunit', 'ifbegin1_result.inc'); CompareComplete('ifbeginelse1.inc','6 28 ifbeginelse fpcunit', 'ifbeginelse1_result.inc'); CompareComplete('procedurebegin1.inc','3 6 procedurebegin fpcunit', 'procedurebegin1_result.inc'); CompareComplete('procedurebeginend1.inc','4 8 procedurebeginend fpcunit', 'procedurebeginend1_result.inc'); CompareComplete('procedurebeginifbegin1.inc','11 74 procedurebeginifbegin fpcunit', 'procedurebeginifbegin1_result.inc'); CompareComplete('record1.inc','3 22 record fpcunit', 'record1_result1.inc'); CompareComplete('repeatifelse1.inc','11 18 repeatifelse fpcunit', 'repeatifelse1_result.inc'); CompareComplete('tryif1.inc','4 6 tryif fpcunit', 'tryif1_result.inc'); end; function TTestCodetoolsCompleteBlock.CreateFullSrc(Src: string; out Cursor: integer): string; begin Result:=Src; {Result:='unit testcompleteblock;'+LineEnding +'interface'+LineEnding +Src;} if not (Result[length(Result)] in [#10,#13]) then Result:=Result+LineEnding; Cursor:=System.Pos('|',Result); System.Delete(Result,Cursor,1); end; procedure TTestCodetoolsCompleteBlock.CompleteBlock(Src, ExpectedSrc: string; OnlyIfCursorBlockIndented: boolean); var Code: TCodeBuffer; p: integer; Y: integer; X: integer; NewCode: TCodeBuffer; NewX: integer; NewY: integer; NewTopLine: integer; ExpectedCode: TCodeBuffer; ep: integer; eY: integer; eX: integer; FullSrc: String; FullExpectedSrc: String; TrimExpected: String; TrimResult: String; begin AssertEquals('Src is empty',Trim(Src)<>'',true); AssertEquals('ExpectedSrc is empty',Trim(ExpectedSrc)<>'',true); ExpectedCode:=TCodeBuffer.Create; try // replace cursor | marker in Src Code:=CodeToolBoss.CreateFile('TestCompleteBlock.pas'); FullSrc:=CreateFullSrc(Src,p); if p<1 then AssertEquals('missing cursor | in test source: "'+dbgstr(Src)+'"',true,false); Code.Source:=FullSrc; Code.AbsoluteToLineCol(p,Y,X); // replace cursor | marker in ExpectedSrc FullExpectedSrc:=CreateFullSrc(ExpectedSrc,ep); if ep<1 then AssertEquals('missing cursor | in expected source: "'+dbgstr(ExpectedSrc)+'"',true,false); ExpectedCode.Source:=FullExpectedSrc; ExpectedCode.AbsoluteToLineCol(ep,eY,eX); if not CodeToolBoss.CompleteBlock(Code,X,Y,OnlyIfCursorBlockIndented, NewCode,NewX,NewY,NewTopLine) then begin AssertEquals('CodeToolBoss.CompleteBlock returned false for src="'+dbgstr(Src)+'"',true,false); exit; end; TrimExpected:=dbgstr(Trim(FullExpectedSrc)); TrimResult:=dbgstr(Trim(Code.Source)); if TrimExpected<>TrimResult then begin debugln(['TTestCodetoolsCompleteBlock.CompleteBlock FAILED Expected:']); debugln(FullExpectedSrc); debugln(['TTestCodetoolsCompleteBlock.CompleteBlock FAILED Found:']); debugln(Code.Source); debugln(['TTestCodetoolsCompleteBlock.CompleteBlock FAILED end']); end; AssertEquals('CompleteBlock did no or the wrong completion: ',TrimExpected,TrimResult); finally ExpectedCode.Free; end; end; procedure TTestCodetoolsCompleteBlock.CompleteBlock(Src: string; OnlyIfCursorBlockIndented: boolean); begin CompleteBlock(Src,Src,OnlyIfCursorBlockIndented); end; procedure TTestCodetoolsCompleteBlock.CompleteBlockFail(Src: string; OnlyIfCursorBlockIndented: boolean); var Code: TCodeBuffer; p: integer; FullSrc: String; Y: integer; X: integer; NewCode: TCodeBuffer; NewX: integer; NewY: integer; NewTopLine: integer; begin AssertEquals('Src is empty',Trim(Src)<>'',true); // replace cursor | marker in Src Code:=CodeToolBoss.CreateFile('TestCompleteBlock.pas'); FullSrc:=CreateFullSrc(Src,p); if p<1 then AssertEquals('missing cursor | in test source: "'+dbgstr(Src)+'"',true,false); Code.Source:=FullSrc; Code.AbsoluteToLineCol(p,Y,X); if CodeToolBoss.CompleteBlock(Code,X,Y,OnlyIfCursorBlockIndented, NewCode,NewX,NewY,NewTopLine) then begin debugln(['TTestCodetoolsCompleteBlock.CompleteBlockFail completion: ',dbgstr(Code.Source)]); AssertEquals('CodeToolBoss.CompleteBlock returned true for incompletable src="'+dbgstr(Src)+'"',true,false); end; end; procedure TTestCodetoolsCompleteBlock.TestCompleteBlockClassStart; begin CompleteBlock('type'+LineEnding +' TTestClass = class(TObject)|', 'type'+LineEnding +' TTestClass = class(TObject)'+LineEnding +' |end;'); CompleteBlock('type'+LineEnding +' TTestClass = class(TObject)|'+LineEnding +' TSecondClass =', 'type'+LineEnding +' TTestClass = class(TObject)'+LineEnding +' |end;'+LineEnding +LineEnding +' TSecondClass ='); CompleteBlock('type'+LineEnding +' TTestClass = class(TObject)|'+LineEnding +'implementation', 'type'+LineEnding +' TTestClass = class(TObject)'+LineEnding +' |end;'+LineEnding +LineEnding +'implementation'); end; procedure TTestCodetoolsCompleteBlock.TestCompleteBlockBegin; begin CompleteBlock('begin'+LineEnding +' begin|'+LineEnding +'end.', 'begin'+LineEnding +' begin|'+LineEnding +' end;'+LineEnding +'end.'); CompleteBlock('begin'+LineEnding +' while do begin|'+LineEnding +'end.', 'begin'+LineEnding +' while do begin|'+LineEnding +' end;'+LineEnding +'end.'); CompleteBlock('begin'+LineEnding +' while do'+LineEnding +' begin|'+LineEnding +'end.', 'begin'+LineEnding +' while do'+LineEnding +' begin|'+LineEnding +' end;'+LineEnding +'end.'); CompleteBlock('begin'+LineEnding +' begin|'+LineEnding +' writeln;'+LineEnding +'end.', 'begin'+LineEnding +' begin|'+LineEnding +' writeln;'+LineEnding +' end;'+LineEnding +'end.'); CompleteBlock('begin'+LineEnding +' begin|'+LineEnding +' writeln;'+LineEnding +'end.', 'begin'+LineEnding +' begin|'+LineEnding +' end;'+LineEnding +' writeln;'+LineEnding +'end.'); { Todo: Not implemented yet CompleteBlock('procedure a;'+LineEnding +'begin|'+LineEnding +'begin'+LineEnding +'end.', 'procedure a;'+LineEnding +'begin|'+LineEnding +'end;'+LineEnding +'begin'+LineEnding +'end.');} end; procedure TTestCodetoolsCompleteBlock.TestCompleteBlockRepeat; begin CompleteBlock('begin'+LineEnding +' repeat|'+LineEnding +'end.', 'begin'+LineEnding +' repeat|'+LineEnding +' until ;'+LineEnding +'end.'); CompleteBlock( 'begin'+LineEnding +' if FindFirstUTF8(Dir+FileMask,faAnyFile,FileInfo)=0 then begin'+LineEnding +' repeat'+LineEnding +' // check if special file'+LineEnding +' if (FileInfo.Name=''.'') or (FileInfo.Name=''..'') or (FileInfo.Name='''')'+LineEnding +' then'+LineEnding +' continue;'+LineEnding +' |'+LineEnding +' if FilenameIsPascalUnit(FileInfo.Name,false) then begin'+LineEnding +' List.Add(Dir+FileInfo.Name);'+LineEnding +' end else if (FileInfo.Attr and faDirectory)>0 then begin'+LineEnding +' CollectUnits(Dir+);'+LineEnding +' end;'+LineEnding +' until FindNextUTF8(FileInfo)<>0;'+LineEnding +' end;'+LineEnding +' FindCloseUTF8(FileInfo);'+LineEnding); end; procedure TTestCodetoolsCompleteBlock.TestCompleteBlockCase; begin CompleteBlock('begin'+LineEnding +' case of|'+LineEnding +'end.', 'begin'+LineEnding +' case of|'+LineEnding +' end;'+LineEnding +'end.'); CompleteBlock('begin'+LineEnding +' case of|'+LineEnding +'end.', 'begin'+LineEnding +' case of|'+LineEnding +' end;'+LineEnding +'end.'); end; procedure TTestCodetoolsCompleteBlock.TestCompleteBlockTry; begin CompleteBlock('begin'+LineEnding +' try|'+LineEnding +'end.', 'begin'+LineEnding +' try|'+LineEnding +' finally'+LineEnding +' end;'+LineEnding +'end.'); CompleteBlock('begin'+LineEnding +' try'+LineEnding +' finally|'+LineEnding +'end.', 'begin'+LineEnding +' try'+LineEnding +' finally|'+LineEnding +' end;'+LineEnding +'end.'); CompleteBlock('begin'+LineEnding +' try'+LineEnding +' except|'+LineEnding +'end.', 'begin'+LineEnding +' try'+LineEnding +' except|'+LineEnding +' end;'+LineEnding +'end.'); { ToDo: if True then i:=1 else if True then if True then i:=2 else i:=3 else i:=4; if True then Caption:='retz' else if False then Caption:='qretz'; try except on e: Exception do begin fErrorMsg:=e.Message; end; else begin fErrorMsg:='Error'; end; MyResult:=mrAbort; end; try try finally end; except on E: Exception do begin end; end; } end; procedure TTestCodetoolsCompleteBlock.TestCompleteBlockAsm; begin CompleteBlock('begin'+LineEnding +' asm|'+LineEnding +'end.', 'begin'+LineEnding +' asm|'+LineEnding +' end;'+LineEnding +'end.'); end; procedure TTestCodetoolsCompleteBlock.TestCompleteBlockIf; begin CompleteBlock('begin'+LineEnding +' if then begin|'+LineEnding +'end.', 'begin'+LineEnding +' if then begin|'+LineEnding +' end;'+LineEnding +'end.'); CompleteBlock('begin'+LineEnding +' if then begin|'+LineEnding +' else'+LineEnding +'end.', 'begin'+LineEnding +' if then begin|'+LineEnding +' end'+LineEnding +' else'+LineEnding +'end.'); CompleteBlockFail('begin'+LineEnding +' try'+LineEnding +' if|'+LineEnding +' finally'+LineEnding +' end;'+LineEnding +'end.'); end; initialization RegisterTest(TTestCodetoolsCompleteBlock); end.