Pārlūkot izejas kodu

pastojs: started write/read precompiled unit

git-svn-id: trunk@38507 -
Mattias Gaertner 7 gadi atpakaļ
vecāks
revīzija
a4500faa59

+ 9 - 5
packages/pastojs/src/fppas2js.pp

@@ -308,6 +308,7 @@ ToDos:
 - stdcall of methods: pass original 'this' as first parameter
 
 Not in Version 1.0:
+- property read Arr[0]  https://bugs.freepascal.org/view.php?id=33416
 - write, writeln
 - arrays
   - array of const
@@ -1190,6 +1191,9 @@ type
     coStoreImplJS  // store references to JS code in procscopes
     );
   TPasToJsConverterOptions = set of TPasToJsConverterOption;
+const
+  DefaultPasToJSOptions = [coLowerCase];
+type
 
   TPas2JSIsElementUsedEvent = function(Sender: TObject; El: TPasElement): boolean of object;
 
@@ -1513,7 +1517,7 @@ type
     destructor Destroy; override;
     Function ConvertPasElement(El: TPasElement; Resolver: TPas2JSResolver) : TJSElement;
     // options
-    Property Options: TPasToJsConverterOptions read FOptions write FOptions;
+    Property Options: TPasToJsConverterOptions read FOptions write FOptions default DefaultPasToJSOptions;
     Property TargetPlatform: TPasToJsPlatform read FTargetPlatform write FTargetPlatform;
     Property TargetProcessor: TPasToJsProcessor read FTargetProcessor write FTargetProcessor;
     Property UseLowerCase: boolean read GetUseLowerCase write SetUseLowerCase default true;
@@ -1856,7 +1860,7 @@ begin
     end;
   PopOverloadScope;
   {$IFDEF VerbosePas2JS}
-  writeln('TPas2JSResolver.RenameOverloadsInSection END ',GetObjName(aSection));
+  //writeln('TPas2JSResolver.RenameOverloadsInSection END ',GetObjName(aSection));
   {$ENDIF}
 end;
 
@@ -1910,7 +1914,7 @@ begin
       end;
     end;
   {$IFDEF VerbosePas2JS}
-  writeln('TPas2JSResolver.RenameOverloads END ',GetObjName(DeclEl));
+  //writeln('TPas2JSResolver.RenameOverloads END ',GetObjName(DeclEl));
   {$ENDIF}
 end;
 
@@ -1984,7 +1988,7 @@ begin
       RenameOverload(El);
     end;
   {$IFDEF VerbosePas2JS}
-  writeln('TPas2JSResolver.RenameSubOverloads END');
+  //writeln('TPas2JSResolver.RenameSubOverloads END');
   {$ENDIF}
 end;
 
@@ -9500,7 +9504,7 @@ constructor TPasToJSConverter.Create;
 var
   n: TPas2JSBuiltInName;
 begin
-  FOptions:=[coLowerCase];
+  FOptions:=DefaultPasToJSOptions;
   for n in TPas2JSBuiltInName do
     FBuiltInNames[n]:=Pas2JSBuiltInNames[n];
 end;

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 496 - 151
packages/pastojs/src/pas2jscompiler.pp


+ 68 - 13
packages/pastojs/src/pas2jsfilecache.pp

@@ -27,7 +27,7 @@ interface
 uses
   Classes, SysUtils, AVL_Tree,
   PScanner, PasResolver, FPPJsSrcMap,
-  Pas2jsLogger, Pas2jsFileUtils;
+  Pas2jsLogger, Pas2jsFileUtils, Pas2JsFiler;
 
 const // Messages
   nIncludeSearch = 201; sIncludeSearch = 'Include file search: %s';
@@ -36,9 +36,6 @@ const // Messages
   nSearchingFileNotFound = 204; sSearchingFileNotFound = 'Searching file: %s... not found';
   nDuplicateFileFound = 205; sDuplicateFileFound = 'Duplicate file found: "%s" and "%s"';
 
-const
-  PrecompiledExt = 'pju';
-
 type
   EPas2jsFileCache = class(Exception);
 
@@ -172,6 +169,7 @@ const
     'Search files like FPC'
     );
 
+  EncodingBinary = 'Binary';
 type
   TPas2jsFilesCache = class;
   TPas2jsCachedFile = class;
@@ -228,13 +226,15 @@ type
     FLoadedFileAge: longint;
     FSource: string;
     FCacheStamp: TChangeStamp; // Cache.ResetStamp when file was loaded
+    function GetIsBinary: boolean; inline;
   public
     constructor Create(aCache: TPas2jsFilesCache; const aFilename: string); reintroduce;
-    function Load(RaiseOnError: boolean): boolean;
+    function Load(RaiseOnError: boolean; Binary: boolean = false): boolean;
     function CreateLineReader(RaiseOnError: boolean): TPas2jsFileLineReader;
+    property IsBinary: boolean read GetIsBinary;
     property FileEncoding: string read FFileEncoding;
     property Filename: string read FFilename;
-    property Source: string read FSource; // UTF-8 without BOM
+    property Source: string read FSource; // UTF-8 without BOM or Binary
     property Cache: TPas2jsFilesCache read FCache;
     property ChangeStamp: TChangeStamp read FChangeStamp;// changed when Source changed
     property Loaded: boolean read FLoaded; // Source valid, but may contain an old version
@@ -276,6 +276,7 @@ type
     FOnReadFile: TPas2jsReadFileEvent;
     FOnWriteFile: TPas2jsWriteFileEvent;
     FOptions: TP2jsFileCacheOptions;
+    FPrecompileFormat: TPas2JSPrecompileFormat;
     FReadLineCounter: SizeInt;
     FResetStamp: TChangeStamp;
     FSrcMapBaseDir: string;
@@ -314,7 +315,8 @@ type
     function CreateResolver: TPas2jsFileResolver;
     function FormatPath(const aPath: string): string;
     function GetResolvedMainJSFile: string;
-    function LoadTextFile(Filename: string): TPas2jsCachedFile;
+    function FindFile(Filename: string): TPas2jsCachedFile;
+    function LoadFile(Filename: string; Binary: boolean = false): TPas2jsCachedFile;
     function NormalizeFilename(const Filename: string; RaiseOnError: boolean): string;
     procedure InsertCustomJSFiles(aWriter: TPas2JSMapper);
     function IndexOfInsertJSFilename(const aFilename: string): integer;
@@ -340,6 +342,7 @@ type
     property Namespaces: TStringList read FNamespaces;
     property NamespacesFromCmdLine: integer read FNamespacesFromCmdLine;
     property Options: TP2jsFileCacheOptions read FOptions write SetOptions default DefaultPas2jsFileCacheOptions;
+    property PrecompileFormat: TPas2JSPrecompileFormat read FPrecompileFormat write FPrecompileFormat;
     property ReadLineCounter: SizeInt read FReadLineCounter write FReadLineCounter;
     property ResetStamp: TChangeStamp read FResetStamp;
     property SearchLikeFPC: boolean read GetSearchLikeFPC write SetSearchLikeFPC;
