1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
|
{
Test all with:
./runtests --format=plain --suite=TTestPas2js
Test specific with:
./runtests --format=plain --suite=TestPas2js_ReadSettings
}
unit TestCTPas2js;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, CodeToolManager, FileProcs, DefineTemplates, LinkScanner,
CodeCache, ExprEval, TestGlobals, LazLogger, LazFileUtils, LazUTF8, fpcunit,
testregistry, TestFindDeclaration;
type
{ TCustomTestPas2js }
TCustomTestPas2js = class(TCustomTestFindDeclaration)
private
FAutoSearchPas2js: boolean;
FBaseDir: string;
FCode: TCodeBuffer;
FPas2jsFilename: string;
FUnitSetCache: TFPCUnitSetCache;
FVirtualDirDefines: TDefineTemplate;
protected
procedure SetUp; override;
procedure TearDown; override;
procedure DoParseModule(aCode: TCodeBuffer; out Tool: TCodeTool); virtual;
public
constructor Create; override;
procedure Add(const s: string);
procedure Add(Args: array of const);
function FindPas2js: string;
function StartProgram: boolean; override;
procedure ParseModule; virtual;
procedure WriteSource(CleanPos: integer; Tool: TCodeTool);
procedure WriteSource(const CursorPos: TCodeXYPosition);
property AutoSearchPas2js: boolean read FAutoSearchPas2js write FAutoSearchPas2js;
property Code: TCodeBuffer read FCode;
property Pas2jsFilename: string read FPas2jsFilename write FPas2jsFilename; // compiler filename
property UnitSetCache: TFPCUnitSetCache read FUnitSetCache write FUnitSetCache;
property VirtualDirDefines: TDefineTemplate read FVirtualDirDefines write FVirtualDirDefines;
property BaseDir: string read FBaseDir write FBaseDir;
end;
{ TTestPas2js }
TTestPas2js = class(TCustomTestPas2js)
published
procedure TestPas2js_ReadSettings;
procedure TestPas2js_FindDeclaration;
procedure TestPas2js_FindDeclaration_AWait;
end;
implementation
{ TCustomTestPas2js }
procedure TCustomTestPas2js.SetUp;
var
CurUnitSet: TFPCUnitSetCache;
UnitSetID: String;
CompilerDefines: TDefineTemplate;
begin
inherited SetUp;
if (Pas2jsFilename='') and AutoSearchPas2js then begin
FPas2jsFilename:=FindPas2js;
AutoSearchPas2js:=false;
end;
if FPas2jsFilename<>'' then begin
if UnitSetCache=nil then begin
UnitSetCache:=CodeToolBoss.CompilerDefinesCache.FindUnitSet(Pas2jsFilename,
'','','','',true);
// parse compiler settings
UnitSetCache.Init;
end;
UnitSetID:=UnitSetCache.GetUnitSetID;
// set pas2js for virtual directory
if VirtualDirDefines=nil then begin
VirtualDirDefines:=TDefineTemplate.Create(
'VirtualDirPas2js', 'set pas2js as compiler for virtual directory',
'',VirtualDirectory,da_Directory);
VirtualDirDefines.AddChild(TDefineTemplate.Create('Reset','','','',da_UndefineAll));
// create template for Pas2js settings
CompilerDefines:=CreateFPCTemplate(UnitSetCache,nil);
VirtualDirDefines.AddChild(CompilerDefines);
end;
CodeToolBoss.DefineTree.Add(VirtualDirDefines);
// check
CurUnitSet:=CodeToolBoss.GetUnitSetForDirectory('');
if CurUnitSet=nil then
Fail('CodeToolBoss.GetUnitSetForDirectory=nil');
if CurUnitSet<>UnitSetCache then
AssertEquals('UnitSet VirtualDirectory should be pas2js',UnitSetID,CurUnitSet.GetUnitSetID);
if CodeToolBoss.GetPascalCompilerForDirectory('')<>pcPas2js then
AssertEquals('VirtualDirectory compiler should be pas2js',
PascalCompilerNames[pcPas2js],
PascalCompilerNames[CodeToolBoss.GetPascalCompilerForDirectory('')]);
end;
FCode:=CodeToolBoss.CreateFile('test1.pas');
end;
procedure TCustomTestPas2js.TearDown;
begin
FCode:=nil;
CodeToolBoss.DefineTree.RemoveDefineTemplate(VirtualDirDefines);
inherited TearDown;
end;
procedure TCustomTestPas2js.DoParseModule(aCode: TCodeBuffer; out
Tool: TCodeTool);
var
i: Integer;
Line: String;
begin
if not CodeToolBoss.Explore(aCode,Tool,true) then begin
debugln(aCode.Filename+'------------------------------------------');
for i:=1 to aCode.LineCount do begin
Line:=aCode.GetLine(i-1,false);
if i=CodeToolBoss.ErrorLine then
System.Insert('|',Line,CodeToolBoss.ErrorColumn);
debugln(Format('%:4d: ',[i]),Line);
end;
debugln('Error: '+CodeToolBoss.ErrorDbgMsg);
Fail('PascalParser failed: '+CodeToolBoss.ErrorMessage);
end;
end;
constructor TCustomTestPas2js.Create;
begin
inherited Create;
FAutoSearchPas2js:=true;
FBaseDir:='pas2js';
end;
procedure TCustomTestPas2js.Add(const s: string);
begin
FCode.Source:=FCode.Source+s+LineEnding;
end;
procedure TCustomTestPas2js.Add(Args: array of const);
begin
FCode.Source:=FCode.Source+LinesToStr(Args);
end;
function TCustomTestPas2js.FindPas2js: string;
var
ShortFilename: String;
begin
Result:=GetEnvironmentVariable('PAS2JS');
if Result<>'' then begin
if not FileExistsUTF8(Result) then
Fail('Environment variable PAS2JS is non existing file "'+Result+'"');
exit;
end;
ShortFilename:='pas2js'+ExeExt;
Result:=SearchFileInPath(ShortFilename,'',
GetEnvironmentVariableUTF8('PATH'),PathSeparator,ctsfcDefault);
end;
function TCustomTestPas2js.StartProgram: boolean;
begin
if FPas2jsFilename='' then exit(false);
Result:=true;
AssertEquals('compiler kind',PascalCompilerNames[pcPas2js],PascalCompilerNames[UnitSetCache.GetCompilerKind]);
end;
procedure TCustomTestPas2js.ParseModule;
var
Tool: TCodeTool;
begin
Add('end.');
DoParseModule(Code,Tool);
end;
procedure TCustomTestPas2js.WriteSource(CleanPos: integer; Tool: TCodeTool);
var
Caret: TCodeXYPosition;
begin
if Tool=nil then
Fail('TCustomTestPas2js.WriteSource: missing Tool');
if not Tool.CleanPosToCaret(CleanPos,Caret) then
Fail('TCustomTestPas2js.WriteSource: invalid cleanpos '+IntToStr(CleanPos)+' Tool='+Tool.MainFilename);
WriteSource(Caret);
end;
procedure TCustomTestPas2js.WriteSource(const CursorPos: TCodeXYPosition);
var
CurCode: TCodeBuffer;
i: Integer;
Line: String;
begin
CurCode:=CursorPos.Code;
if CurCode=nil then
Fail('TCustomTestPas2js.WriteSource CurCode=nil');
for i:=1 to CurCode.LineCount do begin
Line:=CurCode.GetLine(i-1,false);
if (i=CursorPos.Y) then begin
write('*');
Line:=LeftStr(Line,CursorPos.X-1)+'|'+copy(Line,CursorPos.X,length(Line));
end;
writeln(Format('%:4d: ',[i]),Line);
end;
end;
{ TTestPas2js }
procedure TTestPas2js.TestPas2js_ReadSettings;
var
Cfg: TPCTargetConfigCache;
aFilename, AnUnitName, InFilename, SystemUnit: String;
begin
if Pas2jsFilename='' then exit;
AssertEquals('compiler kind',PascalCompilerNames[pcPas2js],PascalCompilerNames[UnitSetCache.GetCompilerKind]);
Cfg:=UnitSetCache.GetConfigCache(false);
if not Cfg.Defines.Contains('PAS2JS_FULLVERSION') then
Fail('macro PAS2JS_FULLVERSION is misssing');
SystemUnit:=Cfg.Units['system'];
if SystemUnit='' then
Fail('pas2js.cfg is missing path to system unit');
AnUnitName:='system';
InFilename:='';
aFilename:=CodeToolBoss.DirectoryCachePool.FindUnitSourceInCompletePath('',AnUnitName,InFilename,true);
if aFilename='' then
Fail('system unit not found from virtual directory');
if CompareFilenames(aFilename,SystemUnit)<>0 then
AssertEquals('pas2js system unit',SystemUnit,aFilename);
end;
procedure TTestPas2js.TestPas2js_FindDeclaration;
begin
if not StartProgram then exit;
Add([
'var Cow: longint;',
'begin',
' cow{declaration:Cow}:=3;',
' test1{declaration:Test1}.cow{declaration:Cow}:=3;',
'end.',
'']);
ParseModule;
//FindDeclarations(Code);
end;
procedure TTestPas2js.TestPas2js_FindDeclaration_AWait;
begin
if not StartProgram then exit;
Add([
'{$modeswitch externalclass}',
'type',
' TJSPromise = class external name ''Promise''',
' end;',
'function Crawl(d: double = 1.3): word; ',
'begin',
'end;',
'function Run(d: double): word; async;',
'var',
' p: TJSPromise;',
'begin',
' Result:=await(word,p{declaration:Run.p});',
' Result:=await(1);',
' Result:=await(Crawl{declaration:Crawl});',
' Result:=await(Crawl{declaration:Crawl}(4.5));',
'end;',
'begin',
' Run{declaration:run}(3);',
'end.']);
FindDeclarations(Code);
end;
initialization
RegisterTest(TTestPas2js);
end.
|