dw_xml.pp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702
  1. {
  2. FPDoc - Free Pascal Documentation Tool
  3. Copyright (C) 2000 - 2003 by
  4. Areca Systems GmbH / Sebastian Guenther, [email protected]
  5. 2005-2012 by
  6. various FPC contributors
  7. * 'XML struct' output generator
  8. See the file COPYING, included in this distribution,
  9. for details about the copyright.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. }
  14. {$mode objfpc}
  15. {$H+}
  16. unit dw_XML;
  17. interface
  18. uses DOM, PasTree, dGlobals, dwriter, xmlWrite, SysUtils, Classes;
  19. Type
  20. { TXMLWriter }
  21. TXMLWriter = Class(TMultiFileDocWriter)
  22. private
  23. FShowSourceInfo:Boolean;
  24. FUseFlatStructure:Boolean;
  25. protected
  26. function CreateAllocator : TFileAllocator; override;
  27. procedure AllocatePackagePages; override;
  28. procedure AllocateModulePages(AModule: TPasModule; {%H-}LinkList: TObjectList); override;
  29. procedure WriteDocPage(const aFileName: String; aElement: TPasElement; {%H-}aSubPageIndex: Integer); override;
  30. public
  31. constructor Create(APackage: TPasPackage; AEngine: TFPDocEngine); override;
  32. function ModuleToXMLStruct(AModule: TPasModule): TXMLDocument;
  33. Procedure WriteDoc; override;
  34. class procedure Usage(List: TStrings); override;
  35. function InterPretOption(const Cmd,Arg : String): boolean; override;
  36. end;
  37. { TFlatFileAllocator }
  38. TFlatFileAllocator = class(TFileAllocator)
  39. private
  40. FExtension: String;
  41. public
  42. constructor Create(const AExtension: String);
  43. function GetFilename(AElement: TPasElement; ASubindex: Integer): String; override;
  44. function GetRelativePathToTop(AElement: TPasElement): String; override;
  45. property Extension: String read FExtension;
  46. end;
  47. implementation
  48. const
  49. DefaultVisibility = [visDefault, visPublic, visPublished, visProtected];
  50. { TXmlFileAllocator }
  51. constructor TFlatFileAllocator.Create(const AExtension: String);
  52. begin
  53. FExtension:= AExtension;
  54. inherited Create();
  55. end;
  56. function TFlatFileAllocator.GetFilename(AElement: TPasElement; ASubindex: Integer
  57. ): String;
  58. begin
  59. Result:='';
  60. if AElement.ClassType = TPasPackage then
  61. Result := 'index'
  62. else if AElement.ClassType = TPasModule then
  63. Result := LowerCase(AElement.Name);
  64. Result := Result + Extension;
  65. end;
  66. function TFlatFileAllocator.GetRelativePathToTop(AElement: TPasElement): String;
  67. begin
  68. Result:=inherited GetRelativePathToTop(AElement);
  69. end;
  70. function TXMLWriter.ModuleToXMLStruct(AModule: TPasModule): TXMLDocument;
  71. var
  72. ModuleElement: TDOMElement;
  73. Doc: TXMLDocument absolute Result;
  74. function VisibilityToString(vis: TPasMemberVisibility): String;
  75. begin
  76. case vis of
  77. visDefault : Result := '';
  78. visPrivate : Result := 'private';
  79. visProtected : Result := 'protected';
  80. visPublic : Result := 'public';
  81. visPublished : Result := 'published';
  82. visAutomated : Result := 'automated';
  83. visStrictPrivate : Result := 'strictprivate';
  84. visStrictProtected : Result := 'strictprotected';
  85. end;
  86. end;
  87. function Sanitize(AString: String): String;
  88. var
  89. i: Integer;
  90. begin
  91. Result := AString;
  92. for i := 1 to length(Result) do
  93. if Result[i] in [' '] then
  94. Result[i] := '_';
  95. end;
  96. procedure AddSourceInfo(ADecl: TPasElement; AElement: TDOMElement);
  97. var
  98. SourceNode: TDOMElement;
  99. begin
  100. if not FShowSourceInfo then
  101. Exit;
  102. SourceNode := Doc.CreateElement('source');
  103. SourceNode['line'] := UTF8Decode(IntToStr(ADecl.SourceLinenumber));
  104. SourceNode['file'] := UTF8Decode(ADecl.SourceFilename);
  105. AElement.AppendChild(SourceNode);
  106. end;
  107. procedure AddProcedureModifiers(ADecl: TPasProcedure; Node: TDOMElement);
  108. begin
  109. {pmVirtual , pmDynamic, pmAbstract, pmOverride,
  110. pmExport, pmOverload, pmMessage, pmReintroduce,
  111. pmStatic,pmInline,pmAssembler,pmVarargs, pmPublic,
  112. pmCompilerProc,pmExternal,pmForward}
  113. if (pmVirtual in ADecl.Modifiers) or (pmDynamic in ADecl.Modifiers) then
  114. Node['virtual'] := 'true';
  115. if pmAbstract in ADecl.Modifiers then
  116. Node['abstract'] := 'true';
  117. if assigned(ADecl.ProcType) and (ptmStatic in ADecl.ProcType.Modifiers) then
  118. Node['static'] := 'true';
  119. if pmReintroduce in ADecl.Modifiers then
  120. Node['reintroduce'] := 'true';
  121. if pmOverload in ADecl.Modifiers then
  122. Node['overload'] := 'true';
  123. if pmForward in ADecl.Modifiers then
  124. Node['forward'] := 'true';
  125. if pmOverride in ADecl.Modifiers then
  126. Node['override'] := 'true';
  127. end;
  128. procedure AddTypeNode(ToNode: TDOMElement; AType: String);
  129. begin
  130. ToNode.AttribStrings['type'] := UTF8Decode(AType);
  131. end;
  132. function AddTypeNode(ToNode: TDOMElement; AType: TPasType): Boolean;
  133. //var
  134. // TypeNode: TDOMElement;
  135. begin
  136. Result := False;
  137. if not Assigned(AType) then
  138. Exit;
  139. //TypeNode := Doc.CreateElement('type');
  140. //TypeNode.TextContent:=AType.Name;
  141. //ToNode.AppendChild(TypeNode);
  142. AddTypeNode(ToNode, AType.Name);
  143. Result := True;
  144. end;
  145. procedure ProcessArgs(Args: TFPList; ProcNode: TDomElement);
  146. var
  147. i: Integer;
  148. ArgNode: TDOMElement;
  149. Arg: TPasArgument;
  150. begin
  151. for i := 0 to Args.Count-1 do
  152. begin
  153. Arg := TPasArgument(Args.Items[i]);
  154. ArgNode := Doc.CreateElement('argument');
  155. ArgNode.AttribStrings['name'] := UTF8Decode(Arg.Name);
  156. AddTypeNode(ArgNode, Arg.ArgType);
  157. ProcNode.AppendChild(ArgNode);
  158. end;
  159. end;
  160. procedure DoVisibility(PasEl: TPasElement; Element: TDOMElement);
  161. begin
  162. if PasEl.Visibility <> visDefault then
  163. Element['visibility'] := UTF8Decode(VisibilityToString(PasEl.Visibility));
  164. end;
  165. function ProcessProcedure(Proc: TPasProcedure; Element: TDOMElement): TDOMElement;
  166. var
  167. ProcEl: TDOMElement;
  168. ReturnEl: TDOMElement;
  169. begin
  170. Result := nil;
  171. ProcEl := Doc.CreateElement(UTF8Decode(Sanitize(Proc.TypeName)));
  172. Element.AppendChild(ProcEl);
  173. ProcEl['name'] := UTF8Decode(Proc.Name);
  174. DoVisibility(Proc, ProcEl);
  175. AddProcedureModifiers(Proc, ProcEl);
  176. AddSourceInfo(Proc,ProcEl);
  177. if Proc.InheritsFrom(TPasFunction) then
  178. begin
  179. ReturnEl := Doc.CreateElement('return');
  180. ProcEl.AppendChild(ReturnEl);
  181. AddTypeNode(ReturnEl, TPasFunction(Proc).FuncType.ResultEl.ResultType);
  182. end;
  183. ProcessArgs(Proc.ProcType.Args, ProcEl);
  184. Result := ProcEl;
  185. end;
  186. procedure ProcessArrayType(AType: TPasArrayType; Element: TDOMElement);
  187. var
  188. TypeEl: TDOMElement;
  189. begin
  190. TypeEl := Doc.CreateElement('array');
  191. TypeEl['name'] := UTF8Decode(AType.Name);
  192. if not AddTypeNode(TypeEl, AType.ElType) then
  193. TypeEl['const'] := 'true';
  194. TypeEl['range'] := UTF8Decode(AType.IndexRange);
  195. DoVisibility(AType, Element);
  196. AddSourceInfo(AType,Element);
  197. Element.AppendChild(TypeEl);
  198. end;
  199. procedure ProcessPointerType(AType: TPasPointerType; Element: TDOMElement);
  200. var
  201. TypeEl: TDOMElement;
  202. begin
  203. TypeEl := Doc.CreateElement('pointer');
  204. TypeEl['name'] := UTF8Decode(AType.Name);
  205. AddTypeNode(TypeEl, AType.DestType);
  206. DoVisibility(AType, Element);
  207. AddSourceInfo(AType,Element);
  208. Element.AppendChild(TypeEl);
  209. end;
  210. procedure ProcessAliasType(AType: TPasAliasType; Element: TDOMElement);
  211. var
  212. TypeEl: TDOMElement;
  213. begin
  214. TypeEl := Doc.CreateElement('alias');
  215. TypeEl['name'] := UTF8Decode(AType.Name);
  216. AddTypeNode(TypeEl, AType.DestType);
  217. DoVisibility(AType, Element);
  218. AddSourceInfo(AType,Element);
  219. Element.AppendChild(TypeEl);
  220. end;
  221. procedure ProcessVariable(AVar: TPasVariable; Element: TDOMElement);
  222. var
  223. VarEl: TDOMElement;
  224. begin
  225. VarEl := Result.CreateElement('var');
  226. Element.AppendChild(VarEl);
  227. VarEl['name'] := UTF8Decode(AVar.Name);
  228. if not AVar.VarType.InheritsFrom(TPasArrayType) then
  229. AddTypeNode(VarEl, AVar.VarType)
  230. else
  231. begin
  232. VarEl['array'] := 'true';
  233. ProcessArrayType(TPasArrayType(AVar.VarType), VarEl);
  234. end;
  235. DoVisibility(Avar, VarEl);
  236. AddSourceInfo(AVar,VarEl);
  237. end;
  238. procedure ProcessProperty(AProp: TPasProperty; Element: TDOMElement);
  239. var
  240. PropEl: TDOMElement;
  241. begin
  242. PropEl := Doc.CreateElement('property');
  243. Element.AppendChild(PropEl);
  244. PropEl.AttribStrings['name'] := UTF8Decode(AProp.Name);
  245. AddTypeNode(PropEL, AProp.ResolvedType);
  246. if AProp.IndexValue <> '' then
  247. PropEl['index'] := UTF8Decode(AProp.IndexValue);
  248. if AProp.DefaultValue <> '' then
  249. PropEl['default'] := UTF8Decode(AProp.DefaultValue);
  250. if AProp.WriteAccessorName <> '' then
  251. PropEl.AttribStrings['writable'] := 'true';
  252. ProcessArgs(AProp.Args, PropEl);
  253. DoVisibility(AProp, Element);
  254. AddSourceInfo(AProp,PropEl);
  255. // this isn't quite right
  256. //if AProp.ReadAccessorName = '' then
  257. // PropEl.AttribStrings['inherited'] := 'true';
  258. end;
  259. procedure ProcessOverloadedProcedure(AOverload: TPasOverloadedProc; Element: TDOMElement);
  260. var
  261. OverEl: TDOMElement;
  262. i: Integer;
  263. begin
  264. for i := 0 to AOverload.Overloads.Count-1 do
  265. begin
  266. OverEl := ProcessProcedure(TPasProcedure(AOverload.Overloads.Items[i]), Element);
  267. OverEl['overload'] := 'true';
  268. end;
  269. end;
  270. procedure ProcessConst(AConst: TPasConst; Element: TDOMElement);
  271. var
  272. ConstEl: TDOMElement;
  273. begin
  274. ConstEl := Doc.CreateElement('const');
  275. ConstEl['name'] := UTF8Decode(AConst.name);
  276. ConstEl['value'] := UTF8Decode(AConst.Value);
  277. Element.AppendChild(ConstEl);
  278. AddSourceInfo(AConst,ConstEl);
  279. end;
  280. procedure ProcessEnumType(AType: TPasEnumType; Element: TDOMElement);
  281. var
  282. TypeEl: TDOMElement;
  283. ValEl: TDOMELement;
  284. i: Integer;
  285. begin
  286. TypeEl := Doc.CreateElement('enum');
  287. TypeEl['name'] := UTF8Decode(AType.name);
  288. AddSourceInfo(AType,TypeEl);
  289. //ConstEl['value'] := AConst.Value;
  290. for i := 0 to AType.Values.Count-1 do
  291. begin
  292. ValEl := Doc.CreateElement('enumvalue');
  293. ValEl['name'] := UTF8Decode(TPasEnumValue(AType.Values.Items[i]).Name);
  294. AddSourceInfo(TPasEnumValue(AType.Values.Items[i]),ValEl);
  295. TypeEl.AppendChild(ValEl);
  296. end;
  297. Element.AppendChild(TypeEl);
  298. end;
  299. procedure ProcessSetType(AType: TPasSetType; Element: TDOMElement);
  300. var
  301. SetEl: TDOMElement;
  302. begin
  303. SetEl := Doc.CreateElement('set');
  304. SetEl['name'] := UTF8Decode(AType.name);
  305. AddTypeNode(SetEl, AType.EnumType);
  306. AddSourceInfo(AType,SetEl);
  307. Element.AppendChild(SetEl);
  308. end;
  309. procedure ProcessProcedureType(AType: TPasProcedureType; Element: TDOMElement);
  310. var
  311. TypeEl: TDOMElement;
  312. begin
  313. TypeEl := Doc.CreateElement(UTF8Decode(AType.TypeName));
  314. TypeEl['name'] := UTF8Decode(AType.name);
  315. TypeEl['istype'] := 'true';
  316. if AType.IsOfObject then
  317. TypeEl['object'] := 'true';
  318. ProcessArgs(AType.Args, TypeEl);
  319. AddSourceInfo(AType,TypeEl);
  320. Element.AppendChild(TypeEl);
  321. end;
  322. procedure ProcessRecordType(AType: TPasRecordType; Element: TDOMElement);
  323. var
  324. TypeEl: TDOMElement;
  325. Decl: TPasElement;
  326. i: Integer;
  327. begin
  328. TypeEl := Doc.CreateElement('record');
  329. TypeEl['name'] := UTF8Decode(AType.name);
  330. Element.AppendChild(TypeEl);
  331. AddSourceInfo(AType,TypeEl);
  332. if Assigned(AType.Members) then
  333. for i := 0 to AType.Members.Count - 1 do
  334. begin
  335. Decl := TPasElement(AType.Members[i]);
  336. if Decl.InheritsFrom(TPasProcedure)then
  337. ProcessProcedure(TPasProcedure(Decl), TypeEl)
  338. else if Decl.ClassType = TPasVariable then
  339. ProcessVariable(TPasVariable(Decl), TypeEl)
  340. else if Decl.ClassType = TPasProperty then
  341. ProcessProperty(TPasProperty(Decl), TypeEl)
  342. else writeln('Unhandled record member: ', Decl.ClassName, ' ', Decl.Name);
  343. end;
  344. end;
  345. procedure ProcessGenericTypes(AGenericTypes: TFPList; ANode: TDOMElement);
  346. var
  347. i: Integer;
  348. Node: TDOMElement;
  349. begin
  350. for i := 0 to AGenericTypes.Count-1 do
  351. begin
  352. Node := Doc.CreateElement('t');
  353. Node['name'] := UTF8Decode(TPasGenericTemplateType(AGenericTypes.Items[i]).Name);
  354. ANode.AppendChild(Node);
  355. AddSourceInfo(TPasGenericTemplateType(AGenericTypes.Items[i]),Node);
  356. end;
  357. end;
  358. procedure ProcessRangeType(AType: TPasRangeType; Element: TDOMElement);
  359. var
  360. TypeEl: TDOMElement;
  361. begin
  362. TypeEl := Doc.CreateElement('range');
  363. TypeEl['name'] := UTF8Decode(AType.Name);
  364. TypeEl['start'] := UTF8Decode(AType.RangeStart);
  365. TypeEl['end'] := UTF8Decode(AType.RangeEnd);
  366. AddSourceInfo(AType,TypeEl);
  367. Element.AppendChild(TypeEl);
  368. end;
  369. procedure ProcessClassType(AClass: TPasClassType; Element: TDOMElement); forward;
  370. function ProcessType(AType: TPasElement; Element: TDOMElement): Boolean;
  371. begin
  372. Result := True;
  373. if AType.ClassType = TPasVariable then
  374. ProcessVariable(TPasVariable(AType), Element)
  375. else if AType.ClassType = TPasProperty then
  376. ProcessProperty(TPasProperty(AType), Element)
  377. else if AType.InheritsFrom(TPasOverloadedProc) then
  378. ProcessOverloadedProcedure(TPasOverloadedProc(AType), Element)
  379. else if AType.InheritsFrom(TPasConst) then
  380. ProcessConst(TPasConst(AType), Element)
  381. else if AType.InheritsFrom(TPasEnumType) then
  382. ProcessEnumType(TPasEnumType(AType), Element)
  383. else if AType.InheritsFrom(TPasClassType) then
  384. ProcessClassType(TPasClassType(AType), Element)
  385. else if AType.InheritsFrom(TPasAliasType) then
  386. ProcessAliasType(TPasAliasType(AType), Element)
  387. else if AType.InheritsFrom(TPasSetType) then
  388. ProcessSetType(TPasSetType(AType), Element)
  389. else if AType.InheritsFrom(TPasProcedureType) then
  390. ProcessProcedureType(TPasProcedureType(AType), Element)
  391. else if AType.InheritsFrom(TPasRecordType) then
  392. ProcessRecordType(TPasRecordType(AType), Element)
  393. else if AType.InheritsFrom(TPasArrayType) then
  394. ProcessArrayType(TPasArrayType(AType), Element)
  395. else if AType.InheritsFrom(TPasPointerType) then
  396. ProcessPointerType(TPasPointerType(AType), Element)
  397. else if AType.InheritsFrom(TPasRangeType) then
  398. ProcessRangeType(TPasRangeType(AType), Element)
  399. else
  400. Result := False;
  401. end;
  402. procedure ProcessClassType(AClass: TPasClassType; Element: TDOMElement);
  403. var
  404. ClassEl: TDOMElement = nil;
  405. i: Integer;
  406. Decl: TPasElement;
  407. SubNode: TDomElement;
  408. InterfaceEl: TDomElement;
  409. Vis: TPasMemberVisibilities = DefaultVisibility;
  410. begin
  411. if not Engine.HidePrivate then Include(Vis, visPrivate);
  412. if Engine.HideProtected then Exclude(Vis, visProtected);
  413. case AClass.ObjKind of
  414. okClass: ClassEl := Result.CreateElement('class');
  415. okObject: ClassEl := Result.CreateElement('object');
  416. okInterface: ClassEl := Result.CreateElement('interface');
  417. //okGeneric: Result.CreateElement('generic');
  418. //okClassHelper: Result.CreateElement('classhelper');
  419. //okRecordHelper: Result.CreateElement('recordhelper');
  420. //okTypeHelper: Result.CreateElement('typehelper');
  421. else
  422. //raise Exception.Create('ProcessClass: unknown class kind');
  423. WriteLn('Unhandled Class kind: ', AClass.ObjKind);
  424. end;
  425. if Assigned(ClassEl) then
  426. begin
  427. Element.AppendChild(ClassEl);
  428. ClassEl['name'] := UTF8Decode(AClass.Name);
  429. if Assigned(AClass.AncestorType) then
  430. ClassEl['parentclass'] := UTF8Decode(AClass.AncestorType.Name);
  431. AddSourceInfo(AClass,ClassEl);
  432. if Assigned(AClass.Interfaces) then
  433. for i := 0 to AClass.Interfaces.Count-1 do
  434. begin
  435. InterfaceEl := Doc.CreateElement('interface');
  436. ClassEl.AppendChild(InterfaceEl);
  437. InterfaceEl['name'] := UTF8Decode(TPasElement(AClass.Interfaces.Items[i]).Name);
  438. end;
  439. if Assigned(AClass.Members) then
  440. for i := 0 to AClass.Members.Count - 1 do
  441. begin
  442. Decl := TPasElement(AClass.Members[i]);
  443. if not (Decl.Visibility in Vis) then
  444. continue;
  445. if Decl.InheritsFrom(TPasProcedure)then
  446. begin
  447. SubNode := ProcessProcedure(TPasProcedure(Decl), ClassEl);
  448. if Assigned(SubNode) then
  449. begin
  450. if SubNode.InheritsFrom(TPasClassConstructor) then
  451. SubNode.SetAttribute('type', 'constructor')
  452. else if SubNode.InheritsFrom(TPasClassDestructor) then
  453. SubNode.SetAttribute('type', 'destructor');
  454. end;
  455. end
  456. else if not ProcessType(Decl, ClassEl) then
  457. writeln('Unhandled class member: ', Decl.ClassName, ' ', Decl.Name);
  458. end;
  459. end;
  460. end;
  461. function FindInList(AName: String; AList: TFPList): Boolean;
  462. var
  463. El: TPasElement;
  464. I: Integer;
  465. begin
  466. Result := False;
  467. I := 0;
  468. while not Result and (I < AList.Count) do
  469. begin
  470. El := TPasElement(AList[I]);
  471. if El.Name = AName then
  472. Result := True;
  473. Inc(I);
  474. end;
  475. end;
  476. procedure ProcessSection(ASection: TPasSection; const Name: DOMString);
  477. var
  478. Element, UsesElement, UnitElement: TDOMElement;
  479. i: Integer;
  480. Decl: TPasElement;
  481. begin
  482. Element := Result.CreateElement(Name);
  483. ModuleElement.AppendChild(Element);
  484. if ASection.UsesList.Count > 0 then
  485. begin
  486. UsesElement := Result.CreateElement('uses');
  487. Element.AppendChild(UsesElement);
  488. for i := 0 to ASection.UsesList.Count - 1 do
  489. begin
  490. UnitElement := Result.CreateElement('unit-ref');
  491. UnitElement['name'] := UTF8Decode(TPasType(ASection.UsesList[i]).Name);
  492. UsesElement.AppendChild(UnitElement);
  493. end;
  494. end;
  495. for i := 0 to ASection.Classes.Count -1 do
  496. begin
  497. Decl := TPasElement(ASection.Classes[i]);
  498. ProcessClassType(TPasClassType(Decl), Element);
  499. end;
  500. for i := 0 to ASection.Consts.Count - 1 do
  501. begin
  502. Decl := TPasElement(ASection.Consts[i]);
  503. ProcessConst(TPasConst(Decl), Element)
  504. end;
  505. for i := 0 to ASection.Types.Count - 1 do
  506. begin
  507. Decl := TPasElement(ASection.Types[i]);
  508. if not ProcessType(Decl, Element) then
  509. WriteLn('Unhandled type: ',Decl.ClassName, ' ', Decl.Name);
  510. end;
  511. for i := 0 to ASection.Declarations.Count - 1 do
  512. begin
  513. Decl := TPasElement(ASection.Declarations[i]);
  514. if Decl.InheritsFrom(TPasProcedure) then
  515. ProcessProcedure(TPasProcedure(Decl), Element)
  516. else if Decl.ClassType = TPasVariable then
  517. ProcessVariable(TPasVariable(Decl), Element);
  518. end;
  519. for i := 0 to ASection.Functions.Count - 1 do
  520. begin
  521. // many of these (all?) seem to be in ASection.Declarations
  522. Decl := TPasElement(ASection.Functions[i]);
  523. if FindInList(Decl.Name, ASection.Declarations) then
  524. WriteLn('Duplicate proc definition in declarations. Skipping: ', Decl.Name)
  525. else
  526. WriteLn('Unhandled function: ',Decl.ClassName, ' ', Decl.Name);
  527. end;
  528. for i := 0 to ASection.Properties.Count - 1 do
  529. begin
  530. Decl := TPasElement(ASection.Properties[i]);
  531. ProcessProperty(TPasProperty(Decl), Element);
  532. end;
  533. end;
  534. begin
  535. Result := TXMLDocument.Create;
  536. Result.AppendChild(Result.CreateComment(UTF8Decode(SDocGeneratedByComment)));
  537. Result.AppendChild(Result.CreateElement('fp-refdoc'));
  538. ModuleElement := Result.CreateElement('unit');
  539. ModuleElement['name'] := UTF8Decode(AModule.Name);
  540. Result.DocumentElement.AppendChild(ModuleElement);
  541. ProcessSection(AModule.InterfaceSection, 'interface');
  542. end;
  543. { TXMLWriter }
  544. procedure TXMLWriter.WriteDoc;
  545. begin
  546. inherited WriteDoc;
  547. end;
  548. function TXMLWriter.CreateAllocator: TFileAllocator;
  549. begin
  550. if FUseFlatStructure then
  551. Result:=TFlatFileAllocator.Create('.xml')
  552. else
  553. Result:=TLongNameFileAllocator.Create('.xml');
  554. end;
  555. procedure TXMLWriter.AllocatePackagePages;
  556. var
  557. H: Boolean;
  558. begin
  559. H:= false; // TODO: I want to public TreeClass for package
  560. if H then
  561. AddPage(Package,ClassHierarchySubIndex);
  562. end;
  563. procedure TXMLWriter.AllocateModulePages(AModule: TPasModule;
  564. LinkList: TObjectList);
  565. begin
  566. if not assigned(Amodule.Interfacesection) then
  567. exit;
  568. AddPage(AModule, 0);
  569. end;
  570. procedure TXMLWriter.WriteDocPage(const aFileName: String;
  571. aElement: TPasElement; aSubPageIndex: Integer);
  572. var
  573. doc: TXMLDocument;
  574. begin
  575. if (aElement is TPasModule) then
  576. begin
  577. doc := ModuleToXMLStruct(TPasModule(aElement));
  578. WriteXMLFile(doc, GetFileBaseDir(Engine.Output) + aFileName);
  579. doc.Free;
  580. end;
  581. end;
  582. constructor TXMLWriter.Create(APackage: TPasPackage; AEngine: TFPDocEngine);
  583. begin
  584. FUseFlatStructure:= False;
  585. FShowSourceInfo:= False;
  586. inherited Create(APackage, AEngine);
  587. end;
  588. class procedure TXMLWriter.Usage(List: TStrings);
  589. begin
  590. List.AddStrings(['--source-info', SXMLUsageSource]);
  591. List.AddStrings(['--flat-structure', SXMLUsageFlatStructure]);
  592. end;
  593. function TXMLWriter.InterPretOption(const Cmd, Arg: String): boolean;
  594. begin
  595. Result := True;
  596. if Cmd = '--source-info' then
  597. FShowSourceInfo:=True
  598. else if Cmd = '--flat-structure' then
  599. FUseFlatStructure:=True
  600. else
  601. Result:=inherited InterPretOption(Cmd, Arg);
  602. end;
  603. initialization
  604. // Do not localize.
  605. RegisterWriter(TXMLWriter,'xml','fpdoc XML output.');
  606. finalization
  607. UnRegisterWriter('xml');
  608. end.