123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411 |
- unit mkfpdoc;
- {$mode objfpc}{$H+}
- {$WARN 5024 off : Parameter "$1" not used}
- interface
- uses
- Classes, SysUtils, dglobals, DOM, fpdocxmlopts, dwriter, pscanner, pparser, fpdocproj;
- const
- DefOSTarget = {$I %FPCTARGETOS%};
- DefCPUTarget = {$I %FPCTARGETCPU%};
- DefFPCVersion = {$I %FPCVERSION%};
- DefFPCDate = {$I %FPCDATE%};
- {$IFDEF FPC_BIG_ENDIAN}
- DefEndianNess = 'FPC_BIG_ENDIAN';
- {$ELSE}
- DefEndianNess = 'FPC_LITTLE_ENDIAN';
- {$ENDIF}
- Type
- { TFPDocCreator }
- TFPDocCreator = Class(TComponent)
- Private
- FBaseDescrDir: String;
- FBaseInputDir: String;
- FCurPackage : TFPDocPackage;
- FExamplesPath: String;
- FProcessedUnits : TStrings;
- FOnLog: TPasParserLogHandler;
- FPParserLogEvents: TPParserLogEvents;
- FProject : TFPDocProject;
- FProjectMacros: TStrings;
- FScannerLogEvents: TPScannerLogEvents;
- FVerbose: Boolean;
- function GetLogLevels: TFPDocLogLevels;
- function GetOptions: TEngineOptions;
- function GetPackages: TFPDocPackages;
- procedure SetBaseDescrDir(AValue: String);
- procedure SetBaseInputDir(AValue: String);
- procedure SetExamplesPath(AValue: String);
- procedure SetProjectMacros(AValue: TStrings);
- Protected
- Function FixInputFile(Const AFileName : String) : String;
- Function FixDescrFile(Const AFileName : String) : String;
- Procedure DoBeforeEmitNote(Sender : TObject; Note : TDomElement; Var EmitNote : Boolean); virtual;
- procedure HandleOnParseUnit(Sender: TObject; const AUnitName: String; out AInputFile, OSTarget, CPUTarget: String);
- procedure SetVerbose(AValue: Boolean); virtual;
- Procedure DoLog(Const Msg : String);
- procedure DoLog(Const Fmt : String; Args : Array of Const);
- Procedure DoLogSender(Sender : TObject; Const Msg : String);
- // Create documetation by specified Writer class
- procedure CreateOutput(APackage: TFPDocPackage; Engine: TFPDocEngine); virtual;
- Public
- Constructor Create(AOwner : TComponent); override;
- Destructor Destroy; override;
- Procedure CreateDocumentation(APackage : TFPDocPackage; ParseOnly : Boolean); virtual; //Writes out documentation in selected format
- Procedure CreateProjectFile(Const AFileName : string); //Writes out project file with the chosen options
- Procedure LoadProjectFile(Const AFileName: string);
- Property Project : TFPDocProject Read FProject;
- Property ScannerLogEvents : TPScannerLogEvents Read FScannerLogEvents Write FScannerLogEvents;
- Property ParserLogEvents : TPParserLogEvents Read FPParserLogEvents Write FPParserLogEvents;
- Property Verbose : Boolean Read FVerbose Write SetVerbose;
- Property OnLog : TPasParserLogHandler Read FOnLog Write FOnLog;
- // Easy access
- Property Options : TEngineOptions Read GetOptions;
- Property Packages : TFPDocPackages Read GetPackages;
- // When set, they will be prepended to non-absolute filenames.
- Property BaseInputDir : String Read FBaseInputDir Write SetBaseInputDir;
- Property BaseDescrDir : String Read FBaseDescrDir Write SetBaseDescrDir;
- Property ExamplesPath : String Read FExamplesPath Write SetExamplesPath;
- // Macros used when loading the project file
- Property ProjectMacros : TStrings Read FProjectMacros Write SetProjectMacros;
- end;
- implementation
- uses fpdocstrs;
- { TFPDocCreator }
- procedure TFPDocCreator.SetVerbose(AValue: Boolean);
- begin
- if FVerbose=AValue then Exit;
- FVerbose:=AValue;
- if FVerbose then
- begin
- ScannerLogEvents:=[sleFile];
- ParserLogEvents:=[];
- Options.InfoUsedFile:= true;
- Options.WarnDocumentationEmpty:= true;
- Options.WarnXCT:= true;
- end
- else
- begin
- ScannerLogEvents:=[];
- ParserLogEvents:=[];
- end;
- end;
- procedure TFPDocCreator.DoLog(const Msg: String);
- begin
- If Assigned(OnLog) then
- OnLog(Self,Msg);
- end;
- procedure TFPDocCreator.DoLog(const Fmt: String; Args: array of const);
- begin
- DoLog(Format(Fmt,Args));
- end;
- procedure TFPDocCreator.DoLogSender ( Sender: TObject; const Msg: String ) ;
- begin
- if Assigned(Sender) then
- DoLog(Format('%s - Sender: %s', [Msg, Sender.ClassName]))
- else
- DoLog(Msg);
- end;
- procedure TFPDocCreator.HandleOnParseUnit(Sender: TObject;
- const AUnitName: String; out AInputFile, OSTarget, CPUTarget: String);
- Var
- I : Integer;
- S,un,opts : String;
- begin
- AInputFile:='';
- OSTarget:='';
- CPUTarget:='';
- if Assigned(FCurPackage) then
- begin
- I:=0;
- While (AInputFIle='') and (I<FCurPackage.Inputs.Count) do
- begin
- S:=FCurPackage.Inputs[i];
- SplitInputFIleOption(S,UN,Opts);
- if CompareText(ChangeFileExt(ExtractFileName(Un),''),AUnitName)=0 then
- begin
- AInputFile:=FixInputFile(UN)+' '+Opts+' -d'+Options.EndianNess;
- OSTarget:=FProject.Options.OSTarget;
- CPUTarget:=FProject.Options.CPUTarget;
- FProcessedUnits.Add(UN);
- end;
- Inc(I);
- end;
- end;
- end;
- function TFPDocCreator.GetOptions: TEngineOptions;
- begin
- Result:=FProject.Options;
- end;
- function TFPDocCreator.GetPackages: TFPDocPackages;
- begin
- Result:=FProject.Packages;
- end;
- function TFPDocCreator.FixInputFile(const AFileName: String): String;
- begin
- Result:=AFileName;
- If Result='' then exit;
- if (ExtractFileDrive(Result)='') and (Result[1]<>PathDelim) then
- Result:=BaseInputDir+Result;
- end;
- function TFPDocCreator.FixDescrFile(const AFileName: String): String;
- begin
- Result:=AFileName;
- If Result='' then exit;
- if (ExtractFileDrive(Result)='') and (Result[1]<>PathDelim) then
- Result:=BaseDescrDir+Result;
- end;
- procedure TFPDocCreator.SetBaseDescrDir(AValue: String);
- begin
- if FBaseDescrDir=AValue then Exit;
- FBaseDescrDir:=AValue;
- If FBaseDescrDir<>'' then
- FBaseDescrDir:=IncludeTrailingPathDelimiter(FBaseDescrDir);
- end;
- procedure TFPDocCreator.SetBaseInputDir(AValue: String);
- begin
- if FBaseInputDir=AValue then Exit;
- FBaseInputDir:=AValue;
- If FBaseInputDir<>'' then
- FBaseInputDir:=IncludeTrailingPathDelimiter(FBaseInputDir);
- end;
- procedure TFPDocCreator.SetExamplesPath(AValue: String);
- begin
- if FExamplesPath=AValue then Exit;
- FExamplesPath:=AValue;
- If FExamplesPath<>'' then
- FExamplesPath:=IncludeTrailingPathDelimiter(FExamplesPath);
- end;
- procedure TFPDocCreator.SetProjectMacros(AValue: TStrings);
- begin
- if FProjectMacros=AValue then Exit;
- FProjectMacros.Assign(AValue);
- end;
- procedure TFPDocCreator.DoBeforeEmitNote(Sender: TObject; Note: TDomElement;
- var EmitNote: Boolean);
- begin
- EmitNote:=True;
- end;
- constructor TFPDocCreator.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FProject:=TFPDocProject.Create(Self);
- FProject.Options.StopOnParseError:=False;
- FProject.Options.CPUTarget:=DefCPUTarget;
- FProject.Options.OSTarget:=DefOSTarget;
- FProject.Options.EndianNess:=DefEndianNess;
- FProcessedUnits:=TStringList.Create;
- FProjectMacros:=TStringList.Create;
- end;
- destructor TFPDocCreator.Destroy;
- begin
- FreeAndNil(FProcessedUnits);
- FreeAndNil(FProject);
- FreeAndNil(FProjectMacros);
- inherited Destroy;
- end;
- procedure TFPDocCreator.CreateOutput(APackage: TFPDocPackage;Engine : TFPDocEngine);
- Var
- WriterClass : TFPDocWriterClass;
- Writer : TFPDocWriter;
- I : Integer;
- Cmd,Arg : String;
- begin
- // Now is used the specified writer
- WriterClass:=GetWriterClass(Options.Backend);
- // ALL CONTENT CREATED HERE
- Writer:=WriterClass.Create(Engine.Package,Engine);
- With Writer do
- Try
- If FVerbose then
- DoLog('Writing documentation');
- OnLog:=Self.OnLog;
- BeforeEmitNote:[email protected];
- EmitNotes:=Options.EmitNotes;
- If Options.BackendOptions.Count>0 then
- for I:=0 to ((Options.BackendOptions.Count-1) div 2) do
- begin
- Cmd:=Options.BackendOptions[I*2];
- Arg:=Options.BackendOptions[I*2+1];
- If not InterPretOption(Cmd,Arg) then
- DoLog(SCmdLineInvalidOption,[Cmd+'='+Arg]);
- end;
- // Create documentation by writer
- WriteDocumentation();
- Finally
- Free;
- end;
- // Output content files
- if FVerbose then
- DoLog('Content file : '+APackage.ContentFile);
- if Length(APackage.ContentFile) > 0 then
- Engine.WriteContentFile(APackage.ContentFile);
- end;
- function TFPDocCreator.GetLogLevels: TFPDocLogLevels;
- Procedure DoOpt(doSet : Boolean; aLevel: TFPDocLogLevel);
- begin
- if DoSet then
- Result:=Result+[aLevel];
- end;
- begin
- Result:=[];
- DoOpt(Options.WarnNoNode,dleWarnNoNode);
- DoOpt(Options.InfoUsedFile,dleWarnUsedFile);
- DoOpt(Options.WarnDocumentationEmpty,dleDocumentationEmpty);
- DoOpt(Options.WarnXCT,dleXCT);
- end;
- procedure TFPDocCreator.CreateDocumentation(APackage: TFPDocPackage;
- ParseOnly: Boolean);
- var
- i,j: Integer;
- Engine : TFPDocEngine;
- Cmd,Arg : String;
- WriterClass: TFPDocWriterClass;
- eMsg: String;
- begin
- Cmd:='';
- FCurPackage:=APackage;
- Engine:=TFPDocEngine.Create;
- try
- Engine.OnLog:= @DoLogSender;
- Engine.ExamplesPath:=Self.ExamplesPath;
- // get documentation Writer html, latex, and other
- WriterClass:=GetWriterClass(Options.Backend);
- For J:=0 to Apackage.Imports.Count-1 do
- begin
- Arg:=Apackage.Imports[j];
- // conversion import FilePathes
- WriterClass.SplitImport(Arg,Cmd);
- // create tree of imported objects
- Engine.ReadContentFile(Arg, Cmd);
- end;
- for i := 0 to APackage.Descriptions.Count - 1 do
- Engine.AddDocFile(FixDescrFile(APackage.Descriptions[i]),Options.donttrim);
- // set engine options
- Engine.SetPackageName(APackage.Name);
- Engine.Output:=APackage.Output;
- Engine.OnLog:=Self.OnLog;
- Engine.ScannerLogEvents:=Self.ScannerLogEvents;
- Engine.ParserLogEvents:=Self.ParserLogEvents;
- Engine.HideProtected:=Options.HideProtected;
- Engine.HidePrivate:=Not Options.ShowPrivate;
- Engine.OnParseUnit:=@HandleOnParseUnit;
- Engine.DocLogLevels:=GetLogLevels;
- Engine.FalbackSeeAlsoLinks:= Options.FallBackSeeAlsoLinks;
- if Length(Options.Language) > 0 then
- TranslateDocStrings(Options.Language);
- // scan the input source files
- for i := 0 to APackage.Inputs.Count - 1 do
- try
- try
- eMsg:='';
- // get options from input packages
- SplitInputFileOption(APackage.Inputs[i],Cmd,Arg);
- arg:=Arg+' -d'+Options.EndianNess;
- // make absolute filepath
- Cmd:=FixInputFile(Cmd);
- if FProcessedUnits.IndexOf(Cmd)=-1 then
- begin
- FProcessedUnits.Add(Cmd);
- // Parce sources for OS Target
- //WriteLn(Format('Parsing unit: %s', [ExtractFilenameOnly(Cmd)]));
- ParseSource(Engine,Cmd+' '+Arg, Options.OSTarget, Options.CPUTarget,[poUseStreams]); // poSkipDefaultDefs
- end;
- //else WriteLn(Format('Processed unit: %s', [ExtractFilenameOnly(Cmd)]));
- except
- on E: EParserError do
- begin
- eMsg:= Format('Parser error: %s (%d,%d): %s',[E.Filename, E.Row, E.Column, E.Message]);
- If Options.StopOnParseError then Raise;
- end;
- on E: EFileNotFoundError do
- begin
- eMsg:= Format('Error: file not found - %s', [E.Message]);
- If Options.StopOnParseError then Raise;
- end;
- on E: Exception do
- begin
- eMsg:= Format('Error: %s', [E.Message]);
- If Options.StopOnParseError then Raise;
- end;
- end; // try except
- finally
- if eMsg <> '' then
- begin
- DoLog(eMsg);
- If not Options.StopOnParseError then
- DoLog('Ignoring error, continuing with next unit (if any).');
- end;
- end; // try finally
- if Not ParseOnly then
- begin
- Engine.StartDocumenting;
- // Create documentation
- CreateOutput(APackage,Engine);
- end;
- finally
- FreeAndNil(Engine);
- FCurPackage:=Nil;
- end;
- end;
- procedure TFPDocCreator.CreateProjectFile(const AFileName: string);
- begin
- With TXMLFPDocOptions.Create(Self) do
- try
- SaveOptionsToFile(FProject,AFileName);
- finally
- Free;
- end;
- end;
- procedure TFPDocCreator.LoadProjectFile(const AFileName: string);
- begin
- With TXMLFPDocOptions.Create(self) do
- try
- if (ProjectMacros.Count>0) then
- LoadOptionsFromFile(FProject,AFileName,ProjectMacros)
- else
- LoadOptionsFromFile(FProject,AFileName,Nil);
- finally
- Free;
- end;
- end;
- end.
|