gobject-introspection 2.2.4-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.
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)