@@ -469,6 +472,21 @@ begin
     end;
   until false;
 
+  // check binary
+  p:=PChar(Src);
+  repeat
+    case p^ of
+    #0:
+      if (p-PChar(Src)>=l) then
+        break
+      else
+        exit(EncodingBinary);
+    #1..#8,#11,#14..#31:
+      exit(EncodingBinary);
+    end;
+    inc(p);
+  until false;
+
   // use system encoding
   Result:=GetDefaultTextEncoding;
 end;
@@ -1103,6 +1121,12 @@ end;
 
 { TPas2jsCachedFile }
 
+// inline
+function TPas2jsCachedFile.GetIsBinary: boolean;
+begin
+  Result:=FFileEncoding=EncodingBinary;
+end;
+
 constructor TPas2jsCachedFile.Create(aCache: TPas2jsFilesCache;
   const aFilename: string);
 begin
@@ -1112,7 +1136,8 @@ begin
   FFilename:=aFilename;
 end;
 
-function TPas2jsCachedFile.Load(RaiseOnError: boolean): boolean;
+function TPas2jsCachedFile.Load(RaiseOnError: boolean; Binary: boolean
+  ): boolean;
 
   procedure Err(const ErrorMsg: string);
   begin
@@ -1164,7 +1189,13 @@ begin
   {$IFDEF VerboseFileCache}
   writeln('TPas2jsCachedFile.Load ENCODE ',Filename,' FFileEncoding=',FFileEncoding);
   {$ENDIF}
-  FSource:=ConvertTextToUTF8(NewSource,FFileEncoding);
+  if Binary then
+    FSource:=ConvertTextToUTF8(NewSource,FFileEncoding)
+  else
+  begin
+    FSource:=NewSource;
+    FFileEncoding:=EncodingBinary;
+  end;
   FLoaded:=true;
   FCacheStamp:=Cache.ResetStamp;
   FLoadedFileAge:=Cache.DirectoryCache.FileAge(Filename);
@@ -1278,7 +1309,7 @@ begin
   if not Found then
     raise EFileNotFoundError.Create(aFilename)
   else
