unit dw_dXML;
{$mode objfpc}{$H+}
interface
uses
PasTree, dwriter, SysUtils;
//uses DOM, PasTree, dwriter, xmlWrite, SysUtils;
type
{ TXMLWriter }
TDXMLWriter = class(TFPDocWriter)
procedure WriteDoc; override;
end;
{ TDocumentation }
TDocumentation = class(TPassTreeVisitor)
f: Text;
lvl: integer;
procedure GenerateDoc(OutputName: string; Module: TPasModule);
procedure DocParameters(obj: TPasProcedureType);
function DocProcFlags(obj: TPasProcedure): string;
procedure Visit(obj: TPasElement); override;
procedure DoVisit(obj: TPasSection); virtual;
procedure DoVisit(obj: TPasRecordType); virtual;
procedure DoVisit(obj: TPasEnumType); virtual;
procedure DoVisit(obj: TPasProperty); virtual;
procedure DoVisit(obj: TPasConst); virtual;
procedure DoVisit(obj: TPasVariable); virtual;
procedure DoVisit(obj: TPasProcedure); virtual;
procedure DoVisit(obj: TPasDestructor); virtual;
procedure DoVisit(obj: TPasConstructor); virtual;
procedure DoVisit(obj: TPasFunction); virtual;
procedure DoVisit(obj: TPasClassType); virtual;
procedure DoVisit(obj: TPasElement); virtual;
procedure DoVisit(obj: TPasOverloadedProc); virtual;
procedure DoVisit(obj: TPasPointerType); virtual;
procedure DoVisit(obj: TPasArrayType); virtual;
procedure DoVisit(obj: TPasProcedureType); virtual;
procedure DoVisit(obj: TPasFunctionType); virtual;
procedure DoVisit(obj: TPasResString); virtual;
end;
implementation
function EscapeXml(const s: string): string;
begin
Result := StringReplace(s, '&', '&', [rfReplaceAll]);
Result := StringReplace(Result, '<', '<', [rfReplaceAll]);
Result := StringReplace(Result, '>', '>', [rfReplaceAll]);
end;
{ TDocumentation }
procedure TDocumentation.Visit(obj: TPasElement);
begin
If (Obj.ClassType=TPasSection) then
DoVisit(TPasSection(Obj))
else if (Obj.ClassType=TPasRecordType) then
DoVisit(TPasRecordType(Obj))
else if (Obj.ClassType=TPasEnumType) then
DoVisit(TPasEnumType(Obj))
else if (Obj.ClassType=TPasProperty) then
DoVisit(TPasProperty(Obj))
else if (Obj.ClassType=TPasConst) then
DoVisit(TPasConst(Obj))
else if (Obj.ClassType=TPasVariable) then
DoVisit(TPasVariable(Obj))
else if (Obj.ClassType=TPasProcedure) then
DoVisit(TPasProcedure(Obj))
else if (Obj.ClassType=TPasDestructor) then
DoVisit(TPasDestructor(Obj))
else if (Obj.ClassType=TPasConstructor) then
DoVisit(TPasConstructor(Obj))
else if (Obj.ClassType=TPasFunction) then
DoVisit(TPasFunction(Obj))
else if (Obj.ClassType=TPasClassType) then
DoVisit(TPasClassType(Obj))
else if (Obj.ClassType=TPasOverloadedProc) then
DoVisit(TPasOverloadedProc(Obj))
else if (Obj.ClassType=TPasPointerType) then
DoVisit(TPasPointerType(Obj))
else if (Obj.ClassType=TPasArrayType) then
DoVisit(TPasArrayType(Obj))
else if (Obj.ClassType=TPasProcedureType) then
DoVisit(TPasProcedureType(Obj))
else if (Obj.ClassType=TPasFunctionType) then
DoVisit(TPasFunctionType(Obj))
else if (Obj.ClassType=TPasResString) then
DoVisit(TPasResString(Obj));
end;
procedure TDocumentation.GenerateDoc(OutputName: string; Module: TPasModule);
begin
lvl := 0;
Assign(f, OutputName);
Rewrite(f);
WriteLn(f, '');
WriteLn(f, '');
Module.InterfaceSection.Accept(Self);
//Module.Accept(Self);
WriteLn(f, '');
Close(f);
end;
procedure TDocumentation.DocParameters(obj: TPasProcedureType);
var
I: integer;
begin
for I := 0 to obj.Args.Count - 1 do
begin
Write(f, ' ': lvl * 2, ' nil then
Write(f, ' type="' + TPasArgument(obj.Args[i]).ArgType.Name + '"');
if TPasArgument(obj.Args[i]).Access <> argDefault then
if (TPasArgument(obj.Args[i]).ArgType is TPasClassType) then
Write(f, ' paramflags="' + 'var' + '"')
else
Write(f, ' paramflags="' +
Trim(AccessNames[TPasArgument(obj.Args[i]).Access]) + '"');
if TPasArgument(obj.Args[i]).Value <> '' then
begin
WriteLn(f, '>');
WriteLn(f, ' ': lvl * 2 + 2, '');
WriteLn(f, ' ': lvl * 2 + 4, EscapeXml(TPasArgument(obj.Args[i]).Value));
WriteLn(f, ' ': lvl * 2 + 2, '');
WriteLn(f, ' ': lvl * 2, '');
end
else
WriteLn(f, ' />');
end;
end;
function TDocumentation.DocProcFlags(obj: TPasProcedure): string;
procedure DoAdd(B: boolean; S: string);
begin
if B then
begin
if Result <> '' then
Result := Result + ' ';
Result := Result + S;
end;
end;
begin
Result := '';
DoAdd(obj.IsAbstract, 'abstract');
Doadd(obj.IsVirtual, 'virtual');
DoAdd(obj.IsDynamic, 'dynamic');
DoAdd(obj.IsOverride, 'override');
DoAdd(obj.IsOverload, 'overload');
DoAdd(obj.IsReintroduced, 'reintroduce');
DoAdd(obj.IsStatic, 'static');
DoAdd(obj.IsMessage, 'message');
end;
procedure TDocumentation.DoVisit(obj: TPasSection);
var
i: integer;
begin
Inc(lvl);
for i := 0 to obj.Declarations.Count - 1 do
TPasElement(obj.Declarations[i]).Accept(Self);
Dec(lvl);
end;
procedure TDocumentation.DoVisit(obj: TPasRecordType);
var
I: integer;
begin
Write(f, StringOfChar(' ', lvl * 2) + ' '' then
Write(f, ' name="' + obj.Name + '"');
if obj.IsPacked then
Write(f, ' packed="true"');
WriteLn(f, '>');
Inc(lvl);
for I := 0 to obj.Members.Count - 1 do
TPasVariable(obj.Members[i]).Accept(Self);
Dec(lvl);
WriteLn(f, StringOfChar(' ', lvl * 2) + '');
end;
procedure TDocumentation.DoVisit(obj: TPasEnumType);
var
I: integer;
begin
for I := 0 to obj.Values.Count - 1 do
begin
WriteLn(f, ' ': lvl * 2, '');
WriteLn(f, ' ': lvl * 2 + 2, '');
WriteLn(f, ' ': lvl * 2 + 4, TPasEnumValue(obj.Values[i]).Name);
WriteLn(f, ' ': lvl * 2 + 2, '');
WriteLn(f, ' ': lvl * 2, '');
end;
WriteLn(f, ' ': lvl * 2, '');
for I := 0 to obj.Values.Count - 1 do
WriteLn(f, ' ': lvl * 2 + 2, '');
WriteLn(f, ' ': lvl * 2, '');
end;
procedure TDocumentation.DoVisit(obj: TPasProperty);
begin
if (obj.VarType <> nil) and (obj.VarType is TPasProcedureType) and
(TPasProcedureType(obj.VarType).IsOfObject) then
Write(f, ' ': lvl * 2, ' '' then
Write(f, ' read="' + obj.ReadAccessorName + '"');
if obj.WriteAccessorName <> '' then
Write(f, ' write="' + obj.WriteAccessorName + '"');
if obj.VarType <> nil then
Write(f, ' type="' + obj.VarType.Name + '"');
if obj.DefaultValue <> '' then
Write(f, ' default="' + obj.DefaultValue + '"');
WriteLn(f, ' />');
end;
procedure TDocumentation.DoVisit(obj: TPasConst);
begin
Write(f, ' ': lvl * 2, ' nil) and (obj.VarType.Name <> '') then
Write(f, ' type="' + obj.VarType.Name + '"');
WriteLn(f, '>');
WriteLn(f, ' ': lvl * 2 + 2, '');
WriteLn(f, ' ': lvl * 2 + 4, EscapeXml(obj.Value));
WriteLn(f, ' ': lvl * 2 + 2, '');
WriteLn(f, ' ': lvl * 2, '');
end;
procedure TDocumentation.DoVisit(obj: TPasVariable);
begin
Write(f, ' ': lvl * 2, ' nil) and (obj.VarType.Name <> '') then
Write(f, ' type="' + obj.VarType.Name {.GetDeclaration(True)} + '"');
if obj.Visibility <> visDefault then
Write(f, ' visibility="' + VisibilityNames[obj.Visibility] + '"');
if (obj.VarType <> nil) and (obj.VarType.Name = '')
{(VarType.ElementTypeName <> SPasTreeType) and (VarType.ElementTypeName <> SPasTreeUnresolvedTypeRef)}
then
begin
WriteLn(f, '>');
Inc(lvl);
obj.VarType.Accept(Self);
Dec(lvl);
WriteLn(f, ' ': lvl * 2, '');
end
else
WriteLn(f, ' />');
end;
procedure TDocumentation.DoVisit(obj: TPasProcedure);
var
t: string;
begin
Write(f, ' ': lvl * 2, ' visDefault then
Write(f, ' visibility="' + VisibilityNames[obj.Visibility] + '"');
t := DocProcFlags(obj);
if t <> '' then
Write(f, ' procflags="' + t + '"');
WriteLn(f, '>');
Inc(lvl);
if obj.ProcType.Args.Count > 0 then
begin
WriteLn(f, ' ': lvl * 2, '');
Inc(lvl);
DocParameters(obj.ProcType);
Dec(lvl);
WriteLn(f, ' ': lvl * 2, '');
end;
Dec(lvl);
WriteLn(f, ' ': lvl * 2, '');
end;
procedure TDocumentation.DoVisit(obj: TPasDestructor);
begin
Write(f, ' ': lvl * 2, ' visDefault then
Write(f, ' visibility="' + VisibilityNames[obj.Visibility] + '"');
WriteLn(f, '>');
Inc(lvl);
WriteLn(f, ' ': lvl * 2, '');
Inc(lvl);
DocParameters(obj.ProcType);
Dec(lvl);
WriteLn(f, ' ': lvl * 2, '');
Dec(lvl);
WriteLn(f, ' ': lvl * 2, '');
end;
procedure TDocumentation.DoVisit(obj: TPasConstructor);
begin
Write(f, ' ': lvl * 2, ' visDefault then
Write(f, ' visibility="' + VisibilityNames[obj.Visibility] + '"');
WriteLn(f, '>');
Inc(lvl);
WriteLn(f, ' ': lvl * 2, '');
Inc(lvl);
DocParameters(obj.ProcType);
Dec(lvl);
WriteLn(f, ' ': lvl * 2, '');
Dec(lvl);
WriteLn(f, ' ': lvl * 2, '');
end;
procedure TDocumentation.DoVisit(obj: TPasFunction);
var
t: string;
begin
Write(f, ' ': lvl * 2, ' visDefault then
Write(f, ' visibility="' + VisibilityNames[obj.Visibility] + '"');
t := DocProcFlags(obj);
if t <> '' then
Write(f, ' procflags="' + t + '"');
WriteLn(f, '>');
Inc(lvl);
WriteLn(f, ' ': lvl * 2, '');
Inc(lvl);
DocParameters(obj.ProcType);
WriteLn(f, ' ': lvl * 2, '');
Dec(lvl);
WriteLn(f, ' ': lvl * 2, '');
Dec(lvl);
WriteLn(f, ' ': lvl * 2, '');
end;
procedure TDocumentation.DoVisit(obj: TPasClassType);
var
i: integer;
begin
case obj.ObjKind of
okObject: WriteLn(f, ' ': lvl * 2, '');
okClass: WriteLn(f, ' ': lvl * 2, '');
okInterface: WriteLn(f, ' ': lvl * 2, '');
end;
end;
procedure TDocumentation.DoVisit(obj: TPasElement);
begin
WriteLn('Warning: NOT supported: ' + obj.ClassName + ' (' + obj.Name + ')');
end;
procedure TDocumentation.DoVisit(obj: TPasOverloadedProc);
var
i: integer;
begin
for i := 0 to obj.Overloads.Count - 1 do
TPasProcedure(obj.Overloads[i]).Accept(Self);
end;
procedure TDocumentation.DoVisit(obj: TPasPointerType);
begin
Write(f, ' ': lvl * 2, ' nil then
Write(f, ' type="' + obj.DestType.Name + '"');
WriteLn(f, ' indircnt="1" />');
end;
procedure TDocumentation.DoVisit(obj: TPasArrayType);
begin
Write(f, ' ': lvl * 2, ' '' then
begin
if Pos('..', obj.IndexRange) <> 0 then
begin
Write(f, ' low="' + Copy(obj.IndexRange, 1, Pos('..', obj.IndexRange) - 1) + '"');
Write(f, ' high="' + Copy(obj.IndexRange, Pos('..', obj.IndexRange) + 2,
MaxInt) + '"');
end
else
Write(f, ' high="' + obj.IndexRange + '"');
end;
WriteLn(f, '>');
WriteLn(f, ' ');
WriteLn(f, ' ');
end;
procedure TDocumentation.DoVisit(obj: TPasProcedureType);
begin
Write(f, ' ': lvl * 2, ' visDefault then
Write(f, ' visibility="' + VisibilityNames[obj.Visibility] + '"');
WriteLn(f, '>');
if obj.Args.Count > 0 then
begin
WriteLn(f, ' ': lvl * 2 + 2, '');
DocParameters(obj);
WriteLn(f, ' ': lvl * 2 + 2, '');
end;
WriteLn(f, ' ': lvl * 2, '');
end;
procedure TDocumentation.DoVisit(obj: TPasFunctionType);
begin
Write(f, ' ': lvl * 2, ' visDefault then
Write(f, ' visibility="' + VisibilityNames[obj.Visibility] + '"');
WriteLn(f, '>');
WriteLn(f, ' ': lvl * 2 + 2, '');
DocParameters(obj);
WriteLn(f, ' ': lvl * 2 + 4, '');
WriteLn(f, ' ': lvl * 2 + 2, '');
WriteLn(f, ' ': lvl * 2, '');
end;
procedure TDocumentation.DoVisit(obj: TPasResString);
begin
WriteLn(f, ' ': lvl * 2, '');
WriteLn(f, ' ': lvl * 2 + 2, '');
WriteLn(f, ' ': lvl * 2 + 4, EscapeXml(obj.GetDeclaration(false)));
WriteLn(f, ' ': lvl * 2 + 2, '');
WriteLn(f, ' ': lvl * 2, '');
end;
{ TXMLWriter }
procedure TDXMLWriter.WriteDoc;
var
i: integer;
begin
if Engine.Output <> '' then
Engine.Output := IncludeTrailingBackSlash(Engine.Output);
for i := 0 to Package.Modules.Count - 1 do
begin
with TDocumentation.Create do
begin
GenerateDoc(Engine.Output + TPasModule(Package.Modules[i]).Name +
'.xml', TPasModule(Package.Modules[i]));
Free;
end;
end;
end;
initialization
// Do not localize.
RegisterWriter(TDXMLWriter, 'dxml', 'fpdoc Delphi XML output.');
finalization
UnRegisterWriter('dxml');
end.