dw_dxml.pp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. unit dw_dXML;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. PasTree, dwriter, SysUtils;
  6. //uses DOM, PasTree, dwriter, xmlWrite, SysUtils;
  7. type
  8. { TXMLWriter }
  9. TDXMLWriter = class(TFPDocWriter)
  10. procedure WriteDoc; override;
  11. end;
  12. { TDocumentation }
  13. TDocumentation = class(TPassTreeVisitor)
  14. f: Text;
  15. lvl: integer;
  16. procedure GenerateDoc(OutputName: string; Module: TPasModule);
  17. procedure DocParameters(obj: TPasProcedureType);
  18. function DocProcFlags(obj: TPasProcedure): string;
  19. procedure Visit(obj: TPasElement); override;
  20. procedure DoVisit(obj: TPasSection); virtual;
  21. procedure DoVisit(obj: TPasRecordType); virtual;
  22. procedure DoVisit(obj: TPasEnumType); virtual;
  23. procedure DoVisit(obj: TPasProperty); virtual;
  24. procedure DoVisit(obj: TPasConst); virtual;
  25. procedure DoVisit(obj: TPasVariable); virtual;
  26. procedure DoVisit(obj: TPasProcedure); virtual;
  27. procedure DoVisit(obj: TPasDestructor); virtual;
  28. procedure DoVisit(obj: TPasConstructor); virtual;
  29. procedure DoVisit(obj: TPasFunction); virtual;
  30. procedure DoVisit(obj: TPasClassType); virtual;
  31. procedure DoVisit(obj: TPasElement); virtual;
  32. procedure DoVisit(obj: TPasOverloadedProc); virtual;
  33. procedure DoVisit(obj: TPasPointerType); virtual;
  34. procedure DoVisit(obj: TPasArrayType); virtual;
  35. procedure DoVisit(obj: TPasProcedureType); virtual;
  36. procedure DoVisit(obj: TPasFunctionType); virtual;
  37. procedure DoVisit(obj: TPasResString); virtual;
  38. end;
  39. implementation
  40. function EscapeXml(const s: string): string;
  41. begin
  42. Result := StringReplace(s, '&', '&', [rfReplaceAll]);
  43. Result := StringReplace(Result, '<', '&lt;', [rfReplaceAll]);
  44. Result := StringReplace(Result, '>', '&gt;', [rfReplaceAll]);
  45. end;
  46. { TDocumentation }
  47. procedure TDocumentation.Visit(obj: TPasElement);
  48. begin
  49. If (Obj.ClassType=TPasSection) then
  50. DoVisit(TPasSection(Obj))
  51. else if (Obj.ClassType=TPasRecordType) then
  52. DoVisit(TPasRecordType(Obj))
  53. else if (Obj.ClassType=TPasEnumType) then
  54. DoVisit(TPasEnumType(Obj))
  55. else if (Obj.ClassType=TPasProperty) then
  56. DoVisit(TPasProperty(Obj))
  57. else if (Obj.ClassType=TPasConst) then
  58. DoVisit(TPasConst(Obj))
  59. else if (Obj.ClassType=TPasVariable) then
  60. DoVisit(TPasVariable(Obj))
  61. else if (Obj.ClassType=TPasProcedure) then
  62. DoVisit(TPasProcedure(Obj))
  63. else if (Obj.ClassType=TPasDestructor) then
  64. DoVisit(TPasDestructor(Obj))
  65. else if (Obj.ClassType=TPasConstructor) then
  66. DoVisit(TPasConstructor(Obj))
  67. else if (Obj.ClassType=TPasFunction) then
  68. DoVisit(TPasFunction(Obj))
  69. else if (Obj.ClassType=TPasClassType) then
  70. DoVisit(TPasClassType(Obj))
  71. else if (Obj.ClassType=TPasOverloadedProc) then
  72. DoVisit(TPasOverloadedProc(Obj))
  73. else if (Obj.ClassType=TPasPointerType) then
  74. DoVisit(TPasPointerType(Obj))
  75. else if (Obj.ClassType=TPasArrayType) then
  76. DoVisit(TPasArrayType(Obj))
  77. else if (Obj.ClassType=TPasProcedureType) then
  78. DoVisit(TPasProcedureType(Obj))
  79. else if (Obj.ClassType=TPasFunctionType) then
  80. DoVisit(TPasFunctionType(Obj))
  81. else if (Obj.ClassType=TPasResString) then
  82. DoVisit(TPasResString(Obj));
  83. end;
  84. procedure TDocumentation.GenerateDoc(OutputName: string; Module: TPasModule);
  85. begin
  86. lvl := 0;
  87. Assign(f, OutputName);
  88. Rewrite(f);
  89. WriteLn(f, '<?xml version="1.0" encoding="utf-8"?>');
  90. WriteLn(f, '<namespace name="', Module.Name, '">');
  91. Module.InterfaceSection.Accept(Self);
  92. //Module.Accept(Self);
  93. WriteLn(f, '</namespace>');
  94. Close(f);
  95. end;
  96. procedure TDocumentation.DocParameters(obj: TPasProcedureType);
  97. var
  98. I: integer;
  99. begin
  100. for I := 0 to obj.Args.Count - 1 do
  101. begin
  102. Write(f, ' ': lvl * 2, '<parameter name="' + TPasArgument(obj.Args[i]).Name + '"');
  103. if TPasArgument(obj.Args[i]).ArgType <> nil then
  104. Write(f, ' type="' + TPasArgument(obj.Args[i]).ArgType.Name + '"');
  105. if TPasArgument(obj.Args[i]).Access <> argDefault then
  106. if (TPasArgument(obj.Args[i]).ArgType is TPasClassType) then
  107. Write(f, ' paramflags="' + 'var' + '"')
  108. else
  109. Write(f, ' paramflags="' +
  110. Trim(AccessNames[TPasArgument(obj.Args[i]).Access]) + '"');
  111. if TPasArgument(obj.Args[i]).Value <> '' then
  112. begin
  113. WriteLn(f, '>');
  114. WriteLn(f, ' ': lvl * 2 + 2, '<value>');
  115. WriteLn(f, ' ': lvl * 2 + 4, EscapeXml(TPasArgument(obj.Args[i]).Value));
  116. WriteLn(f, ' ': lvl * 2 + 2, '</value>');
  117. WriteLn(f, ' ': lvl * 2, '</parameter>');
  118. end
  119. else
  120. WriteLn(f, ' />');
  121. end;
  122. end;
  123. function TDocumentation.DocProcFlags(obj: TPasProcedure): string;
  124. procedure DoAdd(B: boolean; S: string);
  125. begin
  126. if B then
  127. begin
  128. if Result <> '' then
  129. Result := Result + ' ';
  130. Result := Result + S;
  131. end;
  132. end;
  133. begin
  134. Result := '';
  135. DoAdd(obj.IsAbstract, 'abstract');
  136. Doadd(obj.IsVirtual, 'virtual');
  137. DoAdd(obj.IsDynamic, 'dynamic');
  138. DoAdd(obj.IsOverride, 'override');
  139. DoAdd(obj.IsOverload, 'overload');
  140. DoAdd(obj.IsReintroduced, 'reintroduce');
  141. DoAdd(obj.IsStatic, 'static');
  142. DoAdd(obj.IsMessage, 'message');
  143. end;
  144. procedure TDocumentation.DoVisit(obj: TPasSection);
  145. var
  146. i: integer;
  147. begin
  148. Inc(lvl);
  149. for i := 0 to obj.Declarations.Count - 1 do
  150. TPasElement(obj.Declarations[i]).Accept(Self);
  151. Dec(lvl);
  152. end;
  153. procedure TDocumentation.DoVisit(obj: TPasRecordType);
  154. var
  155. I: integer;
  156. begin
  157. Write(f, StringOfChar(' ', lvl * 2) + '<struct');
  158. if obj.Name <> '' then
  159. Write(f, ' name="' + obj.Name + '"');
  160. if obj.IsPacked then
  161. Write(f, ' packed="true"');
  162. WriteLn(f, '>');
  163. Inc(lvl);
  164. for I := 0 to obj.Members.Count - 1 do
  165. TPasVariable(obj.Members[i]).Accept(Self);
  166. Dec(lvl);
  167. WriteLn(f, StringOfChar(' ', lvl * 2) + '</struct>');
  168. end;
  169. procedure TDocumentation.DoVisit(obj: TPasEnumType);
  170. var
  171. I: integer;
  172. begin
  173. for I := 0 to obj.Values.Count - 1 do
  174. begin
  175. WriteLn(f, ' ': lvl * 2, '<const name="' + TPasEnumValue(obj.Values[i]).Name + '" type="' +
  176. obj.Name + '">');
  177. WriteLn(f, ' ': lvl * 2 + 2, '<value>');
  178. WriteLn(f, ' ': lvl * 2 + 4, TPasEnumValue(obj.Values[i]).Name);
  179. WriteLn(f, ' ': lvl * 2 + 2, '</value>');
  180. WriteLn(f, ' ': lvl * 2, '</const>');
  181. end;
  182. WriteLn(f, ' ': lvl * 2, '<enum name="' + obj.Name + '">');
  183. for I := 0 to obj.Values.Count - 1 do
  184. WriteLn(f, ' ': lvl * 2 + 2, '<element name="' + TPasEnumValue(obj.Values[i]).Name + '" />');
  185. WriteLn(f, ' ': lvl * 2, '</enum>');
  186. end;
  187. procedure TDocumentation.DoVisit(obj: TPasProperty);
  188. begin
  189. if (obj.VarType <> nil) and (obj.VarType is TPasProcedureType) and
  190. (TPasProcedureType(obj.VarType).IsOfObject) then
  191. Write(f, ' ': lvl * 2, '<event name="' + obj.Name + '" visibility="' +
  192. VisibilityNames[obj.Visibility] + '"')
  193. else
  194. Write(f, ' ': lvl * 2, '<property name="' + obj.Name + '" visibility="' +
  195. VisibilityNames[obj.Visibility] + '"');
  196. if obj.ReadAccessorName <> '' then
  197. Write(f, ' read="' + obj.ReadAccessorName + '"');
  198. if obj.WriteAccessorName <> '' then
  199. Write(f, ' write="' + obj.WriteAccessorName + '"');
  200. if obj.VarType <> nil then
  201. Write(f, ' type="' + obj.VarType.Name + '"');
  202. if obj.DefaultValue <> '' then
  203. Write(f, ' default="' + obj.DefaultValue + '"');
  204. WriteLn(f, ' />');
  205. end;
  206. procedure TDocumentation.DoVisit(obj: TPasConst);
  207. begin
  208. Write(f, ' ': lvl * 2, '<const name="' + obj.Name + '"');
  209. if (obj.VarType <> nil) and (obj.VarType.Name <> '') then
  210. Write(f, ' type="' + obj.VarType.Name + '"');
  211. WriteLn(f, '>');
  212. WriteLn(f, ' ': lvl * 2 + 2, '<value>');
  213. WriteLn(f, ' ': lvl * 2 + 4, EscapeXml(obj.Value));
  214. WriteLn(f, ' ': lvl * 2 + 2, '</value>');
  215. WriteLn(f, ' ': lvl * 2, '</const>');
  216. end;
  217. procedure TDocumentation.DoVisit(obj: TPasVariable);
  218. begin
  219. Write(f, ' ': lvl * 2, '<field name="' + obj.Name + '"');
  220. if (obj.VarType <> nil) and (obj.VarType.Name <> '') then
  221. Write(f, ' type="' + obj.VarType.Name {.GetDeclaration(True)} + '"');
  222. if obj.Visibility <> visDefault then
  223. Write(f, ' visibility="' + VisibilityNames[obj.Visibility] + '"');
  224. if (obj.VarType <> nil) and (obj.VarType.Name = '')
  225. {(VarType.ElementTypeName <> SPasTreeType) and (VarType.ElementTypeName <> SPasTreeUnresolvedTypeRef)}
  226. then
  227. begin
  228. WriteLn(f, '>');
  229. Inc(lvl);
  230. obj.VarType.Accept(Self);
  231. Dec(lvl);
  232. WriteLn(f, ' ': lvl * 2, '</field>');
  233. end
  234. else
  235. WriteLn(f, ' />');
  236. end;
  237. procedure TDocumentation.DoVisit(obj: TPasProcedure);
  238. var
  239. t: string;
  240. begin
  241. Write(f, ' ': lvl * 2, '<procedure name="' + obj.Name + '"');
  242. if obj.Visibility <> visDefault then
  243. Write(f, ' visibility="' + VisibilityNames[obj.Visibility] + '"');
  244. t := DocProcFlags(obj);
  245. if t <> '' then
  246. Write(f, ' procflags="' + t + '"');
  247. WriteLn(f, '>');
  248. Inc(lvl);
  249. if obj.ProcType.Args.Count > 0 then
  250. begin
  251. WriteLn(f, ' ': lvl * 2, '<parameters>');
  252. Inc(lvl);
  253. DocParameters(obj.ProcType);
  254. Dec(lvl);
  255. WriteLn(f, ' ': lvl * 2, '</parameters>');
  256. end;
  257. Dec(lvl);
  258. WriteLn(f, ' ': lvl * 2, '</procedure>');
  259. end;
  260. procedure TDocumentation.DoVisit(obj: TPasDestructor);
  261. begin
  262. Write(f, ' ': lvl * 2, '<destructor name="' + obj.Name + '"');
  263. if obj.Visibility <> visDefault then
  264. Write(f, ' visibility="' + VisibilityNames[obj.Visibility] + '"');
  265. WriteLn(f, '>');
  266. Inc(lvl);
  267. WriteLn(f, ' ': lvl * 2, '<parameters>');
  268. Inc(lvl);
  269. DocParameters(obj.ProcType);
  270. Dec(lvl);
  271. WriteLn(f, ' ': lvl * 2, '</parameters>');
  272. Dec(lvl);
  273. WriteLn(f, ' ': lvl * 2, '</destructor>');
  274. end;
  275. procedure TDocumentation.DoVisit(obj: TPasConstructor);
  276. begin
  277. Write(f, ' ': lvl * 2, '<constructor name="' + obj.Name + '"');
  278. if obj.Visibility <> visDefault then
  279. Write(f, ' visibility="' + VisibilityNames[obj.Visibility] + '"');
  280. WriteLn(f, '>');
  281. Inc(lvl);
  282. WriteLn(f, ' ': lvl * 2, '<parameters>');
  283. Inc(lvl);
  284. DocParameters(obj.ProcType);
  285. Dec(lvl);
  286. WriteLn(f, ' ': lvl * 2, '</parameters>');
  287. Dec(lvl);
  288. WriteLn(f, ' ': lvl * 2, '</constructor>');
  289. end;
  290. procedure TDocumentation.DoVisit(obj: TPasFunction);
  291. var
  292. t: string;
  293. begin
  294. Write(f, ' ': lvl * 2, '<function name="' + obj.Name + '"');
  295. if obj.Visibility <> visDefault then
  296. Write(f, ' visibility="' + VisibilityNames[obj.Visibility] + '"');
  297. t := DocProcFlags(obj);
  298. if t <> '' then
  299. Write(f, ' procflags="' + t + '"');
  300. WriteLn(f, '>');
  301. Inc(lvl);
  302. WriteLn(f, ' ': lvl * 2, '<parameters>');
  303. Inc(lvl);
  304. DocParameters(obj.ProcType);
  305. WriteLn(f, ' ': lvl * 2, '<retval type="' +
  306. TPasFunctionType(obj.ProcType).ResultEl.ResultType.Name + '" />');
  307. Dec(lvl);
  308. WriteLn(f, ' ': lvl * 2, '</parameters>');
  309. Dec(lvl);
  310. WriteLn(f, ' ': lvl * 2, '</function>');
  311. end;
  312. procedure TDocumentation.DoVisit(obj: TPasClassType);
  313. var
  314. i: integer;
  315. begin
  316. case obj.ObjKind of
  317. okObject: WriteLn(f, ' ': lvl * 2, '<object name="' + obj.Name + '">');
  318. okClass: WriteLn(f, ' ': lvl * 2, '<class name="' + obj.Name + '">');
  319. okInterface: WriteLn(f, ' ': lvl * 2, '<interface name="' + obj.Name + '">');
  320. end;
  321. Inc(lvl);
  322. if obj.AncestorType <> nil then
  323. WriteLn(f, ' ': lvl * 2, '<ancestor name="' + obj.AncestorType.GetDeclaration(True) +
  324. '" namespace="StdCtrls2">')
  325. else
  326. WriteLn(f, ' ': lvl * 2, '<ancestor name="TObject" namespace="System">');
  327. WriteLn(f, ' ': lvl * 2, '</ancestor>');
  328. if obj.Members.Count > 0 then
  329. begin
  330. WriteLn(f, ' ': lvl * 2, '<members>');
  331. Inc(lvl);
  332. for i := 0 to obj.Members.Count - 1 do
  333. TPasProperty(obj.Members[i]).Accept(Self);
  334. Dec(lvl);
  335. WriteLn(f, ' ': lvl * 2, '</members>');
  336. end;
  337. Dec(lvl);
  338. case obj.ObjKind of
  339. okObject: WriteLn(f, ' ': lvl * 2, '</object>');
  340. okClass: WriteLn(f, ' ': lvl * 2, '</class>');
  341. okInterface: WriteLn(f, ' ': lvl * 2, '</interface>');
  342. end;
  343. end;
  344. procedure TDocumentation.DoVisit(obj: TPasElement);
  345. begin
  346. WriteLn('Warning: NOT supported: ' + obj.ClassName + ' (' + obj.Name + ')');
  347. end;
  348. procedure TDocumentation.DoVisit(obj: TPasOverloadedProc);
  349. var
  350. i: integer;
  351. begin
  352. for i := 0 to obj.Overloads.Count - 1 do
  353. TPasProcedure(obj.Overloads[i]).Accept(Self);
  354. end;
  355. procedure TDocumentation.DoVisit(obj: TPasPointerType);
  356. begin
  357. Write(f, ' ': lvl * 2, '<pointer name="' + obj.Name + '"');
  358. if obj.DestType <> nil then
  359. Write(f, ' type="' + obj.DestType.Name + '"');
  360. WriteLn(f, ' indircnt="1" />');
  361. end;
  362. procedure TDocumentation.DoVisit(obj: TPasArrayType);
  363. begin
  364. Write(f, ' ': lvl * 2, '<array name="' + obj.Name + '"');
  365. if obj.IndexRange <> '' then
  366. begin
  367. if Pos('..', obj.IndexRange) <> 0 then
  368. begin
  369. Write(f, ' low="' + Copy(obj.IndexRange, 1, Pos('..', obj.IndexRange) - 1) + '"');
  370. Write(f, ' high="' + Copy(obj.IndexRange, Pos('..', obj.IndexRange) + 2,
  371. MaxInt) + '"');
  372. end
  373. else
  374. Write(f, ' high="' + obj.IndexRange + '"');
  375. end;
  376. WriteLn(f, '>');
  377. WriteLn(f, ' <element type="' + obj.ElType.Name + '" />');
  378. WriteLn(f, ' </array>');
  379. end;
  380. procedure TDocumentation.DoVisit(obj: TPasProcedureType);
  381. begin
  382. Write(f, ' ': lvl * 2, '<procedureDef name="' + obj.Name + '"');
  383. if obj.Visibility <> visDefault then
  384. Write(f, ' visibility="' + VisibilityNames[obj.Visibility] + '"');
  385. WriteLn(f, '>');
  386. if obj.Args.Count > 0 then
  387. begin
  388. WriteLn(f, ' ': lvl * 2 + 2, '<parameters>');
  389. DocParameters(obj);
  390. WriteLn(f, ' ': lvl * 2 + 2, '</parameters>');
  391. end;
  392. WriteLn(f, ' ': lvl * 2, '</procedureDef>');
  393. end;
  394. procedure TDocumentation.DoVisit(obj: TPasFunctionType);
  395. begin
  396. Write(f, ' ': lvl * 2, '<functionDef name="' + obj.Name + '"');
  397. if obj.Visibility <> visDefault then
  398. Write(f, ' visibility="' + VisibilityNames[obj.Visibility] + '"');
  399. WriteLn(f, '>');
  400. WriteLn(f, ' ': lvl * 2 + 2, '<parameters>');
  401. DocParameters(obj);
  402. WriteLn(f, ' ': lvl * 2 + 4, '<retval type="' + obj.ResultEl.ResultType.Name + '" />');
  403. WriteLn(f, ' ': lvl * 2 + 2, '</parameters>');
  404. WriteLn(f, ' ': lvl * 2, '</functionDef>');
  405. end;
  406. procedure TDocumentation.DoVisit(obj: TPasResString);
  407. begin
  408. WriteLn(f, ' ': lvl * 2, '<resourceString name="' + obj.Name + '">');
  409. WriteLn(f, ' ': lvl * 2 + 2, '<value>');
  410. WriteLn(f, ' ': lvl * 2 + 4, EscapeXml(obj.GetDeclaration(false)));
  411. WriteLn(f, ' ': lvl * 2 + 2, '</value>');
  412. WriteLn(f, ' ': lvl * 2, '</resourceString>');
  413. end;
  414. { TXMLWriter }
  415. procedure TDXMLWriter.WriteDoc;
  416. var
  417. i: integer;
  418. begin
  419. if Engine.Output <> '' then
  420. Engine.Output := IncludeTrailingBackSlash(Engine.Output);
  421. for i := 0 to Package.Modules.Count - 1 do
  422. begin
  423. with TDocumentation.Create do
  424. begin
  425. GenerateDoc(Engine.Output + TPasModule(Package.Modules[i]).Name +
  426. '.xml', TPasModule(Package.Modules[i]));
  427. Free;
  428. end;
  429. end;
  430. end;
  431. initialization
  432. // Do not localize.
  433. RegisterWriter(TDXMLWriter, 'dxml', 'fpdoc Delphi XML output.');
  434. finalization
  435. UnRegisterWriter('dxml');
  436. end.