-    Result:=Cache.LoadTextFile(CurFilename).CreateLineReader(false);
+    Result:=Cache.LoadFile(CurFilename).CreateLineReader(false);
 end;
 
 function TPas2jsFileResolver.FindUnitFileName(const aUnitname,
@@ -1782,17 +1813,29 @@ procedure TPas2jsFilesCache.Reset;
 begin
   IncreaseChangeStamp(FResetStamp);
   FDirectoryCache.Invalidate;
+  // FFiles: TAVLTree; keep data, files are checked against LoadedFileAge
   FOptions:=DefaultPas2jsFileCacheOptions;
   FMainJSFile:='';
+  FMainJSFileResolved:='';
   FMainSrcFile:='';
   FBaseDirectory:='';
   FSrcMapBaseDir:='';
   FUnitOutputPath:='';
   FReadLineCounter:=0;
   FForeignUnitPaths.Clear;
+  FForeignUnitPathsFromCmdLine:=0;
   FUnitPaths.Clear;
+  FUnitPathsFromCmdLine:=0;
   FIncludePaths.Clear;
+  FIncludePathsFromCmdLine:=0;
+  FInsertFilenames.Clear;
   FStates:=FStates-[cfsMainJSFileResolved];
+  FNamespaces.Clear;
+  FNamespacesFromCmdLine:=0;
+  FPrecompileFormat:=nil;
+  FSrcMapBaseDir:='';
+  // FOnReadFile: TPas2jsReadFileEvent; keep
+  // FOnWriteFile: TPas2jsWriteFileEvent; keep
 end;
 
 function TPas2jsFilesCache.AddIncludePaths(const Paths: string;
@@ -1877,7 +1920,19 @@ begin
   Result:=FMainJSFileResolved;
 end;
 
-function TPas2jsFilesCache.LoadTextFile(Filename: string): TPas2jsCachedFile;
+function TPas2jsFilesCache.FindFile(Filename: string): TPas2jsCachedFile;
+var
+  Node: TAVLTreeNode;
+begin
+  Filename:=NormalizeFilename(Filename,true);
+  Node:=FFiles.FindKey(Pointer(Filename),@CompareFilenameWithCachedFile);
+  if Node=nil then
+    exit(nil);
+  Result:=TPas2jsCachedFile(Node.Data);
+end;
+
+function TPas2jsFilesCache.LoadFile(Filename: string; Binary: boolean
+  ): TPas2jsCachedFile;
 var
   Node: TAVLTreeNode;
 begin
@@ -1891,7 +1946,7 @@ begin
   end else begin
     Result:=TPas2jsCachedFile(Node.Data);
   end;
-  Result.Load(true);
+  Result.Load(true,Binary);
 end;
 
 function TPas2jsFilesCache.NormalizeFilename(const Filename: string;
@@ -1921,7 +1976,7 @@ begin
       Filename:=FileResolver.FindCustomJSFileName(ResolveDots(InsertFilenames[i]));
       if Filename='' then
         raise EFileNotFoundError.Create('invalid custom JS file name "'+InsertFilenames[i]+'"');
-      aFile:=LoadTextFile(Filename);
+      aFile:=LoadFile(Filename);
       if aFile.Source='' then continue;
       aWriter.WriteFile(aFile.Source,Filename);
     end

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 327 - 234
packages/pastojs/src/pas2jsfiler.pp


+ 26 - 26
packages/pastojs/tests/tcfiler.pas

@@ -35,9 +35,9 @@ type
   TCustomTestPrecompile = Class(TCustomTestModule)
   private
     FAnalyzer: TPasAnalyzer;
-    FInitialFlags: TPJUInitialFlags;
-    FPJUReader: TPJUReader;
-    FPJUWriter: TPJUWriter;
+    FInitialFlags: TPCUInitialFlags;
+    FPJUReader: TPCUReader;
+    FPJUWriter: TPCUWriter;
     FRestAnalyzer: TPasAnalyzer;
     procedure OnFilerGetSrc(Sender: TObject; aFilename: string; out p: PChar;
       out Count: integer);
@@ -121,9 +121,9 @@ type
   public
     property Analyzer: TPasAnalyzer read FAnalyzer;
     property RestAnalyzer: TPasAnalyzer read FRestAnalyzer;
-    property PJUWriter: TPJUWriter read FPJUWriter write FPJUWriter;
-    property PJUReader: TPJUReader read FPJUReader write FPJUReader;
-    property InitialFlags: TPJUInitialFlags read FInitialFlags;
+    property PJUWriter: TPCUWriter read FPJUWriter write FPJUWriter;
+    property PJUReader: TPCUReader read FPJUReader write FPJUReader;
+    property InitialFlags: TPCUInitialFlags read FInitialFlags;
   end;
 
   { TTestPrecompile }
@@ -259,7 +259,7 @@ end;
 procedure TCustomTestPrecompile.SetUp;
 begin
   inherited SetUp;
-  FInitialFlags:=TPJUInitialFlags.Create;
+  FInitialFlags:=TPCUInitialFlags.Create;
   FAnalyzer:=TPasAnalyzer.Create;
   Analyzer.Resolver:=Engine;
   Analyzer.Options:=Analyzer.Options+[paoImplReferences];
@@ -302,8 +302,8 @@ var
 begin
   ConvertUnit;
 
-  FPJUWriter:=TPJUWriter.Create;
-  FPJUReader:=TPJUReader.Create;
+  FPJUWriter:=TPCUWriter.Create;
+  FPJUReader:=TPCUReader.Create;
   ms:=TMemoryStream.Create;
   RestParser:=nil;
   RestScanner:=nil;
@@ -315,7 +315,7 @@ begin
     try
       PJUWriter.OnGetSrc:=@OnFilerGetSrc;
       PJUWriter.OnIsElementUsed:=@OnConverterIsElementUsed;
-      PJUWriter.WritePJU(Engine,Converter,InitialFlags,ms,false);
+      PJUWriter.WritePCU(Engine,Converter,InitialFlags,ms,false);
     except
       on E: Exception do
       begin
@@ -345,9 +345,9 @@ begin
       RestParser.Options:=po_tcmodules;
       RestResolver.CurrentParser:=RestParser;
       ms.Position:=0;
-      PJUReader.ReadPJU(RestResolver,ms);
-      if not PJUReader.ReadJSONContinue then
-        Fail('ReadJSONContinue=false, pending used interfaces');
+      PJUReader.ReadPCU(RestResolver,ms);
+      if not PJUReader.ReadContinue then
+        Fail('ReadContinue=false, pending used interfaces');
     except
       on E: Exception do
       begin
@@ -604,7 +604,7 @@ begin
         AssertEquals(Path+'.Local.Identifier',OrigIdentifier.Identifier,RestIdentifier.Identifier);
         CheckRestoredReference(Path+'.Local',OrigIdentifier.Element,RestIdentifier.Element);
         if OrigIdentifier.Kind<>RestIdentifier.Kind then
-          Fail(Path+'.Local['+OrigIdentifier.Identifier+'] Orig='+PJUIdentifierKindNames[OrigIdentifier.Kind]+' Rest='+PJUIdentifierKindNames[RestIdentifier.Kind]);
+          Fail(Path+'.Local['+OrigIdentifier.Identifier+'] Orig='+PCUIdentifierKindNames[OrigIdentifier.Kind]+' Rest='+PCUIdentifierKindNames[RestIdentifier.Kind]);
         if OrigIdentifier.NextSameIdentifier=nil then
         begin
           if RestIdentifier.NextSameIdentifier<>nil then
@@ -719,7 +719,7 @@ begin
 
     CheckRestoredScopeReference(Path+'.ClassScope',Orig.ClassScope,Rest.ClassScope);
     CheckRestoredElement(Path+'.SelfArg',Orig.SelfArg,Rest.SelfArg);
-    AssertEquals(Path+'.Mode',PJUModeSwitchNames[Orig.Mode],PJUModeSwitchNames[Rest.Mode]);
+    AssertEquals(Path+'.Mode',PCUModeSwitchNames[Orig.Mode],PCUModeSwitchNames[Rest.Mode]);
     if Orig.Flags<>Rest.Flags then
       Fail(Path+'.Flags');
     if Orig.BoolSwitches<>Rest.BoolSwitches then
@@ -758,7 +758,7 @@ begin
       CheckRestoredReference(Path+'['+IntToStr(i)+'].Name="'+OrigRef.Element.Name+'"',OrigRef.Element,RestRef.Element);
       if OrigRef.Access<>RestRef.Access then
         AssertEquals(Path+'['+IntToStr(i)+']"'+OrigRef.Element.Name+'".Access',
-          PJUPSRefAccessNames[OrigRef.Access],PJUPSRefAccessNames[RestRef.Access]);
+          PCUPSRefAccessNames[OrigRef.Access],PCUPSRefAccessNames[RestRef.Access]);
       end;
     if RestList.Count>OrigList.Count then
       begin
@@ -787,7 +787,7 @@ begin
   if Orig.Flags<>Rest.Flags then
     Fail(Path+'.Flags');
   if Orig.Access<>Rest.Access then
-    AssertEquals(Path+'.Access',PJUResolvedRefAccessNames[Orig.Access],PJUResolvedRefAccessNames[Rest.Access]);
+    AssertEquals(Path+'.Access',PCUResolvedRefAccessNames[Orig.Access],PCUResolvedRefAccessNames[Rest.Access]);
   if not CheckRestoredObject(Path+'.Context',Orig.Context,Rest.Context) then exit;
   if Orig.Context<>nil then
     begin
@@ -962,7 +962,7 @@ begin
   AssertEquals(Path+'.SourceLinenumber',Orig.SourceLinenumber,Rest.SourceLinenumber);
   //AssertEquals(Path+'.SourceEndLinenumber',Orig.SourceEndLinenumber,Rest.SourceEndLinenumber);
   if Orig.Visibility<>Rest.Visibility then
-    Fail(Path+'.Visibility '+PJUMemberVisibilityNames[Orig.Visibility]+' '+PJUMemberVisibilityNames[Rest.Visibility]);
+    Fail(Path+'.Visibility '+PCUMemberVisibilityNames[Orig.Visibility]+' '+PCUMemberVisibilityNames[Rest.Visibility]);
   if Orig.Hints<>Rest.Hints then
     Fail(Path+'.Hints');
   AssertEquals(Path+'.HintMessage',Orig.HintMessage,Rest.HintMessage);
@@ -1237,7 +1237,7 @@ procedure TCustomTestPrecompile.CheckRestoredArrayType(const Path: string;
 begin
   CheckRestoredPasExprArray(Path+'.Ranges',Orig.Ranges,Rest.Ranges);
   if Orig.PackMode<>Rest.PackMode then
-    Fail(Path+'.PackMode Orig='+PJUPackModeNames[Orig.PackMode]+' Rest='+PJUPackModeNames[Rest.PackMode]);
+    Fail(Path+'.PackMode Orig='+PCUPackModeNames[Orig.PackMode]+' Rest='+PCUPackModeNames[Rest.PackMode]);
   CheckRestoredElOrRef(Path+'.ElType',Orig,Orig.ElType,Rest,Rest.ElType);
 end;
 
@@ -1277,7 +1277,7 @@ procedure TCustomTestPrecompile.CheckRestoredRecordType(const Path: string;
   Orig, Rest: TPasRecordType);
 begin
   if Orig.PackMode<>Rest.PackMode then
-    Fail(Path+'.PackMode Orig='+PJUPackModeNames[Orig.PackMode]+' Rest='+PJUPackModeNames[Rest.PackMode]);
+    Fail(Path+'.PackMode Orig='+PCUPackModeNames[Orig.PackMode]+' Rest='+PCUPackModeNames[Rest.PackMode]);
   CheckRestoredElementList(Path+'.Members',Orig.Members,Rest.Members);
   CheckRestoredElOrRef(Path+'.VariantEl',Orig,Orig.VariantEl,Rest,Rest.VariantEl);
   CheckRestoredElementList(Path+'.Variants',Orig.Variants,Rest.Variants);
@@ -1288,9 +1288,9 @@ procedure TCustomTestPrecompile.CheckRestoredClassType(const Path: string;
   Orig, Rest: TPasClassType);
 begin
   if Orig.PackMode<>Rest.PackMode then
-    Fail(Path+'.PackMode Orig='+PJUPackModeNames[Orig.PackMode]+' Rest='+PJUPackModeNames[Rest.PackMode]);
+    Fail(Path+'.PackMode Orig='+PCUPackModeNames[Orig.PackMode]+' Rest='+PCUPackModeNames[Rest.PackMode]);
   if Orig.ObjKind<>Rest.ObjKind then
-    Fail(Path+'.ObjKind Orig='+PJUObjKindNames[Orig.ObjKind]+' Rest='+PJUObjKindNames[Rest.ObjKind]);
+    Fail(Path+'.ObjKind Orig='+PCUObjKindNames[Orig.ObjKind]+' Rest='+PCUObjKindNames[Rest.ObjKind]);
   CheckRestoredReference(Path+'.AncestorType',Orig.AncestorType,Rest.AncestorType);
   CheckRestoredReference(Path+'.HelperForType',Orig.HelperForType,Rest.HelperForType);
   AssertEquals(Path+'.IsForward',Orig.IsForward,Rest.IsForward);
@@ -1309,7 +1309,7 @@ procedure TCustomTestPrecompile.CheckRestoredArgument(const Path: string; Orig,
   Rest: TPasArgument);
 begin
   if Orig.Access<>Rest.Access then
-    Fail(Path+'.Access Orig='+PJUArgumentAccessNames[Orig.Access]+' Rest='+PJUArgumentAccessNames[Rest.Access]);
+    Fail(Path+'.Access Orig='+PCUArgumentAccessNames[Orig.Access]+' Rest='+PCUArgumentAccessNames[Rest.Access]);
   CheckRestoredElOrRef(Path+'.ArgType',Orig,Orig.ArgType,Rest,Rest.ArgType);
   CheckRestoredElement(Path+'.ValueExpr',Orig.ValueExpr,Rest.ValueExpr);
 end;
@@ -1319,7 +1319,7 @@ procedure TCustomTestPrecompile.CheckRestoredProcedureType(const Path: string;
 begin
   CheckRestoredElementList(Path+'.Args',Orig.Args,Rest.Args);
   if Orig.CallingConvention<>Rest.CallingConvention then
-    Fail(Path+'.CallingConvention Orig='+PJUCallingConventionNames[Orig.CallingConvention]+' Rest='+PJUCallingConventionNames[Rest.CallingConvention]);
+    Fail(Path+'.CallingConvention Orig='+PCUCallingConventionNames[Orig.CallingConvention]+' Rest='+PCUCallingConventionNames[Rest.CallingConvention]);
   if Orig.Modifiers<>Rest.Modifiers then
     Fail(Path+'.Modifiers');
 end;
@@ -1409,7 +1409,7 @@ begin
       Fail(Path+'.Modifiers');
     AssertEquals(Path+'.MessageName',Orig.MessageName,Rest.MessageName);
     if Orig.MessageType<>Rest.MessageType then
-      Fail(Path+'.MessageType Orig='+PJUProcedureMessageTypeNames[Orig.MessageType]+' Rest='+PJUProcedureMessageTypeNames[Rest.MessageType]);
+      Fail(Path+'.MessageType Orig='+PCUProcedureMessageTypeNames[Orig.MessageType]+' Rest='+PCUProcedureMessageTypeNames[Rest.MessageType]);
     end
   else
     begin
@@ -1422,7 +1422,7 @@ procedure TCustomTestPrecompile.CheckRestoredOperator(const Path: string; Orig,
   Rest: TPasOperator);
 begin
   if Orig.OperatorType<>Rest.OperatorType then
-    Fail(Path+'.OperatorType Orig='+PJUOperatorTypeNames[Orig.OperatorType]+' Rest='+PJUOperatorTypeNames[Rest.OperatorType]);
+    Fail(Path+'.OperatorType Orig='+PCUOperatorTypeNames[Orig.OperatorType]+' Rest='+PCUOperatorTypeNames[Rest.OperatorType]);
   AssertEquals(Path+'.TokenBased',Orig.TokenBased,Rest.TokenBased);
   CheckRestoredProcedure(Path,Orig,Rest);
 end;

+ 35 - 556
packages/pastojs/tests/tcprecompile.pas

@@ -14,588 +14,67 @@
  **********************************************************************
 
  Examples:
-    ./testpas2js --suite=TestCLI_UnitSearch.
-    ./testpas2js --suite=TestUS_Program
-    ./testpas2js --suite=TestUS_UsesEmptyFileFail
+    ./testpas2js --suite=TTestCLI_Precompile
+    ./testpas2js --suite=TTestModule.TestEmptyUnit
 }
-unit tcunitsearch;
+unit tcprecompile;
 
 {$mode objfpc}{$H+}
 
 interface
 
 uses
-  Classes, SysUtils, contnrs,
+  Classes, SysUtils,
   fpcunit, testregistry,
-  PScanner, Pas2jsFileUtils, Pas2jsCompiler, Pas2jsFileCache, Pas2jsLogger,
-  tcmodules;
+  tcunitsearch, tcmodules;
 
 type
 
-  { TTestCompiler }
+  { TTestCLI_Precompile }
 
-  TTestCompiler = class(TPas2jsCompiler)
-  private
-    FExitCode: longint;
-  protected
-    function GetExitCode: Longint; override;
-    procedure SetExitCode(Value: Longint); override;
-  end;
-
-  { TCLIFile }
-
-  TCLIFile = class
-  public
-    Filename: string;
-    Source: string;
-    Age: TPas2jsFileAgeTime;
-    Attr: TPas2jsFileAttr;
-    constructor Create(const aFilename, Src: string; aAge: TPas2jsFileAgeTime;
-       aAttr: TPas2jsFileAttr);
-  end;
-
-  { TCLILogMsg }
-
-  TCLILogMsg = class
+  TTestCLI_Precompile = class(TCustomTestCLI)
   public
-    Msg: string;
-    MsgTxt: string;
-    MsgType: TMessageType;
-    MsgNumber: integer;
-    MsgFile: string;
-    MsgLine: integer;
-    MsgCol: integer;
-  end;
-
-  { TCustomTestCLI }
-
-  TCustomTestCLI = class(TTestCase)
-  private
-    FErrorCol: integer;
-    FErrorFile: string;
-    FErrorLine: integer;
-    FErrorMsg: string;
-    FErrorNumber: integer;
-    FWorkDir: string;
-    FCompilerExe: string;
-    FCompiler: TTestCompiler;
-    FDefaultFileAge: longint;
-    FFiles: TObjectList; // list of TCLIFile
-    FLogMsgs: TObjectList; // list ot TCLILogMsg
-    FParams: TStringList;
-    function GetExitCode: integer;
-    function GetFiles(Index: integer): TCLIFile;
-    function GetLogMsgs(Index: integer): TCLILogMsg;
-    procedure SetExitCode(const AValue: integer);
-    procedure SetWorkDir(const AValue: string);
-  protected
-    procedure SetUp; override;
-    procedure TearDown; override;
-    procedure DoLog(Sender: TObject; const Msg: String);
-    Function OnReadDirectory(Dir: TPas2jsCachedDirectory): boolean; virtual;
-    Function OnReadFile(aFilename: string; var aSource: string): boolean; virtual;
-    procedure OnWriteFile(aFilename: string; Source: string);
-    procedure WriteSources;
-  public
-    constructor Create; override;
-    destructor Destroy; override;
-    procedure Compile(const Args: array of string; ExpectedExitCode: longint = 0);
-    property Compiler: TTestCompiler read FCompiler;
-    property CompilerExe: string read FCompilerExe write FCompilerExe;
-    property Params: TStringList read FParams;
-    property Files[Index: integer]: TCLIFile read GetFiles; // files an directories
-    function FileCount: integer;
-    function FindFile(Filename: string): TCLIFile; // files and directories
-    function ExpandFilename(const Filename: string): string;
-    function AddFile(Filename, Source: string): TCLIFile;
-    function AddFile(Filename: string; const SourceLines: array of string): TCLIFile;
-    function AddUnit(Filename: string; const Intf, Impl: array of string): TCLIFile;
-    function AddDir(Filename: string): TCLIFile;
-    property WorkDir: string read FWorkDir write SetWorkDir;
-    property DefaultFileAge: longint read FDefaultFileAge write FDefaultFileAge;
-    property ExitCode: integer read GetExitCode write SetExitCode;
-    property LogMsgs[Index: integer]: TCLILogMsg read GetLogMsgs;
-    function GetLogCount: integer;
-    property ErrorMsg: string read FErrorMsg write FErrorMsg;
-    property ErrorFile: string read FErrorFile write FErrorFile;
-    property ErrorLine: integer read FErrorLine write FErrorLine;
-    property ErrorCol: integer read FErrorCol write FErrorCol;
-    property ErrorNumber: integer read FErrorNumber write FErrorNumber;
-  end;
-
-  { TTestCLI_UnitSearch }
-
-  TTestCLI_UnitSearch = class(TCustomTestCLI)
   published
-    procedure TestUS_Program;
-    procedure TestUS_UsesEmptyFileFail;
-
-    procedure TestUS_UsesInFile;
-    procedure TestUS_UsesInFile_Duplicate;
-    procedure TestUS_UsesInFile_IndirectDuplicate;
+    procedure TestPCU_EmptyUnit;
   end;
 
-function LinesToStr(const Lines: array of string): string;
-
 implementation
 
-function LinesToStr(const Lines: array of string): string;
-var
-  i: Integer;
-begin
-  Result:='';
-  for i:=low(Lines) to high(Lines) do
-    Result:=Result+Lines[i]+LineEnding;
-end;
-
-{ TCLIFile }
-
-constructor TCLIFile.Create(const aFilename, Src: string;
-  aAge: TPas2jsFileAgeTime; aAttr: TPas2jsFileAttr);
-begin
-  Filename:=aFilename;
-  Source:=Src;
-  Age:=aAge;
-  Attr:=aAttr;
-end;
-
-{ TTestCompiler }
-
-function TTestCompiler.GetExitCode: Longint;
-begin
-  Result:=FExitCode;
-end;
-
-procedure TTestCompiler.SetExitCode(Value: Longint);
-begin
-  FExitCode:=Value;
-end;
-
-{ TCustomTestCLI }
-
-function TCustomTestCLI.GetFiles(Index: integer): TCLIFile;
-begin
-  Result:=TCLIFile(FFiles[Index]);
-end;
-
-function TCustomTestCLI.GetExitCode: integer;
-begin
-  Result:=Compiler.ExitCode;
-end;
-
-function TCustomTestCLI.GetLogMsgs(Index: integer): TCLILogMsg;
-begin
-  Result:=TCLILogMsg(FLogMsgs[Index]);
-end;
-
-procedure TCustomTestCLI.SetExitCode(const AValue: integer);
-begin
-  Compiler.ExitCode:=AValue;
-end;
-
-procedure TCustomTestCLI.SetWorkDir(const AValue: string);
-var
-  NewValue: String;
-begin
-  NewValue:=IncludeTrailingPathDelimiter(ResolveDots(AValue));
-  if FWorkDir=NewValue then Exit;
-  FWorkDir:=NewValue;
-end;
-
-procedure TCustomTestCLI.SetUp;
-begin
-  inherited SetUp;
-  FDefaultFileAge:=DateTimeToFileDate(Now);
-  {$IFDEF Windows}
-  WorkDir:='P:\test';
-  CompilerExe:='P:\bin\pas2js.exe';
-  {$ELSE}
-  WorkDir:='/home/user';
-  CompilerExe:='/usr/bin/pas2js';
-  {$ENDIF}
-  FCompiler:=TTestCompiler.Create;
-  Compiler.Log.OnLog:=@DoLog;
-  Compiler.FileCache.DirectoryCache.OnReadDirectory:=@OnReadDirectory;
-  Compiler.FileCache.OnReadFile:=@OnReadFile;
-  Compiler.FileCache.OnWriteFile:=@OnWriteFile;
-end;
-
-procedure TCustomTestCLI.TearDown;
-begin
-  FreeAndNil(FCompiler);
-  FParams.Clear;
-  FFiles.Clear;
-  FLogMsgs.Clear;
-  FErrorMsg:='';
-  FErrorFile:='';
-  FErrorLine:=0;
-  FErrorCol:=0;
-  FErrorNumber:=0;
-  inherited TearDown;
-end;
-
-procedure TCustomTestCLI.DoLog(Sender: TObject; const Msg: String);
-var
-  LogMsg: TCLILogMsg;
-begin
-  {$IFDEF VerbosePasResolver}
-  writeln('TCustomTestCLI.DoLog ',Msg,' File=',Compiler.Log.LastMsgFile,' Line=',Compiler.Log.LastMsgLine);
-  {$ENDIF}
-  LogMsg:=TCLILogMsg.Create;
-  LogMsg.Msg:=Msg;
-  LogMsg.MsgTxt:=Compiler.Log.LastMsgTxt;
-  LogMsg.MsgType:=Compiler.Log.LastMsgType;
-  LogMsg.MsgFile:=Compiler.Log.LastMsgFile;
-  LogMsg.MsgLine:=Compiler.Log.LastMsgLine;
-  LogMsg.MsgCol:=Compiler.Log.LastMsgCol;
-  LogMsg.MsgNumber:=Compiler.Log.LastMsgNumber;
-  FLogMsgs.Add(LogMsg);
-  if (LogMsg.MsgType<=mtError) then
-  begin
-    if (ErrorFile='')
-        or ((ErrorLine<1) and (LogMsg.MsgLine>0)) then
-    begin
-      ErrorMsg:=LogMsg.MsgTxt;
-      ErrorFile:=LogMsg.MsgFile;
-      ErrorLine:=LogMsg.MsgLine;
-      ErrorCol:=LogMsg.MsgCol;
-    end;
-  end;
-end;
-
-function TCustomTestCLI.OnReadDirectory(Dir: TPas2jsCachedDirectory): boolean;
-var
-  i: Integer;
-  aFile: TCLIFile;
-  Path: String;
-begin
-  Path:=Dir.Path;
-  //writeln('TCustomTestCLI.ReadDirectory START ',Path,' ',Dir.Count);
-  Dir.Add('.',DefaultFileAge,faDirectory,4096);
-  Dir.Add('..',DefaultFileAge,faDirectory,4096);
-  for i:=0 to FileCount-1 do
-    begin
-    aFile:=Files[i];
-    if CompareFilenames(ExtractFilePath(aFile.Filename),Path)<>0 then continue;
-    //writeln('TCustomTestCLI.ReadDirectory ',aFile.Filename);
-    Dir.Add(ExtractFileName(aFile.Filename),aFile.Age,aFile.Attr,length(aFile.Source));
-    end;
-  //writeln('TCustomTestCLI.ReadDirectory END ',Path,' ',Dir.Count);
-  Result:=true;
-end;
+{ TTestCLI_Precompile }
 
-function TCustomTestCLI.OnReadFile(aFilename: string; var aSource: string
-  ): boolean;
+procedure TTestCLI_Precompile.TestPCU_EmptyUnit;
 var
-  aFile: TCLIFile;
+  aFile, JSFile: TCLIFile;
+  OrigSrc, NewSrc, s: String;
 begin
-  aFile:=FindFile(aFilename);
-  //writeln('TCustomTestCLI.ReadFile ',aFilename,' Found=',aFile<>nil);
-  if aFile=nil then exit(false);
-  if (faDirectory and aFile.Attr)>0 then
-  begin
-    {$IFDEF VerbosePasResolver}
-    writeln('[20180224000557] TCustomTestCLI.OnReadFile ',aFilename);
-    {$ENDIF}
-    EPas2jsFileCache.Create('TCustomTestCLI.OnReadFile: reading directory '+aFilename);
-  end;
-  aSource:=aFile.Source;
-  Result:=true;
-end;
-
-procedure TCustomTestCLI.OnWriteFile(aFilename: string; Source: string);
-var
-  aFile: TCLIFile;
-begin
-  aFile:=FindFile(aFilename);
-  {$IFDEF VerbosePasResolver}
-  writeln('TCustomTestCLI.WriteFile ',aFilename,' Found=',aFile<>nil);
-  {$ENDIF}
-  if aFile<>nil then
-  begin
-    if faDirectory and aFile.Attr>0 then
-    begin
-      {$IFDEF VerbosePasResolver}
-      writeln('[20180223175616] TCustomTestCLI.OnWriteFile ',aFilename);
-      {$ENDIF}
-      raise EPas2jsFileCache.Create('unable to write file to directory "'+aFilename+'"');
-    end;
-  end else
-  begin
-    aFile:=TCLIFile.Create(aFilename,'',0,0);
-    FFiles.Add(aFile);
-  end;
-  aFile.Source:=Source;
-  aFile.Attr:=faDirectory;
-  aFile.Age:=DateTimeToFileDate(Now);
-end;
-
-procedure TCustomTestCLI.WriteSources;
-var
-  i, j, aRow, aCol: Integer;
-  aFile: TCLIFile;
-  SrcLines: TStringList;
-  Line, aFilename: String;
-  IsSrc: Boolean;
-begin
-  writeln('TCustomTestCLI.WriteSources START');
-  aFilename:=ErrorFile;
-  aRow:=ErrorLine;
-  aCol:=ErrorCol;
-  SrcLines:=TStringList.Create;
-  try
-    for i:=0 to FileCount-1 do
-    begin
-      aFile:=Files[i];
-      if (faDirectory and aFile.Attr)>0 then continue;
-      writeln('Testcode:-File="',aFile.Filename,'"----------------------------------:');
-      SrcLines.Text:=aFile.Source;
-      IsSrc:=ExtractFilename(aFile.Filename)=ExtractFileName(aFilename);
-      for j:=1 to SrcLines.Count do
-        begin
-        Line:=SrcLines[j-1];
-        if IsSrc and (j=aRow) then
-          begin
-          write('*');
-          Line:=LeftStr(Line,aCol-1)+'|'+copy(Line,aCol,length(Line));
-          end;
-        writeln(Format('%:4d: ',[j]),Line);
-        end;
-    end;
-  finally
-    SrcLines.Free;
-  end;
-end;
-
-constructor TCustomTestCLI.Create;
-begin
-  inherited Create;
-  FFiles:=TObjectList.Create(true);
-  FLogMsgs:=TObjectList.Create(true);
-  FParams:=TStringList.Create;
-end;
-
-destructor TCustomTestCLI.Destroy;
-begin
-  FreeAndNil(FFiles);
-  FreeAndNil(FLogMsgs);
-  FreeAndNil(FParams);
-  inherited Destroy;
-end;
-
-procedure TCustomTestCLI.Compile(const Args: array of string;
-  ExpectedExitCode: longint);
-var
-  i: Integer;
-begin
-  AssertEquals('Initial System.ExitCode',0,system.ExitCode);
-  for i:=low(Args) to High(Args) do
-    Params.Add(Args[i]);
-  try
-    try
-      //writeln('TCustomTestCLI.Compile WorkDir=',WorkDir);
-      Compiler.Run(CompilerExe,WorkDir,Params,false);
-    except
-      on E: ECompilerTerminate do
-      begin
-        {$IFDEF VerbosePasResolver}
-        writeln('TCustomTestCLI.Compile ',E.ClassName,':',E.Message);
-        {$ENDIF}
-      end;
-      on E: Exception do
-      begin
-        {$IFDEF VerbosePasResolver}
-        writeln('TCustomTestCLI.Compile ',E.ClassName,':',E.Message);
-        {$ENDIF}
-        Fail('TCustomTestCLI.Compile '+E.ClassName+':'+E.Message);
-      end;
-    end;
-  finally
-    Compiler.Log.CloseOutputFile;
-  end;
-
-  if ExpectedExitCode<>ExitCode then
-  begin
-    WriteSources;
-    AssertEquals('ExitCode',ExpectedExitCode,ExitCode);
-  end;
-end;
-
-function TCustomTestCLI.FileCount: integer;
-begin
-  Result:=FFiles.Count;
-end;
-
-function TCustomTestCLI.FindFile(Filename: string): TCLIFile;
-var
-  i: Integer;
-begin
-  Filename:=ExpandFilename(Filename);
-  for i:=0 to FileCount-1 do
-    if CompareFilenames(Files[i].Filename,Filename)=0 then
-      exit(Files[i]);
-  Result:=nil;
-end;
-
-function TCustomTestCLI.ExpandFilename(const Filename: string): string;
-begin
-  Result:=SetDirSeparators(Filename);
-  if not FilenameIsAbsolute(Result) then
-    Result:=WorkDir+Result;
-  Result:=ResolveDots(Result);
-end;
-
-function TCustomTestCLI.AddFile(Filename, Source: string): TCLIFile;
-begin
-  Filename:=ExpandFilename(Filename);
-  {$IFDEF VerbosePJUFiler}
-  writeln('TCustomTestCLI.AddFile ',Filename);
-  {$ENDIF}
-  Result:=FindFile(Filename);
-  if Result<>nil then
-    raise Exception.Create('[20180224001050] TCustomTestCLI.AddFile already exists: '+Filename);
-  FFiles.Add(TCLIFile.Create(Filename,Source,DefaultFileAge,faNormal));
-  AddDir(ExtractFilePath(Filename));
-end;
-
-function TCustomTestCLI.AddFile(Filename: string;
-  const SourceLines: array of string): TCLIFile;
-begin
-  Result:=AddFile(Filename,LinesToStr(SourceLines));
-end;
-
-function TCustomTestCLI.AddUnit(Filename: string; const Intf,
-  Impl: array of string): TCLIFile;
-var
-  Name: String;
-begin
-  Name:=ExtractFilenameOnly(Filename);
-  Result:=AddFile(Filename,
-    'unit '+Name+';'+LineEnding
-    +'interface'+LineEnding
-    +LinesToStr(Intf)
-    +'implementation'+LineEnding
-    +LinesToStr(Impl)
-    +'end.'+LineEnding);
-end;
-
-function TCustomTestCLI.AddDir(Filename: string): TCLIFile;
-var
-  p: Integer;
-  Dir: String;
-  aFile: TCLIFile;
-begin
-  Result:=nil;
-  Filename:=ExpandFilename(Filename);
-  p:=length(Filename);
-  while p>1 do
-  begin
-    if Filename[p]=PathDelim then
-    begin
-      Dir:=LeftStr(Filename,p-1);
-      aFile:=FindFile(Dir);
-      if Result=nil then
-        Result:=aFile;
-      if aFile=nil then
-        FFiles.Add(TCLIFile.Create(Dir,'',DefaultFileAge,faDirectory))
-      else if (aFile.Attr and faDirectory)=0 then
-      begin
-        {$IFDEF VerbosePasResolver}
-        writeln('[20180224001036] TCustomTestCLI.AddDir Dir=',Dir);
-        {$ENDIF}
-        raise EPas2jsFileCache.Create('[20180224001036] TCustomTestCLI.AddDir Dir='+Dir);
-      end;
-      dec(p);
-    end else
-      dec(p);
-  end;
-end;
-
-function TCustomTestCLI.GetLogCount: integer;
-begin
-  Result:=FLogMsgs.Count;
-end;
-
-{ TTestCLI_UnitSearch }
-
-procedure TTestCLI_UnitSearch.TestUS_Program;
-begin
-  AddUnit('system.pp',[''],['']);
+  AddUnit('sub/system.pp',[''],['']);
   AddFile('test1.pas',[
     'begin',
     'end.']);
-  Compile(['test1.pas','-va']);
-end;
-
-procedure TTestCLI_UnitSearch.TestUS_UsesEmptyFileFail;
-begin
-  AddFile('system.pp','');
-  AddFile('test1.pas',[
-    'begin',
-    'end.']);
-  Compile(['test1.pas',''],ExitCodeSyntaxError);
-  AssertEquals('ErrorMsg','Expected "unit"',ErrorMsg);
-end;
-
-procedure TTestCLI_UnitSearch.TestUS_UsesInFile;
-begin
-  AddUnit('system.pp',[''],['']);
-  AddUnit('unit1.pas',
-  ['uses bird in ''unit2.pas'';',
-   'var a: longint;'],
-  ['']);
-  AddUnit('unit2.pas',
-  ['var b: longint;'],
-  ['']);
-  AddFile('test1.pas',[
-    'uses foo in ''unit1.pas'', bar in ''unit2.pas'';',
-    'begin',
-    '  bar.b:=foo.a;',
-    '  a:=b;',
-    'end.']);
-  Compile(['test1.pas','-Jc']);
-end;
-
-procedure TTestCLI_UnitSearch.TestUS_UsesInFile_Duplicate;
-begin
-  AddUnit('system.pp',[''],['']);
-  AddUnit('unit1.pas',
-  ['var a: longint;'],
-  ['']);
-  AddUnit('sub/unit1.pas',
-  ['var b: longint;'],
-  ['']);
-  AddFile('test1.pas',[
-    'uses foo in ''unit1.pas'', bar in ''sub/unit1.pas'';',
-    'begin',
-    '  bar.b:=foo.a;',
-    '  a:=b;',
-    'end.']);
-  Compile(['test1.pas','-Jc'],ExitCodeSyntaxError);
-  AssertEquals('ErrorMsg','Duplicate file found: "/home/user/sub/unit1.pas" and "/home/user/unit1.pas"',ErrorMsg);
-end;
-
-procedure TTestCLI_UnitSearch.TestUS_UsesInFile_IndirectDuplicate;
-begin
-  AddUnit('system.pp',[''],['']);
-  AddUnit('unit1.pas',
-  ['var a: longint;'],
-  ['']);
-  AddUnit('sub/unit1.pas',
-  ['var b: longint;'],
-  ['']);
-  AddUnit('unit2.pas',
-  ['uses unit1 in ''unit1.pas'';'],
-  ['']);
-  AddFile('test1.pas',[
-    'uses unit2, foo in ''sub/unit1.pas'';',
-    'begin',
-    'end.']);
-  Compile(['test1.pas','-Jc'],ExitCodeSyntaxError);
-  AssertEquals('ErrorMsg','Duplicate file found: "/home/user/unit1.pas" and "/home/user/sub/unit1.pas"',ErrorMsg);
+  AddDir('units');
+  // compile, create  .pcu files
+  {$IFDEF VerbosePJUFiler}
+  writeln('TTestCLI_Precompile.TestPCU_EmptyUnit create pcu files=========================');
+  {$ENDIF}
+  Compile(['test1.pas','-Jc','-Fusub','-JUpcu','-FUunits']);
+  aFile:=FindFile('units/system.pcu');
+  AssertNotNull('units/system.pcu',aFile);
+  JSFile:=FindFile('units/test1.js');
+  AssertNotNull('units/test1.js',JSFile);
+  OrigSrc:=JSFile.Source;
+
+  // compile, using .pcu files
+  {$IFDEF VerbosePJUFiler}
+  writeln('TTestCLI_Precompile.TestPCU_EmptyUnit compile using pcu files==================');
+  {$ENDIF}
+  Compiler.Reset;
+  Compile(['test1.pas','-Jc','-Fuunits']);
+  NewSrc:=JSFile.Source;
+  if not CheckSrcDiff(OrigSrc,NewSrc,s) then
+    Fail('test1.js: '+s);
 end;
 
 Initialization
-  RegisterTests([TTestCLI_UnitSearch]);
+  RegisterTests([TTestCLI_Precompile]);
 end.
 

+ 25 - 14
packages/pastojs/tests/tcunitsearch.pas

@@ -71,6 +71,7 @@ type
 
   TCustomTestCLI = class(TTestCase)
   private
+    FCurDate: TDateTime;
     FErrorCol: integer;
     FErrorFile: string;
     FErrorLine: integer;
@@ -94,7 +95,7 @@ type
     procedure DoLog(Sender: TObject; const Msg: String);
     Function OnReadDirectory(Dir: TPas2jsCachedDirectory): boolean; virtual;
     Function OnReadFile(aFilename: string; var aSource: string): boolean; virtual;
-    procedure OnWriteFile(aFilename: string; Source: string);
+    procedure OnWriteFile(aFilename: string; Source: string); virtual;
     procedure WriteSources;
   public
     constructor Create; override;
@@ -121,6 +122,7 @@ type
     property ErrorLine: integer read FErrorLine write FErrorLine;
     property ErrorCol: integer read FErrorCol write FErrorCol;
     property ErrorNumber: integer read FErrorNumber write FErrorNumber;
+    property CurDate: TDateTime read FCurDate write FCurDate;
   end;
 
   { TTestCLI_UnitSearch }
@@ -238,7 +240,7 @@ procedure TCustomTestCLI.DoLog(Sender: TObject; const Msg: String);
 var
   LogMsg: TCLILogMsg;
 begin
-  {$IFDEF VerbosePasResolver}
+  {$IF defined(VerbosePasResolver) or defined(VerbosePJUFiler)}
   writeln('TCustomTestCLI.DoLog ',Msg,' File=',Compiler.Log.LastMsgFile,' Line=',Compiler.Log.LastMsgLine);
   {$ENDIF}
   LogMsg:=TCLILogMsg.Create;
@@ -294,12 +296,13 @@ begin
   if aFile=nil then exit(false);
   if (faDirectory and aFile.Attr)>0 then
   begin
-    {$IFDEF VerbosePasResolver}
+    {$IF defined(VerbosePasResolver) or defined(VerbosePJUFiler)}
     writeln('[20180224000557] TCustomTestCLI.OnReadFile ',aFilename);
     {$ENDIF}
     EPas2jsFileCache.Create('TCustomTestCLI.OnReadFile: reading directory '+aFilename);
   end;
   aSource:=aFile.Source;
+  //writeln('TCustomTestCLI.OnReadFile ',aFile.Filename,' "',LeftStr(aFile.Source,50),'"');
   Result:=true;
 end;
 
@@ -308,14 +311,14 @@ var
   aFile: TCLIFile;
 begin
   aFile:=FindFile(aFilename);
-  {$IFDEF VerbosePasResolver}
-  writeln('TCustomTestCLI.WriteFile ',aFilename,' Found=',aFile<>nil);
+  {$IF defined(VerbosePasResolver) or defined(VerbosePJUFiler)}
+  writeln('TCustomTestCLI.WriteFile ',aFilename,' Found=',aFile<>nil,' SrcLen=',length(Source));
   {$ENDIF}
   if aFile<>nil then
   begin
     if faDirectory and aFile.Attr>0 then
     begin
-      {$IFDEF VerbosePasResolver}
+      {$IF defined(VerbosePasResolver) or defined(VerbosePJUFiler)}
       writeln('[20180223175616] TCustomTestCLI.OnWriteFile ',aFilename);
       {$ENDIF}
       raise EPas2jsFileCache.Create('unable to write file to directory "'+aFilename+'"');
@@ -326,8 +329,9 @@ begin
     FFiles.Add(aFile);
   end;
   aFile.Source:=Source;
-  aFile.Attr:=faDirectory;
-  aFile.Age:=DateTimeToFileDate(Now);
+  aFile.Attr:=faNormal;
+  aFile.Age:=DateTimeToFileDate(CurDate);
+  //writeln('TCustomTestCLI.OnWriteFile ',aFile.Filename,' "',LeftStr(aFile.Source,50),'"');
 end;
 
 procedure TCustomTestCLI.WriteSources;
@@ -373,6 +377,7 @@ begin
   FFiles:=TObjectList.Create(true);
   FLogMsgs:=TObjectList.Create(true);
   FParams:=TStringList.Create;
+  CurDate:=Now;
 end;
 
 destructor TCustomTestCLI.Destroy;
@@ -389,6 +394,7 @@ var
   i: Integer;
 begin
   AssertEquals('Initial System.ExitCode',0,system.ExitCode);
+  Params.Clear;
   for i:=low(Args) to High(Args) do
     Params.Add(Args[i]);
   try
@@ -398,13 +404,13 @@ begin
     except
       on E: ECompilerTerminate do
       begin
-        {$IFDEF VerbosePasResolver}
+        {$IF defined(VerbosePasResolver) or defined(VerbosePJUFiler)}
         writeln('TCustomTestCLI.Compile ',E.ClassName,':',E.Message);
         {$ENDIF}
       end;
       on E: Exception do
       begin
-        {$IFDEF VerbosePasResolver}
+        {$IF defined(VerbosePasResolver) or defined(VerbosePJUFiler)}
         writeln('TCustomTestCLI.Compile ',E.ClassName,':',E.Message);
         {$ENDIF}
         Fail('TCustomTestCLI.Compile '+E.ClassName+':'+E.Message);
@@ -486,7 +492,7 @@ var
   aFile: TCLIFile;
 begin
   Result:=nil;
-  Filename:=ExpandFilename(Filename);
+  Filename:=IncludeTrailingPathDelimiter(ExpandFilename(Filename));
   p:=length(Filename);
   while p>1 do
   begin
@@ -497,11 +503,16 @@ begin
       if Result=nil then
         Result:=aFile;
       if aFile=nil then
-        FFiles.Add(TCLIFile.Create(Dir,'',DefaultFileAge,faDirectory))
+        begin
+        {$IFDEF VerbosePJUFiler}
+        writeln('TCustomTestCLI.AddDir add Dir=',Dir);
+        {$ENDIF}
+        FFiles.Add(TCLIFile.Create(Dir,'',DefaultFileAge,faDirectory));
+        end
       else if (aFile.Attr and faDirectory)=0 then
       begin
-        {$IFDEF VerbosePasResolver}
-        writeln('[20180224001036] TCustomTestCLI.AddDir Dir=',Dir);
+        {$IFDEF VerbosePJUFiler}
+        writeln('[20180224001036] TCustomTestCLI.AddDir file exists: Dir=',Dir);
         {$ENDIF}
         raise EPas2jsFileCache.Create('[20180224001036] TCustomTestCLI.AddDir Dir='+Dir);
       end;

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels