dw_xml.pp 18 KB

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