mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-09 15:08:44 +02:00
pastojs: filer: test write/read multiple pcu
git-svn-id: trunk@38516 -
This commit is contained in:
parent
8e393548cf
commit
fa0bf267e2
@ -253,6 +253,10 @@ type
|
||||
out Count: integer);
|
||||
procedure OnPasResolverLog(Sender: TObject; const Msg: String);
|
||||
procedure OnParserLog(Sender: TObject; const Msg: String);
|
||||
function OnPCUConverterIsElementUsed(Sender: TObject; El: TPasElement
|
||||
): boolean;
|
||||
function OnPCUConverterIsTypeInfoUsed(Sender: TObject; El: TPasElement
|
||||
): boolean;
|
||||
procedure OnScannerLog(Sender: TObject; const Msg: String);
|
||||
procedure OnUseAnalyzerMessage(Sender: TObject; Msg: TPAMessage);
|
||||
procedure HandleEParserError(E: EParserError);
|
||||
@ -275,6 +279,7 @@ type
|
||||
function GetInitialConverterOptions: TPasToJsConverterOptions;
|
||||
procedure CreateScannerAndParser(aFileResolver: TPas2jsFileResolver);
|
||||
procedure CreatePCUReader;
|
||||
procedure CreateConverter;
|
||||
function FindPCU(const UseUnitName: string; out aFormat: TPas2JSPrecompileFormat): string;
|
||||
function OnResolverFindModule(const UseUnitName, InFilename: String; NameExpr,
|
||||
InFileExpr: TPasExpr): TPasModule;
|
||||
@ -868,6 +873,15 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TPas2jsCompilerFile.CreateConverter;
|
||||
begin
|
||||
if FConverter<>nil then exit;
|
||||
FConverter:=TPasToJSConverter.Create;
|
||||
FConverter.Options:=GetInitialConverterOptions;
|
||||
FConverter.TargetPlatform:=Compiler.TargetPlatform;
|
||||
FConverter.TargetProcessor:=Compiler.TargetProcessor;
|
||||
end;
|
||||
|
||||
procedure TPas2jsCompilerFile.OnResolverCheckSrcName(const Element: TPasElement);
|
||||
var
|
||||
SrcName, ExpectedSrcName: String;
|
||||
@ -968,6 +982,18 @@ begin
|
||||
aScanner.CurFilename,aScanner.CurRow,aScanner.CurColumn);
|
||||
end;
|
||||
|
||||
function TPas2jsCompilerFile.OnPCUConverterIsElementUsed(Sender: TObject;
|
||||
El: TPasElement): boolean;
|
||||
begin
|
||||
Result:=UseAnalyzer.IsUsed(El);
|
||||
end;
|
||||
|
||||
function TPas2jsCompilerFile.OnPCUConverterIsTypeInfoUsed(Sender: TObject;
|
||||
El: TPasElement): boolean;
|
||||
begin
|
||||
Result:=UseAnalyzer.IsTypeInfoUsed(El);
|
||||
end;
|
||||
|
||||
procedure TPas2jsCompilerFile.OnScannerLog(Sender: TObject; const Msg: String);
|
||||
var
|
||||
aScanner: TPascalScanner;
|
||||
@ -1028,7 +1054,7 @@ end;
|
||||
procedure TPas2jsCompilerFile.HandleUnknownException(E: Exception);
|
||||
begin
|
||||
if not (E is ECompilerTerminate) then
|
||||
Log.Log(mtFatal,'bug: uncaught ECompilerTerminate'+': '+E.Message,0); // must use on E:ECompilerTerminate do raise;
|
||||
Log.Log(mtFatal,'bug: uncaught '+E.ClassName+': '+E.Message,0); // must use on E:ECompilerTerminate do raise;
|
||||
Log.Log(mtFatal,E.ClassName+': '+E.Message,0);
|
||||
Compiler.Terminate(ExitCodeErrorInternal);
|
||||
// Note: a "raise E" is not allowed by caught exceptions, try..except will free it
|
||||
@ -1118,7 +1144,7 @@ begin
|
||||
writeln('TPas2jsCompilerFile.ReaderFinished analyzing ',PasFilename,' ...');
|
||||
{$ENDIF}
|
||||
UseAnalyzer.AnalyzeModule(FPasModule);
|
||||
{$IF defined(VerboseUnitQueue) or defined(VerbosePJUFiler)}
|
||||
{$IF defined(VerboseUnitQueue) or defined(VerbosePCUFiler)}
|
||||
writeln('TPas2jsCompilerFile.ReaderFinished analyzed ',PasFilename,' ScopeModule=',GetObjName(UseAnalyzer.ScopeModule));
|
||||
{$ENDIF}
|
||||
|
||||
@ -1138,10 +1164,11 @@ var
|
||||
Writer: TPCUWriter;
|
||||
ms: TMemoryStream;
|
||||
DestDir: String;
|
||||
JS: TJSElement;
|
||||
begin
|
||||
if PasModule.ClassType<>TPasModule then
|
||||
begin
|
||||
{$IF defined(VerboseUnitQueue) or defined(VerbosePJUFiler)}
|
||||
{$IF defined(VerboseUnitQueue) or defined(VerbosePCUFiler)}
|
||||
writeln('TPas2jsCompilerFile.WritePCU not a unit: ',PasFilename,' skip');
|
||||
{$ENDIF}
|
||||
exit;
|
||||
@ -1149,7 +1176,7 @@ begin
|
||||
|
||||
if (PCUFilename<>'') or (PCUReader<>nil) then
|
||||
begin
|
||||
{$IF defined(VerboseUnitQueue) or defined(VerbosePJUFiler)}
|
||||
{$IF defined(VerboseUnitQueue) or defined(VerbosePCUFiler)}
|
||||
writeln('TPas2jsCompilerFile.WritePCU already precompiled "',PCUFilename,'" Reader=',GetObjName(PCUReader));
|
||||
{$ENDIF}
|
||||
exit;
|
||||
@ -1157,10 +1184,11 @@ begin
|
||||
FPCUFilename:=Compiler.CreatePrecompileFilename(Self);
|
||||
FPCUFormat:=Compiler.FileCache.PrecompileFormat;
|
||||
|
||||
{$IF defined(VerboseUnitQueue) or defined(VerbosePJUFiler)}
|
||||
{$IF defined(VerboseUnitQueue) or defined(VerbosePCUFiler)}
|
||||
writeln('TPas2jsCompilerFile.WritePCU precompiling ',PCUFilename);
|
||||
{$ENDIF}
|
||||
|
||||
JS:=nil;
|
||||
PF:=Compiler.FileCache.PrecompileFormat;
|
||||
ms:=TMemoryStream.Create;
|
||||
Writer:=PF.WriterClass.Create;
|
||||
@ -1168,8 +1196,17 @@ begin
|
||||
Writer.GUID:=Compiler.PrecompileGUID;
|
||||
Writer.OnGetSrc:=@OnFilerGetSrc;
|
||||
Writer.OnIsElementUsed:=@OnWriterIsElementUsed;
|
||||
|
||||
// create JavaScript for procs, initialization, finalization
|
||||
CreateConverter;
|
||||
Converter.Options:=Converter.Options+[coStoreImplJS];
|
||||
Converter.OnIsElementUsed:=@OnPCUConverterIsElementUsed;
|
||||
Converter.OnIsTypeInfoUsed:=@OnPCUConverterIsTypeInfoUsed;
|
||||
JS:=Converter.ConvertPasElement(PasModule,PascalResolver);
|
||||
Converter.Options:=Converter.Options-[coStoreImplJS];
|
||||
|
||||
Writer.WritePCU(PascalResolver,Converter,Compiler.PrecompileInitialFlags,ms,false);
|
||||
{$IF defined(VerboseUnitQueue) or defined(VerbosePJUFiler)}
|
||||
{$IF defined(VerboseUnitQueue) or defined(VerbosePCUFiler)}
|
||||
writeln('TPas2jsCompilerFile.WritePCU precompiled ',PCUFilename);
|
||||
{$ENDIF}
|
||||
|
||||
@ -1180,7 +1217,7 @@ begin
|
||||
DestDir:=ChompPathDelim(ExtractFilePath(PCUFilename));
|
||||
if (DestDir<>'') and not Compiler.DirectoryExists(DestDir) then
|
||||
begin
|
||||
{$IF defined(VerboseUnitQueue) or defined(VerbosePJUFiler)}
|
||||
{$IF defined(VerboseUnitQueue) or defined(VerbosePCUFiler)}
|
||||
writeln('TPas2jsCompilerFile.WritePCU output dir not found "',DestDir,'"');
|
||||
{$ENDIF}
|
||||
Log.LogMsg(nOutputDirectoryNotFound,[Compiler.FileCache.FormatPath(DestDir)]);
|
||||
@ -1188,7 +1225,7 @@ begin
|
||||
end;
|
||||
if Compiler.DirectoryExists(PCUFilename) then
|
||||
begin
|
||||
{$IF defined(VerboseUnitQueue) or defined(VerbosePJUFiler)}
|
||||
{$IF defined(VerboseUnitQueue) or defined(VerbosePCUFiler)}
|
||||
writeln('TPas2jsCompilerFile.WritePCU file is folder "',DestDir,'"');
|
||||
{$ENDIF}
|
||||
Log.LogMsg(nFileIsFolder,[Compiler.FileCache.FormatPath(PCUFilename)]);
|
||||
@ -1197,10 +1234,11 @@ begin
|
||||
|
||||
ms.Position:=0;
|
||||
Compiler.FileCache.SaveToFile(ms,PCUFilename);
|
||||
{$IF defined(VerboseUnitQueue) or defined(VerbosePJUFiler)}
|
||||
{$IF defined(VerboseUnitQueue) or defined(VerbosePCUFiler)}
|
||||
writeln('TPas2jsCompilerFile.WritePCU written ',PCUFilename);
|
||||
{$ENDIF}
|
||||
finally
|
||||
JS.Free;
|
||||
Writer.Free;
|
||||
ms.Free;
|
||||
end;
|
||||
@ -1249,7 +1287,7 @@ begin
|
||||
FReaderState:=prsWaitingForUsedUnits;
|
||||
end;
|
||||
{$IFDEF VerboseUnitQueue}
|
||||
writeln('TPas2jsCompilerFile.ReadUnit ',PasFilename,' Finished=',Parser.CurModule=nil);
|
||||
writeln('TPas2jsCompilerFile.ReadUnit ',PasFilename,' ReaderState=',ReaderState);
|
||||
{$ENDIF}
|
||||
except
|
||||
on E: ECompilerTerminate do
|
||||
@ -1283,7 +1321,7 @@ begin
|
||||
Result:=Parser.CurModule=nil;
|
||||
end;
|
||||
{$IFDEF VerboseUnitQueue}
|
||||
writeln('TPas2jsCompilerFile.ReadContinue ',PasFilename,' finished=',Parser.CurModule=nil);
|
||||
writeln('TPas2jsCompilerFile.ReadContinue ',PasFilename,' finished=',Result);
|
||||
{$ENDIF}
|
||||
if Result then
|
||||
ReaderFinished
|
||||
@ -1322,12 +1360,9 @@ begin
|
||||
UseAnalyzer.EmitModuleHints(PasModule);
|
||||
|
||||
// convert
|
||||
FConverter:=TPasToJSConverter.Create;
|
||||
FConverter.Options:=GetInitialConverterOptions;
|
||||
FConverter.TargetPlatform:=Compiler.TargetPlatform;
|
||||
FConverter.TargetProcessor:=Compiler.TargetProcessor;
|
||||
FConverter.OnIsElementUsed:=@OnConverterIsElementUsed;
|
||||
FConverter.OnIsTypeInfoUsed:=@OnConverterIsTypeInfoUsed;
|
||||
CreateConverter;
|
||||
Converter.OnIsElementUsed:=@OnConverterIsElementUsed;
|
||||
Converter.OnIsTypeInfoUsed:=@OnConverterIsTypeInfoUsed;
|
||||
FJSModule:=Converter.ConvertPasElement(PasModule,PascalResolver);
|
||||
except
|
||||
on E: ECompilerTerminate do
|
||||
@ -1343,14 +1378,12 @@ var
|
||||
begin
|
||||
aModule:=GetCurPasModule;
|
||||
if aModule=nil then exit;
|
||||
if aModule.ClassType=TPasUnitModule then
|
||||
Result:=TPasUnitModule(aModule).InterfaceSection
|
||||
else if aModule.ClassType=TPasProgram then
|
||||
if aModule.ClassType=TPasProgram then
|
||||
Result:=TPasProgram(aModule).ProgramSection
|
||||
else if aModule.ClassType=TPasLibrary then
|
||||
Result:=TPasLibrary(aModule).LibrarySection
|
||||
else
|
||||
Result:=nil;
|
||||
Result:=aModule.InterfaceSection;
|
||||
end;
|
||||
|
||||
function TPas2jsCompilerFile.GetPasImplSection: TPasSection;
|
||||
@ -1406,6 +1439,8 @@ function TPas2jsCompilerFile.GetCurPasModule: TPasModule;
|
||||
begin
|
||||
if PasModule<>nil then
|
||||
Result:=PasModule
|
||||
else if (PascalResolver<>nil) and (PascalResolver.RootElement<>nil) then
|
||||
Result:=PascalResolver.RootElement
|
||||
else if Parser<>nil then
|
||||
Result:=Parser.CurModule
|
||||
else
|
||||
@ -1492,32 +1527,41 @@ end;
|
||||
function TPas2jsCompilerFile.OnResolverFindModule(const UseUnitName,
|
||||
InFilename: String; NameExpr, InFileExpr: TPasExpr): TPasModule;
|
||||
var
|
||||
FoundUnitName: string;
|
||||
FoundIsForeign: Boolean;
|
||||
FoundPasFilename, FoundPasUnitName, FoundPCUFilename, FoundPCUUnitName: string;
|
||||
FoundPasIsForeign: Boolean;
|
||||
FoundPCUFormat: TPas2JSPrecompileFormat;
|
||||
|
||||
function TryUnitName(const TestUnitName: string): string;
|
||||
procedure TryUnitName(const TestUnitName: string);
|
||||
var
|
||||
aFile: TPas2jsCompilerFile;
|
||||
begin
|
||||
// search loaded units
|
||||
aFile:=Compiler.FindUnitWithName(TestUnitName);
|
||||
if aFile<>nil then
|
||||
if FoundPasFilename='' then
|
||||
begin
|
||||
FoundUnitName:=TestUnitName;
|
||||
exit(aFile.PasFilename);
|
||||
// search loaded units
|
||||
aFile:=Compiler.FindUnitWithName(TestUnitName);
|
||||
if aFile<>nil then
|
||||
begin
|
||||
FoundPasFilename:=aFile.PasFilename;
|
||||
FoundPasUnitName:=TestUnitName;
|
||||
end else begin
|
||||
// search pas in unit path
|
||||
FoundPasFilename:=FileResolver.FindUnitFileName(TestUnitName,'',FoundPasIsForeign);
|
||||
if FoundPasFilename<>'' then
|
||||
FoundPasUnitName:=TestUnitName;
|
||||
end;
|
||||
end;
|
||||
if FoundPCUFilename='' then
|
||||
begin
|
||||
FoundPCUFilename:=FindPCU(TestUnitName,FoundPCUFormat);
|
||||
if FoundPCUFilename<>'' then
|
||||
FoundPCUUnitName:=TestUnitName;
|
||||
end;
|
||||
// search pas in unit path
|
||||
Result:=FileResolver.FindUnitFileName(TestUnitName,'',FoundIsForeign);
|
||||
if Result<>'' then
|
||||
FoundUnitName:=TestUnitName;
|
||||
end;
|
||||
|
||||
var
|
||||
aNameSpace, DefNameSpace, FoundPasFilename, FoundPCUFilename: String;
|
||||
LastEl: TPasElement;
|
||||
aNameSpace, DefNameSpace: String;
|
||||
i: Integer;
|
||||
aFile: TPas2jsCompilerFile;
|
||||
FoundPCUFormat: TPas2JSPrecompileFormat;
|
||||
begin
|
||||
Result:=nil;
|
||||
if CompareText(ExtractFilenameOnly(PasFilename),UseUnitname)=0 then
|
||||
@ -1526,29 +1570,19 @@ begin
|
||||
Parser.RaiseParserError(nUnitCycle,[UseUnitname]);
|
||||
end;
|
||||
|
||||
LastEl:=PascalResolver.LastElement;
|
||||
if (LastEl<>nil)
|
||||
and ((LastEl is TPasSection) or (LastEl.ClassType=TPasUsesUnit)
|
||||
or (LastEl.Parent is TPasSection)) then
|
||||
// ok
|
||||
else
|
||||
RaiseInternalError(20170504161408,'internal error TPas2jsCompilerFile.FindModule PasTree.LastElement='+GetObjName(LastEl)+' '+GetObjName(LastEl.Parent));
|
||||
|
||||
FoundPasFilename:='';
|
||||
FoundIsForeign:=false;
|
||||
FoundUnitName:='';
|
||||
FoundPasIsForeign:=false;
|
||||
FoundPasUnitName:='';
|
||||
FoundPCUFilename:='';
|
||||
FoundPCUFormat:=nil;
|
||||
FoundPCUUnitName:='';
|
||||
if (InFilename='') and (Pos('.',UseUnitname)<1) then
|
||||
begin
|
||||
// generic unit -> search with namespaces
|
||||
// first the default program namespace
|
||||
DefNameSpace:=Compiler.GetDefaultNamespace;
|
||||
if DefNameSpace<>'' then
|
||||
begin
|
||||
FoundPasFilename:=TryUnitName(DefNameSpace+'.'+UseUnitname);
|
||||
FoundPCUFilename:=FindPCU(DefNameSpace+'.'+UseUnitname,FoundPCUFormat);
|
||||
end;
|
||||
TryUnitName(DefNameSpace+'.'+UseUnitname);
|
||||
|
||||
if (FoundPasFilename='') or (FoundPCUFilename='') then
|
||||
begin
|
||||
@ -1557,10 +1591,7 @@ begin
|
||||
aNameSpace:=Compiler.FileCache.Namespaces[i];
|
||||
if aNameSpace='' then continue;
|
||||
if SameText(aNameSpace,DefNameSpace) then continue;
|
||||
if FoundPasFilename='' then
|
||||
FoundPasFilename:=TryUnitName(aNameSpace+'.'+UseUnitname);
|
||||
if FoundPCUFilename='' then
|
||||
FoundPCUFilename:=FindPCU(aNameSpace+'.'+UseUnitname,FoundPCUFormat);
|
||||
TryUnitName(aNameSpace+'.'+UseUnitname);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
@ -1574,30 +1605,33 @@ begin
|
||||
if aFile<>nil then
|
||||
begin
|
||||
FoundPasFilename:=aFile.PasFilename;
|
||||
FoundUnitName:=UseUnitName;
|
||||
FoundPasUnitName:=UseUnitName;
|
||||
end;
|
||||
end;
|
||||
if FoundPasFilename='' then
|
||||
begin
|
||||
// search Pascal file
|
||||
FoundPasFilename:=FileResolver.FindUnitFileName(UseUnitname,InFilename,FoundIsForeign);
|
||||
FoundPasFilename:=FileResolver.FindUnitFileName(UseUnitname,InFilename,FoundPasIsForeign);
|
||||
if FoundPasFilename<>'' then
|
||||
begin
|
||||
if InFilename<>'' then
|
||||
FoundUnitName:=ExtractFilenameOnly(InFilename)
|
||||
FoundPasUnitName:=ExtractFilenameOnly(InFilename)
|
||||
else
|
||||
FoundUnitName:=UseUnitName;
|
||||
FoundPasUnitName:=UseUnitName;
|
||||
end
|
||||
else if InFilename<>'' then
|
||||
exit; // an in-filename unit source is missing -> stop
|
||||
end;
|
||||
end;
|
||||
if FoundPCUFilename='' then
|
||||
begin
|
||||
FoundPCUFilename:=FindPCU(UseUnitName,FoundPCUFormat);
|
||||
FoundPCUUnitName:=UseUnitName;
|
||||
end;
|
||||
|
||||
if (FoundPCUFilename<>'') and (FoundPasFilename='') then
|
||||
begin
|
||||
aFile:=LoadUsedUnit(FoundPCUFilename,UseUnitName,'',NameExpr,nil,false,FoundPCUFormat);
|
||||
aFile:=LoadUsedUnit(FoundPCUFilename,FoundPCUUnitName,'',NameExpr,nil,false,FoundPCUFormat);
|
||||
if aFile<>nil then
|
||||
Result:=aFile.PasModule;
|
||||
exit;
|
||||
@ -1606,8 +1640,8 @@ begin
|
||||
if FoundPasFilename<>'' then
|
||||
begin
|
||||
// load unit
|
||||
aFile:=LoadUsedUnit(FoundPasFilename,FoundUnitName,InFilename,
|
||||
NameExpr,InFileExpr,FoundIsForeign,nil);
|
||||
aFile:=LoadUsedUnit(FoundPasFilename,FoundPasUnitName,InFilename,
|
||||
NameExpr,InFileExpr,FoundPasIsForeign,nil);
|
||||
if aFile<>nil then
|
||||
Result:=aFile.PasModule;
|
||||
end;
|
||||
@ -1652,7 +1686,7 @@ var
|
||||
Cycle: TFPList;
|
||||
CyclePath: String;
|
||||
begin
|
||||
if Parser.CurModule.ImplementationSection=nil then
|
||||
if PasModule.ImplementationSection=nil then
|
||||
begin
|
||||
// main uses section (e.g. interface or program, not implementation)
|
||||
// -> check for cycles
|
||||
@ -1910,6 +1944,7 @@ var
|
||||
i: Integer;
|
||||
aFile: TPas2jsCompilerFile;
|
||||
Found: Boolean;
|
||||
Section: TPasSection;
|
||||
begin
|
||||
// parse til exception or all modules have finished
|
||||
repeat
|
||||
@ -1934,6 +1969,13 @@ begin
|
||||
writeln('TPas2jsCompiler.ProcessQueue aFile=',aFile.PasFilename);
|
||||
{$ENDIF}
|
||||
aFile.ReadContinue;
|
||||
if aFile.ReaderState=prsCanContinue then
|
||||
begin
|
||||
{$IF defined(VerbosePasResolver) or defined(VerboseUnitQueue)}
|
||||
writeln('TPas2jsCompiler.ProcessQueue aFile=',aFile.PasFilename,' ReadContinue buggy');
|
||||
{$ENDIF}
|
||||
RaiseInternalError(20180313130300,'File='+aFile.PasFilename+' ReadContinue buggy');
|
||||
end;
|
||||
break;
|
||||
end;
|
||||
until not Found;
|
||||
@ -1945,13 +1987,20 @@ begin
|
||||
for i:=0 to FReadingModules.Count-1 do
|
||||
begin
|
||||
aFile:=TPas2jsCompilerFile(FReadingModules[i]);
|
||||
if aFile.Parser.CurModule<>nil then
|
||||
if aFile.PascalResolver=nil then
|
||||
RaiseInternalError(20180313124125,aFile.PasFilename);
|
||||
if (aFile.PCUReader=nil) and (aFile.Parser.CurModule<>nil) then
|
||||
begin
|
||||
{$IF defined(VerbosePasResolver) or defined(VerboseUnitQueue)}
|
||||
writeln('TPas2jsCompiler.ProcessQueue aFile=',aFile.PasFilename,' was not finished');
|
||||
{$ENDIF}
|
||||
RaiseInternalError(20180305185342,aFile.PasFilename);
|
||||
end;
|
||||
Section:=aFile.PascalResolver.GetLastSection;
|
||||
if Section=nil then
|
||||
RaiseInternalError(20180313124207,aFile.PasFilename);
|
||||
if Section.PendingUsedIntf<>nil then
|
||||
RaiseInternalError(20180313124226,aFile.PasFilename+' '+GetObjName(Section)+' PendingUsedIntf='+GetObjName(Section.PendingUsedIntf));
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -1998,7 +2047,7 @@ begin
|
||||
if FileCache.AllJSIntoMainJS and (WPOAnalyzer<>nil)
|
||||
and not WPOAnalyzer.IsUsed(aFile.PasModule) then
|
||||
begin
|
||||
{$IF defined(VerboseUnitQueue) or defined(VerbosePJUFiler)}
|
||||
{$IF defined(VerboseUnitQueue) or defined(VerbosePCUFiler)}
|
||||
writeln('TPas2jsCompiler.MarkNeedBuilding module not used by WPO: ',aFile.PasFilename);
|
||||
{$ENDIF}
|
||||
exit(false);
|
||||
|
@ -820,7 +820,8 @@ type
|
||||
function ReadMemberHints(Obj: TJSONObject; El: TPasElement; const DefaultValue: TPasMemberHints): TPasMemberHints; virtual;
|
||||
procedure ReadPasElement(Obj: TJSONObject; El: TPasElement; aContext: TPCUReaderContext); virtual;
|
||||
procedure ReadExtRefs(Obj: TJSONObject; El: TPasElement); virtual;
|
||||
procedure ReadUsedUnits(Obj: TJSONObject; Section: TPasSection; aContext: TPCUReaderContext); virtual;
|
||||
procedure ReadUsedUnitsInit(Obj: TJSONObject; Section: TPasSection; aContext: TPCUReaderContext); virtual;
|
||||
procedure ReadUsedUnitsFinish(Obj: TJSONObject; Section: TPasSection; aContext: TPCUReaderContext); virtual;
|
||||
procedure ReadSectionScope(Obj: TJSONObject; Scope: TPasSectionScope; aContext: TPCUReaderContext); virtual;
|
||||
procedure ReadSection(Obj: TJSONObject; Section: TPasSection; aContext: TPCUReaderContext); virtual;
|
||||
procedure ReadDeclarations(Obj: TJSONObject; Section: TPasSection; aContext: TPCUReaderContext); virtual;
|
||||
@ -1365,32 +1366,19 @@ end;
|
||||
{ TPCUCustomReader }
|
||||
|
||||
function TPCUCustomReader.ReadCanContinue: boolean;
|
||||
|
||||
function SectionCanContinue(Section: TPasSection): boolean;
|
||||
var
|
||||
Scope: TPasSectionScope;
|
||||
begin
|
||||
Scope:=Section.CustomData as TPasSectionScope;
|
||||
if Scope.Finished then exit(false);
|
||||
Result:=Section.PendingUsedIntf=nil;
|
||||
end;
|
||||
|
||||
var
|
||||
Module: TPasModule;
|
||||
Section: TPasSection;
|
||||
Scope: TPasSectionScope;
|
||||
begin
|
||||
Result:=false;
|
||||
Module:=Resolver.RootElement;
|
||||
if Module is TPasProgram then
|
||||
Result:=SectionCanContinue(TPasProgram(Module).ProgramSection)
|
||||
else if Module is TPasLibrary then
|
||||
Result:=SectionCanContinue(TPasLibrary(Module).LibrarySection)
|
||||
else
|
||||
begin
|
||||
if Module.ImplementationSection<>nil then
|
||||
Result:=SectionCanContinue(Module.ImplementationSection)
|
||||
else
|
||||
Result:=SectionCanContinue(Module.InterfaceSection);
|
||||
end;
|
||||
if Module=nil then exit(true); // not yet started
|
||||
Section:=Resolver.GetLastSection;
|
||||
if Section=nil then exit(true); // only header
|
||||
Scope:=Section.CustomData as TPasSectionScope;
|
||||
if Scope.Finished then exit(false); // finished
|
||||
Result:=Section.PendingUsedIntf=nil;
|
||||
end;
|
||||
|
||||
{ TPCUFilerElementRef }
|
||||
@ -4626,20 +4614,19 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TPCUReader.ReadUsedUnits(Obj: TJSONObject; Section: TPasSection;
|
||||
procedure TPCUReader.ReadUsedUnitsInit(Obj: TJSONObject; Section: TPasSection;
|
||||
aContext: TPCUReaderContext);
|
||||
// Note: can be called twice for each section if there are pending used interfaces
|
||||
var
|
||||
Arr: TJSONArray;
|
||||
i, Id: Integer;
|
||||
Data: TJSONData;
|
||||
UsesObj, ModuleObj: TJSONObject;
|
||||
UsesObj: TJSONObject;
|
||||
Name, InFilename, ModuleName: string;
|
||||
Use: TPasUsesUnit;
|
||||
Module: TPasModule;
|
||||
Scope, UsedScope: TPasSectionScope;
|
||||
begin
|
||||
if not ReadArray(Obj,'Uses',Arr,Section) then exit;
|
||||
Scope:=Section.CustomData as TPasSectionScope;
|
||||
SetLength(Section.UsesClause,Arr.Count);
|
||||
for i:=0 to length(Section.UsesClause)-1 do
|
||||
Section.UsesClause[i]:=nil;
|
||||
@ -4668,16 +4655,50 @@ begin
|
||||
if Module=nil then
|
||||
RaiseMsg(20180307231247,Use);
|
||||
Use.Module:=Module;
|
||||
UsedScope:=Module.InterfaceSection.CustomData as TPasSectionScope;
|
||||
Scope.UsesScopes.Add(UsedScope);
|
||||
|
||||
Module.AddRef;
|
||||
if ReadInteger(UsesObj,'Id',Id,Use) then
|
||||
AddElReference(Id,Use,Use);
|
||||
end;
|
||||
Resolver.CheckPendingUsedInterface(Section);
|
||||
if aContext=nil then ;
|
||||
end;
|
||||
|
||||
procedure TPCUReader.ReadUsedUnitsFinish(Obj: TJSONObject;
|
||||
Section: TPasSection; aContext: TPCUReaderContext);
|
||||
var
|
||||
Arr: TJSONArray;
|
||||
Scope, UsedScope: TPasSectionScope;
|
||||
i: Integer;
|
||||
Use: TPasUsesUnit;
|
||||
Module: TPasModule;
|
||||
Data: TJSONData;
|
||||
UsesObj, ModuleObj: TJSONObject;
|
||||
begin
|
||||
if not ReadArray(Obj,'Uses',Arr,Section) then exit;
|
||||
Scope:=Section.CustomData as TPasSectionScope;
|
||||
if Scope.UsesFinished then
|
||||
RaiseMsg(20180313133931,Section);
|
||||
if Section.PendingUsedIntf<>nil then
|
||||
RaiseMsg(20180313134142,Section,GetObjName(Section.PendingUsedIntf));
|
||||
if Arr.Count<>length(Section.UsesClause) then
|
||||
RaiseMsg(20180313134338,IntToStr(Arr.Count)+'<>'+IntToStr(length(Section.UsesClause)));
|
||||
for i:=0 to Arr.Count-1 do
|
||||
begin
|
||||
Data:=Arr[i];
|
||||
if not (Data is TJSONObject) then
|
||||
RaiseMsg(20180313134409,Section,GetObjName(Data));
|
||||
UsesObj:=TJSONObject(Data);
|
||||
Use:=Section.UsesClause[i];
|
||||
|
||||
Module:=Use.Module as TPasModule;
|
||||
UsedScope:=Module.InterfaceSection.CustomData as TPasSectionScope;
|
||||
Scope.UsesScopes.Add(UsedScope);
|
||||
// Refs
|
||||
if ReadObject(UsesObj,'Module',ModuleObj,Use) then
|
||||
ReadExtRefs(ModuleObj,Module);
|
||||
end;
|
||||
Resolver.CheckPendingUsedInterface(Section);
|
||||
end;
|
||||
Scope.UsesFinished:=true;
|
||||
|
||||
if aContext=nil then ;
|
||||
end;
|
||||
|
||||
@ -4689,6 +4710,7 @@ end;
|
||||
|
||||
procedure TPCUReader.ReadSection(Obj: TJSONObject; Section: TPasSection;
|
||||
aContext: TPCUReaderContext);
|
||||
// Note: can be called twice for each section if there are pending used interfaces
|
||||
var
|
||||
Scope: TPasSectionScope;
|
||||
begin
|
||||
@ -4699,24 +4721,22 @@ begin
|
||||
begin
|
||||
ReadPasElement(Obj,Section,aContext);
|
||||
Scope:=TPasSectionScope(Resolver.CreateScope(Section,TPasSectionScope));
|
||||
ReadUsedUnits(Obj,Section,aContext);
|
||||
ReadUsedUnitsInit(Obj,Section,aContext);
|
||||
if Section.PendingUsedIntf<>nil then exit;
|
||||
end
|
||||
else
|
||||
begin
|
||||
Scope:=Section.CustomData as TPasSectionScope;
|
||||
if Scope.Finished then
|
||||
RaiseMsg(20180308160336,Section);
|
||||
if Section.PendingUsedIntf<>nil then
|
||||
RaiseMsg(20180308160639,Section,GetObjName(Section.PendingUsedIntf));
|
||||
end;
|
||||
|
||||
if Scope.Finished then
|
||||
RaiseMsg(20180308160336,Section);
|
||||
if Scope.UsesFinished then
|
||||
RaiseMsg(20180308160337,Section);
|
||||
Scope.UsesFinished:=true;
|
||||
|
||||
// read external references
|
||||
ReadUsedUnitsFinish(Obj,Section,aContext);
|
||||
// read scope, needs external refs
|
||||
ReadSectionScope(Obj,Scope,aContext);
|
||||
|
||||
// read declarations, needs external refs
|
||||
ReadDeclarations(Obj,Section,aContext);
|
||||
Scope.Finished:=true;
|
||||
if Section is TInterfaceSection then
|
||||
|
@ -36,8 +36,8 @@ type
|
||||
private
|
||||
FAnalyzer: TPasAnalyzer;
|
||||
FInitialFlags: TPCUInitialFlags;
|
||||
FPJUReader: TPCUReader;
|
||||
FPJUWriter: TPCUWriter;
|
||||
FPCUReader: TPCUReader;
|
||||
FPCUWriter: TPCUWriter;
|
||||
FRestAnalyzer: TPasAnalyzer;
|
||||
procedure OnFilerGetSrc(Sender: TObject; aFilename: string; out p: PChar;
|
||||
out Count: integer);
|
||||
@ -121,8 +121,8 @@ type
|
||||
public
|
||||
property Analyzer: TPasAnalyzer read FAnalyzer;
|
||||
property RestAnalyzer: TPasAnalyzer read FRestAnalyzer;
|
||||
property PJUWriter: TPCUWriter read FPJUWriter write FPJUWriter;
|
||||
property PJUReader: TPCUReader read FPJUReader write FPJUReader;
|
||||
property PCUWriter: TPCUWriter read FPCUWriter write FPCUWriter;
|
||||
property PCUReader: TPCUReader read FPCUReader write FPCUReader;
|
||||
property InitialFlags: TPCUInitialFlags read FInitialFlags;
|
||||
end;
|
||||
|
||||
@ -220,7 +220,7 @@ function TCustomTestPrecompile.OnRestResolverFindUnit(const aUnitName: String
|
||||
begin
|
||||
CurEngine:=Resolvers[i];
|
||||
CurUnitName:=ExtractFileUnitName(CurEngine.Filename);
|
||||
{$IFDEF VerbosePJUFiler}
|
||||
{$IFDEF VerbosePCUFiler}
|
||||
//writeln('TCustomTestPrecompile.FindRestUnit Checking ',i,'/',ResolverCount,' ',CurEngine.Filename,' ',CurUnitName);
|
||||
{$ENDIF}
|
||||
if CompareText(Name,CurUnitName)=0 then
|
||||
@ -228,12 +228,12 @@ function TCustomTestPrecompile.OnRestResolverFindUnit(const aUnitName: String
|
||||
Result:=CurEngine.Module;
|
||||
if Result<>nil then
|
||||
begin
|
||||
{$IFDEF VerbosePJUFiler}
|
||||
{$IFDEF VerbosePCUFiler}
|
||||
//writeln('TCustomTestPrecompile.FindRestUnit Found parsed module: ',Result.Filename);
|
||||
{$ENDIF}
|
||||
exit;
|
||||
end;
|
||||
{$IFDEF VerbosePJUFiler}
|
||||
{$IFDEF VerbosePCUFiler}
|
||||
writeln('TCustomTestPrecompile.FindRestUnit PARSING unit "',CurEngine.Filename,'"');
|
||||
{$ENDIF}
|
||||
Fail('not parsed');
|
||||
@ -270,8 +270,8 @@ end;
|
||||
procedure TCustomTestPrecompile.TearDown;
|
||||
begin
|
||||
FreeAndNil(FAnalyzer);
|
||||
FreeAndNil(FPJUWriter);
|
||||
FreeAndNil(FPJUReader);
|
||||
FreeAndNil(FPCUWriter);
|
||||
FreeAndNil(FPCUReader);
|
||||
FreeAndNil(FInitialFlags);
|
||||
inherited TearDown;
|
||||
end;
|
||||
@ -291,7 +291,7 @@ end;
|
||||
procedure TCustomTestPrecompile.WriteReadUnit;
|
||||
var
|
||||
ms: TMemoryStream;
|
||||
PJU, RestJSSrc, OrigJSSrc: string;
|
||||
PCU, RestJSSrc, OrigJSSrc: string;
|
||||
// restored classes:
|
||||
RestResolver: TTestEnginePasResolver;
|
||||
RestFileResolver: TFileResolver;
|
||||
@ -302,8 +302,8 @@ var
|
||||
begin
|
||||
ConvertUnit;
|
||||
|
||||
FPJUWriter:=TPCUWriter.Create;
|
||||
FPJUReader:=TPCUReader.Create;
|
||||
FPCUWriter:=TPCUWriter.Create;
|
||||
FPCUReader:=TPCUReader.Create;
|
||||
ms:=TMemoryStream.Create;
|
||||
RestParser:=nil;
|
||||
RestScanner:=nil;
|
||||
@ -313,9 +313,9 @@ begin
|
||||
RestJSModule:=nil;
|
||||
try
|
||||
try
|
||||
PJUWriter.OnGetSrc:=@OnFilerGetSrc;
|
||||
PJUWriter.OnIsElementUsed:=@OnConverterIsElementUsed;
|
||||
PJUWriter.WritePCU(Engine,Converter,InitialFlags,ms,false);
|
||||
PCUWriter.OnGetSrc:=@OnFilerGetSrc;
|
||||
PCUWriter.OnIsElementUsed:=@OnConverterIsElementUsed;
|
||||
PCUWriter.WritePCU(Engine,Converter,InitialFlags,ms,false);
|
||||
except
|
||||
on E: Exception do
|
||||
begin
|
||||
@ -327,12 +327,12 @@ begin
|
||||
end;
|
||||
|
||||
try
|
||||
SetLength(PJU,ms.Size);
|
||||
System.Move(ms.Memory^,PJU[1],length(PJU));
|
||||
SetLength(PCU,ms.Size);
|
||||
System.Move(ms.Memory^,PCU[1],length(PCU));
|
||||
|
||||
writeln('TCustomTestPrecompile.WriteReadUnit PJU START-----');
|
||||
writeln(PJU);
|
||||
writeln('TCustomTestPrecompile.WriteReadUnit PJU END-------');
|
||||
writeln('TCustomTestPrecompile.WriteReadUnit PCU START-----');
|
||||
writeln(PCU);
|
||||
writeln('TCustomTestPrecompile.WriteReadUnit PCU END-------');
|
||||
|
||||
RestFileResolver:=TFileResolver.Create;
|
||||
RestScanner:=TPascalScanner.Create(RestFileResolver);
|
||||
@ -345,8 +345,8 @@ begin
|
||||
RestParser.Options:=po_tcmodules;
|
||||
RestResolver.CurrentParser:=RestParser;
|
||||
ms.Position:=0;
|
||||
PJUReader.ReadPCU(RestResolver,ms);
|
||||
if not PJUReader.ReadContinue then
|
||||
PCUReader.ReadPCU(RestResolver,ms);
|
||||
if not PCUReader.ReadContinue then
|
||||
Fail('ReadContinue=false, pending used interfaces');
|
||||
except
|
||||
on E: Exception do
|
||||
@ -641,8 +641,8 @@ begin
|
||||
Fail(Path+'.UsesScopes['+IntToStr(i)+'] Rest='+GetObjName(TObject(Rest.UsesScopes[i])));
|
||||
RestUses:=TPasSectionScope(Rest.UsesScopes[i]);
|
||||
if OrigUses.ClassType<>RestUses.ClassType then
|
||||
Fail(Path+'.Uses['+IntToStr(i)+'] Orig='+GetObjName(OrigUses)+' Rest='+GetObjName(RestUses));
|
||||
CheckRestoredReference(Path+'.Uses['+IntToStr(i)+']',OrigUses.Element,RestUses.Element);
|
||||
Fail(Path+'.UsesScopes['+IntToStr(i)+'] Orig='+GetObjName(OrigUses)+' Rest='+GetObjName(RestUses));
|
||||
CheckRestoredReference(Path+'.UsesScopes['+IntToStr(i)+']',OrigUses.Element,RestUses.Element);
|
||||
end;
|
||||
AssertEquals(Path+'.Finished',Orig.Finished,Rest.Finished);
|
||||
CheckRestoredIdentifierScope(Path,Orig,Rest);
|
||||
|
@ -662,31 +662,40 @@ var
|
||||
Result:=p;
|
||||
end;
|
||||
|
||||
procedure SkipLineEnd(var p: PChar);
|
||||
begin
|
||||
if p^ in [#10,#13] then
|
||||
begin
|
||||
if (p[1] in [#10,#13]) and (p^<>p[1]) then
|
||||
inc(p,2)
|
||||
else
|
||||
inc(p);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure DiffFound;
|
||||
var
|
||||
ActLineStartP, ActLineEndP, p, StartPos: PChar;
|
||||
ExpLine, ActLine: String;
|
||||
i: Integer;
|
||||
i, LineNo, DiffLineNo: Integer;
|
||||
begin
|
||||
writeln('Diff found "',Msg,'". Lines:');
|
||||
// write correct lines
|
||||
p:=PChar(Expected);
|
||||
LineNo:=0;
|
||||
DiffLineNo:=0;
|
||||
repeat
|
||||
StartPos:=p;
|
||||
while not (p^ in [#0,#10,#13]) do inc(p);
|
||||
ExpLine:=copy(Expected,StartPos-PChar(Expected)+1,p-StartPos);
|
||||
if p^ in [#10,#13] then
|
||||
begin
|
||||
if (p[1] in [#10,#13]) and (p^<>p[1]) then
|
||||
inc(p,2)
|
||||
else
|
||||
inc(p);
|
||||
end;
|
||||
SkipLineEnd(p);
|
||||
inc(LineNo);
|
||||
if (p<=ExpectedP) and (p^<>#0) then
|
||||
begin
|
||||
writeln('= ',ExpLine);
|
||||
end else begin
|
||||
// diff line
|
||||
if DiffLineNo=0 then DiffLineNo:=LineNo;
|
||||
// write actual line
|
||||
ActLineStartP:=FindLineStart(ActualP,PChar(Actual));
|
||||
ActLineEndP:=FindLineEnd(ActualP);
|
||||
@ -699,6 +708,15 @@ var
|
||||
writeln('^');
|
||||
Msg:='expected "'+ExpLine+'", but got "'+ActLine+'".';
|
||||
CheckSrcDiff:=false;
|
||||
// write up to three following actual lines to get some context
|
||||
for i:=1 to 3 do begin
|
||||
ActLineStartP:=ActLineEndP;
|
||||
SkipLineEnd(ActLineStartP);
|
||||
if ActLineStartP^=#0 then break;
|
||||
ActLineEndP:=FindLineEnd(ActLineStartP);
|
||||
ActLine:=copy(Actual,ActLineStartP-PChar(Actual)+1,ActLineEndP-ActLineStartP);
|
||||
writeln('~ ',ActLine);
|
||||
end;
|
||||
exit;
|
||||
end;
|
||||
until p^=#0;
|
||||
|
@ -26,52 +26,133 @@ interface
|
||||
uses
|
||||
Classes, SysUtils,
|
||||
fpcunit, testregistry,
|
||||
tcunitsearch, tcmodules;
|
||||
tcunitsearch, tcmodules, Pas2jsFileUtils;
|
||||
|
||||
type
|
||||
|
||||
{ TTestCLI_Precompile }
|
||||
|
||||
TTestCLI_Precompile = class(TCustomTestCLI)
|
||||
public
|
||||
protected
|
||||
procedure CheckPrecompile(MainFile, UnitPaths: string;
|
||||
SharedParams: TStringList = nil;
|
||||
FirstRunParams: TStringList = nil;
|
||||
SecondRunParams: TStringList = nil);
|
||||
published
|
||||
procedure TestPCU_EmptyUnit;
|
||||
procedure TestPCU_ParamNS;
|
||||
procedure TestPCU_UnitCycle;
|
||||
end;
|
||||
|
||||
function LinesToList(const Lines: array of string): TStringList;
|
||||
|
||||
implementation
|
||||
|
||||
function LinesToList(const Lines: array of string): TStringList;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
Result:=TStringList.Create;
|
||||
for i:=Low(Lines) to High(Lines) do Result.Add(Lines[i]);
|
||||
end;
|
||||
|
||||
{ TTestCLI_Precompile }
|
||||
|
||||
procedure TTestCLI_Precompile.TestPCU_EmptyUnit;
|
||||
procedure TTestCLI_Precompile.CheckPrecompile(MainFile, UnitPaths: string;
|
||||
SharedParams: TStringList; FirstRunParams: TStringList;
|
||||
SecondRunParams: TStringList);
|
||||
var
|
||||
aFile, JSFile: TCLIFile;
|
||||
OrigSrc, NewSrc, s: String;
|
||||
UnitOutputDir, JSFilename, OrigSrc, NewSrc, s: String;
|
||||
JSFile: TCLIFile;
|
||||
begin
|
||||
AddUnit('sub/system.pp',[''],['']);
|
||||
try
|
||||
UnitOutputDir:='units';
|
||||
AddDir(UnitOutputDir);
|
||||
// compile, create .pcu files
|
||||
{$IFDEF VerbosePCUFiler}
|
||||
writeln('TTestCLI_Precompile.CheckPrecompile create pcu files=========================');
|
||||
{$ENDIF}
|
||||
Params.Clear;
|
||||
if SharedParams<>nil then
|
||||
Params.Assign(SharedParams);
|
||||
if FirstRunParams<>nil then
|
||||
Params.AddStrings(FirstRunParams);
|
||||
Compile([MainFile,'-Jc','-Fu'+UnitPaths,'-JUpcu','-FU'+UnitOutputDir]);
|
||||
AssertFileExists('units/system.pcu');
|
||||
JSFilename:=UnitOutputDir+PathDelim+ExtractFilenameOnly(MainFile)+'.js';
|
||||
AssertFileExists(JSFilename);
|
||||
JSFile:=FindFile(JSFilename);
|
||||
OrigSrc:=JSFile.Source;
|
||||
// compile, using .pcu files
|
||||
{$IFDEF VerbosePCUFiler}
|
||||
writeln('TTestCLI_Precompile.CheckPrecompile compile using pcu files==================');
|
||||
{$ENDIF}
|
||||
JSFile.Source:='';
|
||||
Compiler.Reset;
|
||||
Params.Clear;
|
||||
if SharedParams<>nil then
|
||||
Params.Assign(SharedParams);
|
||||
if SecondRunParams<>nil then
|
||||
Params.AddStrings(SecondRunParams);
|
||||
Compile([MainFile,'-Jc','-FU'+UnitOutputDir]);
|
||||
NewSrc:=JSFile.Source;
|
||||
if not CheckSrcDiff(OrigSrc,NewSrc,s) then
|
||||
begin
|
||||
WriteSources;
|
||||
Fail('test1.js: '+s);
|
||||
end;
|
||||
finally
|
||||
SharedParams.Free;
|
||||
FirstRunParams.Free;
|
||||
SecondRunParams.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TTestCLI_Precompile.TestPCU_EmptyUnit;
|
||||
begin
|
||||
AddUnit('src/system.pp',[''],['']);
|
||||
AddFile('test1.pas',[
|
||||
'begin',
|
||||
'end.']);
|
||||
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;
|
||||
CheckPrecompile('test1.pas','src');
|
||||
end;
|
||||
|
||||
// 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);
|
||||
procedure TTestCLI_Precompile.TestPCU_ParamNS;
|
||||
begin
|
||||
AddUnit('src/system.pp',[''],['']);
|
||||
AddUnit('src/foo.unit1.pp',['var i: longint;'],['']);
|
||||
AddFile('test1.pas',[
|
||||
'uses unit1;',
|
||||
'begin',
|
||||
' i:=3;',
|
||||
'end.']);
|
||||
CheckPrecompile('test1.pas','src',LinesToList(['-NSfoo']));
|
||||
end;
|
||||
|
||||
procedure TTestCLI_Precompile.TestPCU_UnitCycle;
|
||||
begin
|
||||
AddUnit('src/system.pp',['type integer = longint;'],['']);
|
||||
AddUnit('src/unit1.pp',
|
||||
['var i: integer;',
|
||||
'procedure Do1(j: integer);'],
|
||||
['uses unit2;',
|
||||
'procedure Do1(j: integer);',
|
||||
'begin',
|
||||
' Do2(j);',
|
||||
'end;']);
|
||||
AddUnit('src/unit2.pp',
|
||||
['uses unit1;',
|
||||
'procedure Do2(j: integer);'],
|
||||
['procedure Do2(j: integer);',
|
||||
'begin',
|
||||
' unit1.i:=j;',
|
||||
'end;']);
|
||||
AddFile('test1.pas',[
|
||||
'uses unit1;',
|
||||
'begin',
|
||||
' Do1(3);',
|
||||
'end.']);
|
||||
CheckPrecompile('test1.pas','src');
|
||||
end;
|
||||
|
||||
Initialization
|
||||
|
@ -112,6 +112,7 @@ type
|
||||
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;
|
||||
procedure AssertFileExists(Filename: string);
|
||||
property WorkDir: string read FWorkDir write SetWorkDir;
|
||||
property DefaultFileAge: longint read FDefaultFileAge write FDefaultFileAge;
|
||||
property ExitCode: integer read GetExitCode write SetExitCode;
|
||||
@ -240,7 +241,7 @@ procedure TCustomTestCLI.DoLog(Sender: TObject; const Msg: String);
|
||||
var
|
||||
LogMsg: TCLILogMsg;
|
||||
begin
|
||||
{$IF defined(VerbosePasResolver) or defined(VerbosePJUFiler)}
|
||||
{$IF defined(VerbosePasResolver) or defined(VerbosePCUFiler)}
|
||||
writeln('TCustomTestCLI.DoLog ',Msg,' File=',Compiler.Log.LastMsgFile,' Line=',Compiler.Log.LastMsgLine);
|
||||
{$ENDIF}
|
||||
LogMsg:=TCLILogMsg.Create;
|
||||
@ -296,7 +297,7 @@ begin
|
||||
if aFile=nil then exit(false);
|
||||
if (faDirectory and aFile.Attr)>0 then
|
||||
begin
|
||||
{$IF defined(VerbosePasResolver) or defined(VerbosePJUFiler)}
|
||||
{$IF defined(VerbosePasResolver) or defined(VerbosePCUFiler)}
|
||||
writeln('[20180224000557] TCustomTestCLI.OnReadFile ',aFilename);
|
||||
{$ENDIF}
|
||||
EPas2jsFileCache.Create('TCustomTestCLI.OnReadFile: reading directory '+aFilename);
|
||||
@ -309,29 +310,40 @@ end;
|
||||
procedure TCustomTestCLI.OnWriteFile(aFilename: string; Source: string);
|
||||
var
|
||||
aFile: TCLIFile;
|
||||
{$IF defined(VerboseUnitQueue) or defined(VerbosePCUFiler)}
|
||||
//i: Integer;
|
||||
{$ENDIF}
|
||||
begin
|
||||
aFile:=FindFile(aFilename);
|
||||
{$IF defined(VerbosePasResolver) or defined(VerbosePJUFiler)}
|
||||
{$IF defined(VerboseUnitQueue) or defined(VerbosePCUFiler)}
|
||||
writeln('TCustomTestCLI.WriteFile ',aFilename,' Found=',aFile<>nil,' SrcLen=',length(Source));
|
||||
{$ENDIF}
|
||||
if aFile<>nil then
|
||||
begin
|
||||
if faDirectory and aFile.Attr>0 then
|
||||
if (faDirectory and aFile.Attr)>0 then
|
||||
begin
|
||||
{$IF defined(VerbosePasResolver) or defined(VerbosePJUFiler)}
|
||||
{$IF defined(VerboseUnitQueue) or defined(VerbosePCUFiler)}
|
||||
writeln('[20180223175616] TCustomTestCLI.OnWriteFile ',aFilename);
|
||||
{$ENDIF}
|
||||
raise EPas2jsFileCache.Create('unable to write file to directory "'+aFilename+'"');
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
{$IF defined(VerboseUnitQueue) or defined(VerbosePCUFiler)}
|
||||
//writeln('TCustomTestCLI.OnWriteFile FFiles: ',FFiles.Count);
|
||||
//for i:=0 to FFiles.Count-1 do
|
||||
//begin
|
||||
// aFile:=TCLIFile(FFiles[i]);
|
||||
// writeln(' ',i,': Filename=',aFile.Filename,' ',CompareFilenames(aFile.Filename,aFilename),' Dir=',(aFile.Attr and faDirectory)>0,' Len=',length(aFile.Source));
|
||||
//end;
|
||||
{$ENDIF}
|
||||
aFile:=TCLIFile.Create(aFilename,'',0,0);
|
||||
FFiles.Add(aFile);
|
||||
end;
|
||||
aFile.Source:=Source;
|
||||
aFile.Attr:=faNormal;
|
||||
aFile.Age:=DateTimeToFileDate(CurDate);
|
||||
//writeln('TCustomTestCLI.OnWriteFile ',aFile.Filename,' "',LeftStr(aFile.Source,50),'"');
|
||||
writeln('TCustomTestCLI.OnWriteFile ',aFile.Filename,' Found=',FindFile(aFilename)<>nil,' "',LeftStr(aFile.Source,50),'" ');
|
||||
end;
|
||||
|
||||
procedure TCustomTestCLI.WriteSources;
|
||||
@ -394,7 +406,6 @@ 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
|
||||
@ -404,13 +415,13 @@ begin
|
||||
except
|
||||
on E: ECompilerTerminate do
|
||||
begin
|
||||
{$IF defined(VerbosePasResolver) or defined(VerbosePJUFiler)}
|
||||
{$IF defined(VerbosePasResolver) or defined(VerbosePCUFiler)}
|
||||
writeln('TCustomTestCLI.Compile ',E.ClassName,':',E.Message);
|
||||
{$ENDIF}
|
||||
end;
|
||||
on E: Exception do
|
||||
begin
|
||||
{$IF defined(VerbosePasResolver) or defined(VerbosePJUFiler)}
|
||||
{$IF defined(VerbosePasResolver) or defined(VerbosePCUFiler)}
|
||||
writeln('TCustomTestCLI.Compile ',E.ClassName,':',E.Message);
|
||||
{$ENDIF}
|
||||
Fail('TCustomTestCLI.Compile '+E.ClassName+':'+E.Message);
|
||||
@ -454,7 +465,7 @@ end;
|
||||
function TCustomTestCLI.AddFile(Filename, Source: string): TCLIFile;
|
||||
begin
|
||||
Filename:=ExpandFilename(Filename);
|
||||
{$IFDEF VerbosePJUFiler}
|
||||
{$IFDEF VerbosePCUFiler}
|
||||
writeln('TCustomTestCLI.AddFile ',Filename);
|
||||
{$ENDIF}
|
||||
Result:=FindFile(Filename);
|
||||
@ -504,14 +515,14 @@ begin
|
||||
Result:=aFile;
|
||||
if aFile=nil then
|
||||
begin
|
||||
{$IFDEF VerbosePJUFiler}
|
||||
{$IFDEF VerbosePCUFiler}
|
||||
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 VerbosePJUFiler}
|
||||
{$IFDEF VerbosePCUFiler}
|
||||
writeln('[20180224001036] TCustomTestCLI.AddDir file exists: Dir=',Dir);
|
||||
{$ENDIF}
|
||||
raise EPas2jsFileCache.Create('[20180224001036] TCustomTestCLI.AddDir Dir='+Dir);
|
||||
@ -522,6 +533,14 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TCustomTestCLI.AssertFileExists(Filename: string);
|
||||
var
|
||||
aFile: TCLIFile;
|
||||
begin
|
||||
aFile:=FindFile(Filename);
|
||||
AssertNotNull('File not found: '+Filename,aFile);
|
||||
end;
|
||||
|
||||
function TCustomTestCLI.GetLogCount: integer;
|
||||
begin
|
||||
Result:=FLogMsgs.Count;
|
||||
|
Loading…
Reference in New Issue
Block a user