yard 0.9.18 → 0.9.19
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of yard might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.yardopts +26 -26
- data/CHANGELOG.md +742 -728
- data/LEGAL +66 -66
- data/LICENSE +22 -22
- data/README.md +328 -328
- data/Rakefile +42 -53
- data/benchmarks/builtins_vs_eval.rb +24 -24
- data/benchmarks/concat_vs_join.rb +13 -13
- data/benchmarks/erb_vs_erubis.rb +54 -54
- data/benchmarks/format_args.rb +47 -47
- data/benchmarks/generation.rb +38 -38
- data/benchmarks/marshal_vs_dbm.rb +64 -64
- data/benchmarks/parsing.rb +46 -46
- data/benchmarks/pathname_vs_string.rb +50 -50
- data/benchmarks/rdoc_vs_yardoc.rb +11 -11
- data/benchmarks/registry_store_types.rb +49 -49
- data/benchmarks/ri_vs_yri.rb +19 -19
- data/benchmarks/ripper_parser.rb +13 -13
- data/benchmarks/splat_vs_flatten.rb +13 -13
- data/benchmarks/template_erb.rb +23 -23
- data/benchmarks/template_format.rb +7 -7
- data/benchmarks/template_profile.rb +18 -18
- data/benchmarks/yri_cache.rb +20 -20
- data/bin/yard +13 -13
- data/bin/yardoc +13 -13
- data/bin/yri +13 -13
- data/docs/CodeObjects.md +115 -115
- data/docs/GettingStarted.md +679 -679
- data/docs/Handlers.md +152 -152
- data/docs/Overview.md +61 -61
- data/docs/Parser.md +191 -191
- data/docs/Tags.md +283 -283
- data/docs/TagsArch.md +123 -123
- data/docs/Templates.md +496 -496
- data/docs/WhatsNew.md +1245 -1245
- data/docs/templates/default/fulldoc/html/full_list_tag.erb +8 -8
- data/docs/templates/default/fulldoc/html/setup.rb +6 -6
- data/docs/templates/default/layout/html/setup.rb +9 -9
- data/docs/templates/default/layout/html/tag_list.erb +11 -11
- data/docs/templates/default/yard_tags/html/list.erb +18 -18
- data/docs/templates/default/yard_tags/html/setup.rb +26 -26
- data/docs/templates/plugin.rb +70 -70
- data/lib/rubygems_plugin.rb +9 -9
- data/lib/yard.rb +69 -69
- data/lib/yard/autoload.rb +308 -303
- data/lib/yard/cli/command.rb +85 -85
- data/lib/yard/cli/command_parser.rb +93 -93
- data/lib/yard/cli/config.rb +198 -198
- data/lib/yard/cli/diff.rb +270 -270
- data/lib/yard/cli/display.rb +69 -69
- data/lib/yard/cli/gems.rb +84 -84
- data/lib/yard/cli/graph.rb +125 -125
- data/lib/yard/cli/help.rb +20 -20
- data/lib/yard/cli/i18n.rb +70 -70
- data/lib/yard/cli/list.rb +23 -23
- data/lib/yard/cli/markup_types.rb +32 -32
- data/lib/yard/cli/server.rb +257 -257
- data/lib/yard/cli/stats.rb +231 -231
- data/lib/yard/cli/yardoc.rb +789 -788
- data/lib/yard/cli/yardopts_command.rb +110 -110
- data/lib/yard/cli/yri.rb +215 -215
- data/lib/yard/code_objects/base.rb +615 -615
- data/lib/yard/code_objects/class_object.rb +146 -146
- data/lib/yard/code_objects/class_variable_object.rb +11 -11
- data/lib/yard/code_objects/constant_object.rb +16 -16
- data/lib/yard/code_objects/extended_method_object.rb +24 -24
- data/lib/yard/code_objects/extra_file_object.rb +134 -131
- data/lib/yard/code_objects/macro_object.rb +172 -172
- data/lib/yard/code_objects/method_object.rb +196 -196
- data/lib/yard/code_objects/module_object.rb +21 -21
- data/lib/yard/code_objects/namespace_mapper.rb +114 -114
- data/lib/yard/code_objects/namespace_object.rb +200 -200
- data/lib/yard/code_objects/proxy.rb +240 -240
- data/lib/yard/code_objects/root_object.rb +19 -19
- data/lib/yard/config.rb +270 -270
- data/lib/yard/core_ext/array.rb +16 -16
- data/lib/yard/core_ext/file.rb +69 -69
- data/lib/yard/core_ext/hash.rb +16 -16
- data/lib/yard/core_ext/insertion.rb +63 -63
- data/lib/yard/core_ext/module.rb +11 -20
- data/lib/yard/core_ext/string.rb +68 -68
- data/lib/yard/core_ext/symbol_hash.rb +75 -75
- data/lib/yard/docstring.rb +386 -386
- data/lib/yard/docstring_parser.rb +345 -345
- data/lib/yard/gem_index.rb +29 -29
- data/lib/yard/globals.rb +22 -22
- data/lib/yard/handlers/base.rb +595 -595
- data/lib/yard/handlers/c/alias_handler.rb +16 -16
- data/lib/yard/handlers/c/attribute_handler.rb +13 -13
- data/lib/yard/handlers/c/base.rb +129 -129
- data/lib/yard/handlers/c/class_handler.rb +27 -27
- data/lib/yard/handlers/c/constant_handler.rb +13 -13
- data/lib/yard/handlers/c/handler_methods.rb +212 -211
- data/lib/yard/handlers/c/init_handler.rb +20 -20
- data/lib/yard/handlers/c/method_handler.rb +45 -45
- data/lib/yard/handlers/c/mixin_handler.rb +21 -21
- data/lib/yard/handlers/c/module_handler.rb +17 -17
- data/lib/yard/handlers/c/override_comment_handler.rb +31 -31
- data/lib/yard/handlers/c/path_handler.rb +11 -11
- data/lib/yard/handlers/c/struct_handler.rb +13 -13
- data/lib/yard/handlers/c/symbol_handler.rb +8 -8
- data/lib/yard/handlers/common/method_handler.rb +19 -0
- data/lib/yard/handlers/processor.rb +200 -200
- data/lib/yard/handlers/ruby/alias_handler.rb +44 -44
- data/lib/yard/handlers/ruby/attribute_handler.rb +87 -87
- data/lib/yard/handlers/ruby/base.rb +165 -165
- data/lib/yard/handlers/ruby/class_condition_handler.rb +92 -92
- data/lib/yard/handlers/ruby/class_handler.rb +119 -119
- data/lib/yard/handlers/ruby/class_variable_handler.rb +17 -17
- data/lib/yard/handlers/ruby/comment_handler.rb +10 -10
- data/lib/yard/handlers/ruby/constant_handler.rb +59 -59
- data/lib/yard/handlers/ruby/decorator_handler_methods.rb +123 -123
- data/lib/yard/handlers/ruby/dsl_handler.rb +15 -15
- data/lib/yard/handlers/ruby/dsl_handler_methods.rb +96 -96
- data/lib/yard/handlers/ruby/exception_handler.rb +27 -27
- data/lib/yard/handlers/ruby/extend_handler.rb +22 -22
- data/lib/yard/handlers/ruby/legacy/alias_handler.rb +37 -37
- data/lib/yard/handlers/ruby/legacy/attribute_handler.rb +65 -65
- data/lib/yard/handlers/ruby/legacy/base.rb +245 -245
- data/lib/yard/handlers/ruby/legacy/class_condition_handler.rb +83 -83
- data/lib/yard/handlers/ruby/legacy/class_handler.rb +113 -113
- data/lib/yard/handlers/ruby/legacy/class_variable_handler.rb +15 -15
- data/lib/yard/handlers/ruby/legacy/comment_handler.rb +10 -10
- data/lib/yard/handlers/ruby/legacy/constant_handler.rb +29 -29
- data/lib/yard/handlers/ruby/legacy/dsl_handler.rb +17 -17
- data/lib/yard/handlers/ruby/legacy/exception_handler.rb +13 -13
- data/lib/yard/handlers/ruby/legacy/extend_handler.rb +21 -21
- data/lib/yard/handlers/ruby/legacy/method_handler.rb +90 -90
- data/lib/yard/handlers/ruby/legacy/mixin_handler.rb +39 -39
- data/lib/yard/handlers/ruby/legacy/module_function_handler.rb +19 -19
- data/lib/yard/handlers/ruby/legacy/module_handler.rb +12 -12
- data/lib/yard/handlers/ruby/legacy/private_class_method_handler.rb +22 -22
- data/lib/yard/handlers/ruby/legacy/private_constant_handler.rb +22 -22
- data/lib/yard/handlers/ruby/legacy/visibility_handler.rb +17 -17
- data/lib/yard/handlers/ruby/legacy/yield_handler.rb +29 -29
- data/lib/yard/handlers/ruby/method_condition_handler.rb +9 -9
- data/lib/yard/handlers/ruby/method_handler.rb +114 -118
- data/lib/yard/handlers/ruby/mixin_handler.rb +37 -37
- data/lib/yard/handlers/ruby/module_function_handler.rb +27 -27
- data/lib/yard/handlers/ruby/module_handler.rb +12 -12
- data/lib/yard/handlers/ruby/private_class_method_handler.rb +14 -14
- data/lib/yard/handlers/ruby/private_constant_handler.rb +43 -43
- data/lib/yard/handlers/ruby/public_class_method_handler.rb +14 -14
- data/lib/yard/handlers/ruby/struct_handler_methods.rb +143 -143
- data/lib/yard/handlers/ruby/visibility_handler.rb +22 -22
- data/lib/yard/handlers/ruby/yield_handler.rb +31 -31
- data/lib/yard/i18n/locale.rb +67 -67
- data/lib/yard/i18n/message.rb +57 -57
- data/lib/yard/i18n/messages.rb +56 -56
- data/lib/yard/i18n/po_parser.rb +61 -61
- data/lib/yard/i18n/pot_generator.rb +290 -290
- data/lib/yard/i18n/text.rb +173 -173
- data/lib/yard/logging.rb +205 -205
- data/lib/yard/options.rb +217 -217
- data/lib/yard/parser/base.rb +57 -57
- data/lib/yard/parser/c/c_parser.rb +235 -235
- data/lib/yard/parser/c/comment_parser.rb +134 -134
- data/lib/yard/parser/c/statement.rb +64 -64
- data/lib/yard/parser/ruby/ast_node.rb +540 -540
- data/lib/yard/parser/ruby/legacy/ruby_lex.rb +1354 -1354
- data/lib/yard/parser/ruby/legacy/ruby_parser.rb +32 -32
- data/lib/yard/parser/ruby/legacy/statement.rb +66 -66
- data/lib/yard/parser/ruby/legacy/statement_list.rb +394 -394
- data/lib/yard/parser/ruby/legacy/token_list.rb +74 -74
- data/lib/yard/parser/ruby/ruby_parser.rb +687 -687
- data/lib/yard/parser/ruby/token_resolver.rb +156 -156
- data/lib/yard/parser/source_parser.rb +526 -526
- data/lib/yard/rake/yardoc_task.rb +81 -81
- data/lib/yard/registry.rb +439 -439
- data/lib/yard/registry_resolver.rb +189 -189
- data/lib/yard/registry_store.rb +337 -337
- data/lib/yard/rubygems/backports.rb +10 -10
- data/lib/yard/rubygems/backports/LICENSE.txt +57 -57
- data/lib/yard/rubygems/backports/MIT.txt +20 -20
- data/lib/yard/rubygems/backports/gem.rb +10 -10
- data/lib/yard/rubygems/backports/source_index.rb +365 -365
- data/lib/yard/rubygems/doc_manager.rb +90 -90
- data/lib/yard/rubygems/hook.rb +197 -197
- data/lib/yard/rubygems/specification.rb +50 -50
- data/lib/yard/serializers/base.rb +83 -83
- data/lib/yard/serializers/file_system_serializer.rb +123 -123
- data/lib/yard/serializers/process_serializer.rb +24 -24
- data/lib/yard/serializers/stdout_serializer.rb +34 -34
- data/lib/yard/serializers/yardoc_serializer.rb +152 -152
- data/lib/yard/server.rb +13 -13
- data/lib/yard/server/adapter.rb +100 -100
- data/lib/yard/server/commands/base.rb +209 -209
- data/lib/yard/server/commands/display_file_command.rb +29 -29
- data/lib/yard/server/commands/display_object_command.rb +65 -65
- data/lib/yard/server/commands/frames_command.rb +16 -16
- data/lib/yard/server/commands/library_command.rb +187 -187
- data/lib/yard/server/commands/library_index_command.rb +28 -28
- data/lib/yard/server/commands/list_command.rb +25 -25
- data/lib/yard/server/commands/root_request_command.rb +15 -15
- data/lib/yard/server/commands/search_command.rb +79 -79
- data/lib/yard/server/commands/static_file_command.rb +23 -23
- data/lib/yard/server/commands/static_file_helpers.rb +62 -62
- data/lib/yard/server/doc_server_helper.rb +91 -91
- data/lib/yard/server/doc_server_serializer.rb +39 -39
- data/lib/yard/server/library_version.rb +277 -277
- data/lib/yard/server/rack_adapter.rb +89 -89
- data/lib/yard/server/router.rb +187 -187
- data/lib/yard/server/static_caching.rb +46 -46
- data/lib/yard/server/templates/default/fulldoc/html/css/custom.css +127 -127
- data/lib/yard/server/templates/default/fulldoc/html/js/autocomplete.js +11 -11
- data/lib/yard/server/templates/default/layout/html/breadcrumb.erb +37 -37
- data/lib/yard/server/templates/default/layout/html/script_setup.erb +7 -7
- data/lib/yard/server/templates/default/layout/html/setup.rb +8 -8
- data/lib/yard/server/templates/default/method_details/html/permalink.erb +4 -4
- data/lib/yard/server/templates/default/method_details/html/setup.rb +5 -5
- data/lib/yard/server/templates/doc_server/library_list/html/headers.erb +8 -8
- data/lib/yard/server/templates/doc_server/library_list/html/library_list.erb +14 -14
- data/lib/yard/server/templates/doc_server/library_list/html/listing.erb +13 -13
- data/lib/yard/server/templates/doc_server/library_list/html/setup.rb +6 -6
- data/lib/yard/server/templates/doc_server/library_list/html/title.erb +2 -2
- data/lib/yard/server/templates/doc_server/processing/html/processing.erb +52 -52
- data/lib/yard/server/templates/doc_server/processing/html/setup.rb +4 -4
- data/lib/yard/server/templates/doc_server/search/html/search.erb +18 -18
- data/lib/yard/server/templates/doc_server/search/html/setup.rb +9 -9
- data/lib/yard/server/webrick_adapter.rb +45 -45
- data/lib/yard/tags/default_factory.rb +191 -191
- data/lib/yard/tags/default_tag.rb +13 -13
- data/lib/yard/tags/directives.rb +616 -616
- data/lib/yard/tags/library.rb +633 -633
- data/lib/yard/tags/option_tag.rb +13 -13
- data/lib/yard/tags/overload_tag.rb +71 -71
- data/lib/yard/tags/ref_tag.rb +8 -8
- data/lib/yard/tags/ref_tag_list.rb +28 -28
- data/lib/yard/tags/tag.rb +71 -71
- data/lib/yard/tags/tag_format_error.rb +7 -7
- data/lib/yard/tags/types_explainer.rb +162 -162
- data/lib/yard/templates/engine.rb +186 -186
- data/lib/yard/templates/erb_cache.rb +23 -23
- data/lib/yard/templates/helpers/base_helper.rb +215 -215
- data/lib/yard/templates/helpers/filter_helper.rb +27 -27
- data/lib/yard/templates/helpers/html_helper.rb +646 -646
- data/lib/yard/templates/helpers/html_syntax_highlight_helper.rb +78 -78
- data/lib/yard/templates/helpers/markup/rdoc_markdown.rb +23 -23
- data/lib/yard/templates/helpers/markup/rdoc_markup.rb +109 -109
- data/lib/yard/templates/helpers/markup_helper.rb +172 -172
- data/lib/yard/templates/helpers/method_helper.rb +75 -75
- data/lib/yard/templates/helpers/module_helper.rb +21 -21
- data/lib/yard/templates/helpers/text_helper.rb +112 -112
- data/lib/yard/templates/helpers/uml_helper.rb +47 -47
- data/lib/yard/templates/section.rb +105 -105
- data/lib/yard/templates/template.rb +418 -418
- data/lib/yard/templates/template_options.rb +92 -92
- data/lib/yard/verifier.rb +151 -151
- data/lib/yard/version.rb +6 -6
- data/spec/cli/command_parser_spec.rb +43 -43
- data/spec/cli/command_spec.rb +36 -36
- data/spec/cli/config_spec.rb +148 -148
- data/spec/cli/diff_spec.rb +254 -254
- data/spec/cli/display_spec.rb +30 -30
- data/spec/cli/gems_spec.rb +81 -81
- data/spec/cli/graph_spec.rb +18 -18
- data/spec/cli/help_spec.rb +22 -22
- data/spec/cli/i18n_spec.rb +107 -107
- data/spec/cli/list_spec.rb +8 -8
- data/spec/cli/markup_types_spec.rb +22 -22
- data/spec/cli/server_spec.rb +324 -324
- data/spec/cli/stats_spec.rb +96 -96
- data/spec/cli/yard_on_yard_spec.rb +38 -38
- data/spec/cli/yardoc_spec.rb +896 -862
- data/spec/cli/yri_spec.rb +101 -101
- data/spec/code_objects/base_spec.rb +470 -470
- data/spec/code_objects/class_object_spec.rb +226 -226
- data/spec/code_objects/code_object_list_spec.rb +36 -36
- data/spec/code_objects/constants_spec.rb +116 -116
- data/spec/code_objects/extra_file_object_spec.rb +160 -160
- data/spec/code_objects/macro_object_spec.rb +150 -150
- data/spec/code_objects/method_object_spec.rb +184 -184
- data/spec/code_objects/module_object_spec.rb +142 -142
- data/spec/code_objects/namespace_object_spec.rb +171 -171
- data/spec/code_objects/proxy_spec.rb +141 -141
- data/spec/code_objects/spec_helper.rb +3 -3
- data/spec/config_spec.rb +171 -171
- data/spec/core_ext/array_spec.rb +13 -13
- data/spec/core_ext/file_spec.rb +72 -72
- data/spec/core_ext/hash_spec.rb +14 -14
- data/spec/core_ext/insertion_spec.rb +37 -37
- data/spec/core_ext/module_spec.rb +9 -15
- data/spec/core_ext/string_spec.rb +42 -42
- data/spec/core_ext/symbol_hash_spec.rb +89 -89
- data/spec/docstring_parser_spec.rb +280 -280
- data/spec/docstring_spec.rb +373 -373
- data/spec/examples.txt +1883 -1875
- data/spec/handlers/alias_handler_spec.rb +82 -82
- data/spec/handlers/attribute_handler_spec.rb +96 -96
- data/spec/handlers/base_spec.rb +216 -216
- data/spec/handlers/c/alias_handler_spec.rb +34 -34
- data/spec/handlers/c/attribute_handler_spec.rb +41 -41
- data/spec/handlers/c/class_handler_spec.rb +78 -78
- data/spec/handlers/c/constant_handler_spec.rb +71 -71
- data/spec/handlers/c/init_handler_spec.rb +48 -48
- data/spec/handlers/c/method_handler_spec.rb +327 -325
- data/spec/handlers/c/mixin_handler_spec.rb +44 -44
- data/spec/handlers/c/module_handler_spec.rb +71 -71
- data/spec/handlers/c/override_comment_handler_spec.rb +47 -47
- data/spec/handlers/c/path_handler_spec.rb +36 -36
- data/spec/handlers/c/spec_helper.rb +23 -23
- data/spec/handlers/c/struct_handler_spec.rb +16 -16
- data/spec/handlers/class_condition_handler_spec.rb +87 -87
- data/spec/handlers/class_handler_spec.rb +247 -247
- data/spec/handlers/class_method_handler_shared_examples.rb +133 -133
- data/spec/handlers/class_variable_handler_spec.rb +12 -12
- data/spec/handlers/constant_handler_spec.rb +112 -112
- data/spec/handlers/decorator_handler_methods_spec.rb +393 -393
- data/spec/handlers/dsl_handler_spec.rb +219 -219
- data/spec/handlers/examples/alias_handler_001.rb.txt +45 -45
- data/spec/handlers/examples/attribute_handler_001.rb.txt +31 -31
- data/spec/handlers/examples/class_condition_handler_001.rb.txt +68 -68
- data/spec/handlers/examples/class_handler_001.rb.txt +120 -120
- data/spec/handlers/examples/class_variable_handler_001.rb.txt +9 -9
- data/spec/handlers/examples/constant_handler_001.rb.txt +35 -35
- data/spec/handlers/examples/dsl_handler_001.rb.txt +154 -154
- data/spec/handlers/examples/exception_handler_001.rb.txt +58 -58
- data/spec/handlers/examples/extend_handler_001.rb.txt +15 -15
- data/spec/handlers/examples/method_condition_handler_001.rb.txt +9 -9
- data/spec/handlers/examples/method_handler_001.rb.txt +128 -128
- data/spec/handlers/examples/mixin_handler_001.rb.txt +37 -37
- data/spec/handlers/examples/module_handler_001.rb.txt +29 -29
- data/spec/handlers/examples/private_constant_handler_001.rb.txt +8 -8
- data/spec/handlers/examples/process_handler_001.rb.txt +11 -11
- data/spec/handlers/examples/visibility_handler_001.rb.txt +35 -35
- data/spec/handlers/examples/yield_handler_001.rb.txt +54 -54
- data/spec/handlers/exception_handler_spec.rb +49 -49
- data/spec/handlers/extend_handler_spec.rb +24 -24
- data/spec/handlers/legacy_base_spec.rb +128 -128
- data/spec/handlers/method_condition_handler_spec.rb +15 -15
- data/spec/handlers/method_handler_spec.rb +190 -190
- data/spec/handlers/mixin_handler_spec.rb +56 -56
- data/spec/handlers/module_function_handler_spec.rb +106 -106
- data/spec/handlers/module_handler_spec.rb +35 -35
- data/spec/handlers/private_class_method_handler_spec.rb +11 -11
- data/spec/handlers/private_constant_handler_spec.rb +25 -25
- data/spec/handlers/processor_spec.rb +35 -35
- data/spec/handlers/public_class_method_handler_spec.rb +11 -11
- data/spec/handlers/ruby/base_spec.rb +95 -95
- data/spec/handlers/ruby/legacy/base_spec.rb +84 -84
- data/spec/handlers/spec_helper.rb +33 -33
- data/spec/handlers/visibility_handler_spec.rb +44 -44
- data/spec/handlers/yield_handler_spec.rb +52 -52
- data/spec/i18n/locale_spec.rb +81 -81
- data/spec/i18n/message_spec.rb +52 -52
- data/spec/i18n/messages_spec.rb +67 -67
- data/spec/i18n/pot_generator_spec.rb +295 -295
- data/spec/i18n/text_spec.rb +184 -184
- data/spec/logging_spec.rb +44 -44
- data/spec/options_spec.rb +171 -171
- data/spec/parser/base_spec.rb +24 -24
- data/spec/parser/c_parser_spec.rb +236 -236
- data/spec/parser/examples/array.c.txt +6267 -6267
- data/spec/parser/examples/example1.rb.txt +7 -7
- data/spec/parser/examples/extrafile.c.txt +8 -8
- data/spec/parser/examples/file.c.txt +28 -28
- data/spec/parser/examples/multifile.c.txt +22 -22
- data/spec/parser/examples/namespace.cpp.txt +68 -68
- data/spec/parser/examples/override.c.txt +424 -424
- data/spec/parser/examples/parse_in_order_001.rb.txt +2 -2
- data/spec/parser/examples/parse_in_order_002.rb.txt +1 -1
- data/spec/parser/examples/tag_handler_001.rb.txt +7 -7
- data/spec/parser/ruby/ast_node_spec.rb +33 -33
- data/spec/parser/ruby/legacy/statement_list_spec.rb +299 -299
- data/spec/parser/ruby/legacy/token_list_spec.rb +79 -79
- data/spec/parser/ruby/ruby_parser_spec.rb +508 -508
- data/spec/parser/ruby/token_resolver_spec.rb +165 -165
- data/spec/parser/source_parser_spec.rb +727 -727
- data/spec/parser/tag_parsing_spec.rb +17 -17
- data/spec/rake/yardoc_task_spec.rb +118 -118
- data/spec/registry_spec.rb +463 -463
- data/spec/registry_store_spec.rb +316 -316
- data/spec/rubygems/doc_manager_spec.rb +112 -112
- data/spec/serializers/data/serialized_yardoc/checksums +1 -1
- data/spec/serializers/file_system_serializer_spec.rb +145 -145
- data/spec/serializers/spec_helper.rb +2 -2
- data/spec/serializers/yardoc_serializer_spec.rb +78 -78
- data/spec/server/adapter_spec.rb +39 -39
- data/spec/server/commands/base_spec.rb +91 -91
- data/spec/server/commands/library_command_spec.rb +39 -39
- data/spec/server/doc_server_helper_spec.rb +72 -72
- data/spec/server/doc_server_serializer_spec.rb +60 -60
- data/spec/server/rack_adapter_spec.rb +21 -21
- data/spec/server/router_spec.rb +123 -123
- data/spec/server/spec_helper.rb +22 -22
- data/spec/server/static_caching_spec.rb +47 -47
- data/spec/server/webrick_servlet_spec.rb +20 -20
- data/spec/server_spec.rb +19 -19
- data/spec/spec_helper.rb +212 -212
- data/spec/tags/default_factory_spec.rb +168 -168
- data/spec/tags/default_tag_spec.rb +11 -11
- data/spec/tags/directives_spec.rb +463 -463
- data/spec/tags/library_spec.rb +48 -48
- data/spec/tags/overload_tag_spec.rb +53 -53
- data/spec/tags/ref_tag_list_spec.rb +53 -53
- data/spec/tags/types_explainer_spec.rb +203 -203
- data/spec/templates/class_spec.rb +45 -45
- data/spec/templates/constant_spec.rb +41 -41
- data/spec/templates/engine_spec.rb +131 -131
- data/spec/templates/examples/class001.html +308 -308
- data/spec/templates/examples/class001.txt +36 -36
- data/spec/templates/examples/class002.html +39 -39
- data/spec/templates/examples/constant001.txt +24 -24
- data/spec/templates/examples/constant002.txt +6 -6
- data/spec/templates/examples/constant003.txt +10 -10
- data/spec/templates/examples/method001.html +137 -137
- data/spec/templates/examples/method001.txt +35 -35
- data/spec/templates/examples/method002.html +91 -91
- data/spec/templates/examples/method002.txt +20 -20
- data/spec/templates/examples/method003.html +165 -165
- data/spec/templates/examples/method003.txt +45 -45
- data/spec/templates/examples/method004.html +48 -48
- data/spec/templates/examples/method004.txt +10 -10
- data/spec/templates/examples/method005.html +105 -105
- data/spec/templates/examples/method005.txt +33 -33
- data/spec/templates/examples/method006.html +107 -107
- data/spec/templates/examples/method006.txt +20 -20
- data/spec/templates/examples/module001.dot +33 -33
- data/spec/templates/examples/module001.html +833 -833
- data/spec/templates/examples/module001.txt +33 -33
- data/spec/templates/examples/module002.html +341 -341
- data/spec/templates/examples/module003.html +202 -202
- data/spec/templates/examples/module004.html +394 -394
- data/spec/templates/examples/module005.html +81 -81
- data/spec/templates/examples/tag001.txt +82 -82
- data/spec/templates/helpers/base_helper_spec.rb +171 -171
- data/spec/templates/helpers/html_helper_spec.rb +687 -668
- data/spec/templates/helpers/html_syntax_highlight_helper_spec.rb +65 -65
- data/spec/templates/helpers/markup/rdoc_markup_spec.rb +84 -84
- data/spec/templates/helpers/markup_helper_spec.rb +136 -136
- data/spec/templates/helpers/method_helper_spec.rb +107 -107
- data/spec/templates/helpers/module_helper_spec.rb +35 -35
- data/spec/templates/helpers/shared_signature_examples.rb +126 -126
- data/spec/templates/helpers/text_helper_spec.rb +65 -65
- data/spec/templates/method_spec.rb +118 -118
- data/spec/templates/module_spec.rb +203 -203
- data/spec/templates/onefile_spec.rb +66 -66
- data/spec/templates/section_spec.rb +144 -144
- data/spec/templates/spec_helper.rb +76 -76
- data/spec/templates/tag_spec.rb +52 -52
- data/spec/templates/template_spec.rb +410 -410
- data/spec/verifier_spec.rb +106 -106
- data/templates/default/class/dot/setup.rb +7 -7
- data/templates/default/class/dot/superklass.erb +2 -2
- data/templates/default/class/html/constructor_details.erb +8 -8
- data/templates/default/class/html/setup.rb +2 -2
- data/templates/default/class/html/subclasses.erb +4 -4
- data/templates/default/class/setup.rb +36 -36
- data/templates/default/class/text/setup.rb +12 -12
- data/templates/default/class/text/subclasses.erb +5 -5
- data/templates/default/constant/text/header.erb +11 -11
- data/templates/default/constant/text/setup.rb +4 -4
- data/templates/default/docstring/html/abstract.erb +4 -4
- data/templates/default/docstring/html/deprecated.erb +1 -1
- data/templates/default/docstring/html/index.erb +5 -5
- data/templates/default/docstring/html/note.erb +6 -6
- data/templates/default/docstring/html/private.erb +4 -4
- data/templates/default/docstring/html/text.erb +1 -1
- data/templates/default/docstring/html/todo.erb +6 -6
- data/templates/default/docstring/setup.rb +52 -52
- data/templates/default/docstring/text/abstract.erb +2 -2
- data/templates/default/docstring/text/deprecated.erb +2 -2
- data/templates/default/docstring/text/index.erb +2 -2
- data/templates/default/docstring/text/note.erb +3 -3
- data/templates/default/docstring/text/private.erb +2 -2
- data/templates/default/docstring/text/text.erb +1 -1
- data/templates/default/docstring/text/todo.erb +3 -3
- data/templates/default/fulldoc/html/css/full_list.css +58 -58
- data/templates/default/fulldoc/html/css/style.css +496 -496
- data/templates/default/fulldoc/html/frames.erb +17 -17
- data/templates/default/fulldoc/html/full_list.erb +37 -37
- data/templates/default/fulldoc/html/full_list_class.erb +2 -2
- data/templates/default/fulldoc/html/full_list_file.erb +7 -7
- data/templates/default/fulldoc/html/full_list_method.erb +10 -10
- data/templates/default/fulldoc/html/js/app.js +303 -292
- data/templates/default/fulldoc/html/js/full_list.js +216 -216
- data/templates/default/fulldoc/html/js/jquery.js +3 -3
- data/templates/default/fulldoc/html/setup.rb +241 -241
- data/templates/default/layout/dot/header.erb +5 -5
- data/templates/default/layout/dot/setup.rb +15 -15
- data/templates/default/layout/html/breadcrumb.erb +11 -11
- data/templates/default/layout/html/files.erb +11 -11
- data/templates/default/layout/html/footer.erb +5 -5
- data/templates/default/layout/html/headers.erb +15 -15
- data/templates/default/layout/html/index.erb +2 -2
- data/templates/default/layout/html/layout.erb +23 -23
- data/templates/default/layout/html/listing.erb +4 -4
- data/templates/default/layout/html/objects.erb +32 -32
- data/templates/default/layout/html/script_setup.erb +4 -4
- data/templates/default/layout/html/search.erb +12 -12
- data/templates/default/layout/html/setup.rb +89 -89
- data/templates/default/method/html/header.erb +16 -16
- data/templates/default/method/setup.rb +4 -4
- data/templates/default/method_details/html/header.erb +2 -2
- data/templates/default/method_details/html/method_signature.erb +24 -24
- data/templates/default/method_details/html/source.erb +9 -9
- data/templates/default/method_details/setup.rb +11 -11
- data/templates/default/method_details/text/header.erb +10 -10
- data/templates/default/method_details/text/method_signature.erb +12 -12
- data/templates/default/method_details/text/setup.rb +11 -11
- data/templates/default/module/dot/child.erb +1 -1
- data/templates/default/module/dot/dependencies.erb +2 -2
- data/templates/default/module/dot/header.erb +6 -6
- data/templates/default/module/dot/info.erb +13 -13
- data/templates/default/module/dot/setup.rb +15 -15
- data/templates/default/module/html/attribute_details.erb +10 -10
- data/templates/default/module/html/attribute_summary.erb +8 -8
- data/templates/default/module/html/box_info.erb +43 -43
- data/templates/default/module/html/children.erb +8 -8
- data/templates/default/module/html/constant_summary.erb +17 -17
- data/templates/default/module/html/defines.erb +2 -2
- data/templates/default/module/html/header.erb +5 -5
- data/templates/default/module/html/inherited_attributes.erb +14 -14
- data/templates/default/module/html/inherited_constants.erb +8 -8
- data/templates/default/module/html/inherited_methods.erb +18 -18
- data/templates/default/module/html/item_summary.erb +40 -40
- data/templates/default/module/html/method_details_list.erb +9 -9
- data/templates/default/module/html/method_summary.erb +13 -13
- data/templates/default/module/html/methodmissing.erb +12 -12
- data/templates/default/module/setup.rb +167 -167
- data/templates/default/module/text/children.erb +9 -9
- data/templates/default/module/text/class_meths_list.erb +7 -7
- data/templates/default/module/text/extends.erb +7 -7
- data/templates/default/module/text/header.erb +7 -7
- data/templates/default/module/text/includes.erb +7 -7
- data/templates/default/module/text/instance_meths_list.erb +7 -7
- data/templates/default/module/text/setup.rb +13 -13
- data/templates/default/onefile/html/files.erb +4 -4
- data/templates/default/onefile/html/headers.erb +6 -6
- data/templates/default/onefile/html/layout.erb +17 -17
- data/templates/default/onefile/html/readme.erb +2 -2
- data/templates/default/onefile/html/setup.rb +62 -62
- data/templates/default/root/dot/child.erb +2 -2
- data/templates/default/root/dot/setup.rb +6 -6
- data/templates/default/root/html/setup.rb +2 -2
- data/templates/default/tags/html/example.erb +10 -10
- data/templates/default/tags/html/index.erb +2 -2
- data/templates/default/tags/html/option.erb +24 -24
- data/templates/default/tags/html/overload.erb +13 -13
- data/templates/default/tags/html/see.erb +7 -7
- data/templates/default/tags/html/tag.erb +20 -20
- data/templates/default/tags/setup.rb +57 -57
- data/templates/default/tags/text/example.erb +12 -12
- data/templates/default/tags/text/index.erb +1 -1
- data/templates/default/tags/text/option.erb +20 -20
- data/templates/default/tags/text/overload.erb +19 -19
- data/templates/default/tags/text/see.erb +11 -11
- data/templates/default/tags/text/tag.erb +13 -13
- data/templates/guide/class/html/setup.rb +2 -2
- data/templates/guide/docstring/html/setup.rb +2 -2
- data/templates/guide/fulldoc/html/css/style.css +108 -108
- data/templates/guide/fulldoc/html/js/app.js +33 -33
- data/templates/guide/fulldoc/html/setup.rb +74 -74
- data/templates/guide/layout/html/layout.erb +81 -81
- data/templates/guide/layout/html/setup.rb +25 -25
- data/templates/guide/method/html/header.erb +17 -17
- data/templates/guide/method/html/setup.rb +22 -22
- data/templates/guide/module/html/header.erb +6 -6
- data/templates/guide/module/html/method_list.erb +4 -4
- data/templates/guide/module/html/setup.rb +27 -27
- data/templates/guide/onefile/html/files.erb +4 -4
- data/templates/guide/onefile/html/setup.rb +6 -6
- data/templates/guide/onefile/html/toc.erb +3 -3
- data/templates/guide/tags/html/setup.rb +9 -9
- data/yard.gemspec +43 -43
- metadata +4 -3
@@ -1,134 +1,134 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module YARD
|
3
|
-
module Parser
|
4
|
-
module C
|
5
|
-
module CommentParser
|
6
|
-
protected
|
7
|
-
|
8
|
-
def parse_comments(comments)
|
9
|
-
@overrides = []
|
10
|
-
spaces = nil
|
11
|
-
comments = remove_private_comments(comments)
|
12
|
-
comments = comments.split(/\r?\n/).map do |line|
|
13
|
-
line.gsub!(%r{^\s*/?\*/?}, '')
|
14
|
-
line.gsub!(%r{\*/\s*$}, '')
|
15
|
-
if line =~ /^\s*$/
|
16
|
-
next if spaces.nil?
|
17
|
-
next ""
|
18
|
-
end
|
19
|
-
spaces = (line[/^(\s+)/, 1] || "").size if spaces.nil?
|
20
|
-
line.gsub(/^\s{0,#{spaces}}/, '').rstrip
|
21
|
-
end.compact
|
22
|
-
|
23
|
-
comments = parse_overrides(comments)
|
24
|
-
comments = parse_callseq(comments)
|
25
|
-
comments.join("\n")
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
def parse_overrides(comments)
|
31
|
-
comments.map do |line|
|
32
|
-
type, name = *line.scan(/^\s*Document-(class|module|method|attr|const):\s*(\S.*)\s*$/).first
|
33
|
-
if type
|
34
|
-
@overrides << [type.to_sym, name]
|
35
|
-
nil
|
36
|
-
else
|
37
|
-
line
|
38
|
-
end
|
39
|
-
end.compact
|
40
|
-
end
|
41
|
-
|
42
|
-
def parse_callseq(comments)
|
43
|
-
return comments unless comments[0] =~ /\Acall-seq:\s*(\S.+)?/
|
44
|
-
if $1
|
45
|
-
comments[0] = " #{$1}"
|
46
|
-
else
|
47
|
-
comments.shift
|
48
|
-
end
|
49
|
-
overloads = []
|
50
|
-
seen_data = false
|
51
|
-
while comments.first =~ /^\s+(\S.+)/ || comments.first =~ /^\s*$/
|
52
|
-
line = comments.shift.strip
|
53
|
-
break if line.empty? && seen_data
|
54
|
-
next if line.empty?
|
55
|
-
seen_data = true
|
56
|
-
line.sub!(/^\w+[\.#]/, '')
|
57
|
-
signature, types = *line.split(/ [-=]> /)
|
58
|
-
types = parse_types(types)
|
59
|
-
if signature.sub!(/\[?\s*(\{(?:\s*\|(.+?)\|)?.*\})\s*\]?\s*$/, '') && $1
|
60
|
-
blk = $1
|
61
|
-
blkparams = $2
|
62
|
-
else
|
63
|
-
blk = nil
|
64
|
-
blkparams = nil
|
65
|
-
end
|
66
|
-
case signature
|
67
|
-
when /^(\w+)\s*=\s+(\w+)/
|
68
|
-
signature = "#{$1}=(#{$2})"
|
69
|
-
when /^\w+\s+\S/
|
70
|
-
signature = signature.split(/\s+/)
|
71
|
-
signature = "#{signature[1]}#{signature[2] ? '(' + signature[2..-1].join(' ') + ')' : ''}"
|
72
|
-
when /^\w+\[(.+?)\]\s*(=)?/
|
73
|
-
signature = "[]#{$2}(#{$1})"
|
74
|
-
when /^\w+\s+(#{CodeObjects::METHODMATCH})\s+(\w+)/
|
75
|
-
signature = "#{$1}(#{$2})"
|
76
|
-
end
|
77
|
-
break unless signature =~ /^#{CodeObjects::METHODNAMEMATCH}/
|
78
|
-
signature = signature.rstrip
|
79
|
-
overloads << "@overload #{signature}"
|
80
|
-
overloads << " @yield [#{blkparams}]" if blk
|
81
|
-
overloads << " @return [#{types.join(', ')}]" unless types.empty?
|
82
|
-
end
|
83
|
-
|
84
|
-
comments + [""] + overloads
|
85
|
-
end
|
86
|
-
|
87
|
-
def parse_types(types)
|
88
|
-
if types =~ /true or false/
|
89
|
-
["Boolean"]
|
90
|
-
else
|
91
|
-
(types || "").split(/,| or /).map do |t|
|
92
|
-
case t.strip.gsub(/^an?_/, '')
|
93
|
-
when "class"; "Class"
|
94
|
-
when "obj", "object", "anObject"; "Object"
|
95
|
-
when "arr", "array", "anArray", "ary", "new_ary", /^\[/; "Array"
|
96
|
-
when /^char\s*\*/, "char", "str", "string", "new_str"; "String"
|
97
|
-
when "enum", "anEnumerator"; "Enumerator"
|
98
|
-
when "exc", "exception"; "Exception"
|
99
|
-
when "proc", "proc_obj", "prc"; "Proc"
|
100
|
-
when "binding"; "Binding"
|
101
|
-
when "hsh", "hash", "aHash"; "Hash"
|
102
|
-
when "ios", "io"; "IO"
|
103
|
-
when "file"; "File"
|
104
|
-
when "float"; "Float"
|
105
|
-
when "time", "new_time"; "Time"
|
106
|
-
when "dir", "aDir"; "Dir"
|
107
|
-
when "regexp", "new_regexp"; "Regexp"
|
108
|
-
when "matchdata"; "MatchData"
|
109
|
-
when "encoding"; "Encoding"
|
110
|
-
when "fixnum", "fix"; "Fixnum"
|
111
|
-
when /^(?:un)?signed$/, /^(?:(?:un)?signed\s*)?(?:short|int|long|long\s+long)$/, "integer", "Integer"; "Integer"
|
112
|
-
when "num", "numeric", "Numeric", "number"; "Numeric"
|
113
|
-
when "aBignum"; "Bignum"
|
114
|
-
when "nil"; "nil"
|
115
|
-
when "true"; "true"
|
116
|
-
when "false"; "false"
|
117
|
-
when "bool", "boolean", "Boolean"; "Boolean"
|
118
|
-
when "self"; "self"
|
119
|
-
when /^[-+]?\d/; t
|
120
|
-
when /[A-Z][_a-z0-9]+/; t
|
121
|
-
end
|
122
|
-
end.compact
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
def remove_private_comments(comment)
|
127
|
-
comment = comment.gsub(%r{/?\*--\n(.*?)/?\*\+\+}m, '')
|
128
|
-
comment = comment.sub(%r{/?\*--\n.*}m, '')
|
129
|
-
comment
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module YARD
|
3
|
+
module Parser
|
4
|
+
module C
|
5
|
+
module CommentParser
|
6
|
+
protected
|
7
|
+
|
8
|
+
def parse_comments(comments)
|
9
|
+
@overrides = []
|
10
|
+
spaces = nil
|
11
|
+
comments = remove_private_comments(comments)
|
12
|
+
comments = comments.split(/\r?\n/).map do |line|
|
13
|
+
line.gsub!(%r{^\s*/?\*/?}, '')
|
14
|
+
line.gsub!(%r{\*/\s*$}, '')
|
15
|
+
if line =~ /^\s*$/
|
16
|
+
next if spaces.nil?
|
17
|
+
next ""
|
18
|
+
end
|
19
|
+
spaces = (line[/^(\s+)/, 1] || "").size if spaces.nil?
|
20
|
+
line.gsub(/^\s{0,#{spaces}}/, '').rstrip
|
21
|
+
end.compact
|
22
|
+
|
23
|
+
comments = parse_overrides(comments)
|
24
|
+
comments = parse_callseq(comments)
|
25
|
+
comments.join("\n")
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def parse_overrides(comments)
|
31
|
+
comments.map do |line|
|
32
|
+
type, name = *line.scan(/^\s*Document-(class|module|method|attr|const):\s*(\S.*)\s*$/).first
|
33
|
+
if type
|
34
|
+
@overrides << [type.to_sym, name]
|
35
|
+
nil
|
36
|
+
else
|
37
|
+
line
|
38
|
+
end
|
39
|
+
end.compact
|
40
|
+
end
|
41
|
+
|
42
|
+
def parse_callseq(comments)
|
43
|
+
return comments unless comments[0] =~ /\Acall-seq:\s*(\S.+)?/
|
44
|
+
if $1
|
45
|
+
comments[0] = " #{$1}"
|
46
|
+
else
|
47
|
+
comments.shift
|
48
|
+
end
|
49
|
+
overloads = []
|
50
|
+
seen_data = false
|
51
|
+
while comments.first =~ /^\s+(\S.+)/ || comments.first =~ /^\s*$/
|
52
|
+
line = comments.shift.strip
|
53
|
+
break if line.empty? && seen_data
|
54
|
+
next if line.empty?
|
55
|
+
seen_data = true
|
56
|
+
line.sub!(/^\w+[\.#]/, '')
|
57
|
+
signature, types = *line.split(/ [-=]> /)
|
58
|
+
types = parse_types(types)
|
59
|
+
if signature.sub!(/\[?\s*(\{(?:\s*\|(.+?)\|)?.*\})\s*\]?\s*$/, '') && $1
|
60
|
+
blk = $1
|
61
|
+
blkparams = $2
|
62
|
+
else
|
63
|
+
blk = nil
|
64
|
+
blkparams = nil
|
65
|
+
end
|
66
|
+
case signature
|
67
|
+
when /^(\w+)\s*=\s+(\w+)/
|
68
|
+
signature = "#{$1}=(#{$2})"
|
69
|
+
when /^\w+\s+\S/
|
70
|
+
signature = signature.split(/\s+/)
|
71
|
+
signature = "#{signature[1]}#{signature[2] ? '(' + signature[2..-1].join(' ') + ')' : ''}"
|
72
|
+
when /^\w+\[(.+?)\]\s*(=)?/
|
73
|
+
signature = "[]#{$2}(#{$1})"
|
74
|
+
when /^\w+\s+(#{CodeObjects::METHODMATCH})\s+(\w+)/
|
75
|
+
signature = "#{$1}(#{$2})"
|
76
|
+
end
|
77
|
+
break unless signature =~ /^#{CodeObjects::METHODNAMEMATCH}/
|
78
|
+
signature = signature.rstrip
|
79
|
+
overloads << "@overload #{signature}"
|
80
|
+
overloads << " @yield [#{blkparams}]" if blk
|
81
|
+
overloads << " @return [#{types.join(', ')}]" unless types.empty?
|
82
|
+
end
|
83
|
+
|
84
|
+
comments + [""] + overloads
|
85
|
+
end
|
86
|
+
|
87
|
+
def parse_types(types)
|
88
|
+
if types =~ /true or false/
|
89
|
+
["Boolean"]
|
90
|
+
else
|
91
|
+
(types || "").split(/,| or /).map do |t|
|
92
|
+
case t.strip.gsub(/^an?_/, '')
|
93
|
+
when "class"; "Class"
|
94
|
+
when "obj", "object", "anObject"; "Object"
|
95
|
+
when "arr", "array", "anArray", "ary", "new_ary", /^\[/; "Array"
|
96
|
+
when /^char\s*\*/, "char", "str", "string", "new_str"; "String"
|
97
|
+
when "enum", "anEnumerator"; "Enumerator"
|
98
|
+
when "exc", "exception"; "Exception"
|
99
|
+
when "proc", "proc_obj", "prc"; "Proc"
|
100
|
+
when "binding"; "Binding"
|
101
|
+
when "hsh", "hash", "aHash"; "Hash"
|
102
|
+
when "ios", "io"; "IO"
|
103
|
+
when "file"; "File"
|
104
|
+
when "float"; "Float"
|
105
|
+
when "time", "new_time"; "Time"
|
106
|
+
when "dir", "aDir"; "Dir"
|
107
|
+
when "regexp", "new_regexp"; "Regexp"
|
108
|
+
when "matchdata"; "MatchData"
|
109
|
+
when "encoding"; "Encoding"
|
110
|
+
when "fixnum", "fix"; "Fixnum"
|
111
|
+
when /^(?:un)?signed$/, /^(?:(?:un)?signed\s*)?(?:short|int|long|long\s+long)$/, "integer", "Integer"; "Integer"
|
112
|
+
when "num", "numeric", "Numeric", "number"; "Numeric"
|
113
|
+
when "aBignum"; "Bignum"
|
114
|
+
when "nil"; "nil"
|
115
|
+
when "true"; "true"
|
116
|
+
when "false"; "false"
|
117
|
+
when "bool", "boolean", "Boolean"; "Boolean"
|
118
|
+
when "self"; "self"
|
119
|
+
when /^[-+]?\d/; t
|
120
|
+
when /[A-Z][_a-z0-9]+/; t
|
121
|
+
end
|
122
|
+
end.compact
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def remove_private_comments(comment)
|
127
|
+
comment = comment.gsub(%r{/?\*--\n(.*?)/?\*\+\+}m, '')
|
128
|
+
comment = comment.sub(%r{/?\*--\n.*}m, '')
|
129
|
+
comment
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -1,64 +1,64 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module YARD
|
3
|
-
module Parser
|
4
|
-
module C
|
5
|
-
class Statement
|
6
|
-
attr_accessor :source
|
7
|
-
attr_accessor :line
|
8
|
-
attr_accessor :file
|
9
|
-
|
10
|
-
# @deprecated Groups are now defined by directives
|
11
|
-
# @see Tags::GroupDirective
|
12
|
-
attr_accessor :group
|
13
|
-
|
14
|
-
attr_accessor :comments_hash_flag
|
15
|
-
|
16
|
-
def initialize(source, file = nil, line = nil)
|
17
|
-
@source = source
|
18
|
-
@file = file
|
19
|
-
@line = line
|
20
|
-
end
|
21
|
-
|
22
|
-
def line_range
|
23
|
-
line...(line + source.count("\n"))
|
24
|
-
end
|
25
|
-
|
26
|
-
def comments_range
|
27
|
-
comments.line_range
|
28
|
-
end
|
29
|
-
|
30
|
-
def first_line
|
31
|
-
source.split(/\n/).first
|
32
|
-
end
|
33
|
-
|
34
|
-
def show
|
35
|
-
"\t#{line}: #{first_line}"
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
class BodyStatement < Statement
|
40
|
-
attr_accessor :comments
|
41
|
-
end
|
42
|
-
|
43
|
-
class ToplevelStatement < Statement
|
44
|
-
attr_accessor :block
|
45
|
-
attr_accessor :declaration
|
46
|
-
attr_accessor :comments
|
47
|
-
end
|
48
|
-
|
49
|
-
class Comment < Statement
|
50
|
-
include CommentParser
|
51
|
-
|
52
|
-
attr_accessor :type
|
53
|
-
attr_accessor :overrides
|
54
|
-
attr_accessor :statement
|
55
|
-
|
56
|
-
def initialize(source, file = nil, line = nil)
|
57
|
-
super(parse_comments(source), file, line)
|
58
|
-
end
|
59
|
-
|
60
|
-
def comments; self end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module YARD
|
3
|
+
module Parser
|
4
|
+
module C
|
5
|
+
class Statement
|
6
|
+
attr_accessor :source
|
7
|
+
attr_accessor :line
|
8
|
+
attr_accessor :file
|
9
|
+
|
10
|
+
# @deprecated Groups are now defined by directives
|
11
|
+
# @see Tags::GroupDirective
|
12
|
+
attr_accessor :group
|
13
|
+
|
14
|
+
attr_accessor :comments_hash_flag
|
15
|
+
|
16
|
+
def initialize(source, file = nil, line = nil)
|
17
|
+
@source = source
|
18
|
+
@file = file
|
19
|
+
@line = line
|
20
|
+
end
|
21
|
+
|
22
|
+
def line_range
|
23
|
+
line...(line + source.count("\n"))
|
24
|
+
end
|
25
|
+
|
26
|
+
def comments_range
|
27
|
+
comments.line_range
|
28
|
+
end
|
29
|
+
|
30
|
+
def first_line
|
31
|
+
source.split(/\n/).first
|
32
|
+
end
|
33
|
+
|
34
|
+
def show
|
35
|
+
"\t#{line}: #{first_line}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class BodyStatement < Statement
|
40
|
+
attr_accessor :comments
|
41
|
+
end
|
42
|
+
|
43
|
+
class ToplevelStatement < Statement
|
44
|
+
attr_accessor :block
|
45
|
+
attr_accessor :declaration
|
46
|
+
attr_accessor :comments
|
47
|
+
end
|
48
|
+
|
49
|
+
class Comment < Statement
|
50
|
+
include CommentParser
|
51
|
+
|
52
|
+
attr_accessor :type
|
53
|
+
attr_accessor :overrides
|
54
|
+
attr_accessor :statement
|
55
|
+
|
56
|
+
def initialize(source, file = nil, line = nil)
|
57
|
+
super(parse_comments(source), file, line)
|
58
|
+
end
|
59
|
+
|
60
|
+
def comments; self end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -1,540 +1,540 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module YARD
|
3
|
-
module Parser
|
4
|
-
module Ruby
|
5
|
-
# Builds and s-expression by creating {AstNode} objects with
|
6
|
-
# the type provided by the first argument.
|
7
|
-
#
|
8
|
-
# @example An implicit list of keywords
|
9
|
-
# ast = s(s(:kw, "if"), s(:kw, "else"))
|
10
|
-
# ast.type # => :list
|
11
|
-
# @example A method call
|
12
|
-
# s(:command, s(:var_ref, "mymethod"))
|
13
|
-
#
|
14
|
-
# @overload s(*nodes, opts = {})
|
15
|
-
# @param [Array<AstNode>] nodes a list of nodes.
|
16
|
-
# @param [Hash] opts any extra options (docstring, file, source) to
|
17
|
-
# set on the object
|
18
|
-
# @return [AstNode] an implicit node where node.type == +:list+
|
19
|
-
# @overload s(type, *children, opts = {})
|
20
|
-
# @param [Symbol] type the node type
|
21
|
-
# @param [Array<AstNode>] children any child nodes inside this one
|
22
|
-
# @param [Hash] opts any extra options to set on the object
|
23
|
-
# @return [AstNode] a node of type +type+.
|
24
|
-
# @see AstNode#initialize
|
25
|
-
def s(*args)
|
26
|
-
type = Symbol === args.first ? args.shift : :list
|
27
|
-
opts = Hash === args.last ? args.pop : {}
|
28
|
-
AstNode.node_class_for(type).new(type, args, opts)
|
29
|
-
end
|
30
|
-
|
31
|
-
# An AST node is characterized by a type and a list of children. It
|
32
|
-
# is most easily represented by the s-expression {#s} such as:
|
33
|
-
# # AST for "if true; 5 end":
|
34
|
-
# s(s(:if, s(:var_ref, s(:kw, "true")), s(s(:int, "5")), nil))
|
35
|
-
#
|
36
|
-
# The node type is not considered part of the list, only its children.
|
37
|
-
# So +ast[0]+ does not refer to the type, but rather the first child
|
38
|
-
# (or object). Items that are not +AstNode+ objects can be part of the
|
39
|
-
# list, like Strings or Symbols representing names. To return only
|
40
|
-
# the AstNode children of the node, use {#children}.
|
41
|
-
class AstNode < Array
|
42
|
-
attr_accessor :docstring_hash_flag
|
43
|
-
attr_accessor :docstring, :docstring_range, :source
|
44
|
-
|
45
|
-
# @deprecated Groups are now defined by directives
|
46
|
-
# @see Tags::GroupDirective
|
47
|
-
attr_accessor :group
|
48
|
-
|
49
|
-
attr_writer :source_range, :line_range, :file, :full_source
|
50
|
-
alias comments docstring
|
51
|
-
alias comments_range docstring_range
|
52
|
-
alias comments_hash_flag docstring_hash_flag
|
53
|
-
alias to_s source
|
54
|
-
|
55
|
-
# @return [Symbol] the node's unique symbolic type
|
56
|
-
attr_accessor :type
|
57
|
-
|
58
|
-
# @return [AstNode, nil] the node's parent or nil if it is a root node.
|
59
|
-
attr_accessor :parent
|
60
|
-
|
61
|
-
# @return [Range] the character range in {#full_source} represented
|
62
|
-
# by the node
|
63
|
-
def source_range
|
64
|
-
reset_line_info unless @source_range
|
65
|
-
@source_range
|
66
|
-
end
|
67
|
-
|
68
|
-
# @return [Range] the line range in {#full_source} represented
|
69
|
-
# by the node
|
70
|
-
def line_range
|
71
|
-
reset_line_info unless @line_range
|
72
|
-
@line_range
|
73
|
-
end
|
74
|
-
|
75
|
-
# @return [String] the filename the node was parsed from
|
76
|
-
def file
|
77
|
-
return parent.file if parent
|
78
|
-
@file
|
79
|
-
end
|
80
|
-
|
81
|
-
# @return [String] the full source that the node was parsed from
|
82
|
-
def full_source
|
83
|
-
return parent.full_source if parent
|
84
|
-
return @full_source if @full_source
|
85
|
-
return IO.read(@file) if file && File.exist?(file)
|
86
|
-
end
|
87
|
-
|
88
|
-
# @return [String] the parse of {#full_source} that the node represents
|
89
|
-
def source
|
90
|
-
return parent.full_source[source_range] if parent
|
91
|
-
full_source
|
92
|
-
end
|
93
|
-
|
94
|
-
# List of all known keywords
|
95
|
-
# @return [Hash]
|
96
|
-
KEYWORDS = {:class => true, :alias => true, :lambda => true, :do_block => true,
|
97
|
-
:def => true, :defs => true, :begin => true, :rescue => true, :rescue_mod => true,
|
98
|
-
:if => true, :if_mod => true, :else => true, :elsif => true, :case => true,
|
99
|
-
:when => true, :next => true, :break => true, :retry => true, :redo => true,
|
100
|
-
:return => true, :throw => true, :catch => true, :until => true, :until_mod => true,
|
101
|
-
:while => true, :while_mod => true, :yield => true, :yield0 => true, :zsuper => true,
|
102
|
-
:unless => true, :unless_mod => true, :for => true, :super => true, :return0 => true}
|
103
|
-
|
104
|
-
# @group Creating an AstNode
|
105
|
-
|
106
|
-
# Finds the node subclass that should be instantiated for a specific
|
107
|
-
# node type
|
108
|
-
#
|
109
|
-
# @param [Symbol] type the node type to find a subclass for
|
110
|
-
# @return [Class] a subclass of AstNode to instantiate the node with.
|
111
|
-
def self.node_class_for(type)
|
112
|
-
case type
|
113
|
-
when :params
|
114
|
-
ParameterNode
|
115
|
-
when :call, :fcall, :vcall, :command, :command_call
|
116
|
-
MethodCallNode
|
117
|
-
when :if, :elsif, :if_mod, :unless, :unless_mod
|
118
|
-
ConditionalNode
|
119
|
-
when :for, :while, :while_mod, :until, :until_mod
|
120
|
-
LoopNode
|
121
|
-
when :def, :defs
|
122
|
-
MethodDefinitionNode
|
123
|
-
when :class, :sclass
|
124
|
-
ClassNode
|
125
|
-
when :module
|
126
|
-
ModuleNode
|
127
|
-
else
|
128
|
-
if type.to_s =~ /_ref\Z/
|
129
|
-
ReferenceNode
|
130
|
-
elsif type.to_s =~ /_literal\Z/
|
131
|
-
LiteralNode
|
132
|
-
elsif KEYWORDS.key?(type)
|
133
|
-
KeywordNode
|
134
|
-
else
|
135
|
-
AstNode
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
# Creates a new AST node
|
141
|
-
#
|
142
|
-
# @param [Symbol] type the type of node being created
|
143
|
-
# @param [Array<AstNode>] arr the child nodes
|
144
|
-
# @param [Hash] opts any extra line options
|
145
|
-
# @option opts [Fixnum] :line (nil) the line the node starts on in source
|
146
|
-
# @option opts [String] :char (nil) the character number the node starts on
|
147
|
-
# in source
|
148
|
-
# @option opts [Fixnum] :listline (nil) a special key like :line but for
|
149
|
-
# list nodes
|
150
|
-
# @option opts [Fixnum] :listchar (nil) a special key like :char but for
|
151
|
-
# list nodes
|
152
|
-
# @option opts [Boolean] :token (nil) whether the node represents a token
|
153
|
-
def initialize(type, arr, opts = {})
|
154
|
-
super(arr)
|
155
|
-
self.type = type
|
156
|
-
self.line_range = opts[:line]
|
157
|
-
self.source_range = opts[:char]
|
158
|
-
@fallback_line = opts[:listline]
|
159
|
-
@fallback_source = opts[:listchar]
|
160
|
-
@token = true if opts[:token]
|
161
|
-
@docstring = nil
|
162
|
-
end
|
163
|
-
|
164
|
-
# @return [Boolean] whether the node is equal to another by checking
|
165
|
-
# the list and type
|
166
|
-
# @private
|
167
|
-
def ==(other)
|
168
|
-
super && type == other.type
|
169
|
-
end
|
170
|
-
|
171
|
-
# @group Traversing a Node
|
172
|
-
|
173
|
-
# Searches through the node and all descendants and returns the
|
174
|
-
# first node with a type matching any of +node_types+, otherwise
|
175
|
-
# returns the original node (self).
|
176
|
-
#
|
177
|
-
# @example Returns the first method definition in a block of code
|
178
|
-
# ast = YARD.parse_string("if true; def x; end end").ast
|
179
|
-
# ast.jump(:def)
|
180
|
-
# # => s(:def, s(:ident, "x"), s(:params, nil, nil, nil, nil,
|
181
|
-
# # nil), s(s(:void_stmt, )))
|
182
|
-
# @example Returns first 'def' or 'class' statement
|
183
|
-
# ast = YARD.parse_string("class X; def y; end end")
|
184
|
-
# ast.jump(:def, :class).first
|
185
|
-
# # =>
|
186
|
-
# @example If the node types are not present in the AST
|
187
|
-
# ast = YARD.parse("def x; end")
|
188
|
-
# ast.jump(:def)
|
189
|
-
#
|
190
|
-
# @param [Array<Symbol>] node_types a set of node types to match
|
191
|
-
# @return [AstNode] the matching node, if one was found
|
192
|
-
# @return [self] if no node was found
|
193
|
-
def jump(*node_types)
|
194
|
-
traverse {|child| return(child) if node_types.include?(child.type) }
|
195
|
-
self
|
196
|
-
end
|
197
|
-
|
198
|
-
# @return [Array<AstNode>] the {AstNode} children inside the node
|
199
|
-
def children
|
200
|
-
@children ||= select {|e| AstNode === e }
|
201
|
-
end
|
202
|
-
|
203
|
-
# Traverses the object and yields each node (including descendants) in order.
|
204
|
-
#
|
205
|
-
# @yield each descendant node in order
|
206
|
-
# @yieldparam [AstNode] self, or a child/descendant node
|
207
|
-
# @return [void]
|
208
|
-
def traverse
|
209
|
-
nodes = [self]
|
210
|
-
until nodes.empty?
|
211
|
-
node = nodes.pop
|
212
|
-
yield node
|
213
|
-
nodes += node.children.reverse unless node.children.empty?
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
# @group Node Meta Types
|
218
|
-
|
219
|
-
# @return [Boolean] whether the node is a token
|
220
|
-
def token?
|
221
|
-
@token
|
222
|
-
end
|
223
|
-
|
224
|
-
# @return [Boolean] whether the node is a reference (variable,
|
225
|
-
# constant name)
|
226
|
-
def ref?
|
227
|
-
false
|
228
|
-
end
|
229
|
-
|
230
|
-
# @return [Boolean] whether the node is a literal value
|
231
|
-
def literal?
|
232
|
-
false
|
233
|
-
end
|
234
|
-
|
235
|
-
# @return [Boolean] whether the node is a keyword
|
236
|
-
def kw?
|
237
|
-
false
|
238
|
-
end
|
239
|
-
|
240
|
-
# @return [Boolean] whether the node is a method call
|
241
|
-
def call?
|
242
|
-
false
|
243
|
-
end
|
244
|
-
|
245
|
-
# @return [Boolean] whether the node is a method definition
|
246
|
-
def def?
|
247
|
-
false
|
248
|
-
end
|
249
|
-
|
250
|
-
# @return [Boolean] whether the node is a if/elsif/else condition
|
251
|
-
def condition?
|
252
|
-
false
|
253
|
-
end
|
254
|
-
|
255
|
-
# @return [Boolean] whether the node is a loop
|
256
|
-
def loop?
|
257
|
-
false
|
258
|
-
end
|
259
|
-
|
260
|
-
# @return [Boolean] whether the node has a block
|
261
|
-
def block?
|
262
|
-
respond_to?(:block) || condition?
|
263
|
-
end
|
264
|
-
|
265
|
-
# @group Getting Line Information
|
266
|
-
|
267
|
-
# @return [Boolean] whether the node has a {#line_range} set
|
268
|
-
def has_line?
|
269
|
-
@line_range ? true : false
|
270
|
-
end
|
271
|
-
|
272
|
-
# @return [Fixnum] the starting line number of the node
|
273
|
-
def line
|
274
|
-
line_range && line_range.first
|
275
|
-
end
|
276
|
-
|
277
|
-
# @return [String] the first line of source represented by the node.
|
278
|
-
def first_line
|
279
|
-
full_source.split(/\r?\n/)[line - 1].strip
|
280
|
-
end
|
281
|
-
|
282
|
-
# @group Printing a Node
|
283
|
-
|
284
|
-
# @return [String] the first line of source the node represents
|
285
|
-
def show
|
286
|
-
"\t#{line}: #{first_line}"
|
287
|
-
end
|
288
|
-
|
289
|
-
# @return [nil] pretty prints the node
|
290
|
-
def pretty_print(q)
|
291
|
-
objs = dup + [:__last__]
|
292
|
-
objs.unshift(type) if type && type != :list
|
293
|
-
|
294
|
-
options = []
|
295
|
-
options << ['docstring', docstring] if @docstring
|
296
|
-
if @source_range || @line_range
|
297
|
-
options << ['line', line_range]
|
298
|
-
options << ['source', source_range]
|
299
|
-
end
|
300
|
-
objs.pop if options.empty?
|
301
|
-
|
302
|
-
q.group(3, 's(', ')') do
|
303
|
-
q.seplist(objs, nil, :each) do |v|
|
304
|
-
if v == :__last__
|
305
|
-
q.seplist(options, nil, :each) do |arr|
|
306
|
-
k, v2 = *arr
|
307
|
-
q.group(3) do
|
308
|
-
q.text k
|
309
|
-
q.group(3) do
|
310
|
-
q.text ': '
|
311
|
-
q.pp v2
|
312
|
-
end
|
313
|
-
end
|
314
|
-
end
|
315
|
-
else
|
316
|
-
q.pp v
|
317
|
-
end
|
318
|
-
end
|
319
|
-
end
|
320
|
-
end
|
321
|
-
|
322
|
-
# @return [String] inspects the object
|
323
|
-
def inspect
|
324
|
-
typeinfo = type && type != :list ? ':' + type.to_s + ', ' : ''
|
325
|
-
's(' + typeinfo + map(&:inspect).join(", ") + ')'
|
326
|
-
end
|
327
|
-
|
328
|
-
# @group Managing node state
|
329
|
-
|
330
|
-
# Resets node state in tree
|
331
|
-
def unfreeze
|
332
|
-
@children = nil
|
333
|
-
end
|
334
|
-
|
335
|
-
# @endgroup
|
336
|
-
|
337
|
-
private
|
338
|
-
|
339
|
-
# Resets line information
|
340
|
-
# @return [void]
|
341
|
-
def reset_line_info
|
342
|
-
if size == 0
|
343
|
-
self.line_range = @fallback_line
|
344
|
-
self.source_range = @fallback_source
|
345
|
-
elsif !children.empty?
|
346
|
-
f = children.first
|
347
|
-
l = children.last
|
348
|
-
self.line_range = Range.new(f.line_range.first, l.line_range.last)
|
349
|
-
self.source_range = Range.new(f.source_range.first, l.source_range.last)
|
350
|
-
elsif @fallback_line || @fallback_source
|
351
|
-
self.line_range = @fallback_line
|
352
|
-
self.source_range = @fallback_source
|
353
|
-
else
|
354
|
-
self.line_range = 0...0
|
355
|
-
self.source_range = 0...0
|
356
|
-
end
|
357
|
-
end
|
358
|
-
end
|
359
|
-
|
360
|
-
class ReferenceNode < AstNode
|
361
|
-
def ref?; true end
|
362
|
-
|
363
|
-
def path
|
364
|
-
Array.new flatten
|
365
|
-
end
|
366
|
-
|
367
|
-
def namespace
|
368
|
-
Array.new flatten[0...-1]
|
369
|
-
end
|
370
|
-
end
|
371
|
-
|
372
|
-
class LiteralNode < AstNode
|
373
|
-
def literal?; true end
|
374
|
-
end
|
375
|
-
|
376
|
-
class KeywordNode < AstNode
|
377
|
-
def kw?; true end
|
378
|
-
end
|
379
|
-
|
380
|
-
class ParameterNode < AstNode
|
381
|
-
def unnamed_required_params
|
382
|
-
self[0]
|
383
|
-
end
|
384
|
-
|
385
|
-
def unnamed_optional_params
|
386
|
-
return @unnamed_optional_params if defined?(@unnamed_optional_params)
|
387
|
-
|
388
|
-
params = self[1] || []
|
389
|
-
if self[-3] && self[-3][0] && self[-3][0].type == :unnamed_optional_arg
|
390
|
-
params += self[-3]
|
391
|
-
end
|
392
|
-
|
393
|
-
@unnamed_optional_params = params.empty? ? nil : params
|
394
|
-
end
|
395
|
-
|
396
|
-
def named_params
|
397
|
-
return @named_params if defined?(@named_params)
|
398
|
-
|
399
|
-
if YARD.ruby2? && self[-3] && self[-3][0] && self[-3][0].type == :named_arg
|
400
|
-
@named_params = self[-3]
|
401
|
-
else
|
402
|
-
@named_params = nil
|
403
|
-
end
|
404
|
-
end
|
405
|
-
|
406
|
-
def splat_param
|
407
|
-
self[2] ? self[2][0] : nil
|
408
|
-
end
|
409
|
-
|
410
|
-
def unnamed_end_params
|
411
|
-
self[3]
|
412
|
-
end
|
413
|
-
|
414
|
-
def double_splat_param
|
415
|
-
return nil unless YARD.ruby2?
|
416
|
-
if (node = self[-2]).is_a?(AstNode)
|
417
|
-
if node.type == :ident
|
418
|
-
node
|
419
|
-
elsif node.type == :kwrest_param
|
420
|
-
# See https://bugs.ruby-lang.org/issues/12387
|
421
|
-
node.last
|
422
|
-
end
|
423
|
-
end
|
424
|
-
end
|
425
|
-
|
426
|
-
def block_param
|
427
|
-
self[-1] ? self[-1][0] : nil
|
428
|
-
end
|
429
|
-
end
|
430
|
-
|
431
|
-
class MethodCallNode < AstNode
|
432
|
-
def call?; true end
|
433
|
-
def namespace; first if index_adjust > 0 end
|
434
|
-
|
435
|
-
def method_name(name_only = false)
|
436
|
-
name = self[index_adjust]
|
437
|
-
if name == :call
|
438
|
-
nil
|
439
|
-
elsif name_only && Array === name
|
440
|
-
name.jump(:ident).first.to_sym
|
441
|
-
else
|
442
|
-
name
|
443
|
-
end
|
444
|
-
end
|
445
|
-
|
446
|
-
def parameters(include_block_param = true)
|
447
|
-
return [] if type == :vcall
|
448
|
-
params = self[1 + index_adjust]
|
449
|
-
return [] unless params
|
450
|
-
params = call_has_paren? ? params.first : params
|
451
|
-
return [] unless params
|
452
|
-
include_block_param ? params : params[0...-1]
|
453
|
-
end
|
454
|
-
|
455
|
-
def block_param; parameters.last end
|
456
|
-
|
457
|
-
def block
|
458
|
-
last.type == :do_block || last.type == :brace_block ? last : nil
|
459
|
-
end
|
460
|
-
|
461
|
-
private
|
462
|
-
|
463
|
-
def index_adjust
|
464
|
-
[:call, :command_call].include?(type) ? 2 : 0
|
465
|
-
end
|
466
|
-
|
467
|
-
def call_has_paren?
|
468
|
-
[:fcall, :call].include?(type)
|
469
|
-
end
|
470
|
-
end
|
471
|
-
|
472
|
-
class MethodDefinitionNode < AstNode
|
473
|
-
def kw?; true end
|
474
|
-
def def?; true end
|
475
|
-
def namespace; first if index_adjust > 0 end
|
476
|
-
|
477
|
-
def method_name(name_only = false)
|
478
|
-
name = self[index_adjust]
|
479
|
-
name_only ? name.jump(:ident).first.to_sym : name
|
480
|
-
end
|
481
|
-
|
482
|
-
def parameters(include_block_param = true)
|
483
|
-
params = self[1 + index_adjust]
|
484
|
-
params = params[0] if params.type == :paren
|
485
|
-
include_block_param ? params : params[0...-1]
|
486
|
-
end
|
487
|
-
|
488
|
-
alias block last
|
489
|
-
|
490
|
-
private
|
491
|
-
|
492
|
-
def index_adjust
|
493
|
-
type == :defs ? 2 : 0
|
494
|
-
end
|
495
|
-
end
|
496
|
-
|
497
|
-
class ConditionalNode < KeywordNode
|
498
|
-
def condition?; true end
|
499
|
-
def condition; first end
|
500
|
-
def then_block; self[1] end
|
501
|
-
|
502
|
-
def else_block
|
503
|
-
return unless self[2] && !cmod?
|
504
|
-
self[2].type == :elsif ? self[2] : self[2][0]
|
505
|
-
end
|
506
|
-
|
507
|
-
private
|
508
|
-
|
509
|
-
def cmod?; type =~ /_mod$/ end
|
510
|
-
end
|
511
|
-
|
512
|
-
class ClassNode < KeywordNode
|
513
|
-
def class_name; first end
|
514
|
-
def superclass; type == :sclass ? nil : self[1] end
|
515
|
-
def block; last end
|
516
|
-
end
|
517
|
-
|
518
|
-
class ModuleNode < KeywordNode
|
519
|
-
def module_name; first end
|
520
|
-
def block; last end
|
521
|
-
end
|
522
|
-
|
523
|
-
class LoopNode < KeywordNode
|
524
|
-
def loop?; true end
|
525
|
-
def condition; type == :for ? s(self[0], self[1]) : first end
|
526
|
-
def block; last end
|
527
|
-
end
|
528
|
-
|
529
|
-
# Represents a lone comment block in source
|
530
|
-
class CommentNode < AstNode
|
531
|
-
def docstring; first end
|
532
|
-
def docstring=(value) end
|
533
|
-
alias comments docstring
|
534
|
-
|
535
|
-
def source; "" end
|
536
|
-
def first_line; "" end
|
537
|
-
end
|
538
|
-
end
|
539
|
-
end
|
540
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module YARD
|
3
|
+
module Parser
|
4
|
+
module Ruby
|
5
|
+
# Builds and s-expression by creating {AstNode} objects with
|
6
|
+
# the type provided by the first argument.
|
7
|
+
#
|
8
|
+
# @example An implicit list of keywords
|
9
|
+
# ast = s(s(:kw, "if"), s(:kw, "else"))
|
10
|
+
# ast.type # => :list
|
11
|
+
# @example A method call
|
12
|
+
# s(:command, s(:var_ref, "mymethod"))
|
13
|
+
#
|
14
|
+
# @overload s(*nodes, opts = {})
|
15
|
+
# @param [Array<AstNode>] nodes a list of nodes.
|
16
|
+
# @param [Hash] opts any extra options (docstring, file, source) to
|
17
|
+
# set on the object
|
18
|
+
# @return [AstNode] an implicit node where node.type == +:list+
|
19
|
+
# @overload s(type, *children, opts = {})
|
20
|
+
# @param [Symbol] type the node type
|
21
|
+
# @param [Array<AstNode>] children any child nodes inside this one
|
22
|
+
# @param [Hash] opts any extra options to set on the object
|
23
|
+
# @return [AstNode] a node of type +type+.
|
24
|
+
# @see AstNode#initialize
|
25
|
+
def s(*args)
|
26
|
+
type = Symbol === args.first ? args.shift : :list
|
27
|
+
opts = Hash === args.last ? args.pop : {}
|
28
|
+
AstNode.node_class_for(type).new(type, args, opts)
|
29
|
+
end
|
30
|
+
|
31
|
+
# An AST node is characterized by a type and a list of children. It
|
32
|
+
# is most easily represented by the s-expression {#s} such as:
|
33
|
+
# # AST for "if true; 5 end":
|
34
|
+
# s(s(:if, s(:var_ref, s(:kw, "true")), s(s(:int, "5")), nil))
|
35
|
+
#
|
36
|
+
# The node type is not considered part of the list, only its children.
|
37
|
+
# So +ast[0]+ does not refer to the type, but rather the first child
|
38
|
+
# (or object). Items that are not +AstNode+ objects can be part of the
|
39
|
+
# list, like Strings or Symbols representing names. To return only
|
40
|
+
# the AstNode children of the node, use {#children}.
|
41
|
+
class AstNode < Array
|
42
|
+
attr_accessor :docstring_hash_flag
|
43
|
+
attr_accessor :docstring, :docstring_range, :source
|
44
|
+
|
45
|
+
# @deprecated Groups are now defined by directives
|
46
|
+
# @see Tags::GroupDirective
|
47
|
+
attr_accessor :group
|
48
|
+
|
49
|
+
attr_writer :source_range, :line_range, :file, :full_source
|
50
|
+
alias comments docstring
|
51
|
+
alias comments_range docstring_range
|
52
|
+
alias comments_hash_flag docstring_hash_flag
|
53
|
+
alias to_s source
|
54
|
+
|
55
|
+
# @return [Symbol] the node's unique symbolic type
|
56
|
+
attr_accessor :type
|
57
|
+
|
58
|
+
# @return [AstNode, nil] the node's parent or nil if it is a root node.
|
59
|
+
attr_accessor :parent
|
60
|
+
|
61
|
+
# @return [Range] the character range in {#full_source} represented
|
62
|
+
# by the node
|
63
|
+
def source_range
|
64
|
+
reset_line_info unless @source_range
|
65
|
+
@source_range
|
66
|
+
end
|
67
|
+
|
68
|
+
# @return [Range] the line range in {#full_source} represented
|
69
|
+
# by the node
|
70
|
+
def line_range
|
71
|
+
reset_line_info unless @line_range
|
72
|
+
@line_range
|
73
|
+
end
|
74
|
+
|
75
|
+
# @return [String] the filename the node was parsed from
|
76
|
+
def file
|
77
|
+
return parent.file if parent
|
78
|
+
@file
|
79
|
+
end
|
80
|
+
|
81
|
+
# @return [String] the full source that the node was parsed from
|
82
|
+
def full_source
|
83
|
+
return parent.full_source if parent
|
84
|
+
return @full_source if @full_source
|
85
|
+
return IO.read(@file) if file && File.exist?(file)
|
86
|
+
end
|
87
|
+
|
88
|
+
# @return [String] the parse of {#full_source} that the node represents
|
89
|
+
def source
|
90
|
+
return parent.full_source[source_range] if parent
|
91
|
+
full_source
|
92
|
+
end
|
93
|
+
|
94
|
+
# List of all known keywords
|
95
|
+
# @return [Hash]
|
96
|
+
KEYWORDS = {:class => true, :alias => true, :lambda => true, :do_block => true,
|
97
|
+
:def => true, :defs => true, :begin => true, :rescue => true, :rescue_mod => true,
|
98
|
+
:if => true, :if_mod => true, :else => true, :elsif => true, :case => true,
|
99
|
+
:when => true, :next => true, :break => true, :retry => true, :redo => true,
|
100
|
+
:return => true, :throw => true, :catch => true, :until => true, :until_mod => true,
|
101
|
+
:while => true, :while_mod => true, :yield => true, :yield0 => true, :zsuper => true,
|
102
|
+
:unless => true, :unless_mod => true, :for => true, :super => true, :return0 => true}
|
103
|
+
|
104
|
+
# @group Creating an AstNode
|
105
|
+
|
106
|
+
# Finds the node subclass that should be instantiated for a specific
|
107
|
+
# node type
|
108
|
+
#
|
109
|
+
# @param [Symbol] type the node type to find a subclass for
|
110
|
+
# @return [Class] a subclass of AstNode to instantiate the node with.
|
111
|
+
def self.node_class_for(type)
|
112
|
+
case type
|
113
|
+
when :params
|
114
|
+
ParameterNode
|
115
|
+
when :call, :fcall, :vcall, :command, :command_call
|
116
|
+
MethodCallNode
|
117
|
+
when :if, :elsif, :if_mod, :unless, :unless_mod
|
118
|
+
ConditionalNode
|
119
|
+
when :for, :while, :while_mod, :until, :until_mod
|
120
|
+
LoopNode
|
121
|
+
when :def, :defs
|
122
|
+
MethodDefinitionNode
|
123
|
+
when :class, :sclass
|
124
|
+
ClassNode
|
125
|
+
when :module
|
126
|
+
ModuleNode
|
127
|
+
else
|
128
|
+
if type.to_s =~ /_ref\Z/
|
129
|
+
ReferenceNode
|
130
|
+
elsif type.to_s =~ /_literal\Z/
|
131
|
+
LiteralNode
|
132
|
+
elsif KEYWORDS.key?(type)
|
133
|
+
KeywordNode
|
134
|
+
else
|
135
|
+
AstNode
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# Creates a new AST node
|
141
|
+
#
|
142
|
+
# @param [Symbol] type the type of node being created
|
143
|
+
# @param [Array<AstNode>] arr the child nodes
|
144
|
+
# @param [Hash] opts any extra line options
|
145
|
+
# @option opts [Fixnum] :line (nil) the line the node starts on in source
|
146
|
+
# @option opts [String] :char (nil) the character number the node starts on
|
147
|
+
# in source
|
148
|
+
# @option opts [Fixnum] :listline (nil) a special key like :line but for
|
149
|
+
# list nodes
|
150
|
+
# @option opts [Fixnum] :listchar (nil) a special key like :char but for
|
151
|
+
# list nodes
|
152
|
+
# @option opts [Boolean] :token (nil) whether the node represents a token
|
153
|
+
def initialize(type, arr, opts = {})
|
154
|
+
super(arr)
|
155
|
+
self.type = type
|
156
|
+
self.line_range = opts[:line]
|
157
|
+
self.source_range = opts[:char]
|
158
|
+
@fallback_line = opts[:listline]
|
159
|
+
@fallback_source = opts[:listchar]
|
160
|
+
@token = true if opts[:token]
|
161
|
+
@docstring = nil
|
162
|
+
end
|
163
|
+
|
164
|
+
# @return [Boolean] whether the node is equal to another by checking
|
165
|
+
# the list and type
|
166
|
+
# @private
|
167
|
+
def ==(other)
|
168
|
+
super && type == other.type
|
169
|
+
end
|
170
|
+
|
171
|
+
# @group Traversing a Node
|
172
|
+
|
173
|
+
# Searches through the node and all descendants and returns the
|
174
|
+
# first node with a type matching any of +node_types+, otherwise
|
175
|
+
# returns the original node (self).
|
176
|
+
#
|
177
|
+
# @example Returns the first method definition in a block of code
|
178
|
+
# ast = YARD.parse_string("if true; def x; end end").ast
|
179
|
+
# ast.jump(:def)
|
180
|
+
# # => s(:def, s(:ident, "x"), s(:params, nil, nil, nil, nil,
|
181
|
+
# # nil), s(s(:void_stmt, )))
|
182
|
+
# @example Returns first 'def' or 'class' statement
|
183
|
+
# ast = YARD.parse_string("class X; def y; end end")
|
184
|
+
# ast.jump(:def, :class).first
|
185
|
+
# # =>
|
186
|
+
# @example If the node types are not present in the AST
|
187
|
+
# ast = YARD.parse("def x; end")
|
188
|
+
# ast.jump(:def)
|
189
|
+
#
|
190
|
+
# @param [Array<Symbol>] node_types a set of node types to match
|
191
|
+
# @return [AstNode] the matching node, if one was found
|
192
|
+
# @return [self] if no node was found
|
193
|
+
def jump(*node_types)
|
194
|
+
traverse {|child| return(child) if node_types.include?(child.type) }
|
195
|
+
self
|
196
|
+
end
|
197
|
+
|
198
|
+
# @return [Array<AstNode>] the {AstNode} children inside the node
|
199
|
+
def children
|
200
|
+
@children ||= select {|e| AstNode === e }
|
201
|
+
end
|
202
|
+
|
203
|
+
# Traverses the object and yields each node (including descendants) in order.
|
204
|
+
#
|
205
|
+
# @yield each descendant node in order
|
206
|
+
# @yieldparam [AstNode] self, or a child/descendant node
|
207
|
+
# @return [void]
|
208
|
+
def traverse
|
209
|
+
nodes = [self]
|
210
|
+
until nodes.empty?
|
211
|
+
node = nodes.pop
|
212
|
+
yield node
|
213
|
+
nodes += node.children.reverse unless node.children.empty?
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
# @group Node Meta Types
|
218
|
+
|
219
|
+
# @return [Boolean] whether the node is a token
|
220
|
+
def token?
|
221
|
+
@token
|
222
|
+
end
|
223
|
+
|
224
|
+
# @return [Boolean] whether the node is a reference (variable,
|
225
|
+
# constant name)
|
226
|
+
def ref?
|
227
|
+
false
|
228
|
+
end
|
229
|
+
|
230
|
+
# @return [Boolean] whether the node is a literal value
|
231
|
+
def literal?
|
232
|
+
false
|
233
|
+
end
|
234
|
+
|
235
|
+
# @return [Boolean] whether the node is a keyword
|
236
|
+
def kw?
|
237
|
+
false
|
238
|
+
end
|
239
|
+
|
240
|
+
# @return [Boolean] whether the node is a method call
|
241
|
+
def call?
|
242
|
+
false
|
243
|
+
end
|
244
|
+
|
245
|
+
# @return [Boolean] whether the node is a method definition
|
246
|
+
def def?
|
247
|
+
false
|
248
|
+
end
|
249
|
+
|
250
|
+
# @return [Boolean] whether the node is a if/elsif/else condition
|
251
|
+
def condition?
|
252
|
+
false
|
253
|
+
end
|
254
|
+
|
255
|
+
# @return [Boolean] whether the node is a loop
|
256
|
+
def loop?
|
257
|
+
false
|
258
|
+
end
|
259
|
+
|
260
|
+
# @return [Boolean] whether the node has a block
|
261
|
+
def block?
|
262
|
+
respond_to?(:block) || condition?
|
263
|
+
end
|
264
|
+
|
265
|
+
# @group Getting Line Information
|
266
|
+
|
267
|
+
# @return [Boolean] whether the node has a {#line_range} set
|
268
|
+
def has_line?
|
269
|
+
@line_range ? true : false
|
270
|
+
end
|
271
|
+
|
272
|
+
# @return [Fixnum] the starting line number of the node
|
273
|
+
def line
|
274
|
+
line_range && line_range.first
|
275
|
+
end
|
276
|
+
|
277
|
+
# @return [String] the first line of source represented by the node.
|
278
|
+
def first_line
|
279
|
+
full_source.split(/\r?\n/)[line - 1].strip
|
280
|
+
end
|
281
|
+
|
282
|
+
# @group Printing a Node
|
283
|
+
|
284
|
+
# @return [String] the first line of source the node represents
|
285
|
+
def show
|
286
|
+
"\t#{line}: #{first_line}"
|
287
|
+
end
|
288
|
+
|
289
|
+
# @return [nil] pretty prints the node
|
290
|
+
def pretty_print(q)
|
291
|
+
objs = dup + [:__last__]
|
292
|
+
objs.unshift(type) if type && type != :list
|
293
|
+
|
294
|
+
options = []
|
295
|
+
options << ['docstring', docstring] if @docstring
|
296
|
+
if @source_range || @line_range
|
297
|
+
options << ['line', line_range]
|
298
|
+
options << ['source', source_range]
|
299
|
+
end
|
300
|
+
objs.pop if options.empty?
|
301
|
+
|
302
|
+
q.group(3, 's(', ')') do
|
303
|
+
q.seplist(objs, nil, :each) do |v|
|
304
|
+
if v == :__last__
|
305
|
+
q.seplist(options, nil, :each) do |arr|
|
306
|
+
k, v2 = *arr
|
307
|
+
q.group(3) do
|
308
|
+
q.text k
|
309
|
+
q.group(3) do
|
310
|
+
q.text ': '
|
311
|
+
q.pp v2
|
312
|
+
end
|
313
|
+
end
|
314
|
+
end
|
315
|
+
else
|
316
|
+
q.pp v
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
# @return [String] inspects the object
|
323
|
+
def inspect
|
324
|
+
typeinfo = type && type != :list ? ':' + type.to_s + ', ' : ''
|
325
|
+
's(' + typeinfo + map(&:inspect).join(", ") + ')'
|
326
|
+
end
|
327
|
+
|
328
|
+
# @group Managing node state
|
329
|
+
|
330
|
+
# Resets node state in tree
|
331
|
+
def unfreeze
|
332
|
+
@children = nil
|
333
|
+
end
|
334
|
+
|
335
|
+
# @endgroup
|
336
|
+
|
337
|
+
private
|
338
|
+
|
339
|
+
# Resets line information
|
340
|
+
# @return [void]
|
341
|
+
def reset_line_info
|
342
|
+
if size == 0
|
343
|
+
self.line_range = @fallback_line
|
344
|
+
self.source_range = @fallback_source
|
345
|
+
elsif !children.empty?
|
346
|
+
f = children.first
|
347
|
+
l = children.last
|
348
|
+
self.line_range = Range.new(f.line_range.first, l.line_range.last)
|
349
|
+
self.source_range = Range.new(f.source_range.first, l.source_range.last)
|
350
|
+
elsif @fallback_line || @fallback_source
|
351
|
+
self.line_range = @fallback_line
|
352
|
+
self.source_range = @fallback_source
|
353
|
+
else
|
354
|
+
self.line_range = 0...0
|
355
|
+
self.source_range = 0...0
|
356
|
+
end
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
class ReferenceNode < AstNode
|
361
|
+
def ref?; true end
|
362
|
+
|
363
|
+
def path
|
364
|
+
Array.new flatten
|
365
|
+
end
|
366
|
+
|
367
|
+
def namespace
|
368
|
+
Array.new flatten[0...-1]
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
class LiteralNode < AstNode
|
373
|
+
def literal?; true end
|
374
|
+
end
|
375
|
+
|
376
|
+
class KeywordNode < AstNode
|
377
|
+
def kw?; true end
|
378
|
+
end
|
379
|
+
|
380
|
+
class ParameterNode < AstNode
|
381
|
+
def unnamed_required_params
|
382
|
+
self[0]
|
383
|
+
end
|
384
|
+
|
385
|
+
def unnamed_optional_params
|
386
|
+
return @unnamed_optional_params if defined?(@unnamed_optional_params)
|
387
|
+
|
388
|
+
params = self[1] || []
|
389
|
+
if self[-3] && self[-3][0] && self[-3][0].type == :unnamed_optional_arg
|
390
|
+
params += self[-3]
|
391
|
+
end
|
392
|
+
|
393
|
+
@unnamed_optional_params = params.empty? ? nil : params
|
394
|
+
end
|
395
|
+
|
396
|
+
def named_params
|
397
|
+
return @named_params if defined?(@named_params)
|
398
|
+
|
399
|
+
if YARD.ruby2? && self[-3] && self[-3][0] && self[-3][0].type == :named_arg
|
400
|
+
@named_params = self[-3]
|
401
|
+
else
|
402
|
+
@named_params = nil
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
def splat_param
|
407
|
+
self[2] ? self[2][0] : nil
|
408
|
+
end
|
409
|
+
|
410
|
+
def unnamed_end_params
|
411
|
+
self[3]
|
412
|
+
end
|
413
|
+
|
414
|
+
def double_splat_param
|
415
|
+
return nil unless YARD.ruby2?
|
416
|
+
if (node = self[-2]).is_a?(AstNode)
|
417
|
+
if node.type == :ident
|
418
|
+
node
|
419
|
+
elsif node.type == :kwrest_param
|
420
|
+
# See https://bugs.ruby-lang.org/issues/12387
|
421
|
+
node.last
|
422
|
+
end
|
423
|
+
end
|
424
|
+
end
|
425
|
+
|
426
|
+
def block_param
|
427
|
+
self[-1] ? self[-1][0] : nil
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
431
|
+
class MethodCallNode < AstNode
|
432
|
+
def call?; true end
|
433
|
+
def namespace; first if index_adjust > 0 end
|
434
|
+
|
435
|
+
def method_name(name_only = false)
|
436
|
+
name = self[index_adjust]
|
437
|
+
if name == :call
|
438
|
+
nil
|
439
|
+
elsif name_only && Array === name
|
440
|
+
name.jump(:ident).first.to_sym
|
441
|
+
else
|
442
|
+
name
|
443
|
+
end
|
444
|
+
end
|
445
|
+
|
446
|
+
def parameters(include_block_param = true)
|
447
|
+
return [] if type == :vcall
|
448
|
+
params = self[1 + index_adjust]
|
449
|
+
return [] unless params
|
450
|
+
params = call_has_paren? ? params.first : params
|
451
|
+
return [] unless params
|
452
|
+
include_block_param ? params : params[0...-1]
|
453
|
+
end
|
454
|
+
|
455
|
+
def block_param; parameters.last end
|
456
|
+
|
457
|
+
def block
|
458
|
+
last.type == :do_block || last.type == :brace_block ? last : nil
|
459
|
+
end
|
460
|
+
|
461
|
+
private
|
462
|
+
|
463
|
+
def index_adjust
|
464
|
+
[:call, :command_call].include?(type) ? 2 : 0
|
465
|
+
end
|
466
|
+
|
467
|
+
def call_has_paren?
|
468
|
+
[:fcall, :call].include?(type)
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
class MethodDefinitionNode < AstNode
|
473
|
+
def kw?; true end
|
474
|
+
def def?; true end
|
475
|
+
def namespace; first if index_adjust > 0 end
|
476
|
+
|
477
|
+
def method_name(name_only = false)
|
478
|
+
name = self[index_adjust]
|
479
|
+
name_only ? name.jump(:ident).first.to_sym : name
|
480
|
+
end
|
481
|
+
|
482
|
+
def parameters(include_block_param = true)
|
483
|
+
params = self[1 + index_adjust]
|
484
|
+
params = params[0] if params.type == :paren
|
485
|
+
include_block_param ? params : params[0...-1]
|
486
|
+
end
|
487
|
+
|
488
|
+
alias block last
|
489
|
+
|
490
|
+
private
|
491
|
+
|
492
|
+
def index_adjust
|
493
|
+
type == :defs ? 2 : 0
|
494
|
+
end
|
495
|
+
end
|
496
|
+
|
497
|
+
class ConditionalNode < KeywordNode
|
498
|
+
def condition?; true end
|
499
|
+
def condition; first end
|
500
|
+
def then_block; self[1] end
|
501
|
+
|
502
|
+
def else_block
|
503
|
+
return unless self[2] && !cmod?
|
504
|
+
self[2].type == :elsif ? self[2] : self[2][0]
|
505
|
+
end
|
506
|
+
|
507
|
+
private
|
508
|
+
|
509
|
+
def cmod?; type =~ /_mod$/ end
|
510
|
+
end
|
511
|
+
|
512
|
+
class ClassNode < KeywordNode
|
513
|
+
def class_name; first end
|
514
|
+
def superclass; type == :sclass ? nil : self[1] end
|
515
|
+
def block; last end
|
516
|
+
end
|
517
|
+
|
518
|
+
class ModuleNode < KeywordNode
|
519
|
+
def module_name; first end
|
520
|
+
def block; last end
|
521
|
+
end
|
522
|
+
|
523
|
+
class LoopNode < KeywordNode
|
524
|
+
def loop?; true end
|
525
|
+
def condition; type == :for ? s(self[0], self[1]) : first end
|
526
|
+
def block; last end
|
527
|
+
end
|
528
|
+
|
529
|
+
# Represents a lone comment block in source
|
530
|
+
class CommentNode < AstNode
|
531
|
+
def docstring; first end
|
532
|
+
def docstring=(value) end
|
533
|
+
alias comments docstring
|
534
|
+
|
535
|
+
def source; "" end
|
536
|
+
def first_line; "" end
|
537
|
+
end
|
538
|
+
end
|
539
|
+
end
|
540
|
+
end
|