gobject-introspection 2.2.4-x64-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (294) hide show
  1. checksums.yaml +7 -0
  2. data/Rakefile +129 -0
  3. data/ext/gobject-introspection/depend +10 -0
  4. data/ext/gobject-introspection/extconf.rb +94 -0
  5. data/ext/gobject-introspection/gobject_introspection.def +5 -0
  6. data/ext/gobject-introspection/rb-gi-arg-info.c +151 -0
  7. data/ext/gobject-introspection/rb-gi-argument.c +2053 -0
  8. data/ext/gobject-introspection/rb-gi-base-info.c +218 -0
  9. data/ext/gobject-introspection/rb-gi-boxed-info.c +48 -0
  10. data/ext/gobject-introspection/rb-gi-callable-info.c +104 -0
  11. data/ext/gobject-introspection/rb-gi-callback-info.c +48 -0
  12. data/ext/gobject-introspection/rb-gi-constant-info.c +77 -0
  13. data/ext/gobject-introspection/rb-gi-constructor-info.c +133 -0
  14. data/ext/gobject-introspection/rb-gi-conversions.h +145 -0
  15. data/ext/gobject-introspection/rb-gi-enum-info.c +155 -0
  16. data/ext/gobject-introspection/rb-gi-field-info.c +153 -0
  17. data/ext/gobject-introspection/rb-gi-flags-info.c +48 -0
  18. data/ext/gobject-introspection/rb-gi-function-info.c +841 -0
  19. data/ext/gobject-introspection/rb-gi-interface-info.c +222 -0
  20. data/ext/gobject-introspection/rb-gi-loader.c +224 -0
  21. data/ext/gobject-introspection/rb-gi-method-info.c +83 -0
  22. data/ext/gobject-introspection/rb-gi-object-info.c +345 -0
  23. data/ext/gobject-introspection/rb-gi-private.h +105 -0
  24. data/ext/gobject-introspection/rb-gi-property-info.c +77 -0
  25. data/ext/gobject-introspection/rb-gi-registered-type-info.c +86 -0
  26. data/ext/gobject-introspection/rb-gi-repository.c +246 -0
  27. data/ext/gobject-introspection/rb-gi-signal-info.c +77 -0
  28. data/ext/gobject-introspection/rb-gi-struct-info.c +202 -0
  29. data/ext/gobject-introspection/rb-gi-type-info.c +143 -0
  30. data/ext/gobject-introspection/rb-gi-type-tag.c +43 -0
  31. data/ext/gobject-introspection/rb-gi-types.h +71 -0
  32. data/ext/gobject-introspection/rb-gi-union-info.c +206 -0
  33. data/ext/gobject-introspection/rb-gi-unresolved-info.c +48 -0
  34. data/ext/gobject-introspection/rb-gi-value-info.c +57 -0
  35. data/ext/gobject-introspection/rb-gi-vfunc-info.c +91 -0
  36. data/ext/gobject-introspection/rb-gobject-introspection.c +44 -0
  37. data/ext/gobject-introspection/rb-gobject-introspection.h +60 -0
  38. data/extconf.rb +71 -0
  39. data/lib/2.0/gobject_introspection.so +0 -0
  40. data/lib/2.1/gobject_introspection.so +0 -0
  41. data/lib/2.2/gobject_introspection.so +0 -0
  42. data/lib/gobject-introspection.rb +53 -0
  43. data/lib/gobject-introspection/boxed-info.rb +28 -0
  44. data/lib/gobject-introspection/callable-info.rb +100 -0
  45. data/lib/gobject-introspection/collection-reader.rb +34 -0
  46. data/lib/gobject-introspection/interface-info.rb +32 -0
  47. data/lib/gobject-introspection/loader.rb +465 -0
  48. data/lib/gobject-introspection/object-info.rb +33 -0
  49. data/lib/gobject-introspection/repository.rb +32 -0
  50. data/lib/gobject-introspection/struct-info.rb +28 -0
  51. data/lib/gobject-introspection/union-info.rb +28 -0
  52. data/test/gobject-introspection-test-utils.rb +26 -0
  53. data/test/run-test.rb +45 -0
  54. data/test/test-arg-info.rb +68 -0
  55. data/test/test-base-info.rb +31 -0
  56. data/test/test-boxed-info.rb +21 -0
  57. data/test/test-callable-info.rb +49 -0
  58. data/test/test-callback-info.rb +29 -0
  59. data/test/test-constant-info.rb +24 -0
  60. data/test/test-enum-info.rb +61 -0
  61. data/test/test-field-type.rb +42 -0
  62. data/test/test-flags-info.rb +27 -0
  63. data/test/test-function-info.rb +39 -0
  64. data/test/test-interface-info.rb +97 -0
  65. data/test/test-loader.rb +30 -0
  66. data/test/test-object-info.rb +131 -0
  67. data/test/test-property-info.rb +38 -0
  68. data/test/test-registered-type-info.rb +35 -0
  69. data/test/test-repository.rb +62 -0
  70. data/test/test-signal-info.rb +40 -0
  71. data/test/test-struct-info.rb +57 -0
  72. data/test/test-type-info.rb +62 -0
  73. data/test/test-type-tag.rb +29 -0
  74. data/test/test-union-info.rb +21 -0
  75. data/test/test-value-info.rb +28 -0
  76. data/test/test-vfunc-info.rb +42 -0
  77. data/vendor/local/bin/g-ir-compiler.exe +0 -0
  78. data/vendor/local/bin/g-ir-generate.exe +0 -0
  79. data/vendor/local/bin/libgirepository-1.0-1.dll +0 -0
  80. data/vendor/local/include/gobject-introspection-1.0/giarginfo.h +82 -0
  81. data/vendor/local/include/gobject-introspection-1.0/gibaseinfo.h +120 -0
  82. data/vendor/local/include/gobject-introspection-1.0/gicallableinfo.h +110 -0
  83. data/vendor/local/include/gobject-introspection-1.0/giconstantinfo.h +58 -0
  84. data/vendor/local/include/gobject-introspection-1.0/gienuminfo.h +82 -0
  85. data/vendor/local/include/gobject-introspection-1.0/gifieldinfo.h +71 -0
  86. data/vendor/local/include/gobject-introspection-1.0/gifunctioninfo.h +100 -0
  87. data/vendor/local/include/gobject-introspection-1.0/giinterfaceinfo.h +106 -0
  88. data/vendor/local/include/gobject-introspection-1.0/giobjectinfo.h +207 -0
  89. data/vendor/local/include/gobject-introspection-1.0/gipropertyinfo.h +56 -0
  90. data/vendor/local/include/gobject-introspection-1.0/giregisteredtypeinfo.h +64 -0
  91. data/vendor/local/include/gobject-introspection-1.0/girepository.h +239 -0
  92. data/vendor/local/include/gobject-introspection-1.0/girffi.h +104 -0
  93. data/vendor/local/include/gobject-introspection-1.0/gisignalinfo.h +57 -0
  94. data/vendor/local/include/gobject-introspection-1.0/gistructinfo.h +77 -0
  95. data/vendor/local/include/gobject-introspection-1.0/gitypeinfo.h +87 -0
  96. data/vendor/local/include/gobject-introspection-1.0/gitypelib.h +80 -0
  97. data/vendor/local/include/gobject-introspection-1.0/gitypes.h +524 -0
  98. data/vendor/local/include/gobject-introspection-1.0/giunioninfo.h +84 -0
  99. data/vendor/local/include/gobject-introspection-1.0/giversionmacros.h +128 -0
  100. data/vendor/local/include/gobject-introspection-1.0/givfuncinfo.h +73 -0
  101. data/vendor/local/lib/girepository-1.0/DBus-1.0.typelib +0 -0
  102. data/vendor/local/lib/girepository-1.0/DBusGLib-1.0.typelib +0 -0
  103. data/vendor/local/lib/girepository-1.0/GIRepository-2.0.typelib +0 -0
  104. data/vendor/local/lib/girepository-1.0/GL-1.0.typelib +0 -0
  105. data/vendor/local/lib/girepository-1.0/GLib-2.0.typelib +0 -0
  106. data/vendor/local/lib/girepository-1.0/GModule-2.0.typelib +0 -0
  107. data/vendor/local/lib/girepository-1.0/GObject-2.0.typelib +0 -0
  108. data/vendor/local/lib/girepository-1.0/Gio-2.0.typelib +0 -0
  109. data/vendor/local/lib/girepository-1.0/cairo-1.0.typelib +0 -0
  110. data/vendor/local/lib/girepository-1.0/fontconfig-2.0.typelib +0 -0
  111. data/vendor/local/lib/girepository-1.0/freetype2-2.0.typelib +0 -0
  112. data/vendor/local/lib/girepository-1.0/libxml2-2.0.typelib +0 -0
  113. data/vendor/local/lib/girepository-1.0/win32-1.0.typelib +0 -0
  114. data/vendor/local/lib/girepository-1.0/xfixes-4.0.typelib +0 -0
  115. data/vendor/local/lib/girepository-1.0/xft-2.0.typelib +0 -0
  116. data/vendor/local/lib/girepository-1.0/xlib-2.0.typelib +0 -0
  117. data/vendor/local/lib/girepository-1.0/xrandr-1.3.typelib +0 -0
  118. data/vendor/local/lib/gobject-introspection/giscanner/__init__.py +24 -0
  119. data/vendor/local/lib/gobject-introspection/giscanner/__init__.pyc +0 -0
  120. data/vendor/local/lib/gobject-introspection/giscanner/__init__.pyo +0 -0
  121. data/vendor/local/lib/gobject-introspection/giscanner/annotationmain.py +76 -0
  122. data/vendor/local/lib/gobject-introspection/giscanner/annotationmain.pyc +0 -0
  123. data/vendor/local/lib/gobject-introspection/giscanner/annotationmain.pyo +0 -0
  124. data/vendor/local/lib/gobject-introspection/giscanner/annotationparser.py +2161 -0
  125. data/vendor/local/lib/gobject-introspection/giscanner/annotationparser.pyc +0 -0
  126. data/vendor/local/lib/gobject-introspection/giscanner/annotationparser.pyo +0 -0
  127. data/vendor/local/lib/gobject-introspection/giscanner/ast.py +1139 -0
  128. data/vendor/local/lib/gobject-introspection/giscanner/ast.pyc +0 -0
  129. data/vendor/local/lib/gobject-introspection/giscanner/ast.pyo +0 -0
  130. data/vendor/local/lib/gobject-introspection/giscanner/cachestore.py +203 -0
  131. data/vendor/local/lib/gobject-introspection/giscanner/cachestore.pyc +0 -0
  132. data/vendor/local/lib/gobject-introspection/giscanner/cachestore.pyo +0 -0
  133. data/vendor/local/lib/gobject-introspection/giscanner/ccompiler.py +202 -0
  134. data/vendor/local/lib/gobject-introspection/giscanner/ccompiler.pyc +0 -0
  135. data/vendor/local/lib/gobject-introspection/giscanner/ccompiler.pyo +0 -0
  136. data/vendor/local/lib/gobject-introspection/giscanner/codegen.py +173 -0
  137. data/vendor/local/lib/gobject-introspection/giscanner/codegen.pyc +0 -0
  138. data/vendor/local/lib/gobject-introspection/giscanner/codegen.pyo +0 -0
  139. data/vendor/local/lib/gobject-introspection/giscanner/collections/__init__.py +23 -0
  140. data/vendor/local/lib/gobject-introspection/giscanner/collections/__init__.pyc +0 -0
  141. data/vendor/local/lib/gobject-introspection/giscanner/collections/__init__.pyo +0 -0
  142. data/vendor/local/lib/gobject-introspection/giscanner/collections/counter.py +305 -0
  143. data/vendor/local/lib/gobject-introspection/giscanner/collections/counter.pyc +0 -0
  144. data/vendor/local/lib/gobject-introspection/giscanner/collections/counter.pyo +0 -0
  145. data/vendor/local/lib/gobject-introspection/giscanner/collections/ordereddict.py +120 -0
  146. data/vendor/local/lib/gobject-introspection/giscanner/collections/ordereddict.pyc +0 -0
  147. data/vendor/local/lib/gobject-introspection/giscanner/collections/ordereddict.pyo +0 -0
  148. data/vendor/local/lib/gobject-introspection/giscanner/docmain.py +72 -0
  149. data/vendor/local/lib/gobject-introspection/giscanner/docmain.pyc +0 -0
  150. data/vendor/local/lib/gobject-introspection/giscanner/docmain.pyo +0 -0
  151. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/C/callback.tmpl +4 -0
  152. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/C/class.tmpl +2 -0
  153. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/C/constructor.tmpl +1 -0
  154. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/C/default.tmpl +1 -0
  155. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/C/enum.tmpl +2 -0
  156. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/C/field.tmpl +1 -0
  157. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/C/function.tmpl +60 -0
  158. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/C/interface.tmpl +2 -0
  159. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/C/method.tmpl +1 -0
  160. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/C/namespace.tmpl +1 -0
  161. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/C/property.tmpl +5 -0
  162. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/C/record.tmpl +1 -0
  163. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/C/signal.tmpl +5 -0
  164. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/C/vfunc.tmpl +4 -0
  165. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/Gjs/callback.tmpl +27 -0
  166. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/Gjs/class.tmpl +30 -0
  167. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/Gjs/constructor.tmpl +1 -0
  168. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/Gjs/default.tmpl +1 -0
  169. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/Gjs/enum.tmpl +21 -0
  170. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/Gjs/field.tmpl +9 -0
  171. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/Gjs/function.tmpl +47 -0
  172. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/Gjs/interface.tmpl +17 -0
  173. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/Gjs/method.tmpl +1 -0
  174. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/Gjs/namespace.tmpl +2 -0
  175. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/Gjs/property.tmpl +9 -0
  176. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/Gjs/record.tmpl +2 -0
  177. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/Gjs/signal.tmpl +38 -0
  178. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/Gjs/vfunc.tmpl +27 -0
  179. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/Python/callback.tmpl +27 -0
  180. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/Python/class.tmpl +18 -0
  181. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/Python/constructor.tmpl +1 -0
  182. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/Python/default.tmpl +1 -0
  183. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/Python/enum.tmpl +13 -0
  184. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/Python/field.tmpl +1 -0
  185. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/Python/function.tmpl +47 -0
  186. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/Python/interface.tmpl +16 -0
  187. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/Python/method.tmpl +1 -0
  188. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/Python/namespace.tmpl +2 -0
  189. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/Python/property.tmpl +9 -0
  190. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/Python/record.tmpl +2 -0
  191. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/Python/signal.tmpl +41 -0
  192. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/Python/vfunc.tmpl +27 -0
  193. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/base.tmpl +20 -0
  194. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/class.tmpl +61 -0
  195. data/vendor/local/lib/gobject-introspection/giscanner/doctemplates/namespace.tmpl +16 -0
  196. data/vendor/local/lib/gobject-introspection/giscanner/docwriter.py +958 -0
  197. data/vendor/local/lib/gobject-introspection/giscanner/docwriter.pyc +0 -0
  198. data/vendor/local/lib/gobject-introspection/giscanner/docwriter.pyo +0 -0
  199. data/vendor/local/lib/gobject-introspection/giscanner/dumper.py +338 -0
  200. data/vendor/local/lib/gobject-introspection/giscanner/dumper.pyc +0 -0
  201. data/vendor/local/lib/gobject-introspection/giscanner/dumper.pyo +0 -0
  202. data/vendor/local/lib/gobject-introspection/giscanner/gdumpparser.py +529 -0
  203. data/vendor/local/lib/gobject-introspection/giscanner/gdumpparser.pyc +0 -0
  204. data/vendor/local/lib/gobject-introspection/giscanner/gdumpparser.pyo +0 -0
  205. data/vendor/local/lib/gobject-introspection/giscanner/girparser.py +593 -0
  206. data/vendor/local/lib/gobject-introspection/giscanner/girparser.pyc +0 -0
  207. data/vendor/local/lib/gobject-introspection/giscanner/girparser.pyo +0 -0
  208. data/vendor/local/lib/gobject-introspection/giscanner/girwriter.py +612 -0
  209. data/vendor/local/lib/gobject-introspection/giscanner/girwriter.pyc +0 -0
  210. data/vendor/local/lib/gobject-introspection/giscanner/girwriter.pyo +0 -0
  211. data/vendor/local/lib/gobject-introspection/giscanner/introspectablepass.py +240 -0
  212. data/vendor/local/lib/gobject-introspection/giscanner/introspectablepass.pyc +0 -0
  213. data/vendor/local/lib/gobject-introspection/giscanner/introspectablepass.pyo +0 -0
  214. data/vendor/local/lib/gobject-introspection/giscanner/libtoolimporter.py +76 -0
  215. data/vendor/local/lib/gobject-introspection/giscanner/libtoolimporter.pyc +0 -0
  216. data/vendor/local/lib/gobject-introspection/giscanner/libtoolimporter.pyo +0 -0
  217. data/vendor/local/lib/gobject-introspection/giscanner/maintransformer.py +1366 -0
  218. data/vendor/local/lib/gobject-introspection/giscanner/maintransformer.pyc +0 -0
  219. data/vendor/local/lib/gobject-introspection/giscanner/maintransformer.pyo +0 -0
  220. data/vendor/local/lib/gobject-introspection/giscanner/message.py +203 -0
  221. data/vendor/local/lib/gobject-introspection/giscanner/message.pyc +0 -0
  222. data/vendor/local/lib/gobject-introspection/giscanner/message.pyo +0 -0
  223. data/vendor/local/lib/gobject-introspection/giscanner/scannermain.py +561 -0
  224. data/vendor/local/lib/gobject-introspection/giscanner/scannermain.pyc +0 -0
  225. data/vendor/local/lib/gobject-introspection/giscanner/scannermain.pyo +0 -0
  226. data/vendor/local/lib/gobject-introspection/giscanner/sectionparser.py +152 -0
  227. data/vendor/local/lib/gobject-introspection/giscanner/sectionparser.pyc +0 -0
  228. data/vendor/local/lib/gobject-introspection/giscanner/sectionparser.pyo +0 -0
  229. data/vendor/local/lib/gobject-introspection/giscanner/shlibs.py +140 -0
  230. data/vendor/local/lib/gobject-introspection/giscanner/shlibs.pyc +0 -0
  231. data/vendor/local/lib/gobject-introspection/giscanner/shlibs.pyo +0 -0
  232. data/vendor/local/lib/gobject-introspection/giscanner/sourcescanner.py +329 -0
  233. data/vendor/local/lib/gobject-introspection/giscanner/sourcescanner.pyc +0 -0
  234. data/vendor/local/lib/gobject-introspection/giscanner/sourcescanner.pyo +0 -0
  235. data/vendor/local/lib/gobject-introspection/giscanner/testcodegen.py +136 -0
  236. data/vendor/local/lib/gobject-introspection/giscanner/testcodegen.pyc +0 -0
  237. data/vendor/local/lib/gobject-introspection/giscanner/testcodegen.pyo +0 -0
  238. data/vendor/local/lib/gobject-introspection/giscanner/transformer.py +971 -0
  239. data/vendor/local/lib/gobject-introspection/giscanner/transformer.pyc +0 -0
  240. data/vendor/local/lib/gobject-introspection/giscanner/transformer.pyo +0 -0
  241. data/vendor/local/lib/gobject-introspection/giscanner/utils.py +211 -0
  242. data/vendor/local/lib/gobject-introspection/giscanner/utils.pyc +0 -0
  243. data/vendor/local/lib/gobject-introspection/giscanner/utils.pyo +0 -0
  244. data/vendor/local/lib/gobject-introspection/giscanner/xmlwriter.py +156 -0
  245. data/vendor/local/lib/gobject-introspection/giscanner/xmlwriter.pyc +0 -0
  246. data/vendor/local/lib/gobject-introspection/giscanner/xmlwriter.pyo +0 -0
  247. data/vendor/local/lib/libgirepository-1.0.a +0 -0
  248. data/vendor/local/lib/libgirepository-1.0.dll.a +0 -0
  249. data/vendor/local/lib/libgirepository-1.0.la +41 -0
  250. data/vendor/local/lib/pkgconfig/gobject-introspection-1.0.pc +26 -0
  251. data/vendor/local/lib/pkgconfig/gobject-introspection-no-export-1.0.pc +23 -0
  252. data/vendor/local/lib/pkgconfig/patched +0 -0
  253. data/vendor/local/share/aclocal/introspection.m4 +96 -0
  254. data/vendor/local/share/gir-1.0/DBus-1.0.gir +32 -0
  255. data/vendor/local/share/gir-1.0/DBusGLib-1.0.gir +18 -0
  256. data/vendor/local/share/gir-1.0/GIRepository-2.0.gir +4042 -0
  257. data/vendor/local/share/gir-1.0/GL-1.0.gir +31 -0
  258. data/vendor/local/share/gir-1.0/GLib-2.0.gir +47221 -0
  259. data/vendor/local/share/gir-1.0/GModule-2.0.gir +301 -0
  260. data/vendor/local/share/gir-1.0/GObject-2.0.gir +14733 -0
  261. data/vendor/local/share/gir-1.0/Gio-2.0.gir +82459 -0
  262. data/vendor/local/share/gir-1.0/cairo-1.0.gir +70 -0
  263. data/vendor/local/share/gir-1.0/fontconfig-2.0.gir +18 -0
  264. data/vendor/local/share/gir-1.0/freetype2-2.0.gir +22 -0
  265. data/vendor/local/share/gir-1.0/libxml2-2.0.gir +25 -0
  266. data/vendor/local/share/gir-1.0/win32-1.0.gir +19 -0
  267. data/vendor/local/share/gir-1.0/xfixes-4.0.gir +10 -0
  268. data/vendor/local/share/gir-1.0/xft-2.0.gir +23 -0
  269. data/vendor/local/share/gir-1.0/xlib-2.0.gir +67 -0
  270. data/vendor/local/share/gir-1.0/xrandr-1.3.gir +16 -0
  271. data/vendor/local/share/gobject-introspection-1.0/Makefile.introspection +166 -0
  272. data/vendor/local/share/gobject-introspection-1.0/gdump.c +569 -0
  273. data/vendor/local/share/gobject-introspection-1.0/tests/annotation.c +831 -0
  274. data/vendor/local/share/gobject-introspection-1.0/tests/annotation.h +301 -0
  275. data/vendor/local/share/gobject-introspection-1.0/tests/drawable.c +57 -0
  276. data/vendor/local/share/gobject-introspection-1.0/tests/drawable.h +44 -0
  277. data/vendor/local/share/gobject-introspection-1.0/tests/everything.c +1579 -0
  278. data/vendor/local/share/gobject-introspection-1.0/tests/everything.h +535 -0
  279. data/vendor/local/share/gobject-introspection-1.0/tests/foo.c +790 -0
  280. data/vendor/local/share/gobject-introspection-1.0/tests/foo.h +582 -0
  281. data/vendor/local/share/gobject-introspection-1.0/tests/gimarshallingtests.c +5426 -0
  282. data/vendor/local/share/gobject-introspection-1.0/tests/gimarshallingtests.h +1948 -0
  283. data/vendor/local/share/gobject-introspection-1.0/tests/gitestmacros.h +10 -0
  284. data/vendor/local/share/gobject-introspection-1.0/tests/regress.c +4068 -0
  285. data/vendor/local/share/gobject-introspection-1.0/tests/regress.h +1415 -0
  286. data/vendor/local/share/gobject-introspection-1.0/tests/utility.c +47 -0
  287. data/vendor/local/share/gobject-introspection-1.0/tests/utility.h +102 -0
  288. data/vendor/local/share/gobject-introspection-1.0/tests/warnlib.c +47 -0
  289. data/vendor/local/share/gobject-introspection-1.0/tests/warnlib.h +46 -0
  290. data/vendor/local/share/license/gobject-introspection/AUTHORS +9 -0
  291. data/vendor/local/share/license/gobject-introspection/COPYING +12 -0
  292. data/vendor/local/share/man/man1/g-ir-compiler.1 +42 -0
  293. data/vendor/local/share/man/man1/g-ir-generate.1 +29 -0
  294. metadata +363 -0
@@ -0,0 +1,84 @@
1
+ /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2
+ * GObject introspection: Union
3
+ *
4
+ * Copyright (C) 2005 Matthias Clasen
5
+ * Copyright (C) 2008,2009 Red Hat, Inc.
6
+ *
7
+ * This library is free software; you can redistribute it and/or
8
+ * modify it under the terms of the GNU Lesser General Public
9
+ * License as published by the Free Software Foundation; either
10
+ * version 2 of the License, or (at your option) any later version.
11
+ *
12
+ * This library is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ * Lesser General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU Lesser General Public
18
+ * License along with this library; if not, write to the
19
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20
+ * Boston, MA 02111-1307, USA.
21
+ */
22
+
23
+ #ifndef __GIUNIONINFO_H__
24
+ #define __GIUNIONINFO_H__
25
+
26
+ #if !defined (__GIREPOSITORY_H_INSIDE__) && !defined (GI_COMPILATION)
27
+ #error "Only <girepository.h> can be included directly."
28
+ #endif
29
+
30
+ #include <gitypes.h>
31
+
32
+ G_BEGIN_DECLS
33
+
34
+ /**
35
+ * GI_IS_UNION_INFO
36
+ * @info: an info structure
37
+ *
38
+ * Checks if @info is a #GIUnionInfo.
39
+ */
40
+ #define GI_IS_UNION_INFO(info) \
41
+ (g_base_info_get_type((GIBaseInfo*)info) == GI_INFO_TYPE_UNION)
42
+
43
+ GI_AVAILABLE_IN_ALL
44
+ gint g_union_info_get_n_fields (GIUnionInfo *info);
45
+
46
+ GI_AVAILABLE_IN_ALL
47
+ GIFieldInfo * g_union_info_get_field (GIUnionInfo *info,
48
+ gint n);
49
+
50
+ GI_AVAILABLE_IN_ALL
51
+ gint g_union_info_get_n_methods (GIUnionInfo *info);
52
+
53
+ GI_AVAILABLE_IN_ALL
54
+ GIFunctionInfo * g_union_info_get_method (GIUnionInfo *info,
55
+ gint n);
56
+
57
+ GI_AVAILABLE_IN_ALL
58
+ gboolean g_union_info_is_discriminated (GIUnionInfo *info);
59
+
60
+ GI_AVAILABLE_IN_ALL
61
+ gint g_union_info_get_discriminator_offset (GIUnionInfo *info);
62
+
63
+ GI_AVAILABLE_IN_ALL
64
+ GITypeInfo * g_union_info_get_discriminator_type (GIUnionInfo *info);
65
+
66
+ GI_AVAILABLE_IN_ALL
67
+ GIConstantInfo * g_union_info_get_discriminator (GIUnionInfo *info,
68
+ gint n);
69
+
70
+ GI_AVAILABLE_IN_ALL
71
+ GIFunctionInfo * g_union_info_find_method (GIUnionInfo *info,
72
+ const gchar *name);
73
+
74
+ GI_AVAILABLE_IN_ALL
75
+ gsize g_union_info_get_size (GIUnionInfo *info);
76
+
77
+ GI_AVAILABLE_IN_ALL
78
+ gsize g_union_info_get_alignment (GIUnionInfo *info);
79
+
80
+ G_END_DECLS
81
+
82
+
83
+ #endif /* __GIUNIONINFO_H__ */
84
+
@@ -0,0 +1,128 @@
1
+ /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2
+ * GObject introspection: Versioning and export macros
3
+ *
4
+ * Copyright (C) 2014 Chun-wei Fan
5
+ *
6
+ * This library is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2 of the License, or (at your option) any later version.
10
+ *
11
+ * This library is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with this library; if not, write to the
18
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19
+ * Boston, MA 02111-1307, USA.
20
+ */
21
+
22
+ #include <glib.h>
23
+
24
+ #ifndef __GIVERSIONMACROS_H__
25
+ #define __GIVERSIONMACROS_H__
26
+
27
+ #if !defined (__GIREPOSITORY_H_INSIDE__) && !defined (GI_COMPILATION)
28
+ #error "Only <girepository.h> can be included directly."
29
+ #endif
30
+
31
+ #ifndef _GI_EXTERN
32
+ #define _GI_EXTERN extern
33
+ #endif
34
+
35
+ #define GI_AVAILABLE_IN_ALL _GI_EXTERN
36
+
37
+ /* XXX: Every new stable minor release should add a set of macros here
38
+ *
39
+ * We are using the GLib versions here as the G-I minor versions
40
+ * need to be in sync with the GLib minor versions. Api's added
41
+ * at or before 1.30 are marked as GI_AVAILABLE_IN_ALL
42
+ */
43
+
44
+ #if GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_32
45
+ # define GI_DEPRECATED_IN_1_32 GLIB_DEPRECATED
46
+ # define GI_DEPRECATED_IN_1_32_FOR(f) GLIB_DEPRECATED_FOR(f)
47
+ #else
48
+ # define GI_DEPRECATED_IN_1_32 _GI_EXTERN
49
+ # define GI_DEPRECATED_IN_1_32_FOR(f) _GI_EXTERN
50
+ #endif
51
+
52
+ #if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_32
53
+ # define GI_AVAILABLE_IN_1_32 GLIB_UNAVAILABLE(2, 32)
54
+ #else
55
+ # define GI_AVAILABLE_IN_1_32 _GI_EXTERN
56
+ #endif
57
+
58
+ #if GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_34
59
+ # define GI_DEPRECATED_IN_1_34 GLIB_DEPRECATED
60
+ # define GI_DEPRECATED_IN_1_34_FOR(f) GLIB_DEPRECATED_FOR(f)
61
+ #else
62
+ # define GI_DEPRECATED_IN_1_34 _GI_EXTERN
63
+ # define GI_DEPRECATED_IN_1_34_FOR(f) _GI_EXTERN
64
+ #endif
65
+
66
+ #if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_34
67
+ # define GI_AVAILABLE_IN_1_34 GLIB_UNAVAILABLE(2, 34)
68
+ #else
69
+ # define GI_AVAILABLE_IN_1_34 _GI_EXTERN
70
+ #endif
71
+
72
+ #if GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_36
73
+ # define GI_DEPRECATED_IN_1_36 GLIB_DEPRECATED
74
+ # define GI_DEPRECATED_IN_1_36_FOR(f) GLIB_DEPRECATED_FOR(f)
75
+ #else
76
+ # define GI_DEPRECATED_IN_1_36 _GI_EXTERN
77
+ # define GI_DEPRECATED_IN_1_36_FOR(f) _GI_EXTERN
78
+ #endif
79
+
80
+ #if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_36
81
+ # define GI_AVAILABLE_IN_1_36 GLIB_UNAVAILABLE(2, 36)
82
+ #else
83
+ # define GI_AVAILABLE_IN_1_36 _GI_EXTERN
84
+ #endif
85
+
86
+ #if GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_38
87
+ # define GI_DEPRECATED_IN_1_38 GLIB_DEPRECATED
88
+ # define GI_DEPRECATED_IN_1_38_FOR(f) GLIB_DEPRECATED_FOR(f)
89
+ #else
90
+ # define GI_DEPRECATED_IN_1_38 _GI_EXTERN
91
+ # define GI_DEPRECATED_IN_1_38_FOR(f) _GI_EXTERN
92
+ #endif
93
+
94
+ #if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38
95
+ # define GI_AVAILABLE_IN_1_38 GLIB_UNAVAILABLE(2, 38)
96
+ #else
97
+ # define GI_AVAILABLE_IN_1_38 _GI_EXTERN
98
+ #endif
99
+
100
+ #if GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_40
101
+ # define GI_DEPRECATED_IN_1_40 GLIB_DEPRECATED
102
+ # define GI_DEPRECATED_IN_1_40_FOR(f) GLIB_DEPRECATED_FOR(f)
103
+ #else
104
+ # define GI_DEPRECATED_IN_1_40 _GI_EXTERN
105
+ # define GI_DEPRECATED_IN_1_40_FOR(f) _GI_EXTERN
106
+ #endif
107
+
108
+ #if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_40
109
+ # define GI_AVAILABLE_IN_1_40 GLIB_UNAVAILABLE(2, 40)
110
+ #else
111
+ # define GI_AVAILABLE_IN_1_40 _GI_EXTERN
112
+ #endif
113
+
114
+ #if GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_42
115
+ # define GI_DEPRECATED_IN_1_42 GLIB_DEPRECATED
116
+ # define GI_DEPRECATED_IN_1_42_FOR(f) GLIB_DEPRECATED_FOR(f)
117
+ #else
118
+ # define GI_DEPRECATED_IN_1_42 _GI_EXTERN
119
+ # define GI_DEPRECATED_IN_1_42_FOR(f) _GI_EXTERN
120
+ #endif
121
+
122
+ #if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_42
123
+ # define GI_AVAILABLE_IN_1_42 GLIB_UNAVAILABLE(2, 42)
124
+ #else
125
+ # define GI_AVAILABLE_IN_1_42 _GI_EXTERN
126
+ #endif
127
+
128
+ #endif /* __GIVERSIONMACROS_H__ */
@@ -0,0 +1,73 @@
1
+ /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2
+ * GObject introspection: Virtual Functions
3
+ *
4
+ * Copyright (C) 2005 Matthias Clasen
5
+ * Copyright (C) 2008,2009 Red Hat, Inc.
6
+ *
7
+ * This library is free software; you can redistribute it and/or
8
+ * modify it under the terms of the GNU Lesser General Public
9
+ * License as published by the Free Software Foundation; either
10
+ * version 2 of the License, or (at your option) any later version.
11
+ *
12
+ * This library is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ * Lesser General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU Lesser General Public
18
+ * License along with this library; if not, write to the
19
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20
+ * Boston, MA 02111-1307, USA.
21
+ */
22
+
23
+ #ifndef __GIVFUNCINFO_H__
24
+ #define __GIVFUNCINFO_H__
25
+
26
+ #if !defined (__GIREPOSITORY_H_INSIDE__) && !defined (GI_COMPILATION)
27
+ #error "Only <girepository.h> can be included directly."
28
+ #endif
29
+
30
+ #include <gitypes.h>
31
+
32
+ G_BEGIN_DECLS
33
+
34
+ /**
35
+ * GI_IS_VFUNC_INFO
36
+ * @info: an info structure
37
+ *
38
+ * Checks if @info is a #GIVfuncInfo.
39
+ */
40
+ #define GI_IS_VFUNC_INFO(info) \
41
+ (g_base_info_get_type((GIBaseInfo*)info) == GI_INFO_TYPE_VFUNC)
42
+
43
+ GI_AVAILABLE_IN_ALL
44
+ GIVFuncInfoFlags g_vfunc_info_get_flags (GIVFuncInfo *info);
45
+
46
+ GI_AVAILABLE_IN_ALL
47
+ gint g_vfunc_info_get_offset (GIVFuncInfo *info);
48
+
49
+ GI_AVAILABLE_IN_ALL
50
+ GISignalInfo * g_vfunc_info_get_signal (GIVFuncInfo *info);
51
+
52
+ GI_AVAILABLE_IN_ALL
53
+ GIFunctionInfo * g_vfunc_info_get_invoker (GIVFuncInfo *info);
54
+
55
+ GI_AVAILABLE_IN_ALL
56
+ gpointer g_vfunc_info_get_address (GIVFuncInfo *info,
57
+ GType implementor_gtype,
58
+ GError **error);
59
+
60
+ GI_AVAILABLE_IN_ALL
61
+ gboolean g_vfunc_info_invoke (GIVFuncInfo *info,
62
+ GType implementor,
63
+ const GIArgument *in_args,
64
+ int n_in_args,
65
+ const GIArgument *out_args,
66
+ int n_out_args,
67
+ GIArgument *return_value,
68
+ GError **error);
69
+
70
+ G_END_DECLS
71
+
72
+
73
+ #endif /* __GIVFUNCINFO_H__ */
@@ -0,0 +1,24 @@
1
+ # -*- Mode: Python -*-
2
+ # GObject-Introspection - a framework for introspecting GObject libraries
3
+ # Copyright (C) 2008 Johan Dahlin
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License as published by the Free Software Foundation; either
8
+ # version 2 of the License, or (at your option) any later version.
9
+ #
10
+ # This library 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. See the GNU
13
+ # Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public
16
+ # License along with this library; if not, write to the
17
+ # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18
+ # Boston, MA 02111-1307, USA.
19
+ #
20
+
21
+ import os
22
+ builddir = os.environ.get('UNINSTALLED_INTROSPECTION_BUILDDIR')
23
+ if builddir is not None:
24
+ __path__.append(os.path.join(builddir, 'giscanner'))
@@ -0,0 +1,76 @@
1
+ # -*- Mode: Python -*-
2
+ # GObject-Introspection - a framework for introspecting GObject libraries
3
+ # Copyright (C) 2010 Johan Dahlin
4
+ #
5
+ # This program is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU General Public License
7
+ # as published by the Free Software Foundation; either version 2
8
+ # of the License, or (at your option) any later version.
9
+ #
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. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program; if not, write to the Free Software
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
+ # 02110-1301, USA.
19
+ #
20
+
21
+ import optparse
22
+
23
+ from giscanner import message
24
+ from giscanner.annotationparser import GtkDocCommentBlockParser, GtkDocCommentBlockWriter
25
+ from giscanner.scannermain import (get_preprocessor_option_group,
26
+ create_source_scanner,
27
+ process_packages)
28
+
29
+
30
+ def annotation_main(args):
31
+ parser = optparse.OptionParser('%prog [options] sources')
32
+
33
+ group = optparse.OptionGroup(parser, "Tool modes, one is required")
34
+ group.add_option("-e", "--extract",
35
+ action="store_true", dest="extract",
36
+ help="Extract annotations from the input files")
37
+ parser.add_option_group(group)
38
+
39
+ group = get_preprocessor_option_group(parser)
40
+ group.add_option("-L", "--library-path",
41
+ action="append", dest="library_paths", default=[],
42
+ help="directories to search for libraries")
43
+ group.add_option("", "--pkg",
44
+ action="append", dest="packages", default=[],
45
+ help="pkg-config packages to get cflags from")
46
+ parser.add_option_group(group)
47
+
48
+ options, args = parser.parse_args(args)
49
+
50
+ if not options.extract:
51
+ raise SystemExit("ERROR: Nothing to do")
52
+
53
+ if options.packages:
54
+ process_packages(options, options.packages)
55
+
56
+ logger = message.MessageLogger.get(namespace=None)
57
+
58
+ ss = create_source_scanner(options, args)
59
+
60
+ if options.extract:
61
+ parser = GtkDocCommentBlockParser()
62
+ writer = GtkDocCommentBlockWriter(indent=False)
63
+ blocks = parser.parse_comment_blocks(ss.get_comments())
64
+ print '/' + ('*' * 60) + '/'
65
+ print '/* THIS FILE IS GENERATED DO NOT EDIT */'
66
+ print '/' + ('*' * 60) + '/'
67
+ print
68
+ for block in sorted(blocks.values()):
69
+ print writer.write(block)
70
+ print
71
+ print
72
+ print '/' + ('*' * 60) + '/'
73
+ print '/* THIS FILE IS GENERATED DO NOT EDIT */'
74
+ print '/' + ('*' * 60) + '/'
75
+
76
+ return 0
@@ -0,0 +1,2161 @@
1
+ # -*- coding: utf-8 -*-
2
+ # -*- Mode: Python -*-
3
+
4
+ # GObject-Introspection - a framework for introspecting GObject libraries
5
+ # Copyright (C) 2008-2010 Johan Dahlin
6
+ # Copyright (C) 2012-2013 Dieter Verfaillie <dieterv@optionexplicit.be>
7
+ #
8
+ # This program is free software; you can redistribute it and/or
9
+ # modify it under the terms of the GNU General Public License
10
+ # as published by the Free Software Foundation; either version 2
11
+ # of the License, or (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program; if not, write to the Free Software
20
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21
+ # 02110-1301, USA.
22
+ #
23
+
24
+
25
+ '''
26
+ GTK-Doc comment block format
27
+ ----------------------------
28
+
29
+ A GTK-Doc comment block is built out of multiple parts. Each part can be further
30
+ divided into fields which are separated by a colon ("``:``") delimiter.
31
+
32
+ Known parts and the fields they are constructed from look like the following
33
+ (optional fields are enclosed in square brackets)::
34
+
35
+ ┌───────────────────────────────────────────────────────────┐
36
+ │ /** │ ─▷ start token
37
+ ├────────────────────┬──────────────────────────────────────┤
38
+ │ * identifier_name │ [: annotations] │ ─▷ identifier part
39
+ ├────────────────────┼─────────────────┬────────────────────┤
40
+ │ * @parameter_name │ [: annotations] │ : description │ ─▷ parameter part
41
+ ├────────────────────┴─────────────────┴────────────────────┤
42
+ │ * │ ─▷ comment block description
43
+ │ * comment_block_description │
44
+ ├─────────────┬─────────────────┬───────────┬───────────────┤
45
+ │ * tag_name │ [: annotations] │ [: value] │ : description │ ─▷ tag part
46
+ ├─────────────┴─────────────────┴───────────┴───────────────┤
47
+ │ */ │ ─▷ end token
48
+ └───────────────────────────────────────────────────────────┘
49
+
50
+ There are two conditions that must be met before a comment block is recognized
51
+ as a GTK-Doc comment block:
52
+
53
+ #. The comment block is opened with a GTK-Doc start token ("``/**``")
54
+ #. The first line following the start token contains a valid identifier part
55
+
56
+ Once a GTK-Doc comment block has been identified as such and has been stripped
57
+ from its start and end tokens the remaining parts have to be written in a
58
+ specific order:
59
+
60
+ #. There must be exactly 1 `identifier` part on the first line of the
61
+ comment block which consists of:
62
+
63
+ * a required `identifier_name` field
64
+ * an optional `annotations` field
65
+
66
+ #. Zero or more `parameter` parts, each consisting of:
67
+
68
+ * a required `parameter_name` field
69
+ * an optional `annotations` field
70
+ * a required `description` field (can be the empty string)
71
+
72
+ #. One optional `comment block description` part which must begin with at
73
+ least 1 empty line signaling the start of this part.
74
+
75
+ #. Zero or more `tag` parts, each consisting of:
76
+
77
+ * a required `tag_name` field
78
+ * an optional `annotations` field
79
+ * an optional `value` field
80
+ * a required `description` field (can be the empty string)
81
+
82
+ Additionally, the following restrictions are in effect:
83
+
84
+ #. Separating parts with an empty line:
85
+
86
+ * `identifier` and `parameter` parts cannot be separated from each other by
87
+ an empty line as this would signal the start of the
88
+ `comment block description` part (see above).
89
+ * it is required to separate the `comment block description` part from the
90
+ `identifier` or `parameter` parts with an empty line (see above)
91
+ * `comment block description` and `tag` parts can optionally be separated
92
+ by an empty line
93
+
94
+ #. Parts and fields cannot span multiple lines, except for:
95
+
96
+ * the `comment_block_description` part
97
+ * `parameter description` and `tag description` fields
98
+
99
+ #. Taking the above restrictions into account, spanning multiple paragraphs is
100
+ limited to the `comment block description` part and `tag description` fields.
101
+
102
+ Refer to the `GTK-Doc manual`_ for more detailed usage information.
103
+
104
+ .. _GTK-Doc manual:
105
+ http://developer.gnome.org/gtk-doc-manual/1.18/documenting.html.en
106
+ '''
107
+
108
+
109
+ from __future__ import absolute_import
110
+
111
+ import os
112
+ import re
113
+
114
+ from collections import namedtuple
115
+ from operator import ne, gt, lt
116
+
117
+ from .collections import Counter, OrderedDict
118
+ from .message import Position, warn, error
119
+
120
+
121
+ # GTK-Doc comment block parts
122
+ PART_IDENTIFIER = 0
123
+ PART_PARAMETERS = 1
124
+ PART_DESCRIPTION = 2
125
+ PART_TAGS = 3
126
+
127
+ # GTK-Doc comment block tags
128
+ # 1) Basic GTK-Doc tags.
129
+ # Note: This list cannot be extended unless the GTK-Doc project defines new tags.
130
+ TAG_DEPRECATED = 'deprecated'
131
+ TAG_RETURNS = 'returns'
132
+ TAG_SINCE = 'since'
133
+ TAG_STABILITY = 'stability'
134
+
135
+ GTKDOC_TAGS = [TAG_DEPRECATED,
136
+ TAG_RETURNS,
137
+ TAG_SINCE,
138
+ TAG_STABILITY]
139
+
140
+ # 2) Deprecated basic GTK-Doc tags.
141
+ # Note: This list cannot be extended unless the GTK-Doc project defines new deprecated tags.
142
+ TAG_DESCRIPTION = 'description'
143
+ TAG_RETURN_VALUE = 'return value'
144
+
145
+ DEPRECATED_GTKDOC_TAGS = [TAG_DESCRIPTION,
146
+ TAG_RETURN_VALUE]
147
+
148
+ # 3) Deprecated GObject-Introspection tags.
149
+ # Unfortunately, these where accepted by old versions of this module.
150
+ TAG_RETURN = 'return'
151
+ TAG_RETURNS_VALUE = 'returns value'
152
+
153
+ DEPRECATED_GI_TAGS = [TAG_RETURN,
154
+ TAG_RETURNS_VALUE]
155
+
156
+ # 4) Deprecated GObject-Introspection annotation tags.
157
+ # Accepted by old versions of this module while they should have been
158
+ # annotations on the identifier part instead.
159
+ # Note: This list can not be extended ever again. The GObject-Introspection project is not
160
+ # allowed to invent GTK-Doc tags. Please create new annotations instead.
161
+ TAG_ATTRIBUTES = 'attributes'
162
+ TAG_GET_VALUE_FUNC = 'get value func'
163
+ TAG_REF_FUNC = 'ref func'
164
+ TAG_RENAME_TO = 'rename to'
165
+ TAG_SET_VALUE_FUNC = 'set value func'
166
+ TAG_TRANSFER = 'transfer'
167
+ TAG_TYPE = 'type'
168
+ TAG_UNREF_FUNC = 'unref func'
169
+ TAG_VALUE = 'value'
170
+ TAG_VFUNC = 'virtual'
171
+
172
+ DEPRECATED_GI_ANN_TAGS = [TAG_ATTRIBUTES,
173
+ TAG_GET_VALUE_FUNC,
174
+ TAG_REF_FUNC,
175
+ TAG_RENAME_TO,
176
+ TAG_SET_VALUE_FUNC,
177
+ TAG_TRANSFER,
178
+ TAG_TYPE,
179
+ TAG_UNREF_FUNC,
180
+ TAG_VALUE,
181
+ TAG_VFUNC]
182
+
183
+ ALL_TAGS = GTKDOC_TAGS + DEPRECATED_GTKDOC_TAGS + DEPRECATED_GI_TAGS + DEPRECATED_GI_ANN_TAGS
184
+
185
+ # GObject-Introspection annotation start/end tokens
186
+ ANN_LPAR = '('
187
+ ANN_RPAR = ')'
188
+
189
+ # GObject-Introspection annotations
190
+ # 1) Supported annotations
191
+ # Note: when adding new annotations, GTK-Doc project's gtkdoc-mkdb needs to be modified too!
192
+ ANN_ALLOW_NONE = 'allow-none'
193
+ ANN_ARRAY = 'array'
194
+ ANN_ATTRIBUTES = 'attributes'
195
+ ANN_CLOSURE = 'closure'
196
+ ANN_CONSTRUCTOR = 'constructor'
197
+ ANN_DESTROY = 'destroy'
198
+ ANN_ELEMENT_TYPE = 'element-type'
199
+ ANN_FOREIGN = 'foreign'
200
+ ANN_GET_VALUE_FUNC = 'get-value-func'
201
+ ANN_IN = 'in'
202
+ ANN_INOUT = 'inout'
203
+ ANN_METHOD = 'method'
204
+ ANN_NULLABLE = 'nullable'
205
+ ANN_OPTIONAL = 'optional'
206
+ ANN_OUT = 'out'
207
+ ANN_REF_FUNC = 'ref-func'
208
+ ANN_RENAME_TO = 'rename-to'
209
+ ANN_SCOPE = 'scope'
210
+ ANN_SET_VALUE_FUNC = 'set-value-func'
211
+ ANN_SKIP = 'skip'
212
+ ANN_TRANSFER = 'transfer'
213
+ ANN_TYPE = 'type'
214
+ ANN_UNREF_FUNC = 'unref-func'
215
+ ANN_VFUNC = 'virtual'
216
+ ANN_VALUE = 'value'
217
+
218
+ GI_ANNS = [ANN_ALLOW_NONE,
219
+ ANN_NULLABLE,
220
+ ANN_OPTIONAL,
221
+ ANN_ARRAY,
222
+ ANN_ATTRIBUTES,
223
+ ANN_CLOSURE,
224
+ ANN_CONSTRUCTOR,
225
+ ANN_DESTROY,
226
+ ANN_ELEMENT_TYPE,
227
+ ANN_FOREIGN,
228
+ ANN_GET_VALUE_FUNC,
229
+ ANN_IN,
230
+ ANN_INOUT,
231
+ ANN_METHOD,
232
+ ANN_OUT,
233
+ ANN_REF_FUNC,
234
+ ANN_RENAME_TO,
235
+ ANN_SCOPE,
236
+ ANN_SET_VALUE_FUNC,
237
+ ANN_SKIP,
238
+ ANN_TRANSFER,
239
+ ANN_TYPE,
240
+ ANN_UNREF_FUNC,
241
+ ANN_VFUNC,
242
+ ANN_VALUE]
243
+
244
+ # 2) Deprecated GObject-Introspection annotations
245
+ ANN_ATTRIBUTE = 'attribute'
246
+ ANN_INOUT_ALT = 'in-out'
247
+
248
+ DEPRECATED_GI_ANNS = [ANN_ATTRIBUTE,
249
+ ANN_INOUT_ALT]
250
+
251
+ ALL_ANNOTATIONS = GI_ANNS + DEPRECATED_GI_ANNS
252
+ DICT_ANNOTATIONS = [ANN_ARRAY, ANN_ATTRIBUTES]
253
+ LIST_ANNOTATIONS = [ann for ann in ALL_ANNOTATIONS if ann not in DICT_ANNOTATIONS]
254
+
255
+ # (array) annotation options
256
+ OPT_ARRAY_FIXED_SIZE = 'fixed-size'
257
+ OPT_ARRAY_LENGTH = 'length'
258
+ OPT_ARRAY_ZERO_TERMINATED = 'zero-terminated'
259
+
260
+ ARRAY_OPTIONS = [OPT_ARRAY_FIXED_SIZE,
261
+ OPT_ARRAY_LENGTH,
262
+ OPT_ARRAY_ZERO_TERMINATED]
263
+
264
+ # (out) annotation options
265
+ OPT_OUT_CALLEE_ALLOCATES = 'callee-allocates'
266
+ OPT_OUT_CALLER_ALLOCATES = 'caller-allocates'
267
+
268
+ OUT_OPTIONS = [OPT_OUT_CALLEE_ALLOCATES,
269
+ OPT_OUT_CALLER_ALLOCATES]
270
+
271
+ # (scope) annotation options
272
+ OPT_SCOPE_ASYNC = 'async'
273
+ OPT_SCOPE_CALL = 'call'
274
+ OPT_SCOPE_NOTIFIED = 'notified'
275
+
276
+ SCOPE_OPTIONS = [OPT_SCOPE_ASYNC,
277
+ OPT_SCOPE_CALL,
278
+ OPT_SCOPE_NOTIFIED]
279
+
280
+ # (transfer) annotation options
281
+ OPT_TRANSFER_CONTAINER = 'container'
282
+ OPT_TRANSFER_FLOATING = 'floating'
283
+ OPT_TRANSFER_FULL = 'full'
284
+ OPT_TRANSFER_NONE = 'none'
285
+
286
+ TRANSFER_OPTIONS = [OPT_TRANSFER_CONTAINER,
287
+ OPT_TRANSFER_FLOATING,
288
+ OPT_TRANSFER_FULL,
289
+ OPT_TRANSFER_NONE]
290
+
291
+
292
+ # Pattern used to normalize different types of line endings
293
+ LINE_BREAK_RE = re.compile(r'\r\n|\r|\n', re.UNICODE)
294
+
295
+ # Pattern matching the start token of a comment block.
296
+ COMMENT_BLOCK_START_RE = re.compile(
297
+ r'''
298
+ ^ # start
299
+ (?P<code>.*?) # whitespace, code, ...
300
+ \s* # 0 or more whitespace characters
301
+ (?P<token>/\*{2}(?![\*/])) # 1 forward slash character followed
302
+ # by exactly 2 asterisk characters
303
+ # and not followed by a slash character
304
+ \s* # 0 or more whitespace characters
305
+ (?P<comment>.*?) # GTK-Doc comment text
306
+ \s* # 0 or more whitespace characters
307
+ $ # end
308
+ ''',
309
+ re.UNICODE | re.VERBOSE)
310
+
311
+ # Pattern matching the end token of a comment block.
312
+ COMMENT_BLOCK_END_RE = re.compile(
313
+ r'''
314
+ ^ # start
315
+ \s* # 0 or more whitespace characters
316
+ (?P<comment>.*?) # GTK-Doc comment text
317
+ \s* # 0 or more whitespace characters
318
+ (?P<token>\*+/) # 1 or more asterisk characters followed
319
+ # by exactly 1 forward slash character
320
+ (?P<code>.*?) # whitespace, code, ...
321
+ \s* # 0 or more whitespace characters
322
+ $ # end
323
+ ''',
324
+ re.UNICODE | re.VERBOSE)
325
+
326
+ # Pattern matching the ' * ' at the beginning of every
327
+ # line inside a comment block.
328
+ COMMENT_ASTERISK_RE = re.compile(
329
+ r'''
330
+ ^ # start
331
+ \s* # 0 or more whitespace characters
332
+ (?P<comment>.*?) # invalid comment text
333
+ \s* # 0 or more whitespace characters
334
+ \* # 1 asterisk character
335
+ \s? # 0 or 1 whitespace characters
336
+ # WARNING: removing more than 1
337
+ # whitespace character breaks
338
+ # embedded example program indentation
339
+ ''',
340
+ re.UNICODE | re.VERBOSE)
341
+
342
+ # Pattern matching the indentation level of a line (used
343
+ # to get the indentation before and after the ' * ').
344
+ INDENTATION_RE = re.compile(
345
+ r'''
346
+ ^
347
+ (?P<indentation>\s*) # 0 or more whitespace characters
348
+ .*
349
+ $
350
+ ''',
351
+ re.UNICODE | re.VERBOSE)
352
+
353
+ # Pattern matching an empty line.
354
+ EMPTY_LINE_RE = re.compile(
355
+ r'''
356
+ ^ # start
357
+ \s* # 0 or more whitespace characters
358
+ $ # end
359
+ ''',
360
+ re.UNICODE | re.VERBOSE)
361
+
362
+ # Pattern matching SECTION identifiers.
363
+ SECTION_RE = re.compile(
364
+ r'''
365
+ ^ # start
366
+ \s* # 0 or more whitespace characters
367
+ SECTION # SECTION
368
+ \s* # 0 or more whitespace characters
369
+ (?P<delimiter>:?) # delimiter
370
+ \s* # 0 or more whitespace characters
371
+ (?P<section_name>\w\S+?) # section name
372
+ \s* # 0 or more whitespace characters
373
+ :? # invalid delimiter
374
+ \s* # 0 or more whitespace characters
375
+ $
376
+ ''',
377
+ re.UNICODE | re.VERBOSE)
378
+
379
+ # Pattern matching symbol (function, constant, struct and enum) identifiers.
380
+ SYMBOL_RE = re.compile(
381
+ r'''
382
+ ^ # start
383
+ \s* # 0 or more whitespace characters
384
+ (?P<symbol_name>[\w-]*\w) # symbol name
385
+ \s* # 0 or more whitespace characters
386
+ (?P<delimiter>:?) # delimiter
387
+ \s* # 0 or more whitespace characters
388
+ (?P<fields>.*?) # annotations + description
389
+ \s* # 0 or more whitespace characters
390
+ :? # invalid delimiter
391
+ \s* # 0 or more whitespace characters
392
+ $ # end
393
+ ''',
394
+ re.UNICODE | re.VERBOSE)
395
+
396
+ # Pattern matching property identifiers.
397
+ PROPERTY_RE = re.compile(
398
+ r'''
399
+ ^ # start
400
+ \s* # 0 or more whitespace characters
401
+ (?P<class_name>[\w]+) # class name
402
+ \s* # 0 or more whitespace characters
403
+ :{1} # 1 required colon
404
+ \s* # 0 or more whitespace characters
405
+ (?P<property_name>[\w-]*\w) # property name
406
+ \s* # 0 or more whitespace characters
407
+ (?P<delimiter>:?) # delimiter
408
+ \s* # 0 or more whitespace characters
409
+ (?P<fields>.*?) # annotations + description
410
+ \s* # 0 or more whitespace characters
411
+ :? # invalid delimiter
412
+ \s* # 0 or more whitespace characters
413
+ $ # end
414
+ ''',
415
+ re.UNICODE | re.VERBOSE)
416
+
417
+ # Pattern matching signal identifiers.
418
+ SIGNAL_RE = re.compile(
419
+ r'''
420
+ ^ # start
421
+ \s* # 0 or more whitespace characters
422
+ (?P<class_name>[\w]+) # class name
423
+ \s* # 0 or more whitespace characters
424
+ :{2} # 2 required colons
425
+ \s* # 0 or more whitespace characters
426
+ (?P<signal_name>[\w-]*\w) # signal name
427
+ \s* # 0 or more whitespace characters
428
+ (?P<delimiter>:?) # delimiter
429
+ \s* # 0 or more whitespace characters
430
+ (?P<fields>.*?) # annotations + description
431
+ \s* # 0 or more whitespace characters
432
+ :? # invalid delimiter
433
+ \s* # 0 or more whitespace characters
434
+ $ # end
435
+ ''',
436
+ re.UNICODE | re.VERBOSE)
437
+
438
+ # Pattern matching parameters.
439
+ PARAMETER_RE = re.compile(
440
+ r'''
441
+ ^ # start
442
+ \s* # 0 or more whitespace characters
443
+ @ # @ character
444
+ (?P<parameter_name>[\w-]*\w|.*?\.\.\.) # parameter name
445
+ \s* # 0 or more whitespace characters
446
+ :{1} # 1 required delimiter
447
+ \s* # 0 or more whitespace characters
448
+ (?P<fields>.*?) # annotations + description
449
+ \s* # 0 or more whitespace characters
450
+ $ # end
451
+ ''',
452
+ re.UNICODE | re.VERBOSE)
453
+
454
+ # Pattern matching tags.
455
+ _all_tags = '|'.join(ALL_TAGS).replace(' ', r'\s')
456
+ TAG_RE = re.compile(
457
+ r'''
458
+ ^ # start
459
+ \s* # 0 or more whitespace characters
460
+ (?P<tag_name>''' + _all_tags + r''') # tag name
461
+ \s* # 0 or more whitespace characters
462
+ :{1} # 1 required delimiter
463
+ \s* # 0 or more whitespace characters
464
+ (?P<fields>.*?) # annotations + value + description
465
+ \s* # 0 or more whitespace characters
466
+ $ # end
467
+ ''',
468
+ re.UNICODE | re.VERBOSE | re.IGNORECASE)
469
+
470
+ # Pattern matching value and description fields for TAG_DEPRECATED & TAG_SINCE tags.
471
+ TAG_VALUE_VERSION_RE = re.compile(
472
+ r'''
473
+ ^ # start
474
+ \s* # 0 or more whitespace characters
475
+ (?P<value>([0-9\.])*) # value
476
+ \s* # 0 or more whitespace characters
477
+ (?P<delimiter>:?) # delimiter
478
+ \s* # 0 or more whitespace characters
479
+ (?P<description>.*?) # description
480
+ \s* # 0 or more whitespace characters
481
+ $ # end
482
+ ''',
483
+ re.UNICODE | re.VERBOSE)
484
+
485
+ # Pattern matching value and description fields for TAG_STABILITY tags.
486
+ TAG_VALUE_STABILITY_RE = re.compile(
487
+ r'''
488
+ ^ # start
489
+ \s* # 0 or more whitespace characters
490
+ (?P<value>(stable|unstable|private|internal)?) # value
491
+ \s* # 0 or more whitespace characters
492
+ (?P<delimiter>:?) # delimiter
493
+ \s* # 0 or more whitespace characters
494
+ (?P<description>.*?) # description
495
+ \s* # 0 or more whitespace characters
496
+ $ # end
497
+ ''',
498
+ re.UNICODE | re.VERBOSE | re.IGNORECASE)
499
+
500
+
501
+ class GtkDocAnnotations(OrderedDict):
502
+ '''
503
+ An ordered dictionary mapping annotation names to annotation options (if any). Annotation
504
+ options can be either a :class:`list`, a :class:`giscanner.collections.OrderedDict`
505
+ (depending on the annotation name)or :const:`None`.
506
+ '''
507
+
508
+ __slots__ = ('position')
509
+
510
+ def __init__(self, position=None):
511
+ OrderedDict.__init__(self)
512
+
513
+ #: A :class:`giscanner.message.Position` instance specifying the location of the
514
+ #: annotations in the source file or :const:`None`.
515
+ self.position = position
516
+
517
+
518
+ class GtkDocAnnotatable(object):
519
+ '''
520
+ Base class for GTK-Doc comment block parts that can be annotated.
521
+ '''
522
+
523
+ __slots__ = ('position', 'annotations')
524
+
525
+ #: A :class:`tuple` of annotation name constants that are valid for this object. Annotation
526
+ #: names not in this :class:`tuple` will be reported as *unknown* by :func:`validate`. The
527
+ #: :attr:`valid_annotations` class attribute should be overridden by subclasses.
528
+ valid_annotations = ()
529
+
530
+ def __init__(self, position=None):
531
+ #: A :class:`giscanner.message.Position` instance specifying the location of the
532
+ #: annotatable comment block part in the source file or :const:`None`.
533
+ self.position = position
534
+
535
+ #: A :class:`GtkDocAnnotations` instance representing the annotations
536
+ #: applied to this :class:`GtkDocAnnotatable` instance.
537
+ self.annotations = GtkDocAnnotations()
538
+
539
+ def __repr__(self):
540
+ return '<GtkDocAnnotatable %r %r>' % (self.annotations, )
541
+
542
+ def validate(self):
543
+ '''
544
+ Validate annotations stored by the :class:`GtkDocAnnotatable` instance, if any.
545
+ '''
546
+
547
+ if self.annotations:
548
+ position = self.annotations.position
549
+
550
+ for ann_name, options in self.annotations.items():
551
+ if ann_name in self.valid_annotations:
552
+ validate = getattr(self, '_do_validate_' + ann_name.replace('-', '_'))
553
+ validate(position, ann_name, options)
554
+ elif ann_name in ALL_ANNOTATIONS:
555
+ # Not error() as ann_name might be valid in some newer
556
+ # GObject-Instrospection version.
557
+ warn('unexpected annotation: %s' % (ann_name, ), position)
558
+ else:
559
+ # Not error() as ann_name might be valid in some newer
560
+ # GObject-Instrospection version.
561
+ warn('unknown annotation: %s' % (ann_name, ), position)
562
+
563
+ def _validate_options(self, position, ann_name, n_options, expected_n_options, operator,
564
+ message):
565
+ '''
566
+ Validate the number of options held by an annotation according to the test
567
+ ``operator(n_options, expected_n_options)``.
568
+
569
+ :param position: :class:`giscanner.message.Position` of the line in the source file
570
+ containing the annotation to be validated
571
+ :param ann_name: name of the annotation holding the options to validate
572
+ :param n_options: number of options held by the annotation
573
+ :param expected_n_options: number of expected options
574
+ :param operator: an operator function from python's :mod:`operator` module, for example
575
+ :func:`operator.ne` or :func:`operator.lt`
576
+ :param message: warning message used when the test
577
+ ``operator(n_options, expected_n_options)`` fails.
578
+ '''
579
+
580
+ if n_options == 0:
581
+ t = 'none'
582
+ else:
583
+ t = '%d' % (n_options, )
584
+
585
+ if expected_n_options == 0:
586
+ s = 'no options'
587
+ elif expected_n_options == 1:
588
+ s = 'one option'
589
+ else:
590
+ s = '%d options' % (expected_n_options, )
591
+
592
+ if operator(n_options, expected_n_options):
593
+ warn('"%s" annotation %s %s, %s given' % (ann_name, message, s, t), position)
594
+
595
+ def _validate_annotation(self, position, ann_name, options, choices=None,
596
+ exact_n_options=None, min_n_options=None, max_n_options=None):
597
+ '''
598
+ Validate an annotation.
599
+
600
+ :param position: :class:`giscanner.message.Position` of the line in the source file
601
+ containing the annotation to be validated
602
+ :param ann_name: name of the annotation holding the options to validate
603
+ :param options: annotation options to be validated
604
+ :param choices: an iterable of allowed option names or :const:`None` to skip this test
605
+ :param exact_n_options: exact number of expected options or :const:`None` to skip this test
606
+ :param min_n_options: minimum number of expected options or :const:`None` to skip this test
607
+ :param max_n_options: maximum number of expected options or :const:`None` to skip this test
608
+ '''
609
+
610
+ n_options = len(options)
611
+
612
+ if exact_n_options is not None:
613
+ self._validate_options(position,
614
+ ann_name, n_options, exact_n_options, ne, 'needs')
615
+
616
+ if min_n_options is not None:
617
+ self._validate_options(position,
618
+ ann_name, n_options, min_n_options, lt, 'takes at least')
619
+
620
+ if max_n_options is not None:
621
+ self._validate_options(position,
622
+ ann_name, n_options, max_n_options, gt, 'takes at most')
623
+
624
+ if options and choices is not None:
625
+ option = options[0]
626
+ if option not in choices:
627
+ warn('invalid "%s" annotation option: "%s"' % (ann_name, option), position)
628
+
629
+ def _do_validate_allow_none(self, position, ann_name, options):
630
+ '''
631
+ Validate the ``(allow-none)`` annotation.
632
+
633
+ :param position: :class:`giscanner.message.Position` of the line in the source file
634
+ containing the annotation to be validated
635
+ :param ann_name: name of the annotation holding the options to validate
636
+ :param options: annotation options held by the annotation
637
+ '''
638
+
639
+ self._validate_annotation(position, ann_name, options, exact_n_options=0)
640
+
641
+ def _do_validate_array(self, position, ann_name, options):
642
+ '''
643
+ Validate the ``(array)`` annotation.
644
+
645
+ :param position: :class:`giscanner.message.Position` of the line in the source file
646
+ containing the annotation to be validated
647
+ :param ann_name: name of the annotation holding the options to validate
648
+ :param options: annotation options held by the annotation
649
+ '''
650
+
651
+ if len(options) == 0:
652
+ return
653
+
654
+ for option, value in options.items():
655
+ if option in [OPT_ARRAY_ZERO_TERMINATED, OPT_ARRAY_FIXED_SIZE]:
656
+ try:
657
+ int(value)
658
+ except (TypeError, ValueError):
659
+ if value is None:
660
+ warn('"%s" annotation option "%s" needs a value' % (ann_name, option),
661
+ position)
662
+ else:
663
+ warn('invalid "%s" annotation option "%s" value "%s", must be an integer' %
664
+ (ann_name, option, value),
665
+ position)
666
+ elif option == OPT_ARRAY_LENGTH:
667
+ if value is None:
668
+ warn('"%s" annotation option "length" needs a value' % (ann_name, ),
669
+ position)
670
+ else:
671
+ warn('invalid "%s" annotation option: "%s"' % (ann_name, option),
672
+ position)
673
+
674
+ def _do_validate_attributes(self, position, ann_name, options):
675
+ '''
676
+ Validate the ``(attributes)`` annotation.
677
+
678
+ :param position: :class:`giscanner.message.Position` of the line in the source file
679
+ containing the annotation to be validated
680
+ :param ann_name: name of the annotation holding the options to validate
681
+ :param options: annotation options to validate
682
+ '''
683
+
684
+ # The 'attributes' annotation allows free form annotations.
685
+ pass
686
+
687
+ def _do_validate_closure(self, position, ann_name, options):
688
+ '''
689
+ Validate the ``(closure)`` annotation.
690
+
691
+ :param position: :class:`giscanner.message.Position` of the line in the source file
692
+ containing the annotation to be validated
693
+ :param ann_name: name of the annotation holding the options to validate
694
+ :param options: annotation options to validate
695
+ '''
696
+
697
+ self._validate_annotation(position, ann_name, options, max_n_options=1)
698
+
699
+ def _do_validate_constructor(self, position, ann_name, options):
700
+ '''
701
+ Validate the ``(constructor)`` annotation.
702
+
703
+ :param position: :class:`giscanner.message.Position` of the line in the source file
704
+ containing the annotation to be validated
705
+ :param ann_name: name of the annotation holding the options to validate
706
+ :param options: annotation options to validate
707
+ '''
708
+
709
+ self._validate_annotation(position, ann_name, options, exact_n_options=0)
710
+
711
+ def _do_validate_destroy(self, position, ann_name, options):
712
+ '''
713
+ Validate the ``(destroy)`` annotation.
714
+
715
+ :param position: :class:`giscanner.message.Position` of the line in the source file
716
+ containing the annotation to be validated
717
+ :param ann_name: name of the annotation holding the options to validate
718
+ :param options: annotation options to validate
719
+ '''
720
+
721
+ self._validate_annotation(position, ann_name, options, exact_n_options=1)
722
+
723
+ def _do_validate_element_type(self, position, ann_name, options):
724
+ '''
725
+ Validate the ``(element)`` annotation.
726
+
727
+ :param position: :class:`giscanner.message.Position` of the line in the source file
728
+ containing the annotation to be validated
729
+ :param ann_name: name of the annotation holding the options to validate
730
+ :param options: annotation options to validate
731
+ '''
732
+
733
+ self._validate_annotation(position, ann_name, options, min_n_options=1, max_n_options=2)
734
+
735
+ def _do_validate_foreign(self, position, ann_name, options):
736
+ '''
737
+ Validate the ``(foreign)`` annotation.
738
+
739
+ :param position: :class:`giscanner.message.Position` of the line in the source file
740
+ containing the annotation to be validated
741
+ :param ann_name: name of the annotation holding the options to validate
742
+ :param options: annotation options to validate
743
+ '''
744
+
745
+ self._validate_annotation(position, ann_name, options, exact_n_options=0)
746
+
747
+ def _do_validate_get_value_func(self, position, ann_name, options):
748
+ '''
749
+ Validate the ``(value-func)`` annotation.
750
+
751
+ :param position: :class:`giscanner.message.Position` of the line in the source file
752
+ containing the annotation to be validated
753
+ :param ann_name: name of the annotation holding the options to validate
754
+ :param options: annotation options to validate
755
+ '''
756
+
757
+ self._validate_annotation(position, ann_name, options, exact_n_options=1)
758
+
759
+ def _do_validate_in(self, position, ann_name, options):
760
+ '''
761
+ Validate the ``(in)`` annotation.
762
+
763
+ :param position: :class:`giscanner.message.Position` of the line in the source file
764
+ containing the annotation to be validated
765
+ :param ann_name: name of the annotation holding the options to validate
766
+ :param options: annotation options to validate
767
+ '''
768
+
769
+ self._validate_annotation(position, ann_name, options, exact_n_options=0)
770
+
771
+ def _do_validate_inout(self, position, ann_name, options):
772
+ '''
773
+ Validate the ``(in-out)`` annotation.
774
+
775
+ :param position: :class:`giscanner.message.Position` of the line in the source file
776
+ containing the annotation to be validated
777
+ :param ann_name: name of the annotation holding the options to validate
778
+ :param options: annotation options to validate
779
+ '''
780
+
781
+ self._validate_annotation(position, ann_name, options, exact_n_options=0)
782
+
783
+ def _do_validate_method(self, position, ann_name, options):
784
+ '''
785
+ Validate the ``(method)`` annotation.
786
+
787
+ :param position: :class:`giscanner.message.Position` of the line in the source file
788
+ containing the annotation to be validated
789
+ :param ann_name: name of the annotation holding the options to validate
790
+ :param options: annotation options to validate
791
+ '''
792
+
793
+ self._validate_annotation(position, ann_name, options, exact_n_options=0)
794
+
795
+ def _do_validate_nullable(self, position, ann_name, options):
796
+ '''
797
+ Validate the ``(nullable)`` annotation.
798
+
799
+ :param position: :class:`giscanner.message.Position` of the line in the source file
800
+ containing the annotation to be validated
801
+ :param ann_name: name of the annotation holding the options to validate
802
+ :param options: annotation options held by the annotation
803
+ '''
804
+
805
+ self._validate_annotation(position, ann_name, options, exact_n_options=0)
806
+
807
+ def _do_validate_optional(self, position, ann_name, options):
808
+ '''
809
+ Validate the ``(optional)`` annotation.
810
+
811
+ :param position: :class:`giscanner.message.Position` of the line in the source file
812
+ containing the annotation to be validated
813
+ :param ann_name: name of the annotation holding the options to validate
814
+ :param options: annotation options held by the annotation
815
+ '''
816
+
817
+ self._validate_annotation(position, ann_name, options, exact_n_options=0)
818
+
819
+ def _do_validate_out(self, position, ann_name, options):
820
+ '''
821
+ Validate the ``(out)`` annotation.
822
+
823
+ :param position: :class:`giscanner.message.Position` of the line in the source file
824
+ containing the annotation to be validated
825
+ :param ann_name: name of the annotation holding the options to validate
826
+ :param options: annotation options to validate
827
+ '''
828
+
829
+ self._validate_annotation(position, ann_name, options, max_n_options=1,
830
+ choices=OUT_OPTIONS)
831
+
832
+ def _do_validate_ref_func(self, position, ann_name, options):
833
+ '''
834
+ Validate the ``(ref-func)`` annotation.
835
+
836
+ :param position: :class:`giscanner.message.Position` of the line in the source file
837
+ containing the annotation to be validated
838
+ :param ann_name: name of the annotation holding the options to validate
839
+ :param options: annotation options to validate
840
+ '''
841
+
842
+ self._validate_annotation(position, ann_name, options, exact_n_options=1)
843
+
844
+ def _do_validate_rename_to(self, position, ann_name, options):
845
+ '''
846
+ Validate the ``(rename-to)`` annotation.
847
+
848
+ :param position: :class:`giscanner.message.Position` of the line in the source file
849
+ containing the annotation to be validated
850
+ :param ann_name: name of the annotation holding the options to validate
851
+ :param options: annotation options to validate
852
+ '''
853
+
854
+ self._validate_annotation(position, ann_name, options, exact_n_options=1)
855
+
856
+ def _do_validate_scope(self, position, ann_name, options):
857
+ '''
858
+ Validate the ``(scope)`` annotation.
859
+
860
+ :param position: :class:`giscanner.message.Position` of the line in the source file
861
+ containing the annotation to be validated
862
+ :param ann_name: name of the annotation holding the options to validate
863
+ :param options: annotation options to validate
864
+ '''
865
+
866
+ self._validate_annotation(position, ann_name, options, exact_n_options=1,
867
+ choices=SCOPE_OPTIONS)
868
+
869
+ def _do_validate_set_value_func(self, position, ann_name, options):
870
+ '''
871
+ Validate the ``(value-func)`` annotation.
872
+
873
+ :param position: :class:`giscanner.message.Position` of the line in the source file
874
+ containing the annotation to be validated
875
+ :param ann_name: name of the annotation holding the options to validate
876
+ :param options: annotation options to validate
877
+ '''
878
+
879
+ self._validate_annotation(position, ann_name, options, exact_n_options=1)
880
+
881
+ def _do_validate_skip(self, position, ann_name, options):
882
+ '''
883
+ Validate the ``(skip)`` annotation.
884
+
885
+ :param position: :class:`giscanner.message.Position` of the line in the source file
886
+ containing the annotation to be validated
887
+ :param ann_name: name of the annotation holding the options to validate
888
+ :param options: annotation options to validate
889
+ '''
890
+
891
+ self._validate_annotation(position, ann_name, options, exact_n_options=0)
892
+
893
+ def _do_validate_transfer(self, position, ann_name, options):
894
+ '''
895
+ Validate the ``(transfer)`` annotation.
896
+
897
+ :param position: :class:`giscanner.message.Position` of the line in the source file
898
+ containing the annotation to be validated
899
+ :param ann_name: name of the annotation holding the options to validate
900
+ :param options: annotation options to validate
901
+ '''
902
+
903
+ self._validate_annotation(position, ann_name, options, exact_n_options=1,
904
+ choices=TRANSFER_OPTIONS)
905
+
906
+ def _do_validate_type(self, position, ann_name, options):
907
+ '''
908
+ Validate the ``(type)`` annotation.
909
+
910
+ :param position: :class:`giscanner.message.Position` of the line in the source file
911
+ containing the annotation to be validated
912
+ :param ann_name: name of the annotation holding the options to validate
913
+ :param options: annotation options to validate
914
+ '''
915
+
916
+ self._validate_annotation(position, ann_name, options, exact_n_options=1)
917
+
918
+ def _do_validate_unref_func(self, position, ann_name, options):
919
+ '''
920
+ Validate the ``(unref-func)`` annotation.
921
+
922
+ :param position: :class:`giscanner.message.Position` of the line in the source file
923
+ containing the annotation to be validated
924
+ :param ann_name: name of the annotation holding the options to validate
925
+ :param options: annotation options to validate
926
+ '''
927
+
928
+ self._validate_annotation(position, ann_name, options, exact_n_options=1)
929
+
930
+ def _do_validate_value(self, position, ann_name, options):
931
+ '''
932
+ Validate the ``(value)`` annotation.
933
+
934
+ :param position: :class:`giscanner.message.Position` of the line in the source file
935
+ containing the annotation to be validated
936
+ :param ann_name: name of the annotation holding the options to validate
937
+ :param options: annotation options to validate
938
+ '''
939
+
940
+ self._validate_annotation(position, ann_name, options, exact_n_options=1)
941
+
942
+ def _do_validate_virtual(self, position, ann_name, options):
943
+ '''
944
+ Validate the ``(virtual)`` annotation.
945
+
946
+ :param position: :class:`giscanner.message.Position` of the line in the source file
947
+ containing the annotation to be validated
948
+ :param ann_name: name of the annotation holding the options to validate
949
+ :param options: annotation options to validate
950
+ '''
951
+
952
+ self._validate_annotation(position, ann_name, options, exact_n_options=1)
953
+
954
+
955
+ class GtkDocParameter(GtkDocAnnotatable):
956
+ '''
957
+ Represents a GTK-Doc parameter part.
958
+ '''
959
+
960
+ __slots__ = ('name', 'description')
961
+
962
+ valid_annotations = (ANN_ALLOW_NONE, ANN_ARRAY, ANN_ATTRIBUTES, ANN_CLOSURE, ANN_DESTROY,
963
+ ANN_ELEMENT_TYPE, ANN_IN, ANN_INOUT, ANN_OUT, ANN_SCOPE, ANN_SKIP,
964
+ ANN_TRANSFER, ANN_TYPE, ANN_OPTIONAL, ANN_NULLABLE)
965
+
966
+ def __init__(self, name, position=None):
967
+ GtkDocAnnotatable.__init__(self, position)
968
+
969
+ #: Parameter name.
970
+ self.name = name
971
+
972
+ #: Parameter description or :const:`None`.
973
+ self.description = None
974
+
975
+ def __repr__(self):
976
+ return '<GtkDocParameter %r %r>' % (self.name, self.annotations)
977
+
978
+
979
+ class GtkDocTag(GtkDocAnnotatable):
980
+ '''
981
+ Represents a GTK-Doc tag part.
982
+ '''
983
+
984
+ __slots__ = ('name', 'value', 'description')
985
+
986
+ valid_annotations = (ANN_ALLOW_NONE, ANN_ARRAY, ANN_ATTRIBUTES, ANN_ELEMENT_TYPE, ANN_SKIP,
987
+ ANN_TRANSFER, ANN_TYPE, ANN_NULLABLE, ANN_OPTIONAL)
988
+
989
+ def __init__(self, name, position=None):
990
+ GtkDocAnnotatable.__init__(self, position)
991
+
992
+ #: Tag name.
993
+ self.name = name
994
+
995
+ #: Tag value or :const:`None`.
996
+ self.value = None
997
+
998
+ #: Tag description or :const:`None`.
999
+ self.description = None
1000
+
1001
+ def __repr__(self):
1002
+ return '<GtkDocTag %r %r>' % (self.name, self.annotations)
1003
+
1004
+
1005
+ class GtkDocCommentBlock(GtkDocAnnotatable):
1006
+ '''
1007
+ Represents a GTK-Doc comment block.
1008
+ '''
1009
+
1010
+ __slots__ = ('code_before', 'code_after', 'indentation',
1011
+ 'name', 'params', 'description', 'tags')
1012
+
1013
+ #: Valid annotation names for the GTK-Doc comment block identifier part.
1014
+ valid_annotations = (ANN_ATTRIBUTES, ANN_CONSTRUCTOR, ANN_FOREIGN, ANN_GET_VALUE_FUNC,
1015
+ ANN_METHOD, ANN_REF_FUNC, ANN_RENAME_TO, ANN_SET_VALUE_FUNC,
1016
+ ANN_SKIP, ANN_TRANSFER, ANN_TYPE, ANN_UNREF_FUNC, ANN_VALUE, ANN_VFUNC)
1017
+
1018
+ def __init__(self, name, position=None):
1019
+ GtkDocAnnotatable.__init__(self, position)
1020
+
1021
+ #: Code preceding the GTK-Doc comment block start token ("``/**``"), if any.
1022
+ self.code_before = None
1023
+
1024
+ #: Code following the GTK-Doc comment block end token ("``*/``"), if any.
1025
+ self.code_after = None
1026
+
1027
+ #: List of indentation levels (preceding the "``*``") for all lines in the comment
1028
+ #: block's source text.
1029
+ self.indentation = []
1030
+
1031
+ #: Identifier name.
1032
+ self.name = name
1033
+
1034
+ #: Ordered dictionary mapping parameter names to :class:`GtkDocParameter` instances
1035
+ #: applied to this :class:`GtkDocCommentBlock`.
1036
+ self.params = OrderedDict()
1037
+
1038
+ #: The GTK-Doc comment block description part.
1039
+ self.description = None
1040
+
1041
+ #: Ordered dictionary mapping tag names to :class:`GtkDocTag` instances
1042
+ #: applied to this :class:`GtkDocCommentBlock`.
1043
+ self.tags = OrderedDict()
1044
+
1045
+ def __cmp__(self, other):
1046
+ # Note: This is used by g-ir-annotation-tool, which does a ``sorted(blocks.values())``,
1047
+ # meaning that keeping this around makes update-glib-annotations.py patches
1048
+ # easier to review.
1049
+ return cmp(self.name, other.name)
1050
+
1051
+ def __repr__(self):
1052
+ return '<GtkDocCommentBlock %r %r>' % (self.name, self.annotations)
1053
+
1054
+ def validate(self):
1055
+ '''
1056
+ Validate annotations applied to the :class:`GtkDocCommentBlock` identifier, parameters
1057
+ and tags.
1058
+ '''
1059
+ GtkDocAnnotatable.validate(self)
1060
+
1061
+ for param in self.params.values():
1062
+ param.validate()
1063
+
1064
+ for tag in self.tags.values():
1065
+ tag.validate()
1066
+
1067
+
1068
+ #: Result object returned by :class:`GtkDocCommentBlockParser`._parse_annotations()
1069
+ _ParseAnnotationsResult = namedtuple('Result', ['success', 'annotations', 'start_pos', 'end_pos'])
1070
+
1071
+ #: Result object returned by :class:`GtkDocCommentBlockParser`._parse_fields()
1072
+ _ParseFieldsResult = namedtuple('Result', ['success', 'annotations', 'description'])
1073
+
1074
+
1075
+ class GtkDocCommentBlockParser(object):
1076
+ '''
1077
+ Parse GTK-Doc comment blocks into a parse tree built out of :class:`GtkDocCommentBlock`,
1078
+ :class:`GtkDocParameter`, :class:`GtkDocTag` and :class:`GtkDocAnnotations`
1079
+ objects. This parser tries to accept malformed input whenever possible and does
1080
+ not cause the process to exit on syntax errors. It does however emit:
1081
+
1082
+ * warning messages at the slightest indication of recoverable malformed input and
1083
+ * error messages for unrecoverable malformed input
1084
+
1085
+ whenever possible. Recoverable, in this context, means that we can serialize the
1086
+ :class:`GtkDocCommentBlock` instance using a :class:`GtkDocCommentBlockWriter` without
1087
+ information being lost. It is usually a good idea to heed these warning and error messages
1088
+ as malformed input can result in both:
1089
+
1090
+ * invalid GTK-Doc output (HTML, pdf, ...) when the comment blocks are parsed
1091
+ with GTK-Doc's gtkdoc-mkdb
1092
+ * unexpected introspection behavior, for example missing parameters in the
1093
+ generated .gir and .typelib files
1094
+
1095
+ .. NOTE:: :class:`GtkDocCommentBlockParser` functionality is heavily based on gtkdoc-mkdb's
1096
+ `ScanSourceFile()`_ function and is currently in sync with GTK-Doc
1097
+ commit `47abcd5`_.
1098
+
1099
+ .. _ScanSourceFile():
1100
+ http://git.gnome.org/browse/gtk-doc/tree/gtkdoc-mkdb.in#n3722
1101
+ .. _47abcd5:
1102
+ https://git.gnome.org/browse/gtk-doc/commit/?id=47abcd53b8489ebceec9e394676512a181c1f1f6
1103
+ '''
1104
+
1105
+ def parse_comment_blocks(self, comments):
1106
+ '''
1107
+ Parse multiple GTK-Doc comment blocks.
1108
+
1109
+ :param comments: an iterable of ``(comment, filename, lineno)`` tuples
1110
+ :returns: a dictionary mapping identifier names to :class:`GtkDocCommentBlock` objects
1111
+ '''
1112
+
1113
+ comment_blocks = {}
1114
+
1115
+ for (comment, filename, lineno) in comments:
1116
+ try:
1117
+ comment_block = self.parse_comment_block(comment, filename, lineno)
1118
+ except Exception:
1119
+ error('unrecoverable parse error, please file a GObject-Introspection bug'
1120
+ 'report including the complete comment block at the indicated location.',
1121
+ Position(filename, lineno))
1122
+ continue
1123
+
1124
+ if comment_block is not None:
1125
+ # Note: previous versions of this parser did not check if an identifier was
1126
+ # already stored in comment_blocks, so when different comment blocks where
1127
+ # encountered documenting the same identifier the last comment block seen
1128
+ # "wins". Keep this behavior for backwards compatibility, but emit a warning.
1129
+ if comment_block.name in comment_blocks:
1130
+ firstseen = comment_blocks[comment_block.name]
1131
+ path = os.path.dirname(firstseen.position.filename)
1132
+ warn('multiple comment blocks documenting \'%s:\' identifier '
1133
+ '(already seen at %s).' %
1134
+ (comment_block.name, firstseen.position.format(path)),
1135
+ comment_block.position)
1136
+
1137
+ comment_blocks[comment_block.name] = comment_block
1138
+
1139
+ return comment_blocks
1140
+
1141
+ def parse_comment_block(self, comment, filename, lineno):
1142
+ '''
1143
+ Parse a single GTK-Doc comment block.
1144
+
1145
+ :param comment: string representing the GTK-Doc comment block including it's
1146
+ start ("``/**``") and end ("``*/``") tokens.
1147
+ :param filename: source file name where the comment block originated from
1148
+ :param lineno: line number in the source file where the comment block starts
1149
+ :returns: a :class:`GtkDocCommentBlock` object or ``None``
1150
+ '''
1151
+
1152
+ code_before = ''
1153
+ code_after = ''
1154
+ comment_block_pos = Position(filename, lineno)
1155
+ comment_lines = re.sub(LINE_BREAK_RE, '\n', comment).split('\n')
1156
+ comment_lines_len = len(comment_lines)
1157
+
1158
+ # Check for the start of the comment block.
1159
+ result = COMMENT_BLOCK_START_RE.match(comment_lines[0])
1160
+ if result:
1161
+ # Skip single line comment blocks
1162
+ if comment_lines_len == 1:
1163
+ position = Position(filename, lineno)
1164
+ marker = ' ' * result.end('code') + '^'
1165
+ error('Skipping invalid GTK-Doc comment block:'
1166
+ '\n%s\n%s' % (comment_lines[0], marker),
1167
+ position)
1168
+ return None
1169
+
1170
+ code_before = result.group('code')
1171
+ comment = result.group('comment')
1172
+
1173
+ if code_before:
1174
+ position = Position(filename, lineno)
1175
+ marker = ' ' * result.end('code') + '^'
1176
+ warn('GTK-Doc comment block start token "/**" should '
1177
+ 'not be preceded by code:\n%s\n%s' % (comment_lines[0], marker),
1178
+ position)
1179
+
1180
+ if comment:
1181
+ position = Position(filename, lineno)
1182
+ marker = ' ' * result.start('comment') + '^'
1183
+ warn('GTK-Doc comment block start token "/**" should '
1184
+ 'not be followed by comment text:\n%s\n%s' % (comment_lines[0], marker),
1185
+ position)
1186
+
1187
+ comment_lines[0] = comment
1188
+ else:
1189
+ del comment_lines[0]
1190
+ else:
1191
+ # Not a GTK-Doc comment block.
1192
+ return None
1193
+
1194
+ # Check for the end of the comment block.
1195
+ result = COMMENT_BLOCK_END_RE.match(comment_lines[-1])
1196
+ if result:
1197
+ code_after = result.group('code')
1198
+ comment = result.group('comment')
1199
+ if code_after:
1200
+ position = Position(filename, lineno + comment_lines_len - 1)
1201
+ marker = ' ' * result.end('code') + '^'
1202
+ warn('GTK-Doc comment block end token "*/" should '
1203
+ 'not be followed by code:\n%s\n%s' % (comment_lines[-1], marker),
1204
+ position)
1205
+
1206
+ if comment:
1207
+ position = Position(filename, lineno + comment_lines_len - 1)
1208
+ marker = ' ' * result.end('comment') + '^'
1209
+ warn('GTK-Doc comment block end token "*/" should '
1210
+ 'not be preceded by comment text:\n%s\n%s' % (comment_lines[-1], marker),
1211
+ position)
1212
+
1213
+ comment_lines[-1] = comment
1214
+ else:
1215
+ del comment_lines[-1]
1216
+ else:
1217
+ # Not a GTK-Doc comment block.
1218
+ return None
1219
+
1220
+ # If we get this far, we must be inside something
1221
+ # that looks like a GTK-Doc comment block.
1222
+ comment_block = None
1223
+ identifier_warned = False
1224
+ block_indent = []
1225
+ line_indent = None
1226
+ part_indent = None
1227
+ in_part = None
1228
+ current_part = None
1229
+ returns_seen = False
1230
+
1231
+ for line in comment_lines:
1232
+ lineno += 1
1233
+ position = Position(filename, lineno)
1234
+
1235
+ # Store the original line (without \n) and column offset
1236
+ # so we can generate meaningful warnings later on.
1237
+ original_line = line
1238
+ column_offset = 0
1239
+
1240
+ # Store indentation level of the comment (before the ' * ')
1241
+ result = INDENTATION_RE.match(line)
1242
+ block_indent.append(result.group('indentation'))
1243
+
1244
+ # Get rid of the ' * ' at the start of the line.
1245
+ result = COMMENT_ASTERISK_RE.match(line)
1246
+ if result:
1247
+ comment = result.group('comment')
1248
+ if comment:
1249
+ marker = ' ' * result.start('comment') + '^'
1250
+ error('invalid comment text:\n%s\n%s' %
1251
+ (original_line, marker),
1252
+ position)
1253
+
1254
+ column_offset = result.end(0)
1255
+ line = line[result.end(0):]
1256
+
1257
+ # Store indentation level of the line (after the ' * ').
1258
+ result = INDENTATION_RE.match(line)
1259
+ line_indent = len(result.group('indentation').replace('\t', ' '))
1260
+
1261
+ ####################################################################
1262
+ # Check for GTK-Doc comment block identifier.
1263
+ ####################################################################
1264
+ if comment_block is None:
1265
+ result = SECTION_RE.match(line)
1266
+
1267
+ if result:
1268
+ identifier_name = 'SECTION:%s' % (result.group('section_name'), )
1269
+ identifier_delimiter = None
1270
+ identifier_fields = None
1271
+ identifier_fields_start = None
1272
+ else:
1273
+ result = PROPERTY_RE.match(line)
1274
+
1275
+ if result:
1276
+ identifier_name = '%s:%s' % (result.group('class_name'),
1277
+ result.group('property_name'))
1278
+ identifier_delimiter = result.group('delimiter')
1279
+ identifier_fields = result.group('fields')
1280
+ identifier_fields_start = result.start('fields')
1281
+ else:
1282
+ result = SIGNAL_RE.match(line)
1283
+
1284
+ if result:
1285
+ identifier_name = '%s::%s' % (result.group('class_name'),
1286
+ result.group('signal_name'))
1287
+ identifier_delimiter = result.group('delimiter')
1288
+ identifier_fields = result.group('fields')
1289
+ identifier_fields_start = result.start('fields')
1290
+ else:
1291
+ result = SYMBOL_RE.match(line)
1292
+
1293
+ if result:
1294
+ identifier_name = '%s' % (result.group('symbol_name'), )
1295
+ identifier_delimiter = result.group('delimiter')
1296
+ identifier_fields = result.group('fields')
1297
+ identifier_fields_start = result.start('fields')
1298
+
1299
+ if result:
1300
+ in_part = PART_IDENTIFIER
1301
+ part_indent = line_indent
1302
+
1303
+ comment_block = GtkDocCommentBlock(identifier_name, comment_block_pos)
1304
+ comment_block.code_before = code_before
1305
+ comment_block.code_after = code_after
1306
+
1307
+ if identifier_fields:
1308
+ res = self._parse_annotations(position,
1309
+ column_offset + identifier_fields_start,
1310
+ original_line,
1311
+ identifier_fields)
1312
+
1313
+ if res.success:
1314
+ if identifier_fields[res.end_pos:].strip():
1315
+ # Not an identifier due to invalid trailing description field
1316
+ result = None
1317
+ in_part = None
1318
+ part_indent = None
1319
+ comment_block = None
1320
+ else:
1321
+ comment_block.annotations = res.annotations
1322
+
1323
+ if not identifier_delimiter and res.annotations:
1324
+ marker_position = column_offset + result.start('delimiter')
1325
+ marker = ' ' * marker_position + '^'
1326
+ warn('missing ":" at column %s:\n%s\n%s' %
1327
+ (marker_position + 1, original_line, marker),
1328
+ position)
1329
+
1330
+ if not result:
1331
+ # Emit a single warning when the identifier is not found on the first line
1332
+ if not identifier_warned:
1333
+ identifier_warned = True
1334
+ marker = ' ' * column_offset + '^'
1335
+ error('identifier not found on the first line:\n%s\n%s' %
1336
+ (original_line, marker),
1337
+ position)
1338
+ continue
1339
+
1340
+ ####################################################################
1341
+ # Check for comment block parameters.
1342
+ ####################################################################
1343
+ result = PARAMETER_RE.match(line)
1344
+ if result:
1345
+ part_indent = line_indent
1346
+ param_name = result.group('parameter_name')
1347
+ param_name_lower = param_name.lower()
1348
+ param_fields = result.group('fields')
1349
+ param_fields_start = result.start('fields')
1350
+ marker = ' ' * (result.start('parameter_name') + column_offset) + '^'
1351
+
1352
+ if in_part not in [PART_IDENTIFIER, PART_PARAMETERS]:
1353
+ warn('"@%s" parameter unexpected at this location:\n%s\n%s' %
1354
+ (param_name, original_line, marker),
1355
+ position)
1356
+
1357
+ in_part = PART_PARAMETERS
1358
+
1359
+ if param_name_lower == TAG_RETURNS:
1360
+ # Deprecated return value as parameter instead of tag
1361
+ param_name = TAG_RETURNS
1362
+
1363
+ if not returns_seen:
1364
+ returns_seen = True
1365
+ else:
1366
+ error('encountered multiple "Returns" parameters or tags for "%s".' %
1367
+ (comment_block.name, ),
1368
+ position)
1369
+
1370
+ tag = GtkDocTag(TAG_RETURNS, position)
1371
+
1372
+ if param_fields:
1373
+ result = self._parse_fields(position,
1374
+ column_offset + param_fields_start,
1375
+ original_line,
1376
+ param_fields)
1377
+ if result.success:
1378
+ tag.annotations = result.annotations
1379
+ tag.description = result.description
1380
+ comment_block.tags[TAG_RETURNS] = tag
1381
+ current_part = tag
1382
+ continue
1383
+ elif (param_name == 'Varargs'
1384
+ or (param_name.endswith('...') and param_name != '...')):
1385
+ # Deprecated @Varargs notation or named __VA_ARGS__ instead of @...
1386
+ warn('"@%s" parameter is deprecated, please use "@..." instead:\n%s\n%s' %
1387
+ (param_name, original_line, marker),
1388
+ position)
1389
+ param_name = '...'
1390
+
1391
+ if param_name in comment_block.params.keys():
1392
+ error('multiple "@%s" parameters for identifier "%s":\n%s\n%s' %
1393
+ (param_name, comment_block.name, original_line, marker),
1394
+ position)
1395
+
1396
+ parameter = GtkDocParameter(param_name, position)
1397
+
1398
+ if param_fields:
1399
+ result = self._parse_fields(position,
1400
+ column_offset + param_fields_start,
1401
+ original_line,
1402
+ param_fields)
1403
+ if result.success:
1404
+ parameter.annotations = result.annotations
1405
+ parameter.description = result.description
1406
+
1407
+ comment_block.params[param_name] = parameter
1408
+ current_part = parameter
1409
+ continue
1410
+
1411
+ ####################################################################
1412
+ # Check for comment block description.
1413
+ #
1414
+ # When we are parsing parameter parts or the identifier part (when
1415
+ # there are no parameters) and encounter an empty line, we must be
1416
+ # parsing the comment block description.
1417
+ #
1418
+ # Note: it is unclear why GTK-Doc does not allow paragraph breaks
1419
+ # at this location as those might be handy describing
1420
+ # parameters from time to time...
1421
+ ####################################################################
1422
+ if (EMPTY_LINE_RE.match(line) and in_part in [PART_IDENTIFIER, PART_PARAMETERS]):
1423
+ in_part = PART_DESCRIPTION
1424
+ part_indent = line_indent
1425
+ continue
1426
+
1427
+ ####################################################################
1428
+ # Check for GTK-Doc comment block tags.
1429
+ ####################################################################
1430
+ result = TAG_RE.match(line)
1431
+ if result and line_indent <= part_indent:
1432
+ part_indent = line_indent
1433
+ tag_name = result.group('tag_name')
1434
+ tag_name_lower = tag_name.lower()
1435
+ tag_fields = result.group('fields')
1436
+ tag_fields_start = result.start('fields')
1437
+ marker = ' ' * (result.start('tag_name') + column_offset) + '^'
1438
+
1439
+ if tag_name_lower in DEPRECATED_GI_ANN_TAGS:
1440
+ # Deprecated GObject-Introspection specific tags.
1441
+ # Emit a warning and transform these into annotations on the identifier
1442
+ # instead, as agreed upon in http://bugzilla.gnome.org/show_bug.cgi?id=676133
1443
+ warn('GObject-Introspection specific GTK-Doc tag "%s" '
1444
+ 'has been deprecated, please use annotations on the identifier '
1445
+ 'instead:\n%s\n%s' % (tag_name, original_line, marker),
1446
+ position)
1447
+
1448
+ # Translate deprecated tag name into corresponding annotation name
1449
+ ann_name = tag_name_lower.replace(' ', '-')
1450
+
1451
+ if tag_name_lower == TAG_ATTRIBUTES:
1452
+ transformed = ''
1453
+ result = self._parse_fields(position,
1454
+ result.start('tag_name') + column_offset,
1455
+ line,
1456
+ tag_fields.strip(),
1457
+ False,
1458
+ False)
1459
+
1460
+ if result.success:
1461
+ for annotation in result.annotations:
1462
+ ann_options = self._parse_annotation_options_list(position, marker,
1463
+ line, annotation)
1464
+ n_options = len(ann_options)
1465
+ if n_options == 1:
1466
+ transformed = '%s %s' % (transformed, ann_options[0], )
1467
+ elif n_options == 2:
1468
+ transformed = '%s %s=%s' % (transformed, ann_options[0],
1469
+ ann_options[1])
1470
+ else:
1471
+ # Malformed Attributes: tag
1472
+ error('malformed "Attributes:" tag will be ignored:\n%s\n%s' %
1473
+ (original_line, marker),
1474
+ position)
1475
+ transformed = None
1476
+
1477
+ if transformed:
1478
+ transformed = '%s %s' % (ann_name, transformed.strip())
1479
+ ann_name, docannotation = self._parse_annotation(
1480
+ position,
1481
+ column_offset + tag_fields_start,
1482
+ original_line,
1483
+ transformed)
1484
+ stored_annotation = comment_block.annotations.get('attributes')
1485
+ if stored_annotation:
1486
+ error('Duplicate "Attributes:" annotation will '
1487
+ 'be ignored:\n%s\n%s' % (original_line, marker),
1488
+ position)
1489
+ else:
1490
+ comment_block.annotations[ann_name] = docannotation
1491
+ else:
1492
+ ann_name, options = self._parse_annotation(position,
1493
+ column_offset + tag_fields_start,
1494
+ line,
1495
+ '%s %s' % (ann_name, tag_fields))
1496
+ comment_block.annotations[ann_name] = options
1497
+
1498
+ continue
1499
+ elif tag_name_lower == TAG_DESCRIPTION:
1500
+ # Deprecated GTK-Doc Description: tag
1501
+ warn('GTK-Doc tag "Description:" has been deprecated:\n%s\n%s' %
1502
+ (original_line, marker),
1503
+ position)
1504
+
1505
+ in_part = PART_DESCRIPTION
1506
+
1507
+ if comment_block.description is None:
1508
+ comment_block.description = tag_fields
1509
+ else:
1510
+ comment_block.description += '\n%s' % (tag_fields, )
1511
+ continue
1512
+
1513
+ # Now that the deprecated stuff is out of the way, continue parsing real tags
1514
+ if (in_part == PART_DESCRIPTION
1515
+ or (in_part == PART_PARAMETERS and not comment_block.description)
1516
+ or (in_part == PART_IDENTIFIER and not comment_block.params and not
1517
+ comment_block.description)):
1518
+ in_part = PART_TAGS
1519
+
1520
+ if in_part != PART_TAGS:
1521
+ in_part = PART_TAGS
1522
+ warn('"%s:" tag unexpected at this location:\n%s\n%s' %
1523
+ (tag_name, original_line, marker),
1524
+ position)
1525
+
1526
+ if tag_name_lower in [TAG_RETURN, TAG_RETURNS,
1527
+ TAG_RETURN_VALUE, TAG_RETURNS_VALUE]:
1528
+ if not returns_seen:
1529
+ returns_seen = True
1530
+ else:
1531
+ error('encountered multiple return value parameters or tags for "%s".' %
1532
+ (comment_block.name, ),
1533
+ position)
1534
+
1535
+ tag = GtkDocTag(TAG_RETURNS, position)
1536
+
1537
+ if tag_fields:
1538
+ result = self._parse_fields(position,
1539
+ column_offset + tag_fields_start,
1540
+ original_line,
1541
+ tag_fields)
1542
+ if result.success:
1543
+ tag.annotations = result.annotations
1544
+ tag.description = result.description
1545
+
1546
+ comment_block.tags[TAG_RETURNS] = tag
1547
+ current_part = tag
1548
+ continue
1549
+ else:
1550
+ if tag_name_lower in comment_block.tags.keys():
1551
+ error('multiple "%s:" tags for identifier "%s":\n%s\n%s' %
1552
+ (tag_name, comment_block.name, original_line, marker),
1553
+ position)
1554
+
1555
+ tag = GtkDocTag(tag_name_lower, position)
1556
+
1557
+ if tag_fields:
1558
+ result = self._parse_fields(position,
1559
+ column_offset + tag_fields_start,
1560
+ original_line,
1561
+ tag_fields)
1562
+ if result.success:
1563
+ if result.annotations:
1564
+ error('annotations not supported for tag "%s:".' % (tag_name, ),
1565
+ position)
1566
+
1567
+ if tag_name_lower in [TAG_DEPRECATED, TAG_SINCE]:
1568
+ result = TAG_VALUE_VERSION_RE.match(result.description)
1569
+ tag.value = result.group('value')
1570
+ tag.description = result.group('description')
1571
+ elif tag_name_lower == TAG_STABILITY:
1572
+ result = TAG_VALUE_STABILITY_RE.match(result.description)
1573
+ tag.value = result.group('value').capitalize()
1574
+ tag.description = result.group('description')
1575
+
1576
+ comment_block.tags[tag_name_lower] = tag
1577
+ current_part = tag
1578
+ continue
1579
+
1580
+ ####################################################################
1581
+ # If we get here, we must be in the middle of a multiline
1582
+ # comment block, parameter or tag description.
1583
+ ####################################################################
1584
+ if EMPTY_LINE_RE.match(line) is None:
1585
+ line = line.rstrip()
1586
+
1587
+ if in_part in [PART_IDENTIFIER, PART_DESCRIPTION]:
1588
+ if not comment_block.description:
1589
+ if in_part == PART_IDENTIFIER:
1590
+ self._validate_multiline_annotation_continuation(line, original_line,
1591
+ column_offset, position)
1592
+ if comment_block.description is None:
1593
+ comment_block.description = line
1594
+ else:
1595
+ comment_block.description += '\n' + line
1596
+ continue
1597
+ elif in_part in [PART_PARAMETERS, PART_TAGS]:
1598
+ if not current_part.description:
1599
+ self._validate_multiline_annotation_continuation(line, original_line,
1600
+ column_offset, position)
1601
+ if current_part.description is None:
1602
+ current_part.description = line
1603
+ else:
1604
+ current_part.description += '\n' + line
1605
+ continue
1606
+
1607
+ ########################################################################
1608
+ # Finished parsing this comment block.
1609
+ ########################################################################
1610
+ if comment_block:
1611
+ # We have picked up a couple of \n characters that where not
1612
+ # intended. Strip those.
1613
+ if comment_block.description:
1614
+ comment_block.description = comment_block.description.strip()
1615
+
1616
+ for tag in comment_block.tags.values():
1617
+ self._clean_description_field(tag)
1618
+
1619
+ for param in comment_block.params.values():
1620
+ self._clean_description_field(param)
1621
+
1622
+ comment_block.indentation = block_indent
1623
+ comment_block.validate()
1624
+ return comment_block
1625
+ else:
1626
+ return None
1627
+
1628
+ def _clean_description_field(self, part):
1629
+ '''
1630
+ Remove extraneous leading and trailing whitespace from description fields.
1631
+
1632
+ :param part: a GTK-Doc comment block part having a description field
1633
+ '''
1634
+
1635
+ if part.description:
1636
+ if part.description.strip() == '':
1637
+ part.description = None
1638
+ else:
1639
+ if EMPTY_LINE_RE.match(part.description.split('\n', 1)[0]):
1640
+ part.description = part.description.rstrip()
1641
+ else:
1642
+ part.description = part.description.strip()
1643
+
1644
+ def _validate_multiline_annotation_continuation(self, line, original_line,
1645
+ column_offset, position):
1646
+ '''
1647
+ Validate annotatable parts' source text ensuring annotations don't span multiple lines.
1648
+ For example, the following comment block would result in a warning being emitted for
1649
+ the forth line::
1650
+
1651
+ /**
1652
+ * shiny_function:
1653
+ * @array_: (out caller-allocates) (array)
1654
+ * (element-type utf8) (transfer full): A beautiful array
1655
+ */
1656
+
1657
+ :param line: line to validate, stripped from ("``*/``") at start of the line.
1658
+ :param original_line: original line (including ("``*/``")) being validated
1659
+ :param column_offset: number of characters stripped from `line` when ("``*/``")
1660
+ was removed
1661
+ :param position: :class:`giscanner.message.Position` of `line` in the source file
1662
+ '''
1663
+
1664
+ result = self._parse_annotations(position, column_offset, original_line, line)
1665
+
1666
+ if result.success and result.annotations:
1667
+ marker = ' ' * (result.start_pos + column_offset) + '^'
1668
+ error('ignoring invalid multiline annotation continuation:\n%s\n%s' %
1669
+ (original_line, marker),
1670
+ position)
1671
+
1672
+ def _parse_annotation_options_list(self, position, column, line, options):
1673
+ '''
1674
+ Parse annotation options into a list. For example::
1675
+
1676
+ ┌──────────────────────────────────────────────────────────────┐
1677
+ │ 'option1 option2 option3' │ ─▷ source
1678
+ ├──────────────────────────────────────────────────────────────┤
1679
+ │ ['option1', 'option2', 'option3'] │ ◁─ parsed options
1680
+ └──────────────────────────────────────────────────────────────┘
1681
+
1682
+ :param position: :class:`giscanner.message.Position` of `line` in the source file
1683
+ :param column: start column of the `options` in the source file
1684
+ :param line: complete source line
1685
+ :param options: annotation options to parse
1686
+ :returns: a list of annotation options
1687
+ '''
1688
+
1689
+ parsed = []
1690
+
1691
+ if options:
1692
+ result = options.find('=')
1693
+ if result >= 0:
1694
+ marker = ' ' * (column + result) + '^'
1695
+ warn('invalid annotation options: expected a "list" but '
1696
+ 'received "key=value pairs":\n%s\n%s' % (line, marker),
1697
+ position)
1698
+ parsed = self._parse_annotation_options_unknown(position, column, line, options)
1699
+ else:
1700
+ parsed = options.split(' ')
1701
+
1702
+ return parsed
1703
+
1704
+ def _parse_annotation_options_dict(self, position, column, line, options):
1705
+ '''
1706
+ Parse annotation options into a dict. For example::
1707
+
1708
+ ┌──────────────────────────────────────────────────────────────┐
1709
+ │ 'option1=value1 option2 option3=value2' │ ─▷ source
1710
+ ├──────────────────────────────────────────────────────────────┤
1711
+ │ {'option1': 'value1', 'option2': None, 'option3': 'value2'} │ ◁─ parsed options
1712
+ └──────────────────────────────────────────────────────────────┘
1713
+
1714
+ :param position: :class:`giscanner.message.Position` of `line` in the source file
1715
+ :param column: start column of the `options` in the source file
1716
+ :param line: complete source line
1717
+ :param options: annotation options to parse
1718
+ :returns: an ordered dictionary of annotation options
1719
+ '''
1720
+
1721
+ parsed = OrderedDict()
1722
+
1723
+ if options:
1724
+ for p in options.split(' '):
1725
+ parts = p.split('=', 1)
1726
+ key = parts[0]
1727
+ value = parts[1] if len(parts) == 2 else None
1728
+ parsed[key] = value
1729
+
1730
+ return parsed
1731
+
1732
+ def _parse_annotation_options_unknown(self, position, column, line, options):
1733
+ '''
1734
+ Parse annotation options into a list holding a single item. This is used when the
1735
+ annotation options to parse in not known to be a list nor dict. For example::
1736
+
1737
+ ┌──────────────────────────────────────────────────────────────┐
1738
+ │ ' option1 option2 option3=value1 ' │ ─▷ source
1739
+ ├──────────────────────────────────────────────────────────────┤
1740
+ │ ['option1 option2 option3=value1'] │ ◁─ parsed options
1741
+ └──────────────────────────────────────────────────────────────┘
1742
+
1743
+ :param position: :class:`giscanner.message.Position` of `line` in the source file
1744
+ :param column: start column of the `options` in the source file
1745
+ :param line: complete source line
1746
+ :param options: annotation options to parse
1747
+ :returns: a list of annotation options
1748
+ '''
1749
+
1750
+ if options:
1751
+ return [options.strip()]
1752
+
1753
+ def _parse_annotation(self, position, column, line, annotation):
1754
+ '''
1755
+ Parse an annotation into the annotation name and a list or dict (depending on the
1756
+ name of the annotation) holding the options. For example::
1757
+
1758
+ ┌──────────────────────────────────────────────────────────────┐
1759
+ │ 'name opt1=value1 opt2=value2 opt3' │ ─▷ source
1760
+ ├──────────────────────────────────────────────────────────────┤
1761
+ │ 'name', {'opt1': 'value1', 'opt2':'value2', 'opt3':None} │ ◁─ parsed annotation
1762
+ └──────────────────────────────────────────────────────────────┘
1763
+
1764
+ ┌──────────────────────────────────────────────────────────────┐
1765
+ │ 'name opt1 opt2' │ ─▷ source
1766
+ ├──────────────────────────────────────────────────────────────┤
1767
+ │ 'name', ['opt1', 'opt2'] │ ◁─ parsed annotation
1768
+ └──────────────────────────────────────────────────────────────┘
1769
+
1770
+ ┌──────────────────────────────────────────────────────────────┐
1771
+ │ 'unkownname unknown list of options' │ ─▷ source
1772
+ ├──────────────────────────────────────────────────────────────┤
1773
+ │ 'unkownname', ['unknown list of options'] │ ◁─ parsed annotation
1774
+ └──────────────────────────────────────────────────────────────┘
1775
+
1776
+ :param position: :class:`giscanner.message.Position` of `line` in the source file
1777
+ :param column: start column of the `annotation` in the source file
1778
+ :param line: complete source line
1779
+ :param annotation: annotation to parse
1780
+ :returns: a tuple containing the annotation name and options
1781
+ '''
1782
+
1783
+ # Transform deprecated type syntax "tokens"
1784
+ annotation = annotation.replace('<', ANN_LPAR).replace('>', ANN_RPAR)
1785
+
1786
+ parts = annotation.split(' ', 1)
1787
+ ann_name = parts[0].lower()
1788
+ ann_options = parts[1] if len(parts) == 2 else None
1789
+
1790
+ if ann_name == ANN_INOUT_ALT:
1791
+ marker = ' ' * (column) + '^'
1792
+ warn('"%s" annotation has been deprecated, please use "%s" instead:\n%s\n%s' %
1793
+ (ANN_INOUT_ALT, ANN_INOUT, line, marker),
1794
+ position)
1795
+
1796
+ ann_name = ANN_INOUT
1797
+ elif ann_name == ANN_ATTRIBUTE:
1798
+ marker = ' ' * (column) + '^'
1799
+ warn('"%s" annotation has been deprecated, please use "%s" instead:\n%s\n%s' %
1800
+ (ANN_ATTRIBUTE, ANN_ATTRIBUTES, line, marker),
1801
+ position)
1802
+
1803
+ ann_name = ANN_ATTRIBUTES
1804
+ ann_options = self._parse_annotation_options_list(position, column, line, ann_options)
1805
+ n_options = len(ann_options)
1806
+ if n_options == 1:
1807
+ ann_options = ann_options[0]
1808
+ elif n_options == 2:
1809
+ ann_options = '%s=%s' % (ann_options[0], ann_options[1])
1810
+ else:
1811
+ marker = ' ' * (column) + '^'
1812
+ error('malformed "(attribute)" annotation will be ignored:\n%s\n%s' %
1813
+ (line, marker),
1814
+ position)
1815
+ return None, None
1816
+
1817
+ column += len(ann_name) + 2
1818
+
1819
+ if ann_name in LIST_ANNOTATIONS:
1820
+ ann_options = self._parse_annotation_options_list(position, column, line, ann_options)
1821
+ elif ann_name in DICT_ANNOTATIONS:
1822
+ ann_options = self._parse_annotation_options_dict(position, column, line, ann_options)
1823
+ else:
1824
+ ann_options = self._parse_annotation_options_unknown(position, column, line,
1825
+ ann_options)
1826
+
1827
+ return ann_name, ann_options
1828
+
1829
+ def _parse_annotations(self, position, column, line, fields, parse_options=True):
1830
+ '''
1831
+ Parse annotations into a :class:`GtkDocAnnotations` object.
1832
+
1833
+ :param position: :class:`giscanner.message.Position` of `line` in the source file
1834
+ :param column: start column of the `annotations` in the source file
1835
+ :param line: complete source line
1836
+ :param fields: string containing the fields to parse
1837
+ :param parse_options: whether options will be parsed into a :class:`GtkDocAnnotations`
1838
+ object or into a :class:`list`
1839
+ :returns: if `parse_options` evaluates to True a :class:`GtkDocAnnotations` object,
1840
+ a :class:`list` otherwise. If `line` does not contain any annotations,
1841
+ :const:`None`
1842
+ '''
1843
+
1844
+ if parse_options:
1845
+ parsed_annotations = GtkDocAnnotations(position)
1846
+ else:
1847
+ parsed_annotations = []
1848
+
1849
+ i = 0
1850
+ parens_level = 0
1851
+ prev_char = ''
1852
+ char_buffer = []
1853
+ start_pos = 0
1854
+ end_pos = 0
1855
+
1856
+ for i, cur_char in enumerate(fields):
1857
+ cur_char_is_space = cur_char.isspace()
1858
+
1859
+ if cur_char == ANN_LPAR:
1860
+ parens_level += 1
1861
+
1862
+ if parens_level == 1:
1863
+ start_pos = i
1864
+
1865
+ if prev_char == ANN_LPAR:
1866
+ marker = ' ' * (column + i) + '^'
1867
+ error('unexpected parentheses, annotations will be ignored:\n%s\n%s' %
1868
+ (line, marker),
1869
+ position)
1870
+ return _ParseAnnotationsResult(False, None, None, None)
1871
+ elif parens_level > 1:
1872
+ char_buffer.append(cur_char)
1873
+ elif cur_char == ANN_RPAR:
1874
+ parens_level -= 1
1875
+
1876
+ if prev_char == ANN_LPAR:
1877
+ marker = ' ' * (column + i) + '^'
1878
+ error('unexpected parentheses, annotations will be ignored:\n%s\n%s' %
1879
+ (line, marker),
1880
+ position)
1881
+ return _ParseAnnotationsResult(False, None, None, None)
1882
+ elif parens_level < 0:
1883
+ marker = ' ' * (column + i) + '^'
1884
+ error('unbalanced parentheses, annotations will be ignored:\n%s\n%s' %
1885
+ (line, marker),
1886
+ position)
1887
+ return _ParseAnnotationsResult(False, None, None, None)
1888
+ elif parens_level == 0:
1889
+ end_pos = i + 1
1890
+
1891
+ if parse_options is True:
1892
+ name, options = self._parse_annotation(position,
1893
+ column + start_pos,
1894
+ line,
1895
+ ''.join(char_buffer).strip())
1896
+ if name is not None:
1897
+ if name in parsed_annotations:
1898
+ marker = ' ' * (column + i) + '^'
1899
+ error('multiple "%s" annotations:\n%s\n%s' %
1900
+ (name, line, marker), position)
1901
+ parsed_annotations[name] = options
1902
+ else:
1903
+ parsed_annotations.append(''.join(char_buffer).strip())
1904
+
1905
+ char_buffer = []
1906
+ else:
1907
+ char_buffer.append(cur_char)
1908
+ elif cur_char_is_space:
1909
+ if parens_level > 0:
1910
+ char_buffer.append(cur_char)
1911
+ else:
1912
+ if parens_level == 0:
1913
+ break
1914
+ else:
1915
+ char_buffer.append(cur_char)
1916
+
1917
+ prev_char = cur_char
1918
+
1919
+ if parens_level > 0:
1920
+ marker = ' ' * (column + i) + '^'
1921
+ error('unbalanced parentheses, annotations will be ignored:\n%s\n%s' %
1922
+ (line, marker),
1923
+ position)
1924
+ return _ParseAnnotationsResult(False, None, None, None)
1925
+ else:
1926
+ return _ParseAnnotationsResult(True, parsed_annotations, start_pos, end_pos)
1927
+
1928
+ def _parse_fields(self, position, column, line, fields, parse_options=True,
1929
+ validate_description_field=True):
1930
+ '''
1931
+ Parse annotations out of field data. For example::
1932
+
1933
+ ┌──────────────────────────────────────────────────────────────┐
1934
+ │ '(skip): description of some parameter │ ─▷ source
1935
+ ├──────────────────────────────────────────────────────────────┤
1936
+ │ ({'skip': []}, 'description of some parameter') │ ◁─ annotations and
1937
+ └──────────────────────────────────────────────────────────────┘ remaining fields
1938
+
1939
+ :param position: :class:`giscanner.message.Position` of `line` in the source file
1940
+ :param column: start column of `fields` in the source file
1941
+ :param line: complete source line
1942
+ :param fields: string containing the fields to parse
1943
+ :param parse_options: whether options will be parsed into a :class:`GtkDocAnnotations`
1944
+ object or into a :class:`list`
1945
+ :param validate_description_field: :const:`True` to validate the description field
1946
+ :returns: if `parse_options` evaluates to True a :class:`GtkDocAnnotations` object,
1947
+ a :class:`list` otherwise. If `line` does not contain any annotations,
1948
+ :const:`None` and a string holding the remaining fields
1949
+ '''
1950
+ description_field = ''
1951
+ result = self._parse_annotations(position, column, line, fields, parse_options)
1952
+ if result.success:
1953
+ description_field = fields[result.end_pos:].strip()
1954
+
1955
+ if description_field and validate_description_field:
1956
+ if description_field.startswith(':'):
1957
+ description_field = description_field[1:]
1958
+ else:
1959
+ if result.end_pos > 0:
1960
+ marker_position = column + result.end_pos
1961
+ marker = ' ' * marker_position + '^'
1962
+ warn('missing ":" at column %s:\n%s\n%s' %
1963
+ (marker_position + 1, line, marker),
1964
+ position)
1965
+
1966
+ return _ParseFieldsResult(result.success, result.annotations, description_field)
1967
+
1968
+
1969
+ class GtkDocCommentBlockWriter(object):
1970
+ '''
1971
+ Serialized :class:`GtkDocCommentBlock` objects into GTK-Doc comment blocks.
1972
+ '''
1973
+
1974
+ def __init__(self, indent=True):
1975
+ #: :const:`True` if the original indentation preceding the "``*``" needs to be retained,
1976
+ #: :const:`False` otherwise. Default value is :const:`True`.
1977
+ self.indent = indent
1978
+
1979
+ def _serialize_annotations(self, annotations):
1980
+ '''
1981
+ Serialize an annotation field. For example::
1982
+
1983
+ ┌──────────────────────────────────────────────────────────────┐
1984
+ │ {'name': {'opt1': 'value1', 'opt2':'value2', 'opt3':None} │ ◁─ GtkDocAnnotations
1985
+ ├──────────────────────────────────────────────────────────────┤
1986
+ │ '(name opt1=value1 opt2=value2 opt3)' │ ─▷ serialized
1987
+ └──────────────────────────────────────────────────────────────┘
1988
+
1989
+ ┌──────────────────────────────────────────────────────────────┐
1990
+ │ {'name': ['opt1', 'opt2']} │ ◁─ GtkDocAnnotations
1991
+ ├──────────────────────────────────────────────────────────────┤
1992
+ │ '(name opt1 opt2)' │ ─▷ serialized
1993
+ └──────────────────────────────────────────────────────────────┘
1994
+
1995
+ ┌──────────────────────────────────────────────────────────────┐
1996
+ │ {'unkownname': ['unknown list of options']} │ ◁─ GtkDocAnnotations
1997
+ ├──────────────────────────────────────────────────────────────┤
1998
+ │ '(unkownname unknown list of options)' │ ─▷ serialized
1999
+ └──────────────────────────────────────────────────────────────┘
2000
+
2001
+ :param annotations: :class:`GtkDocAnnotations` to be serialized
2002
+ :returns: a string
2003
+ '''
2004
+
2005
+ serialized = []
2006
+
2007
+ for ann_name, options in annotations.items():
2008
+ if options:
2009
+ if isinstance(options, list):
2010
+ serialize_options = ' '.join(options)
2011
+ else:
2012
+ serialize_options = ''
2013
+
2014
+ for key, value in options.items():
2015
+ if value:
2016
+ serialize_options += '%s=%s ' % (key, value)
2017
+ else:
2018
+ serialize_options += '%s ' % (key, )
2019
+
2020
+ serialize_options = serialize_options.strip()
2021
+
2022
+ serialized.append('(%s %s)' % (ann_name, serialize_options))
2023
+ else:
2024
+ serialized.append('(%s)' % (ann_name, ))
2025
+
2026
+ return ' '.join(serialized)
2027
+
2028
+ def _serialize_parameter(self, parameter):
2029
+ '''
2030
+ Serialize a parameter.
2031
+
2032
+ :param parameter: :class:`GtkDocParameter` to be serialized
2033
+ :returns: a string
2034
+ '''
2035
+
2036
+ # parameter_name field
2037
+ serialized = '@%s' % (parameter.name, )
2038
+
2039
+ # annotations field
2040
+ if parameter.annotations:
2041
+ serialized += ': ' + self._serialize_annotations(parameter.annotations)
2042
+
2043
+ # description field
2044
+ if parameter.description:
2045
+ if parameter.description.startswith('\n'):
2046
+ serialized += ':' + parameter.description
2047
+ else:
2048
+ serialized += ': ' + parameter.description
2049
+ else:
2050
+ serialized += ':'
2051
+
2052
+ return serialized.split('\n')
2053
+
2054
+ def _serialize_tag(self, tag):
2055
+ '''
2056
+ Serialize a tag.
2057
+
2058
+ :param tag: :class:`GtkDocTag` to be serialized
2059
+ :returns: a string
2060
+ '''
2061
+
2062
+ # tag_name field
2063
+ serialized = tag.name.capitalize()
2064
+
2065
+ # annotations field
2066
+ if tag.annotations:
2067
+ serialized += ': ' + self._serialize_annotations(tag.annotations)
2068
+
2069
+ # value field
2070
+ if tag.value:
2071
+ serialized += ': ' + tag.value
2072
+
2073
+ # description field
2074
+ if tag.description:
2075
+ if tag.description.startswith('\n'):
2076
+ serialized += ':' + tag.description
2077
+ else:
2078
+ serialized += ': ' + tag.description
2079
+
2080
+ if not tag.value and not tag.description:
2081
+ serialized += ':'
2082
+
2083
+ return serialized.split('\n')
2084
+
2085
+ def write(self, block):
2086
+ '''
2087
+ Serialize a :class:`GtkDocCommentBlock` object.
2088
+
2089
+ :param block: :class:`GtkDocCommentBlock` to be serialized
2090
+ :returns: a string
2091
+ '''
2092
+
2093
+ if block is None:
2094
+ return ''
2095
+ else:
2096
+ lines = []
2097
+
2098
+ # Identifier part
2099
+ if block.name.startswith('SECTION'):
2100
+ lines.append(block.name)
2101
+ else:
2102
+ if block.annotations:
2103
+ annotations = self._serialize_annotations(block.annotations)
2104
+ lines.append('%s: %s' % (block.name, annotations))
2105
+ else:
2106
+ # Note: this delimiter serves no purpose other than most people being used
2107
+ # to reading/writing it. It is completely legal to ommit this.
2108
+ lines.append('%s:' % (block.name, ))
2109
+
2110
+ # Parameter parts
2111
+ for param in block.params.values():
2112
+ lines.extend(self._serialize_parameter(param))
2113
+
2114
+ # Comment block description part
2115
+ if block.description:
2116
+ lines.append('')
2117
+ for l in block.description.split('\n'):
2118
+ lines.append(l)
2119
+
2120
+ # Tag parts
2121
+ if block.tags:
2122
+ # Note: this empty line servers no purpose other than most people being used
2123
+ # to reading/writing it. It is completely legal to ommit this.
2124
+ lines.append('')
2125
+ for tag in block.tags.values():
2126
+ lines.extend(self._serialize_tag(tag))
2127
+
2128
+ # Restore comment block indentation and *
2129
+ if self.indent:
2130
+ indent = Counter(block.indentation).most_common(1)[0][0] or ' '
2131
+ if indent.endswith('\t'):
2132
+ start_indent = indent
2133
+ line_indent = indent + ' '
2134
+ else:
2135
+ start_indent = indent[:-1]
2136
+ line_indent = indent
2137
+ else:
2138
+ start_indent = ''
2139
+ line_indent = ' '
2140
+
2141
+ i = 0
2142
+ while i < len(lines):
2143
+ line = lines[i]
2144
+ if line:
2145
+ lines[i] = '%s* %s\n' % (line_indent, line)
2146
+ else:
2147
+ lines[i] = '%s*\n' % (line_indent, )
2148
+ i += 1
2149
+
2150
+ # Restore comment block start and end tokens
2151
+ lines.insert(0, '%s/**\n' % (start_indent, ))
2152
+ lines.append('%s*/\n' % (line_indent, ))
2153
+
2154
+ # Restore code before and after comment block start and end tokens
2155
+ if block.code_before:
2156
+ lines.insert(0, '%s\n' % (block.code_before, ))
2157
+
2158
+ if block.code_after:
2159
+ lines.append('%s\n' % (block.code_after, ))
2160
+
2161
+ return ''.join(lines)