testability-driver 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. data/README +1 -0
  2. data/bin/start_app_perf +199 -0
  3. data/bin/tdriver-devtools +3 -0
  4. data/config/sut_parameters.rb +39 -0
  5. data/ext/extconf.rb +67 -0
  6. data/ext/native_extensions.c +70 -0
  7. data/lib/matti.rb +30 -0
  8. data/lib/tdriver-devtools/behaviour/old/xml/example/flick-example.rb +223 -0
  9. data/lib/tdriver-devtools/behaviour/old/xml/example/impl.rb_invalid +194 -0
  10. data/lib/tdriver-devtools/behaviour/old/xml/generate_behaviour_xml.rb +95 -0
  11. data/lib/tdriver-devtools/behaviour/old/xml/lib/tdriver_generator.rb +722 -0
  12. data/lib/tdriver-devtools/behaviour/old/xml/qdoc_generator.rb +321 -0
  13. data/lib/tdriver-devtools/behaviour/old/xml/templates/behaviour.method.template +43 -0
  14. data/lib/tdriver-devtools/behaviour/old/xml/templates/behaviour.module.template +54 -0
  15. data/lib/tdriver-devtools/behaviour/old/xml/templates/behaviour.xml.argument.template +7 -0
  16. data/lib/tdriver-devtools/behaviour/old/xml/templates/behaviour.xml.argument_type.template +7 -0
  17. data/lib/tdriver-devtools/behaviour/old/xml/templates/behaviour.xml.exception.template +5 -0
  18. data/lib/tdriver-devtools/behaviour/old/xml/templates/behaviour.xml.howto.line.template +2 -0
  19. data/lib/tdriver-devtools/behaviour/old/xml/templates/behaviour.xml.howto.template +5 -0
  20. data/lib/tdriver-devtools/behaviour/old/xml/templates/behaviour.xml.method.template +23 -0
  21. data/lib/tdriver-devtools/behaviour/old/xml/templates/behaviour.xml.template +14 -0
  22. data/lib/tdriver-devtools/behaviour/old/xml/update +3 -0
  23. data/lib/tdriver-devtools/behaviour/xml/generate.rb +88 -0
  24. data/lib/tdriver-devtools/behaviour/xml/rdoc_behaviour_xml_generator.rb +1924 -0
  25. data/lib/tdriver-devtools/behaviour/xml/templates/behaviour.xml.argument.default.template +1 -0
  26. data/lib/tdriver-devtools/behaviour/xml/templates/behaviour.xml.argument.template +3 -0
  27. data/lib/tdriver-devtools/behaviour/xml/templates/behaviour.xml.argument_type.template +4 -0
  28. data/lib/tdriver-devtools/behaviour/xml/templates/behaviour.xml.exception.template +4 -0
  29. data/lib/tdriver-devtools/behaviour/xml/templates/behaviour.xml.method.arguments.template +4 -0
  30. data/lib/tdriver-devtools/behaviour/xml/templates/behaviour.xml.method.deprecated.template +3 -0
  31. data/lib/tdriver-devtools/behaviour/xml/templates/behaviour.xml.method.exceptions.template +3 -0
  32. data/lib/tdriver-devtools/behaviour/xml/templates/behaviour.xml.method.info.template +1 -0
  33. data/lib/tdriver-devtools/behaviour/xml/templates/behaviour.xml.method.returns.template +3 -0
  34. data/lib/tdriver-devtools/behaviour/xml/templates/behaviour.xml.method.tables.template +3 -0
  35. data/lib/tdriver-devtools/behaviour/xml/templates/behaviour.xml.method.template +12 -0
  36. data/lib/tdriver-devtools/behaviour/xml/templates/behaviour.xml.returns.template +5 -0
  37. data/lib/tdriver-devtools/behaviour/xml/templates/behaviour.xml.table.item.template +1 -0
  38. data/lib/tdriver-devtools/behaviour/xml/templates/behaviour.xml.table.row.template +2 -0
  39. data/lib/tdriver-devtools/behaviour/xml/templates/behaviour.xml.table.template +8 -0
  40. data/lib/tdriver-devtools/behaviour/xml/templates/behaviour.xml.template +14 -0
  41. data/lib/tdriver-devtools/behaviour/xml_generator/example/flick-example.rb +245 -0
  42. data/lib/tdriver-devtools/behaviour/xml_generator/example/sut.rb +964 -0
  43. data/lib/tdriver-devtools/behaviour/xml_generator/generate.rb +68 -0
  44. data/lib/tdriver-devtools/behaviour/xml_generator/lib/custom_rdoc_generator.rb +1865 -0
  45. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.argument.default.template +1 -0
  46. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.argument.template +3 -0
  47. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.argument_type.template +4 -0
  48. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.exception.template +4 -0
  49. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.method.arguments.template +4 -0
  50. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.method.deprecated.template +3 -0
  51. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.method.exceptions.template +3 -0
  52. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.method.info.template +1 -0
  53. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.method.returns.template +3 -0
  54. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.method.tables.template +3 -0
  55. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.method.template +12 -0
  56. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.returns.template +5 -0
  57. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.table.item.template +1 -0
  58. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.table.row.template +2 -0
  59. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.table.template +7 -0
  60. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.template +14 -0
  61. data/lib/tdriver-devtools/behaviour/xml_generator/update +3 -0
  62. data/lib/tdriver-devtools/doc/behaviour_xml/QtExampleGestureBehaviour.xml +138 -0
  63. data/lib/tdriver-devtools/doc/behaviour_xml/created.rid +1 -0
  64. data/lib/tdriver-devtools/doc/behaviour_xml/tdriver.hash +1 -0
  65. data/lib/tdriver-devtools/doc/feature_xml/qt_widget_hold.feature.xml +9 -0
  66. data/lib/tdriver-devtools/doc/feature_xml/qt_widget_tap.feature.xml +9 -0
  67. data/lib/tdriver-devtools/doc/generate.rb +892 -0
  68. data/lib/tdriver-devtools/doc/update +1 -0
  69. data/lib/tdriver-devtools/doc/xslt/html.rb +7 -0
  70. data/lib/tdriver-devtools/doc/xslt/template.xsl +1861 -0
  71. data/lib/tdriver-devtools/doc/xslt/update +3 -0
  72. data/lib/tdriver-devtools/plugin/placeholder.txt +1 -0
  73. data/lib/tdriver-devtools/tdriver-devtools.rb +404 -0
  74. data/lib/tdriver-devtools/tests/feature_tests/example/flick-example.rb +233 -0
  75. data/lib/tdriver-devtools/tests/feature_tests/example/impl.rb +194 -0
  76. data/lib/tdriver-devtools/tests/feature_tests/generate.rb +82 -0
  77. data/lib/tdriver-devtools/tests/feature_tests/lib/custom_rdoc_generator.rb +468 -0
  78. data/lib/tdriver-devtools/tests/feature_tests/templates/feature_attribute.template +5 -0
  79. data/lib/tdriver-devtools/tests/feature_tests/templates/feature_method.template +5 -0
  80. data/lib/tdriver-devtools/tests/feature_tests/templates/scenario_attribute.template +5 -0
  81. data/lib/tdriver-devtools/tests/feature_tests/templates/scenario_method.template +5 -0
  82. data/lib/tdriver-devtools/tests/feature_tests/update +3 -0
  83. data/lib/tdriver.rb +26 -0
  84. data/lib/tdriver/base/behaviour/behaviour.rb +32 -0
  85. data/lib/tdriver/base/behaviour/behaviours/object_behaviour_composition.rb +94 -0
  86. data/lib/tdriver/base/behaviour/behaviours/object_behaviour_description.rb +262 -0
  87. data/lib/tdriver/base/behaviour/behaviours/object_composition.rb +111 -0
  88. data/lib/tdriver/base/behaviour/factory.rb +380 -0
  89. data/lib/tdriver/base/behaviour/loader.rb +28 -0
  90. data/lib/tdriver/base/command_data/command_data.rb +51 -0
  91. data/lib/tdriver/base/command_data/loader.rb +25 -0
  92. data/lib/tdriver/base/errors.rb +131 -0
  93. data/lib/tdriver/base/loader.rb +38 -0
  94. data/lib/tdriver/base/state_object.rb +270 -0
  95. data/lib/tdriver/base/sut/adapter.rb +28 -0
  96. data/lib/tdriver/base/sut/controller.rb +119 -0
  97. data/lib/tdriver/base/sut/factory.rb +287 -0
  98. data/lib/tdriver/base/sut/generic/behaviours/application.rb +243 -0
  99. data/lib/tdriver/base/sut/generic/behaviours/controller.rb +67 -0
  100. data/lib/tdriver/base/sut/generic/behaviours/find.rb +96 -0
  101. data/lib/tdriver/base/sut/generic/behaviours/flash_behaviour.rb +346 -0
  102. data/lib/tdriver/base/sut/generic/behaviours/sut.rb +1268 -0
  103. data/lib/tdriver/base/sut/generic/behaviours/switchbox_behaviour.rb +182 -0
  104. data/lib/tdriver/base/sut/generic/behaviours/verification.rb +119 -0
  105. data/lib/tdriver/base/sut/generic/commands/application.rb +219 -0
  106. data/lib/tdriver/base/sut/generic/commands/key_sequence.rb +82 -0
  107. data/lib/tdriver/base/sut/generic/commands/screen_capture.rb +58 -0
  108. data/lib/tdriver/base/sut/generic/plugin.rb +96 -0
  109. data/lib/tdriver/base/sut/loader.rb +35 -0
  110. data/lib/tdriver/base/sut/sut.rb +67 -0
  111. data/lib/tdriver/base/test_object/abstract.rb +179 -0
  112. data/lib/tdriver/base/test_object/behaviours/syncronization.rb +94 -0
  113. data/lib/tdriver/base/test_object/behaviours/test_object.rb +787 -0
  114. data/lib/tdriver/base/test_object/factory.rb +618 -0
  115. data/lib/tdriver/base/test_object/identificator.rb +511 -0
  116. data/lib/tdriver/base/test_object/loader.rb +37 -0
  117. data/lib/tdriver/env.rb +21 -0
  118. data/lib/tdriver/loader.rb +36 -0
  119. data/lib/tdriver/matti.rb +35 -0
  120. data/lib/tdriver/report/error_recovery/tdriver_custom_error_recovery.rb +83 -0
  121. data/lib/tdriver/report/error_recovery/tdriver_error_recovery.rb +158 -0
  122. data/lib/tdriver/report/error_recovery/tdriver_error_recovery_settings.rb +98 -0
  123. data/lib/tdriver/report/report.rb +47 -0
  124. data/lib/tdriver/report/report_api.rb +207 -0
  125. data/lib/tdriver/report/report_combine.rb +86 -0
  126. data/lib/tdriver/report/report_crash_file_capture.rb +167 -0
  127. data/lib/tdriver/report/report_creator.rb +571 -0
  128. data/lib/tdriver/report/report_cucumber.rb +158 -0
  129. data/lib/tdriver/report/report_cucumber_listener.rb +337 -0
  130. data/lib/tdriver/report/report_cucumber_reporter.rb +335 -0
  131. data/lib/tdriver/report/report_data_presentation.rb +152 -0
  132. data/lib/tdriver/report/report_data_table.rb +64 -0
  133. data/lib/tdriver/report/report_execution_statistics.rb +284 -0
  134. data/lib/tdriver/report/report_file_capture.rb +159 -0
  135. data/lib/tdriver/report/report_grouping.rb +539 -0
  136. data/lib/tdriver/report/report_junit_xml.rb +147 -0
  137. data/lib/tdriver/report/report_rspec.rb +108 -0
  138. data/lib/tdriver/report/report_test_case_run.rb +621 -0
  139. data/lib/tdriver/report/report_test_run.rb +1286 -0
  140. data/lib/tdriver/report/report_test_unit.rb +175 -0
  141. data/lib/tdriver/report/report_writer.rb +1405 -0
  142. data/lib/tdriver/tdriver.rb +158 -0
  143. data/lib/tdriver/util/common.rb +24 -0
  144. data/lib/tdriver/util/common/array.rb +39 -0
  145. data/lib/tdriver/util/common/crc16.rb +100 -0
  146. data/lib/tdriver/util/common/environment.rb +153 -0
  147. data/lib/tdriver/util/common/error.rb +39 -0
  148. data/lib/tdriver/util/common/file.rb +315 -0
  149. data/lib/tdriver/util/common/gem.rb +108 -0
  150. data/lib/tdriver/util/common/kernel.rb +189 -0
  151. data/lib/tdriver/util/common/loader.rb +39 -0
  152. data/lib/tdriver/util/common/retryable.rb +98 -0
  153. data/lib/tdriver/util/common/string.rb +77 -0
  154. data/lib/tdriver/util/dbaccess/dbaccess.rb +188 -0
  155. data/lib/tdriver/util/dbaccess/dbconnection.rb +41 -0
  156. data/lib/tdriver/util/dbaccess/error.rb +35 -0
  157. data/lib/tdriver/util/dbaccess/loader.rb +29 -0
  158. data/lib/tdriver/util/dynamic_attribute_filter.rb +182 -0
  159. data/lib/tdriver/util/hooking.rb +434 -0
  160. data/lib/tdriver/util/loader.rb +65 -0
  161. data/lib/tdriver/util/localisation.rb +24 -0
  162. data/lib/tdriver/util/localisation/error.rb +32 -0
  163. data/lib/tdriver/util/localisation/loader.rb +28 -0
  164. data/lib/tdriver/util/localisation/localisation.rb +479 -0
  165. data/lib/tdriver/util/logger.rb +377 -0
  166. data/lib/tdriver/util/operator_data/error.rb +29 -0
  167. data/lib/tdriver/util/operator_data/loader.rb +26 -0
  168. data/lib/tdriver/util/operator_data/operator_data.rb +93 -0
  169. data/lib/tdriver/util/other/config.rb +221 -0
  170. data/lib/tdriver/util/parameter.rb +24 -0
  171. data/lib/tdriver/util/parameter/error.rb +45 -0
  172. data/lib/tdriver/util/parameter/loader.rb +37 -0
  173. data/lib/tdriver/util/parameter/parameter.rb +285 -0
  174. data/lib/tdriver/util/parameter/parameter_hash.rb +101 -0
  175. data/lib/tdriver/util/parameter/parameter_template.rb +120 -0
  176. data/lib/tdriver/util/parameter/parameter_user_api.rb +84 -0
  177. data/lib/tdriver/util/parameter/parameter_xml.rb +247 -0
  178. data/lib/tdriver/util/plugin/abstract.rb +60 -0
  179. data/lib/tdriver/util/plugin/error.rb +25 -0
  180. data/lib/tdriver/util/plugin/loader.rb +28 -0
  181. data/lib/tdriver/util/plugin/service.rb +200 -0
  182. data/lib/tdriver/util/recorder.rb +292 -0
  183. data/lib/tdriver/util/stats.rb +90 -0
  184. data/lib/tdriver/util/user_data/error.rb +29 -0
  185. data/lib/tdriver/util/user_data/loader.rb +26 -0
  186. data/lib/tdriver/util/user_data/user_data.rb +103 -0
  187. data/lib/tdriver/util/video_rec.rb +264 -0
  188. data/lib/tdriver/util/xml/abstraction.rb +47 -0
  189. data/lib/tdriver/util/xml/builder.rb +54 -0
  190. data/lib/tdriver/util/xml/document.rb +32 -0
  191. data/lib/tdriver/util/xml/element.rb +32 -0
  192. data/lib/tdriver/util/xml/error.rb +46 -0
  193. data/lib/tdriver/util/xml/loader.rb +46 -0
  194. data/lib/tdriver/util/xml/nil_element.rb +89 -0
  195. data/lib/tdriver/util/xml/nodeset.rb +32 -0
  196. data/lib/tdriver/util/xml/parsers/libxml/libxml.rb +140 -0
  197. data/lib/tdriver/util/xml/parsers/loader.rb +22 -0
  198. data/lib/tdriver/util/xml/parsers/nokogiri/abstraction.rb +111 -0
  199. data/lib/tdriver/util/xml/parsers/nokogiri/attribute.rb +54 -0
  200. data/lib/tdriver/util/xml/parsers/nokogiri/builder.rb +58 -0
  201. data/lib/tdriver/util/xml/parsers/nokogiri/document.rb +58 -0
  202. data/lib/tdriver/util/xml/parsers/nokogiri/element.rb +147 -0
  203. data/lib/tdriver/util/xml/parsers/nokogiri/loader.rb +42 -0
  204. data/lib/tdriver/util/xml/parsers/nokogiri/nodeset.rb +187 -0
  205. data/lib/tdriver/util/xml/xml.rb +170 -0
  206. data/lib/tdriver/verify/verify.rb +687 -0
  207. data/lib/tdriver/verify/verify.rb_org +630 -0
  208. data/lib/tdriver/version.rb +21 -0
  209. data/xml/behaviours/generic.xml +495 -0
  210. data/xml/defaults/generic.xml +97 -0
  211. data/xml/defaults/sut_generic.xml +36 -0
  212. data/xml/parameters/tdriver_parameters.xml +23 -0
  213. data/xml/templates/generic.xml +227 -0
  214. metadata +327 -0
@@ -0,0 +1,5 @@
1
+
2
+ <howto description="$HOWTO_DESCRIPTION">
3
+ $HOWTO_CODE
4
+ </howto>
5
+
@@ -0,0 +1,23 @@
1
+
2
+ <method name="$METHOD_NAME">
3
+
4
+ <description>$METHOD_DESCRIPTION</description>
5
+ <example>$METHOD_EXAMPLE</example>
6
+
7
+ <arguments>
8
+ $METHOD_ARGUMENTS
9
+ </arguments>
10
+
11
+ <exceptions>
12
+ $METHOD_EXCEPTIONS
13
+ </exceptions>
14
+
15
+ <howtos>
16
+ $METHOD_HOWTOS
17
+ </howtos>
18
+
19
+ <info>
20
+ $METHOD_INFO
21
+ </info>
22
+
23
+ </method>
@@ -0,0 +1,14 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <behaviours plugin="$REQUIRED_PLUGIN">
3
+
4
+ <behaviour name="$BEHAVIOUR_NAME" object_type="$OBJECT_TYPE" sut_type="$SUT_TYPE" input_type="$INPUT_TYPE" version="$VERSION">
5
+
6
+ <module name="$MODULE_NAME" />
7
+
8
+ <methods>
9
+ $BEHAVIOUR_METHODS
10
+ </methods>
11
+
12
+ </behaviour>
13
+
14
+ </behaviours>
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env sh
2
+ rm -rf doc
3
+ ruby generate_behaviour_xml.rb example/
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env ruby
2
+ ############################################################################
3
+ ##
4
+ ## Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
5
+ ## All rights reserved.
6
+ ## Contact: Nokia Corporation (testabilitydriver@nokia.com)
7
+ ##
8
+ ## This file is part of Testability Driver.
9
+ ##
10
+ ## If you have questions regarding the use of this file, please contact
11
+ ## Nokia at testabilitydriver@nokia.com .
12
+ ##
13
+ ## This library is free software; you can redistribute it and/or
14
+ ## modify it under the terms of the GNU Lesser General Public
15
+ ## License version 2.1 as published by the Free Software Foundation
16
+ ## and appearing in the file LICENSE.LGPL included in the packaging
17
+ ## of this file.
18
+ ##
19
+ ############################################################################
20
+ require 'rdoc/rdoc'
21
+
22
+ module RDoc
23
+
24
+ class RDoc
25
+
26
+ # install custom generator to RDoc
27
+ def install_generator( name, module_name, filename )
28
+
29
+ GENERATORS[ name.to_s.downcase ] = Generator.new( filename, module_name.intern , name.to_s.downcase )
30
+
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+
37
+ if $source.nil? and ARGV.count < 1
38
+
39
+ abort "Usage: #{ $0 } SOURCE_FILES [DESTINATION_FOLDER]"
40
+
41
+ else
42
+
43
+ $source = File.expand_path( $source || ARGV[ 0 ] )
44
+
45
+ $destination = File.expand_path( $destination || ARGV[ 1 ] || 'behaviour_xml' )
46
+
47
+ abort("File or folder %s not found" % $source ) unless File.exist?( $source )
48
+
49
+ end
50
+
51
+ begin
52
+
53
+ RDoc::RDoc.new.tap{ | rdoc |
54
+
55
+ rdoc.install_generator(
56
+ 'tdriver_behaviour_xml',
57
+ 'TDriverBehaviourGenerator',
58
+ File.expand_path( File.join( File.dirname( __FILE__ ), 'rdoc_behaviour_xml_generator.rb' ) )
59
+ )
60
+
61
+
62
+ current_dir = Dir.pwd
63
+
64
+ Dir.chdir( File.expand_path( $destination ) )
65
+
66
+ rdoc.document(
67
+ [
68
+ '--inline-source',
69
+ '--op', $destination,
70
+ '--fmt', 'tdriver_behaviour_xml',
71
+ '--force-update',
72
+ '--one-file',
73
+ ] << $source
74
+ )
75
+
76
+ # delete creater.rid timestamp file
77
+ File.delete('created.rid')
78
+
79
+ Dir.chdir( current_dir )
80
+
81
+ }
82
+
83
+ rescue RDoc::RDocError => exception
84
+
85
+ abort exception.message
86
+
87
+ end
88
+
@@ -0,0 +1,1924 @@
1
+ ############################################################################
2
+ ##
3
+ ## Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4
+ ## All rights reserved.
5
+ ## Contact: Nokia Corporation (testabilitydriver@nokia.com)
6
+ ##
7
+ ## This file is part of Testability Driver.
8
+ ##
9
+ ## If you have questions regarding the use of this file, please contact
10
+ ## Nokia at testabilitydriver@nokia.com .
11
+ ##
12
+ ## This library is free software; you can redistribute it and/or
13
+ ## modify it under the terms of the GNU Lesser General Public
14
+ ## License version 2.1 as published by the Free Software Foundation
15
+ ## and appearing in the file LICENSE.LGPL included in the packaging
16
+ ## of this file.
17
+ ##
18
+ ############################################################################
19
+
20
+ module Generators
21
+
22
+ abort("RDoc not available/loaded") unless defined?( RDoc )
23
+
24
+ class TDriverBehaviourGenerator
25
+
26
+ def initialize( options )
27
+
28
+ @templates = {}
29
+
30
+ @found_modules_and_methods = {}
31
+
32
+ @created_files = {}
33
+
34
+ load_templates
35
+
36
+ @options = options
37
+
38
+ @already_processed_files = []
39
+
40
+ @current_module_tests = []
41
+
42
+ @current_module = nil
43
+
44
+ @output = { :files => [], :classes => [], :modules => [], :attributes => [], :methods => [], :aliases => [], :constants => [], :requires => [], :includes => []}
45
+
46
+ @errors = []
47
+
48
+ end
49
+
50
+ def help( topic )
51
+
52
+ case topic
53
+
54
+ when 'description'
55
+ <<-EXAMPLE
56
+ # == description
57
+ # This method returns "String" as return value
58
+ def my_method( arguments )
59
+ return "string"
60
+ end
61
+ EXAMPLE
62
+
63
+ when 'returns'
64
+ <<-EXAMPLE
65
+ # == returns
66
+ # String
67
+ # description: example description
68
+ # example: "string"
69
+ #
70
+ def my_method( arguments )
71
+ return "string"
72
+ end
73
+ EXAMPLE
74
+
75
+ when 'arguments'
76
+ <<-EXAMPLE
77
+ # == arguments
78
+ # arg1
79
+ # Integer
80
+ # description: first argument can integer
81
+ # example: 10
82
+ # String
83
+ # description: ... or string
84
+ # example: "Hello"
85
+ #
86
+ # arg2
87
+ # Array
88
+ # description: MyArray
89
+ # example: [1,2,3]
90
+ # default: []
91
+ #
92
+ # *arg3
93
+ # Array
94
+ # description: MyMultipleArray
95
+ # example: ['a','b','c']
96
+ # default: []
97
+ #
98
+ # &block
99
+ # Proc
100
+ # description: MyMultipleArray
101
+ # example: ['a','b','c']
102
+ # default: []
103
+ def my_method( arg1, arg2, *arg3, &block )
104
+ # ...
105
+ end
106
+ EXAMPLE
107
+
108
+ when 'attr_argument'
109
+ <<-EXAMPLE
110
+ # == arguments
111
+ # value
112
+ # Integer
113
+ # description: first argument can integer
114
+ # example: 10
115
+ attr_writer :my_attribute
116
+
117
+ or
118
+
119
+ # == arguments
120
+ # value
121
+ # Integer
122
+ # description: first argument can integer
123
+ # example: 10
124
+ # String
125
+ # description: ... or string
126
+ # example: "Hello"
127
+ attr_writer :my_attribute # ... when input value can be either Integer or String
128
+ EXAMPLE
129
+
130
+
131
+ when 'exceptions'
132
+ <<-EXAMPLE
133
+ # == exceptions
134
+ # RuntimeError
135
+ # description: example exception #1
136
+ #
137
+ # ArgumentError
138
+ # description: example exception #2
139
+ def my_method
140
+
141
+ # ...
142
+
143
+ end
144
+ EXAMPLE
145
+
146
+ when 'behaviour_description'
147
+ <<-EXAMPLE
148
+ # == description
149
+ # This module contains demonstration implementation containing tags for documentation generation using gesture as an example
150
+ module MyBehaviour
151
+
152
+ # ...
153
+
154
+ end
155
+ EXAMPLE
156
+
157
+ when 'behaviour_name'
158
+ <<-EXAMPLE
159
+ # == behaviour
160
+ # MyPlatformSpecificBehaviour
161
+ module MyBehaviour
162
+
163
+ # ...
164
+
165
+ end
166
+ EXAMPLE
167
+
168
+ when 'behaviour_object_types'
169
+ <<-EXAMPLE
170
+ # == objects
171
+ # *
172
+ module MyBehaviour
173
+
174
+ # apply behaviour to any test object, except SUT
175
+
176
+ end
177
+
178
+ or
179
+
180
+ # == objects
181
+ # sut
182
+ module MyBehaviour
183
+
184
+ # apply behaviour only to SUT object
185
+
186
+ end
187
+
188
+ # == objects
189
+ # *;sut
190
+ module MyBehaviour
191
+
192
+ # apply behaviour to any test object, including SUT
193
+
194
+ end
195
+
196
+ or
197
+
198
+ # == objects
199
+ # MyObject
200
+ module MyBehaviour
201
+
202
+ # apply behaviour only to objects which type is 'MyObject'
203
+
204
+ end
205
+
206
+ or
207
+
208
+ # == objects
209
+ # MyObject;OtherObject
210
+ module MyBehaviour
211
+
212
+ # apply behaviour only to objects which type is 'MyObject' or 'OtherObject'
213
+ # if more object types needed use ';' as separator.
214
+
215
+ end
216
+
217
+
218
+ EXAMPLE
219
+
220
+ when 'behaviour_version'
221
+ <<-EXAMPLE
222
+ # == sut_version
223
+ # *
224
+ module MyBehaviour
225
+
226
+ # any sut version
227
+
228
+ end
229
+
230
+ or
231
+
232
+ # == sut_version
233
+ # 1.0
234
+ module MyBehaviour
235
+
236
+ # apply behaviour only to sut with version 1.0
237
+
238
+ end
239
+ EXAMPLE
240
+
241
+ when 'behaviour_input_type'
242
+ <<-EXAMPLE
243
+ # == input_type
244
+ # *
245
+ module MyBehaviour
246
+
247
+ # any input type
248
+
249
+ end
250
+
251
+ or
252
+
253
+ # == input_type
254
+ # touch
255
+ module MyBehaviour
256
+
257
+ # apply behaviour only to sut which input type is 'touch'
258
+
259
+ end
260
+
261
+ or
262
+
263
+ # == input_type
264
+ # touch;key
265
+ module MyBehaviour
266
+
267
+ # apply behaviour only to sut which input type is 'touch' or 'key'
268
+ # if more types needed use ';' as separator.
269
+
270
+ end
271
+
272
+ EXAMPLE
273
+
274
+ when 'behaviour_sut_type'
275
+ <<-EXAMPLE
276
+ # == sut_type
277
+ # *
278
+ module MyBehaviour
279
+
280
+ # any input type
281
+
282
+ end
283
+
284
+ or
285
+
286
+ # == sut_type
287
+ # XX
288
+ module MyBehaviour
289
+
290
+ # apply behaviour only to sut which sut type is 'XX'
291
+
292
+ end
293
+
294
+ or
295
+
296
+ # == sut_type
297
+ # XX;YY
298
+ module MyBehaviour
299
+
300
+ # apply behaviour only to sut which sut type is 'XX' or 'YY'
301
+ # if more types needed use ';' as separator.
302
+
303
+ end
304
+ EXAMPLE
305
+
306
+ when 'behaviour_requires'
307
+ <<-EXAMPLE
308
+ # == requires
309
+ # *
310
+ module MyBehaviour
311
+
312
+ # when no plugins required (TDriver internal/generic SUT behaviour)
313
+
314
+ end
315
+
316
+ or
317
+
318
+ # == requires
319
+ # testability-driver-my-plugin
320
+ module MyBehaviour
321
+
322
+ # when plugin 'testability-driver-my-plugin' is required
323
+
324
+ end
325
+ EXAMPLE
326
+
327
+ when 'table_format'
328
+
329
+ <<-EXAMPLE
330
+ # == tables
331
+ # table_name
332
+ # title: My table 1
333
+ # |header1|header2|header3|
334
+ # |1.1|1.2|1.3|
335
+ # |2.1|2.2|2.3|
336
+ # |3.1|3.2|3.3|
337
+ #
338
+ # another_table_name
339
+ # title: My table 2
340
+ # |id|value|
341
+ # |0|true|
342
+ # |1|false|
343
+ def my_method
344
+
345
+ # ...
346
+
347
+ end
348
+ EXAMPLE
349
+
350
+ when 'default_argument_value_already_given'
351
+ <<-EXAMPLE
352
+ # == arguments
353
+ # value
354
+ # Integer
355
+ # description: first argument can integer
356
+ # example: 10
357
+ # default: 1
358
+ # String
359
+ # description: ... or string
360
+ # example: "Hello"
361
+ # default: "a"
362
+ def my_method( value = 1 )
363
+
364
+ # ...
365
+
366
+ end
367
+ EXAMPLE
368
+
369
+ when 'default_value_mandatory_argument'
370
+
371
+ <<-EXAMPLE
372
+ # == arguments
373
+ # value
374
+ # Integer
375
+ # description: first argument can integer
376
+ # example: 10
377
+ # default: 1
378
+ def my_method( value )
379
+
380
+ # ...
381
+
382
+ end
383
+ EXAMPLE
384
+
385
+
386
+ else
387
+
388
+ 'Unknown help topic "%s"' % topic
389
+
390
+ end
391
+
392
+ end
393
+
394
+ def self.for( options )
395
+
396
+ new( options )
397
+
398
+ end
399
+
400
+ def load_templates
401
+
402
+ Dir.glob( File.join( File.dirname( File.expand_path( __FILE__ ) ), 'templates', '*.template' ) ).each{ | file |
403
+
404
+ name = File.basename( file ).gsub( '.template', '' )
405
+
406
+ @templates[ name ] = open( file, 'r' ).read
407
+
408
+ }
409
+
410
+ end
411
+
412
+ def generate( files )
413
+
414
+ # process files
415
+ files.each{ | file |
416
+
417
+ process_file( file ) unless @already_processed_files.include?( file.file_absolute_name )
418
+
419
+
420
+ }
421
+
422
+ # TODO: some other format for writing the hash to file...
423
+ #open("#{ $output_results_name }.hash", "w" ){ | file | file << @found_modules_and_methods.inspect }
424
+
425
+ end
426
+
427
+ def process_file( file )
428
+
429
+ @module_path = []
430
+
431
+ @current_file = file
432
+
433
+ process_modules( file.modules )
434
+
435
+ end
436
+
437
+ def process_modules( modules )
438
+
439
+ modules.each{ | _module |
440
+
441
+ unless @already_processed_files.include?( _module.full_name )
442
+
443
+ @module_path.push( _module.name )
444
+
445
+ process_module( _module )
446
+
447
+ @module_path.pop
448
+
449
+ end
450
+
451
+ }
452
+
453
+ end
454
+
455
+ def process_methods( methods )
456
+
457
+ @processing = "method"
458
+
459
+ results = []
460
+
461
+ methods.each{ | method |
462
+
463
+ results << process_method( method )
464
+
465
+ }
466
+
467
+ Hash[ results ]
468
+
469
+ end
470
+
471
+ def process_method_arguments_section( source, params_array )
472
+
473
+ result = []
474
+
475
+ current_argument = nil
476
+
477
+ current_argument_type = nil
478
+
479
+ current_section = nil
480
+
481
+ argument_index = -1
482
+
483
+ arguments_found = 0
484
+
485
+ source.lines.to_a.each_with_index{ | line, index |
486
+
487
+ # remove cr/lf
488
+ line.chomp!
489
+
490
+ # remove trailing whitespaces
491
+ line.rstrip!
492
+
493
+ # count nesting depth
494
+ line.match( /^(\s*)/ )
495
+
496
+ nesting = $1.size
497
+
498
+ # remove leading whitespaces
499
+ line.lstrip!
500
+
501
+ if nesting == 0
502
+
503
+ line =~ /^([*|&]{0,1}\w+(\#\w+?)*)$/i
504
+
505
+ unless $1.nil?
506
+
507
+ # argument name
508
+ current_argument = $1
509
+
510
+ arguments_found += 1 unless line.include?( "#" )
511
+
512
+ current_section = nil
513
+
514
+ current_argument_type = nil
515
+
516
+ result << { current_argument => { :argument_type_order => [], :types => {} } }
517
+
518
+ argument_index += 1
519
+
520
+ end
521
+
522
+ else
523
+
524
+ # is line content class name? (argument variable type)
525
+ line =~ /^(.*)$/i
526
+
527
+ if !$1.nil? && ( 65..90 ).include?( $1[0] ) && nesting == 1 # "Array", "String", "Integer"
528
+
529
+ #Kernel.const_get( $1 ) rescue abort( "Line %s: \"%s\" is not valid argument variable type. (e.g. OK: \"String\", \"Array\", \"Fixnum\" etc) " % [ index +1, $1 ] )
530
+
531
+ current_argument_type = $1
532
+
533
+ result[ argument_index ][ current_argument ][ :argument_type_order ] << $1
534
+
535
+ result[ argument_index ][ current_argument ][ :types ][ current_argument_type ] = {}
536
+
537
+ #result[ argument_index ][ current_argument ][ current_argument_type ] = {}
538
+
539
+ current_section = nil
540
+
541
+ else
542
+
543
+ raise_error("Unable add argument details (line %s: \"%s\") for \"%s\" due to argument variable type must be defined first.\nPlease note that argument type must start with capital letter (e.g. OK: \"String\" NOK: \"string\")" % [ index + 1, line, current_argument ] ) if current_argument_type.nil?
544
+
545
+ line =~ /^(.*?)\:{1}($|[\r\n\t\s]{1})(.*)$/i
546
+
547
+ if $1.nil?
548
+
549
+ raise_error("Unable add argument details (line %s: \"%s\") for \"%s\" due to section name not defined. Sections names are written in lowercase with trailing colon and whitespace (e.g. OK: \"example: 10\", NOK: \"example:10\")" % [ index +1, line, current_argument]) if $1.nil? && current_section.nil?
550
+
551
+ # remove leading & trailing whitespaces
552
+ section_content = line.strip
553
+
554
+ else
555
+
556
+ current_section = $1
557
+
558
+ if result[ argument_index ][ current_argument ][ :types ].has_key?( current_argument_type )
559
+
560
+ #unless result[ argument_index ][ current_argument ][ current_argument_type ].has_key?( current_section )
561
+ unless result[ argument_index ][ current_argument ][ :types ][ current_argument_type ].has_key?( current_section )
562
+
563
+ #result[ argument_index ][ current_argument ][ current_argument_type ][ current_section ] = ""
564
+ result[ argument_index ][ current_argument ][ :types ][ current_argument_type ][ current_section ] = ""
565
+
566
+ end
567
+
568
+
569
+ end
570
+
571
+ section_content = $3.strip
572
+
573
+ end
574
+
575
+ raise_error("Unable add argument details due to argument not defined. Argument name must start from pos 1 of comment. (e.g. \"# my_variable\" NOK: \"# my_variable\", \"#myvariable\")") if current_argument.nil?
576
+
577
+ if result[ argument_index ][ current_argument ][ :types ].has_key?( current_argument_type )
578
+
579
+ if result[ argument_index ][ current_argument ][ :types ][ current_argument_type ].has_key?( current_section )
580
+
581
+
582
+ # add one leading whitespace if current_section value is not empty
583
+ #section_content = " " + section_content unless result[ argument_index ][ current_argument ][ current_argument_type ][ current_section ].empty?
584
+ section_content = " " + section_content unless result[ argument_index ][ current_argument ][ :types ][ current_argument_type ][ current_section ].empty?
585
+
586
+ # store section_content to current_section
587
+ #result[ argument_index ][ current_argument ][ current_argument_type ][ current_section ] << section_content
588
+ result[ argument_index ][ current_argument ][ :types ][ current_argument_type ][ current_section ] << section_content
589
+
590
+ end
591
+
592
+ end
593
+
594
+ end
595
+
596
+ end
597
+
598
+ }
599
+
600
+ order = []
601
+
602
+ params_array = params_array.collect{ | o | [ o.first, Hash[:default, o[1], :optional, o.last] ] }
603
+
604
+ params_hash = Hash[ params_array ]
605
+
606
+ default_value_already_set = []
607
+
608
+ params_array.each{ | param |
609
+
610
+ if ( item = result.select{ | arg | arg.keys.include?( param.first ) }).empty?
611
+
612
+ raise_error("Error: Argument '#{ param.first }' is implemented but not documented in '#{ @current_method.name }' ($MODULE).\nNote that documented argument and variable name must be identical.", [ 'writer', 'accessor' ].include?( @processing ) ? 'attr_argument' : 'arguments' ) unless param.first.to_s.include?("#")
613
+
614
+ order << { param.first => {} }
615
+
616
+ else
617
+
618
+ arg = item.first
619
+ arg_name = arg.keys.first
620
+
621
+ # apply overriding default argument value from documentation
622
+ arg[ arg_name ][ :argument_type_order ].each{ | type_name |
623
+
624
+ type_hash = arg[ arg_name ][ :types ][ type_name ]
625
+
626
+ unless type_hash["default"].nil?
627
+
628
+ if arg[ arg_name ][ :default ].nil?
629
+
630
+ if params_hash[ arg_name ][ :optional ] == false
631
+
632
+ raise_error("Error: Default value given for mandatory argument #{ arg_name } (type: #{ type_name }).", 'default_value_mandatory_argument' )
633
+
634
+ else
635
+
636
+ arg[ arg_name ][ :default ] = type_hash["default"]
637
+
638
+ end
639
+
640
+ else
641
+ raise_error("Error: Default value already given for #{ arg_name } (type: #{ type_name }).", 'default_argument_value_already_given' )
642
+ end
643
+
644
+ end
645
+ }
646
+
647
+ # if optional parameter and no overriding value defined, add one from implementation
648
+ if arg[ arg_name ][:default].nil?
649
+
650
+ arg[ arg_name ][ :default ] = params_hash[ arg_name ][ :default ] if params_hash[ arg_name ][ :optional ] == true
651
+
652
+ end
653
+
654
+ order << arg
655
+
656
+ end
657
+
658
+ }
659
+
660
+ # collect all argument names and add block arguments if any
661
+ found_keys = order.collect{ | pair | pair.keys }.flatten
662
+
663
+ # collect all documented argument names
664
+ documented_arguments = result.collect{ | arg | arg.keys }.flatten
665
+
666
+ unimplemented_arguments = ( documented_arguments - found_keys )
667
+
668
+ unless [ :attributes ].include?( @processing )
669
+
670
+ unless unimplemented_arguments.empty?
671
+
672
+ unimplemented_arguments.each{ | argument |
673
+
674
+ raise_error("Error: Argument '#{ argument }' is documented but not implemented in '#{ @current_method.name }' ($MODULE).\nNote that documented argument and variable name must be identical.", [ :attributes ].include?( @processing ) ? 'attr_argument' : 'arguments' )
675
+
676
+ }
677
+
678
+ # remove unimplemented argument documentation
679
+ result = result.select{ | documented_argument |
680
+
681
+ # always add block parameters
682
+ unimplemented_arguments.include?( documented_argument.to_a.flatten.first ) == false || documented_argument.to_a.flatten.first.include?("#")
683
+
684
+ }
685
+
686
+ end
687
+
688
+ end
689
+
690
+ # add missing/undocumented arguments to order list
691
+ missing = result.collect{ | value | order << value unless found_keys.include?( value.keys.first ) }
692
+
693
+ [ order, arguments_found ]
694
+
695
+ end
696
+
697
+ def process_table( source )
698
+
699
+ result = []
700
+
701
+ table_name = nil
702
+ header_columns = 0
703
+
704
+ source.lines.to_a.each_with_index{ | line, index |
705
+
706
+ # remove cr/lf
707
+ line.chomp!
708
+
709
+ # remove trailing whitespaces
710
+ line.rstrip!
711
+
712
+ # count nesting depth
713
+ line.match( /^(\s*)/ )
714
+
715
+ nesting = $1.size
716
+
717
+ #puts "%s,%s: %s" % [ index, nesting, line ]
718
+
719
+ # new table
720
+ if nesting == 0
721
+
722
+ # break if for some reason first character is "="
723
+ return result if line[0].chr == "="
724
+
725
+ unless line.empty?
726
+
727
+ line =~ /^(\w+)/i
728
+
729
+ result << { "name" => $1, "content" => [] }
730
+
731
+ table_name = $1.to_s
732
+
733
+ else
734
+
735
+ table_name = nil
736
+
737
+ end
738
+
739
+ else
740
+
741
+ line.lstrip!
742
+
743
+ if line[0].chr == '|'
744
+
745
+ unless table_name.nil?
746
+
747
+ if line[-1].chr != '|'
748
+
749
+ raise_error( "Malformed custom table #{ result.last[ "name" ]}, line '#{ line }' ($MODULE). Line must start and end with '|' character.", "table_format" )
750
+
751
+ else
752
+
753
+ line[0] = ""
754
+ line[-1] = ""
755
+
756
+ columns = line.split("|")
757
+
758
+ unless result.last[ "content" ].empty?
759
+
760
+ raise_error( "Malformed custom table #{ result.last[ "name" ]}, line '#{ line }' ($MODULE). Number of columns (#{ columns.count }) does not match with header (#{ header_columns })", "table_format" ) if columns.count != header_columns
761
+
762
+ else
763
+
764
+ header_columns = columns.count
765
+
766
+ end
767
+
768
+ result.last[ "content" ] << columns
769
+
770
+ end
771
+
772
+ else
773
+
774
+ raise_error( "Malformed custom table #{ result.last[ "name" ]} ($MODULE). Table name is missing.", "table_format" )
775
+
776
+ end
777
+
778
+ else
779
+
780
+ unless line.empty?
781
+
782
+ line =~ /^(.*?)\:{1}($|[\r\n\t\s]{1})(.*)$/i
783
+
784
+ if $1.to_s.empty?
785
+
786
+ raise_error( "Malformed custom table #{ result.last[ "name" ]}, line '#{ line }' ($MODULE). Table section name (e.g title) is missing.", "table_format" )
787
+
788
+ else
789
+
790
+ result.last[ $1.to_s ] = ( $3 || "" ).strip
791
+
792
+ end
793
+
794
+ else
795
+
796
+ table_name = nil
797
+
798
+ end
799
+
800
+ end
801
+
802
+ end
803
+
804
+ }
805
+
806
+ result
807
+
808
+ end
809
+
810
+ def process_formatted_section( source )
811
+
812
+ result = []
813
+
814
+ current_argument_type = nil
815
+
816
+ current_section = nil
817
+
818
+ argument_index = -1
819
+
820
+ constants_to_classes = { "nil" => "NilClass", "true" => "TrueClass", "false" => "FalseClass" }
821
+
822
+ source.lines.to_a.each_with_index{ | line, index |
823
+
824
+ # remove cr/lf
825
+ line.chomp!
826
+
827
+ # remove trailing whitespaces
828
+ line.rstrip!
829
+
830
+ # count nesting depth
831
+ line.match( /^(\s*)/ )
832
+
833
+ nesting = $1.size
834
+
835
+ # remove leading whitespaces
836
+ line.lstrip!
837
+
838
+ if nesting == 0
839
+
840
+ # convert constants nil, true, false to real class names
841
+ line = constants_to_classes[ line.downcase ] if constants_to_classes.include?( line.downcase )
842
+
843
+ line =~ /^(.+)/i
844
+
845
+ if !$1.nil? && (65..90).include?( $1[0] )
846
+
847
+ #Kernel.const_get( $1 ) rescue abort( "Line %s: \"%s\" is not valid argument variable type. (e.g. OK: \"String\", \"Array\", \"Fixnum\" etc) " % [ index + 1, $1 ] ) if verify_type
848
+
849
+ # argument type
850
+ current_argument_type = $1 || ""
851
+
852
+ current_section = nil
853
+
854
+ result << { current_argument_type => {} }
855
+
856
+ argument_index += 1
857
+
858
+ end
859
+
860
+ else
861
+
862
+ raise_error("Unable add value details (line %s: \"%s\") for %s due to detail type must be defined first.\nPlease note that return value and exception type must start with capital letter (e.g. OK: \"String\" NOK: \"string\")" % [ index + 1, line, current_argument_type ] ) if current_argument_type.nil?
863
+
864
+ line =~ /^(.*?)\:{1}($|[\r\n\t\s]{1})(.*)$/i
865
+
866
+ if $1.nil?
867
+
868
+ raise_error("Unable add value details (line %s: \"%s\") for %s due to section name not defined. Sections names are written in lowercase with trailing colon and whitespace (e.g. OK: \"example: 10\", NOK: \"example:10\")" % [ index +1, line, current_argument_type ]) if $1.nil? && current_section.nil?
869
+
870
+ # remove leading & trailing whitespaces
871
+ section_content = line.strip
872
+
873
+ else
874
+
875
+ current_section = $1
876
+
877
+ if result[ argument_index ].has_key?( current_argument_type )
878
+
879
+ unless result[ argument_index ][ current_argument_type ].has_key?( current_section )
880
+
881
+ result[ argument_index ][ current_argument_type ][ current_section ] = ""
882
+
883
+ end
884
+
885
+ end
886
+
887
+ section_content = ( $3 || "" ).strip
888
+
889
+ end
890
+
891
+ if current_argument_type.nil?
892
+
893
+ raise_error("Unable add return value details due to variable type not defined. Argument type must be defined at pos 1 of comment. (e.g. \"# Integer\" NOK: \"# Integer\", \"#Integer\")")
894
+
895
+ else
896
+
897
+ # add one leading whitespace if current_section value is not empty
898
+ section_content = " " + section_content unless result[ argument_index ][ current_argument_type ][ current_section ].empty?
899
+
900
+ # store section_content to current_section
901
+ result[ argument_index ][ current_argument_type ][ current_section ] << section_content
902
+
903
+ end
904
+
905
+ end
906
+
907
+
908
+ }
909
+
910
+ result
911
+
912
+ end
913
+
914
+ =begin
915
+ def store_to_results( module_name, name, type, params )
916
+
917
+ unless @found_modules_and_methods.has_key?( module_name )
918
+
919
+ @found_modules_and_methods[ module_name ] = []
920
+
921
+ end
922
+
923
+ #p params.select{ | param | param.last == false }
924
+ #p params.select{ | param | param.last == true }
925
+
926
+ #exit
927
+
928
+ count = "%s;%s" % [ params.count, params.select{ | param | param.last == true }.count ]
929
+
930
+ @found_modules_and_methods[ module_name ] << "%s#%s#%s" % [ name, type, count ] #{ :name => name, :type => type }
931
+
932
+ end
933
+ =end
934
+
935
+ def process_arguments( arguments )
936
+
937
+ return [] if arguments.to_s.empty?
938
+
939
+ arguments = arguments[ 1 .. -2 ] if arguments[0].chr == "(" and arguments[-1].chr ==")"
940
+
941
+ arguments.strip!
942
+
943
+ # tokenize string
944
+ tokenizer = RubyLex.new( arguments )
945
+
946
+ # get first token
947
+ token = tokenizer.token
948
+
949
+ # set previous token to nil by default
950
+ previous_token = nil
951
+
952
+ args = []
953
+
954
+ capture = true
955
+ capture_depth = []
956
+ capture_default = false
957
+
958
+ default_value = []
959
+
960
+ # loop while tokens available
961
+ while token
962
+
963
+ if [ RubyToken::TkLBRACE, RubyToken::TkLPAREN, RubyToken::TkLBRACK ].include?( token.class )
964
+
965
+ default_value << token.text if capture_default
966
+
967
+ capture_depth << token
968
+
969
+ capture = false
970
+
971
+ elsif [ RubyToken::TkRBRACE, RubyToken::TkRPAREN, RubyToken::TkRBRACK ].include?( token.class )
972
+
973
+ default_value << token.text if capture_default
974
+
975
+ capture_depth.pop
976
+
977
+ capture = true if capture_depth.empty?
978
+
979
+ # argument name
980
+ elsif capture == true
981
+
982
+ # argument name, or part of argument default value
983
+ if token.kind_of?( RubyToken::TkIDENTIFIER ) and ![ RubyToken::TkDOT, RubyToken::TkCOLON2 ].include?( previous_token.class )
984
+
985
+ args << [ token.name, nil, false ]
986
+
987
+ # &blocks and *arguments are handled as optional parameters
988
+ if [ RubyToken::TkBITAND, RubyToken::TkMULT ].include?( previous_token.class )
989
+ #args.last[ 1 ] = previous_token.text
990
+
991
+ args.last[ 0 ] = previous_token.text + args.last[ 0 ]
992
+ args.last[ -1 ] = true
993
+
994
+ end
995
+
996
+ default_value = []
997
+ capture_default = false
998
+
999
+ elsif token.kind_of?( RubyToken::TkCOMMA )
1000
+
1001
+ capture_default = false
1002
+
1003
+ # detect optional argument
1004
+ elsif token.kind_of?( RubyToken::TkASSIGN )
1005
+
1006
+ capture_default = true
1007
+
1008
+ # mark arguments as optional
1009
+ args.last[ -1 ] = true
1010
+
1011
+ else
1012
+
1013
+ default_value << token.text if capture_default && ![ RubyToken::TkSPACE, RubyToken::TkNL ].include?( token.class )
1014
+
1015
+ end
1016
+
1017
+ else
1018
+
1019
+ default_value << token.text if capture_default && ![ RubyToken::TkSPACE, RubyToken::TkNL ].include?( token.class )
1020
+
1021
+ end
1022
+
1023
+ unless default_value.empty?
1024
+
1025
+ args.last[ 1 ] = default_value.join("")
1026
+
1027
+ end
1028
+
1029
+ # store previous token
1030
+ previous_token = token
1031
+
1032
+ # get next token
1033
+ token = tokenizer.token
1034
+
1035
+ end
1036
+
1037
+ args
1038
+
1039
+ end
1040
+
1041
+ def process_undocumented_method_arguments( params )
1042
+
1043
+ params.collect{ | param |
1044
+
1045
+ hash = {}
1046
+ hash[ :types ] = {}
1047
+ hash[ :default ] = param[1] if param[-1] == true
1048
+
1049
+ { param.first.to_s => hash }
1050
+
1051
+ }
1052
+
1053
+ end
1054
+
1055
+ def process_method( method )
1056
+
1057
+ results = []
1058
+
1059
+ method_header = nil
1060
+
1061
+ # if this tag ("== nodoc") is found in method description, it should not be added to documentation
1062
+ no_doc = false
1063
+
1064
+ if ( method.visibility == :public && @module_path.first =~ /MobyBehaviour/ )
1065
+
1066
+ params = method.kind_of?( RDoc::Attr ) ? [] : process_arguments( method.params )
1067
+
1068
+ @current_method = method
1069
+
1070
+ method_header = process_comment( method.comment )
1071
+
1072
+ ## TODO: remember to verify that there are documentation for each argument!
1073
+ ## TODO: verify that there is a tag for visualizer example
1074
+
1075
+ arguments_found = 0
1076
+
1077
+ method_header = Hash[ method_header.collect{ | key, value |
1078
+
1079
+ if key == :nodoc
1080
+
1081
+ no_doc = true
1082
+
1083
+ end
1084
+
1085
+ if key == :arguments
1086
+
1087
+ value, arguments_found = process_method_arguments_section( value, params )
1088
+
1089
+ end
1090
+
1091
+ if key == :returns
1092
+
1093
+ value = process_formatted_section( value )
1094
+
1095
+ end
1096
+
1097
+ if key == :exceptions
1098
+
1099
+ value = process_formatted_section( value )
1100
+
1101
+ end
1102
+
1103
+ if key == :tables
1104
+
1105
+ value = process_table( value )
1106
+
1107
+ end
1108
+
1109
+ [ key, value ]
1110
+
1111
+ }]
1112
+
1113
+ method_header[ :__arguments_found ] = arguments_found
1114
+
1115
+ # if no description found for arguments, add argument names to method_header hash
1116
+ if ( params.count > 0 ) && ( method_header[ :arguments ].nil? || method_header[:arguments].empty? )
1117
+
1118
+ #p params.count,
1119
+ method_header[:arguments] = process_undocumented_method_arguments( params )
1120
+
1121
+ end
1122
+
1123
+ method_name = method.name.clone
1124
+
1125
+ type = "method"
1126
+
1127
+ if method.kind_of?( RDoc::Attr )
1128
+
1129
+ case method.rw
1130
+
1131
+ when "R"
1132
+ type = "reader"
1133
+ #store_to_results( @module_path.join("::"), method.name, type )
1134
+ when "W"
1135
+ type = "writer"
1136
+ method_name << "="
1137
+ #store_to_results( @module_path.join("::"), method.name + "=", type )
1138
+ when "RW"
1139
+ type = "accessor"
1140
+ #method_name << ";#{ method_name }="
1141
+ #store_to_results( @module_path.join("::"), method.name + "=", type )
1142
+
1143
+ else
1144
+
1145
+ raise_error( "Unknown attribute format for '#{ method.name }' ($MODULE). Expected 'R' (attr_reader), 'W' (attr_writer) or 'RW' (attr_accessor), got: '#{ method.rw }'" )
1146
+
1147
+ end
1148
+
1149
+ #store_to_results( @module_path.join("::"), method.name, type )
1150
+
1151
+ method_header.merge!( :__type => type )
1152
+
1153
+ else
1154
+
1155
+ method_header.merge!( :__type => "method" )
1156
+
1157
+ end
1158
+
1159
+ #p params
1160
+
1161
+ #sleep 0.3
1162
+
1163
+ method_header.merge!(
1164
+ :__arguments_implemented => params.count ,
1165
+ :__arguments_optional => params.select{ | param | param.last == true }.count
1166
+ )
1167
+
1168
+ #store_to_results( @module_path.join("::"), method.name, type, params )
1169
+
1170
+ #no_doc ? nil :
1171
+ [ method_name, method_header ]
1172
+
1173
+ else
1174
+
1175
+ nil
1176
+
1177
+ end
1178
+
1179
+ end
1180
+
1181
+ # verify if
1182
+ def has_method?( target, method_name )
1183
+
1184
+ target.method_list.select{ | method |
1185
+
1186
+ method.name == method_name
1187
+
1188
+ }.count > 0
1189
+
1190
+ end
1191
+
1192
+ def encode_string( string )
1193
+
1194
+ return "" if string.nil?
1195
+
1196
+ result = "%s" % string
1197
+
1198
+ result.gsub!( /\&/, '&amp;' )
1199
+ result.gsub!( /\</, '&lt;' )
1200
+ result.gsub!( /\>/, '&gt;' )
1201
+ result.gsub!( /\"/, '&quot;' )
1202
+ result.gsub!( /\'/, '&apos;' )
1203
+
1204
+ result
1205
+
1206
+ end
1207
+
1208
+ def process_attributes( attributes )
1209
+
1210
+ @processing = :attributes
1211
+
1212
+ results = []
1213
+
1214
+ attributes.each{ | attribute |
1215
+
1216
+ results << process_method( attribute )
1217
+
1218
+ }
1219
+
1220
+ Hash[ results ]
1221
+
1222
+ end
1223
+
1224
+ def process_comment( comment )
1225
+
1226
+ header = {}
1227
+
1228
+ current_section = nil
1229
+
1230
+ return header if comment.nil? || comment.empty?
1231
+
1232
+ comment.each_line{ | line |
1233
+
1234
+ # remove '#' char from beginning of line
1235
+ line.slice!( 0 )
1236
+
1237
+ # if next character is whitespace assume that this is valid comment line
1238
+ # NOTE: that if linefeed is required use "#<#32><#10>"
1239
+ if [ 32 ].include?( line[ 0 ] )
1240
+
1241
+ # remove first character
1242
+ line.slice!( 0 )
1243
+
1244
+ # if line is a section header
1245
+ if line[ 0..2 ] == "== "
1246
+
1247
+ # remove section header indicator string ("== ")
1248
+ line.slice!( 0..2 )
1249
+
1250
+ # remove cr/lf
1251
+ line.gsub!( /[\n\r]/, "" )
1252
+
1253
+ current_section = line.to_sym
1254
+
1255
+ header[ current_section ] = "nodoc" if line.to_s == "nodoc"
1256
+
1257
+ else
1258
+
1259
+ unless current_section.nil?
1260
+
1261
+ # remove cr/lf
1262
+ # NOTE: if crlf is required use '\n'
1263
+ line.gsub!( /[\n\r]/, "" )
1264
+
1265
+ # store to header hash
1266
+ if header.has_key?( current_section )
1267
+
1268
+ header[ current_section ] << "\n" << ( line.rstrip )
1269
+
1270
+ else
1271
+
1272
+ header[ current_section ] = line.rstrip
1273
+
1274
+ end
1275
+
1276
+ else
1277
+
1278
+ #puts "[nodoc?] %s" % line
1279
+
1280
+ end
1281
+
1282
+ end
1283
+
1284
+ else
1285
+
1286
+ #puts "[nodoc] %s" % line
1287
+
1288
+ end
1289
+
1290
+ }
1291
+
1292
+ header
1293
+
1294
+ end
1295
+
1296
+ def apply_macros!( source, macros )
1297
+
1298
+ macros.each_pair{ | key, value |
1299
+
1300
+ while result = /(\$#{ key }\b)/.match( source )
1301
+
1302
+ source = source[0..result.begin(0)-1] + value.to_s + source[result.end(0)..-1]
1303
+
1304
+ end
1305
+
1306
+ }
1307
+
1308
+ source
1309
+
1310
+ end
1311
+
1312
+ def raise_error( text, topic = nil )
1313
+
1314
+ type = ( @processing == "method" ) ? "method" : "attribute"
1315
+
1316
+ text.gsub!( '$TYPE', type )
1317
+
1318
+ text.gsub!( '$MODULE', @current_module.full_name )
1319
+
1320
+ text = "=========================================================================================================\n" <<
1321
+ "File: #{ @module_in_files.join(", ") }\n" << text << "\n\nExample:\n\n"
1322
+
1323
+ text << help( topic ) unless topic.nil?
1324
+
1325
+ warn( text << "\n" )
1326
+
1327
+ end
1328
+
1329
+ def generate_return_values_element( header, feature )
1330
+
1331
+ return "" if ( [ 'writer' ].include?( feature.last[ :__type ] ) )
1332
+
1333
+ return if feature.last[ :returns ].nil? || feature.last[ :returns ].empty?
1334
+
1335
+ if feature.last[ :returns ].nil?
1336
+
1337
+ raise_error("Error: $TYPE '#{ feature.first }' ($MODULE) doesn't have return value type(s) defined", 'returns' )
1338
+
1339
+ end
1340
+
1341
+ count = 0
1342
+
1343
+ # generate return value types template
1344
+ returns = feature.last[ :returns ].collect{ | return_types |
1345
+
1346
+ return_types.collect{ | returns |
1347
+
1348
+ count += 1
1349
+
1350
+ # apply types to returns template
1351
+ apply_macros!( @templates["behaviour.xml.returns"].clone, {
1352
+ "RETURN_VALUE_TYPE" => encode_string( returns.first ),
1353
+ "RETURN_VALUE_DESCRIPTION" => encode_string( returns.last["description"] ),
1354
+ "RETURN_VALUE_EXAMPLE" => encode_string( returns.last["example"] ),
1355
+ }
1356
+ )
1357
+
1358
+ }.join
1359
+
1360
+ }.join
1361
+
1362
+ if count > 0
1363
+
1364
+ apply_macros!( @templates["behaviour.xml.method.returns"].clone, {
1365
+
1366
+ "METHOD_RETURNS" => returns
1367
+
1368
+ }
1369
+ )
1370
+
1371
+ else
1372
+
1373
+ ""
1374
+
1375
+ end
1376
+
1377
+ end
1378
+
1379
+ def generate_exceptions_element( header, feature )
1380
+
1381
+ return "" if ( feature.last[:__type] != 'method' )
1382
+
1383
+ #if feature.last[ :exceptions ].nil?
1384
+ # raise_error("Error: $TYPE '#{ feature.first }' ($MODULE) doesn't have exceptions(s) defined", 'exceptions' )
1385
+ #end
1386
+
1387
+ return "" if feature.last[ :exceptions ].nil? || feature.last[ :exceptions ].empty?
1388
+
1389
+ count = 0
1390
+
1391
+ # generate exceptions template
1392
+ exceptions = feature.last[ :exceptions ].collect{ | exceptions |
1393
+
1394
+ exceptions.collect{ | exception |
1395
+
1396
+ count += 1
1397
+
1398
+ # apply types to exception template
1399
+ apply_macros!( @templates["behaviour.xml.exception"].clone, {
1400
+ "EXCEPTION_NAME" => encode_string( exception.first ),
1401
+ "EXCEPTION_DESCRIPTION" => encode_string( exception.last["description"] )
1402
+ }
1403
+ )
1404
+
1405
+ }.join
1406
+
1407
+ }.join
1408
+
1409
+ if count > 0
1410
+
1411
+ apply_macros!( @templates["behaviour.xml.method.exceptions"].clone, {
1412
+
1413
+ "METHOD_EXCEPTIONS" => exceptions
1414
+
1415
+ }
1416
+ )
1417
+
1418
+ else
1419
+
1420
+ ""
1421
+
1422
+ end
1423
+
1424
+ end
1425
+
1426
+ def generate_arguments_element( header, feature )
1427
+
1428
+ return "" if ( feature.last[:__type] == 'reader' )
1429
+
1430
+ argument_types = { "*" => "multi", "&" => "block" }
1431
+ argument_types.default = "normal"
1432
+
1433
+ #return "" if ( @processing == :attributes && feature.last[:__type] == 'R' )
1434
+
1435
+ feature.last[ :__type ]
1436
+
1437
+ if feature.last[ :arguments ].nil? and feature.last[ :__arguments_found ] > 0
1438
+
1439
+ note = ". Note that also attribute writer requires input value defined as argument." if [ 'writer', 'accessor' ].include?( @processing )
1440
+
1441
+ raise_error("Error: $TYPE '#{ feature.first }' ($MODULE) doesn't have arguments(s) defined#{ note }", [ 'writer', 'accessor' ].include?( @processing ) ? 'attr_argument' : 'arguments' )
1442
+
1443
+ end
1444
+
1445
+ # generate arguments xml
1446
+ arguments = ( feature.last[:arguments] || {} ).collect{ | arg |
1447
+
1448
+ # generate argument types template
1449
+ arg.collect{ | argument |
1450
+
1451
+ argument_type = argument_types[ argument.first[0].chr ]
1452
+ argument_name = "%s" % argument.first
1453
+ argument_name[0]="" if argument_types.has_key?( argument_name[0].chr )
1454
+
1455
+ argument_type = "block_argument" if argument_type == "block" && argument_name.include?( "#" )
1456
+
1457
+ default_value_set = false
1458
+ default_value = nil
1459
+
1460
+ if argument.last.has_key?( :argument_type_order )
1461
+
1462
+ argument_types_in_order = argument.last[:argument_type_order].collect{ | type |
1463
+ [ type, argument.last[:types][ type ] ]
1464
+ }
1465
+
1466
+ else
1467
+
1468
+ argument_types_in_order = argument.last[ :types ]
1469
+
1470
+ end
1471
+
1472
+ argument_types_in_order ||= []
1473
+
1474
+ # in case of argument is not documented at all...
1475
+ if argument_types_in_order.empty?
1476
+
1477
+ # set optional flag if default value given
1478
+ unless argument.last[:default].nil?
1479
+
1480
+ default_value = argument.last[:default]
1481
+ default_value_set = true
1482
+
1483
+ end
1484
+
1485
+ end
1486
+
1487
+ types_xml = argument_types_in_order.collect{ | type |
1488
+
1489
+ unless argument.last[:default].nil?
1490
+
1491
+ # show warning if default value for optional argument is already set
1492
+ #raise_error( "Error: Default value for optional argument '%s' ($MODULE) is already set! ('%s' --> '%s')" % [ argument.first, default_value, type.last["default"] ] ) if default_value_set == true
1493
+
1494
+ default_value = argument.last[:default]
1495
+ default_value_set = true
1496
+
1497
+ end
1498
+
1499
+ =begin
1500
+ unless type.last["default"].nil?
1501
+
1502
+ # show warning if default value for optional argument is already set
1503
+ #raise_error( "Error: Default value for optional argument '%s' ($MODULE) is already set! ('%s' --> '%s')" % [ argument.first, default_value, type.last["default"] ] ) if default_value_set == true
1504
+
1505
+
1506
+ default_value = type.last["default"]
1507
+ default_value_set = true
1508
+
1509
+ end
1510
+ =end
1511
+
1512
+ if type.last["description"].nil?
1513
+
1514
+ raise_error("Warning: Argument description for '%s' ($MODULE) is empty." % [ argument.first ], 'argument' )
1515
+
1516
+ end
1517
+
1518
+ if type.last["example"].nil?
1519
+
1520
+ raise_error("Warning: Argument '%s' ($MODULE) example is empty." % [ argument.first ])
1521
+
1522
+ end
1523
+
1524
+ apply_macros!( @templates["behaviour.xml.argument_type"].clone, {
1525
+
1526
+ "ARGUMENT_TYPE" => encode_string( argument_type == 'block' ? "Proc" : type.first ),
1527
+ "ARGUMENT_DESCRIPTION" => encode_string( type.last["description"] ),
1528
+ "ARGUMENT_EXAMPLE" => encode_string( type.last["example"] ),
1529
+
1530
+ }
1531
+ )
1532
+
1533
+ }.join
1534
+
1535
+ if argument_type == "multi"
1536
+
1537
+ default_value = "[]"
1538
+ default_value_set = true
1539
+
1540
+ end
1541
+
1542
+ if default_value_set
1543
+
1544
+ default_value = apply_macros!( @templates["behaviour.xml.argument.default"].clone, {
1545
+ "ARGUMENT_DEFAULT_VALUE" => encode_string( default_value || "" )
1546
+ }
1547
+ )
1548
+
1549
+ else
1550
+
1551
+ default_value = ""
1552
+
1553
+ end
1554
+
1555
+ # apply types to arguments template
1556
+ apply_macros!( @templates["behaviour.xml.argument"].clone, {
1557
+ "ARGUMENT_NAME" => encode_string( argument_name ),
1558
+ "ARGUMENT_TYPE" => encode_string( argument_type ),
1559
+ "ARGUMENT_TYPES" => types_xml,
1560
+ "ARGUMENT_DEFAULT_VALUE" => default_value.to_s,
1561
+ "ARGUMENT_OPTIONAL" => encode_string( ["multi", "block", "block_argument"].include?( argument_type ) ? "true" : default_value_set.to_s )
1562
+ }
1563
+ )
1564
+
1565
+ }.join
1566
+
1567
+ }.join
1568
+
1569
+ apply_macros!( @templates["behaviour.xml.method.arguments"].clone, {
1570
+
1571
+ "ARGUMENTS_IMPLEMENTED" => feature.last[ :__arguments_implemented ] || "0",
1572
+ "ARGUMENT_OPTIONAL_COUNT" => feature.last[ :__arguments_optional ] || "0",
1573
+ "METHOD_ARGUMENTS" => arguments
1574
+
1575
+ }
1576
+ )
1577
+
1578
+
1579
+ end
1580
+
1581
+ def generate_tables_element( header, features )
1582
+
1583
+ tables = []
1584
+
1585
+ unless features.last[:tables].nil? #[:tables]
1586
+
1587
+ #p features.last[:tables]
1588
+ #p features.last[:tables]["content"]
1589
+
1590
+ #return "" if features.last[:tables]["content"] == []
1591
+
1592
+ tables = features.last[:tables].collect{ | table |
1593
+
1594
+ header = table[ "content" ].first.collect{ | header_item |
1595
+ apply_macros!( @templates["behaviour.xml.table.item"].clone, {
1596
+ "ITEM" => encode_string( header_item )
1597
+ }
1598
+ )
1599
+ }
1600
+
1601
+ rows = table[ "content" ][ 1 .. -1 ].collect{ | row |
1602
+
1603
+ row_items = row.collect{ | row_item |
1604
+
1605
+ apply_macros!( @templates["behaviour.xml.table.item"].clone, {
1606
+ "ITEM" => encode_string( row_item )
1607
+ }
1608
+ )
1609
+ }
1610
+
1611
+ apply_macros!( @templates["behaviour.xml.table.row"].clone, {
1612
+
1613
+ "TABLE_ROW_ITEMS" => row_items.join("")
1614
+
1615
+ }
1616
+ )
1617
+
1618
+ }
1619
+
1620
+ apply_macros!( @templates["behaviour.xml.table"].clone, {
1621
+ "TABLE_NAME" => encode_string( table[ "name" ] ),
1622
+ "TABLE_TITLE" => encode_string( table[ "title" ] || "" ),
1623
+ "TABLE_DESCRIPTION" => encode_string( table[ "description" ] || "" ),
1624
+ "TABLE_HEADER_ITEMS" => header.join(""),
1625
+ "TABLE_ROWS" => rows.join("")
1626
+ }
1627
+ )
1628
+ }
1629
+
1630
+ end
1631
+
1632
+ if tables.count > 0
1633
+
1634
+ apply_macros!( @templates["behaviour.xml.method.tables"].clone, {
1635
+
1636
+ "METHOD_TABLES" => tables.join("")
1637
+
1638
+ }
1639
+ )
1640
+
1641
+ else
1642
+
1643
+ ""
1644
+
1645
+ end
1646
+
1647
+ end
1648
+
1649
+ def generate_deprecated_element( header, feature, &block )
1650
+
1651
+ if feature.last.has_key?( :deprecated )
1652
+
1653
+ yield
1654
+
1655
+ apply_macros!( @templates["behaviour.xml.method.deprecated"].clone, {
1656
+ "DEPRECATED_IN_VERSION_NUMBER" => encode_string( feature.last[:deprecated] )
1657
+ }
1658
+ )
1659
+
1660
+ else
1661
+
1662
+ ""
1663
+
1664
+ end
1665
+
1666
+ end
1667
+
1668
+ def generate_info_element( header, feature )
1669
+
1670
+ if feature.last.has_key?( :info )
1671
+
1672
+ apply_macros!( @templates["behaviour.xml.method.info"].clone, {
1673
+ "METHOD_INFO" => encode_string( feature.last[:info] )
1674
+ }
1675
+ )
1676
+
1677
+ else
1678
+
1679
+ ""
1680
+
1681
+ end
1682
+
1683
+ end
1684
+
1685
+ def generate_methods_element( header, features )
1686
+
1687
+ # collect method and attribute templates
1688
+ methods = features.collect{ | feature_set |
1689
+
1690
+ feature_set.collect{ | feature |
1691
+
1692
+ @processing = feature.last[:__type]
1693
+
1694
+ # TODO: tarkista lähdekoodista että onko argument optional vai ei
1695
+ # TODO: tarkista että onko kaikki argumentit dokumentoitu
1696
+
1697
+ arguments = generate_arguments_element( header, feature )
1698
+
1699
+ returns = generate_return_values_element( header, feature )
1700
+
1701
+ exceptions = generate_exceptions_element( header, feature )
1702
+
1703
+ tables = generate_tables_element( header, feature )
1704
+
1705
+ info = generate_info_element( header, feature )
1706
+
1707
+ deprecated = generate_deprecated_element( header, feature ){
1708
+
1709
+ arguments = ""
1710
+ returns = ""
1711
+ exceptions = ""
1712
+ tables = ""
1713
+
1714
+ }
1715
+
1716
+ if feature.last[:description].nil?
1717
+
1718
+ raise_error("Warning: $TYPE description for '#{ feature.first }' ($MODULE) is empty.", 'description')
1719
+
1720
+ end
1721
+
1722
+ # generate method template
1723
+ apply_macros!( @templates["behaviour.xml.method"].clone, {
1724
+ "METHOD_NAME" => encode_string( feature.first ),
1725
+ "METHOD_TYPE" => encode_string( feature.last[:__type] || "unknown" ),
1726
+ "NODOC" => feature.last.has_key?(:nodoc).to_s,
1727
+ "METHOD_DEPRECATED" => deprecated,
1728
+ "METHOD_DESCRIPTION" => encode_string( feature.last[:description] ),
1729
+ "METHOD_ARGUMENTS" => arguments,
1730
+ "METHOD_RETURNS" => returns,
1731
+ "METHOD_EXCEPTIONS" => exceptions,
1732
+ "METHOD_TABLES" => tables,
1733
+ "METHOD_INFO" => info # feature.last[:info]
1734
+ }
1735
+ )
1736
+
1737
+ }.join
1738
+
1739
+ }.join
1740
+
1741
+
1742
+ end
1743
+
1744
+ def generate_behaviour_element( header, methods )
1745
+
1746
+ # verify that behaviour description is defined
1747
+ unless header.has_key?(:description)
1748
+
1749
+ raise_error("Warning: Behaviour description for $MODULE is empty.", 'behaviour_description' ) unless methods.empty?
1750
+
1751
+ end
1752
+
1753
+ # verify that behaviour name is defined
1754
+ unless header.has_key?(:behaviour)
1755
+
1756
+ raise_error("Warning: Behaviour name for $MODULE is not defined.", 'behaviour_name' ) unless methods.empty?
1757
+
1758
+ end
1759
+
1760
+ # verify that behaviour object type(s) is defined
1761
+ unless header.has_key?(:objects)
1762
+
1763
+ raise_error("Warning: Behaviour object type(s) for $MODULE is not defined.", 'behaviour_object_types' ) unless methods.empty?
1764
+
1765
+ end
1766
+
1767
+ # verify that behaviour sut type(s) is defined
1768
+ unless header.has_key?(:sut_type)
1769
+
1770
+ raise_error("Warning: Behaviour SUT type for $MODULE is not defined.", 'behaviour_sut_type' ) unless methods.empty?
1771
+
1772
+ end
1773
+
1774
+ # verify that behaviour input type(s) is defined
1775
+ unless header.has_key?(:input_type)
1776
+
1777
+ raise_error("Warning: Behaviour input type for $MODULE is not defined.", 'behaviour_input_type' ) unless methods.empty?
1778
+
1779
+ end
1780
+
1781
+ # verify that behaviour sut version(s) is defined
1782
+ unless header.has_key?(:sut_version)
1783
+
1784
+ raise_error("Warning: Behaviour SUT version for $MODULE is not defined.", 'behaviour_version' ) unless methods.empty?
1785
+
1786
+ end
1787
+
1788
+ # verify that behaviour sut version(s) is defined
1789
+ unless header.has_key?(:requires)
1790
+
1791
+ raise_error("Warning: Required plugin name is not defined for $MODULE.", 'behaviour_requires' ) unless methods.empty?
1792
+
1793
+ end
1794
+
1795
+ # apply header
1796
+ text = apply_macros!( @templates["behaviour.xml"].clone, {
1797
+ "REQUIRED_PLUGIN" => encode_string( header[:requires] ),
1798
+ "BEHAVIOUR_NAME" => encode_string( header[:behaviour] ),
1799
+ "BEHAVIOUR_METHODS" => methods,
1800
+ "OBJECT_TYPE" => encode_string( header[:objects] ),
1801
+ "SUT_TYPE" => encode_string( header[:sut_type] ),
1802
+ "INPUT_TYPE" => encode_string( header[:input_type] ),
1803
+ "VERSION" => encode_string( header[:sut_version] ),
1804
+ "MODULE_NAME" => encode_string( @module_path.join("::") )
1805
+ }
1806
+ )
1807
+
1808
+ # remove extra linefeeds
1809
+ text.gsub!( /^[\n]+/, "\n" )
1810
+
1811
+ text.gsub!( /^(\s)*$/, "" )
1812
+
1813
+ text
1814
+
1815
+ end
1816
+
1817
+ def generate_behaviour( header, *features )
1818
+
1819
+ methods = generate_methods_element( header, features )
1820
+
1821
+ generate_behaviour_element( header, methods )
1822
+
1823
+ end
1824
+
1825
+ def process_module( _module )
1826
+
1827
+ @already_processed_files << _module.full_name
1828
+
1829
+ # skip if not a behaviour module
1830
+ return if /^MobyBehaviour.*/ !~ _module.full_name.to_s
1831
+
1832
+ module_header = process_comment( _module.comment )
1833
+
1834
+ # store information where module is stored
1835
+ @module_in_files = _module.in_files.collect{ | file | file.file_absolute_name }
1836
+
1837
+ #unless module_header.empty?
1838
+
1839
+ @current_module = _module
1840
+
1841
+ # process methods
1842
+ methods = process_methods( _module.method_list )
1843
+
1844
+ # process attributes
1845
+ attributes = process_attributes( _module.attributes )
1846
+
1847
+ print " ... %s" % module_header[:behaviour]
1848
+
1849
+ xml = generate_behaviour( module_header, methods, attributes )
1850
+
1851
+ xml_file_name = '%s.%s' % [ module_header[:behaviour], 'xml' ]
1852
+
1853
+ begin
1854
+
1855
+ if xml_file_name != '.xml'
1856
+
1857
+ if @created_files.has_key?( xml_file_name )
1858
+
1859
+ xml_file_name = '%s_duplicate_name.%s' % [ module_header[:behaviour], 'xml' ]
1860
+
1861
+ warn("Warning! One of the behaviour modules is already using name '#{ module_header[:behaviour] }', saving as #{ xml_file_name }")
1862
+
1863
+ sleep 1
1864
+
1865
+ end
1866
+
1867
+ @created_files[ xml_file_name ] = {}
1868
+
1869
+ open( xml_file_name, 'w'){ | file | file << xml }
1870
+
1871
+ puts ".xml"
1872
+
1873
+ else
1874
+
1875
+ if methods.count > 0
1876
+
1877
+ xml_file_name = ( @module_path[1..-1].join("") ) + '.xml'
1878
+
1879
+ warn("Warning: #{ @module_path.join("::") } does not have behaviour (module) description defined, saving as %s " % xml_file_name )
1880
+ sleep 2
1881
+
1882
+ if @created_files.has_key?( xml_file_name )
1883
+
1884
+ warn("Warning! One of the behaviour modules is already using name '#{ module_header[:behaviour] }'")
1885
+
1886
+ xml_file_name = ( @module_path[1..-1].join("") ) + '_duplicate_name.xml'
1887
+
1888
+ sleep 1
1889
+
1890
+ end
1891
+
1892
+ @created_files[ xml_file_name ] = {}
1893
+
1894
+ open( xml_file_name, 'w'){ | file | file << xml }
1895
+
1896
+ else
1897
+
1898
+ warn("Skip: #{ @module_path.join("::") } does not have any public methods") unless @module_path.join("::") == "MobyBehaviour"
1899
+
1900
+ end
1901
+
1902
+ #p xml
1903
+
1904
+ #warn("Skip: #{ @module_path.join("::") } XML not saved due to missing behaviour name/description ") #in #{ @module_in_files.join(", ") }")
1905
+
1906
+ end
1907
+
1908
+ rescue Exception => exception
1909
+
1910
+ warn("Warning: Error writing file %s (%s: %s)" % [ xml_file_name, exception.class, exception.message ] )
1911
+
1912
+ end
1913
+
1914
+ #end
1915
+
1916
+ # process if any child modules
1917
+ process_modules( _module.modules ) unless _module.modules.empty?
1918
+
1919
+ end
1920
+
1921
+ end
1922
+
1923
+ end
1924
+