From 1d12df387a3a780c1ea33ccc4d38c698453ee855 Mon Sep 17 00:00:00 2001 From: 7KINGDAVID7 Date: Sun, 24 Apr 2016 00:24:47 +0000 Subject: [PATCH] Done. --- .bundle/bin/coderay | 23 + .bundle/bin/htmldiff | 25 + .bundle/bin/ldiff | 25 + .bundle/bin/pry | 23 + .bundle/bin/rspec | 23 + .bundle/binstubs/coderay | 16 + .bundle/binstubs/htmldiff | 16 + .bundle/binstubs/ldiff | 16 + .bundle/binstubs/pry | 16 + .bundle/binstubs/rspec | 16 + .bundle/cache/coderay-1.1.0.gem | Bin 0 -> 95232 bytes .bundle/cache/diff-lcs-1.2.5.gem | Bin 0 -> 49152 bytes .bundle/cache/method_source-0.8.2.gem | Bin 0 -> 13312 bytes .bundle/cache/pry-0.10.2.gem | Bin 0 -> 135680 bytes .bundle/cache/rspec-3.3.0.gem | Bin 0 -> 10240 bytes .bundle/cache/rspec-core-3.3.2.gem | Bin 0 -> 139264 bytes .bundle/cache/rspec-expectations-3.3.1.gem | Bin 0 -> 73216 bytes .bundle/cache/rspec-mocks-3.3.2.gem | Bin 0 -> 74752 bytes .bundle/cache/rspec-support-3.3.0.gem | Bin 0 -> 28672 bytes .bundle/cache/slop-3.6.0.gem | Bin 0 -> 23552 bytes .bundle/config | 2 + .bundle/gems/coderay-1.1.0/README_INDEX.rdoc | 123 ++ .bundle/gems/coderay-1.1.0/Rakefile | 37 + .bundle/gems/coderay-1.1.0/bin/coderay | 215 ++ .bundle/gems/coderay-1.1.0/lib/coderay.rb | 284 +++ .bundle/gems/coderay-1.1.0/lib/coderay/duo.rb | 81 + .../gems/coderay-1.1.0/lib/coderay/encoder.rb | 201 ++ .../lib/coderay/encoders/_map.rb | 17 + .../lib/coderay/encoders/comment_filter.rb | 25 + .../lib/coderay/encoders/count.rb | 39 + .../lib/coderay/encoders/debug.rb | 49 + .../lib/coderay/encoders/debug_lint.rb | 63 + .../coderay-1.1.0/lib/coderay/encoders/div.rb | 23 + .../lib/coderay/encoders/filter.rb | 58 + .../lib/coderay/encoders/html.rb | 332 +++ .../lib/coderay/encoders/html/css.rb | 65 + .../lib/coderay/encoders/html/numbering.rb | 108 + .../lib/coderay/encoders/html/output.rb | 166 ++ .../lib/coderay/encoders/json.rb | 83 + .../lib/coderay/encoders/lines_of_code.rb | 45 + .../lib/coderay/encoders/lint.rb | 59 + .../lib/coderay/encoders/null.rb | 18 + .../lib/coderay/encoders/page.rb | 24 + .../lib/coderay/encoders/span.rb | 23 + .../lib/coderay/encoders/statistic.rb | 95 + .../lib/coderay/encoders/terminal.rb | 195 ++ .../lib/coderay/encoders/text.rb | 46 + .../lib/coderay/encoders/token_kind_filter.rb | 111 + .../coderay-1.1.0/lib/coderay/encoders/xml.rb | 72 + .../lib/coderay/encoders/yaml.rb | 50 + .../coderay-1.1.0/lib/coderay/for_redcloth.rb | 95 + .../lib/coderay/helpers/file_type.rb | 151 ++ .../lib/coderay/helpers/plugin.rb | 274 +++ .../lib/coderay/helpers/word_list.rb | 72 + .../gems/coderay-1.1.0/lib/coderay/scanner.rb | 355 ++++ .../lib/coderay/scanners/_map.rb | 24 + .../coderay-1.1.0/lib/coderay/scanners/c.rb | 189 ++ .../lib/coderay/scanners/clojure.rb | 217 ++ .../coderay-1.1.0/lib/coderay/scanners/cpp.rb | 215 ++ .../coderay-1.1.0/lib/coderay/scanners/css.rb | 196 ++ .../lib/coderay/scanners/debug.rb | 75 + .../lib/coderay/scanners/delphi.rb | 144 ++ .../lib/coderay/scanners/diff.rb | 221 ++ .../coderay-1.1.0/lib/coderay/scanners/erb.rb | 81 + .../coderay-1.1.0/lib/coderay/scanners/go.rb | 208 ++ .../lib/coderay/scanners/groovy.rb | 268 +++ .../lib/coderay/scanners/haml.rb | 168 ++ .../lib/coderay/scanners/html.rb | 275 +++ .../lib/coderay/scanners/java.rb | 174 ++ .../coderay/scanners/java/builtin_types.rb | 421 ++++ .../lib/coderay/scanners/java_script.rb | 237 +++ .../lib/coderay/scanners/json.rb | 98 + .../coderay-1.1.0/lib/coderay/scanners/lua.rb | 280 +++ .../coderay-1.1.0/lib/coderay/scanners/php.rb | 527 +++++ .../lib/coderay/scanners/python.rb | 287 +++ .../lib/coderay/scanners/raydebug.rb | 75 + .../lib/coderay/scanners/ruby.rb | 470 +++++ .../lib/coderay/scanners/ruby/patterns.rb | 178 ++ .../lib/coderay/scanners/ruby/string_state.rb | 71 + .../lib/coderay/scanners/sass.rb | 232 +++ .../coderay-1.1.0/lib/coderay/scanners/sql.rb | 177 ++ .../lib/coderay/scanners/taskpaper.rb | 36 + .../lib/coderay/scanners/text.rb | 26 + .../coderay-1.1.0/lib/coderay/scanners/xml.rb | 17 + .../lib/coderay/scanners/yaml.rb | 140 ++ .../gems/coderay-1.1.0/lib/coderay/style.rb | 23 + .../coderay-1.1.0/lib/coderay/styles/_map.rb | 7 + .../coderay-1.1.0/lib/coderay/styles/alpha.rb | 152 ++ .../coderay-1.1.0/lib/coderay/token_kinds.rb | 85 + .../gems/coderay-1.1.0/lib/coderay/tokens.rb | 161 ++ .../coderay-1.1.0/lib/coderay/tokens_proxy.rb | 55 + .../gems/coderay-1.1.0/lib/coderay/version.rb | 3 + .../coderay-1.1.0/test/functional/basic.rb | 318 +++ .../coderay-1.1.0/test/functional/examples.rb | 129 ++ .../test/functional/for_redcloth.rb | 78 + .../coderay-1.1.0/test/functional/suite.rb | 15 + .bundle/gems/diff-lcs-1.2.5/.autotest | 3 + .bundle/gems/diff-lcs-1.2.5/.gemtest | 0 .bundle/gems/diff-lcs-1.2.5/.hoerc | 2 + .bundle/gems/diff-lcs-1.2.5/.rspec | 2 + .bundle/gems/diff-lcs-1.2.5/.travis.yml | 22 + .bundle/gems/diff-lcs-1.2.5/Contributing.rdoc | 64 + .bundle/gems/diff-lcs-1.2.5/Gemfile | 20 + .bundle/gems/diff-lcs-1.2.5/History.rdoc | 152 ++ .bundle/gems/diff-lcs-1.2.5/License.rdoc | 39 + .bundle/gems/diff-lcs-1.2.5/Manifest.txt | 38 + .bundle/gems/diff-lcs-1.2.5/README.rdoc | 85 + .bundle/gems/diff-lcs-1.2.5/Rakefile | 41 + .../gems/diff-lcs-1.2.5/autotest/discover.rb | 1 + .bundle/gems/diff-lcs-1.2.5/bin/htmldiff | 32 + .bundle/gems/diff-lcs-1.2.5/bin/ldiff | 6 + .bundle/gems/diff-lcs-1.2.5/docs/COPYING.txt | 339 +++ .bundle/gems/diff-lcs-1.2.5/docs/artistic.txt | 127 ++ .bundle/gems/diff-lcs-1.2.5/lib/diff-lcs.rb | 3 + .bundle/gems/diff-lcs-1.2.5/lib/diff/lcs.rb | 805 +++++++ .../gems/diff-lcs-1.2.5/lib/diff/lcs/array.rb | 7 + .../gems/diff-lcs-1.2.5/lib/diff/lcs/block.rb | 37 + .../diff-lcs-1.2.5/lib/diff/lcs/callbacks.rb | 322 +++ .../diff-lcs-1.2.5/lib/diff/lcs/change.rb | 177 ++ .../diff-lcs-1.2.5/lib/diff/lcs/htmldiff.rb | 149 ++ .../gems/diff-lcs-1.2.5/lib/diff/lcs/hunk.rb | 276 +++ .../diff-lcs-1.2.5/lib/diff/lcs/internals.rb | 301 +++ .../gems/diff-lcs-1.2.5/lib/diff/lcs/ldiff.rb | 195 ++ .../diff-lcs-1.2.5/lib/diff/lcs/string.rb | 5 + .../gems/diff-lcs-1.2.5/spec/change_spec.rb | 65 + .bundle/gems/diff-lcs-1.2.5/spec/diff_spec.rb | 47 + .bundle/gems/diff-lcs-1.2.5/spec/hunk_spec.rb | 72 + .../gems/diff-lcs-1.2.5/spec/issues_spec.rb | 24 + .bundle/gems/diff-lcs-1.2.5/spec/lcs_spec.rb | 54 + .../gems/diff-lcs-1.2.5/spec/patch_spec.rb | 414 ++++ .../gems/diff-lcs-1.2.5/spec/sdiff_spec.rb | 214 ++ .../gems/diff-lcs-1.2.5/spec/spec_helper.rb | 290 +++ .../spec/traverse_balanced_spec.rb | 310 +++ .../spec/traverse_sequences_spec.rb | 139 ++ .bundle/gems/method_source-0.8.2/.gemtest | 0 .bundle/gems/method_source-0.8.2/.travis.yml | 13 + .bundle/gems/method_source-0.8.2/.yardopts | 1 + .bundle/gems/method_source-0.8.2/Gemfile | 2 + .bundle/gems/method_source-0.8.2/LICENSE | 25 + .../gems/method_source-0.8.2/README.markdown | 91 + .bundle/gems/method_source-0.8.2/Rakefile | 79 + .../method_source-0.8.2/lib/method_source.rb | 141 ++ .../lib/method_source/code_helpers.rb | 154 ++ .../lib/method_source/source_location.rb | 138 ++ .../lib/method_source/version.rb | 3 + .../method_source-0.8.2/method_source.gemspec | 33 + .bundle/gems/method_source-0.8.2/test/test.rb | 138 ++ .../test/test_code_helpers.rb | 41 + .../method_source-0.8.2/test/test_helper.rb | 98 + .bundle/gems/pry-0.10.2/CHANGELOG.md | 714 +++++++ .bundle/gems/pry-0.10.2/LICENSE | 25 + .bundle/gems/pry-0.10.2/README.md | 406 ++++ .bundle/gems/pry-0.10.2/bin/pry | 16 + .bundle/gems/pry-0.10.2/lib/pry.rb | 161 ++ .bundle/gems/pry-0.10.2/lib/pry/cli.rb | 220 ++ .bundle/gems/pry-0.10.2/lib/pry/code.rb | 346 +++ .../gems/pry-0.10.2/lib/pry/code/code_file.rb | 103 + .../pry-0.10.2/lib/pry/code/code_range.rb | 71 + .bundle/gems/pry-0.10.2/lib/pry/code/loc.rb | 92 + .../gems/pry-0.10.2/lib/pry/code_object.rb | 172 ++ .../gems/pry-0.10.2/lib/pry/color_printer.rb | 55 + .bundle/gems/pry-0.10.2/lib/pry/command.rb | 692 ++++++ .../gems/pry-0.10.2/lib/pry/command_set.rb | 443 ++++ .bundle/gems/pry-0.10.2/lib/pry/commands.rb | 6 + .../pry-0.10.2/lib/pry/commands/amend_line.rb | 99 + .../gems/pry-0.10.2/lib/pry/commands/bang.rb | 20 + .../pry-0.10.2/lib/pry/commands/bang_pry.rb | 17 + .../gems/pry-0.10.2/lib/pry/commands/cat.rb | 62 + .../pry/commands/cat/abstract_formatter.rb | 27 + .../pry/commands/cat/exception_formatter.rb | 77 + .../lib/pry/commands/cat/file_formatter.rb | 67 + .../cat/input_expression_formatter.rb | 43 + .../gems/pry-0.10.2/lib/pry/commands/cd.rb | 41 + .../lib/pry/commands/change_inspector.rb | 27 + .../lib/pry/commands/change_prompt.rb | 26 + .../lib/pry/commands/code_collector.rb | 165 ++ .../lib/pry/commands/disable_pry.rb | 27 + .../lib/pry/commands/disabled_commands.rb | 2 + .../lib/pry/commands/easter_eggs.rb | 112 + .../gems/pry-0.10.2/lib/pry/commands/edit.rb | 195 ++ .../pry/commands/edit/exception_patcher.rb | 25 + .../commands/edit/file_and_line_locator.rb | 36 + .../gems/pry-0.10.2/lib/pry/commands/exit.rb | 42 + .../pry-0.10.2/lib/pry/commands/exit_all.rb | 29 + .../lib/pry/commands/exit_program.rb | 23 + .../lib/pry/commands/find_method.rb | 193 ++ .../pry-0.10.2/lib/pry/commands/fix_indent.rb | 19 + .../pry-0.10.2/lib/pry/commands/gem_cd.rb | 26 + .../lib/pry/commands/gem_install.rb | 32 + .../pry-0.10.2/lib/pry/commands/gem_list.rb | 33 + .../pry-0.10.2/lib/pry/commands/gem_open.rb | 29 + .../gems/pry-0.10.2/lib/pry/commands/gist.rb | 101 + .../gems/pry-0.10.2/lib/pry/commands/help.rb | 164 ++ .../gems/pry-0.10.2/lib/pry/commands/hist.rb | 180 ++ .../pry-0.10.2/lib/pry/commands/import_set.rb | 22 + .../lib/pry/commands/install_command.rb | 53 + .../pry-0.10.2/lib/pry/commands/jump_to.rb | 29 + .../lib/pry/commands/list_inspectors.rb | 35 + .../lib/pry/commands/list_prompts.rb | 35 + .../gems/pry-0.10.2/lib/pry/commands/ls.rb | 114 + .../lib/pry/commands/ls/constants.rb | 47 + .../lib/pry/commands/ls/formatter.rb | 49 + .../pry-0.10.2/lib/pry/commands/ls/globals.rb | 48 + .../pry-0.10.2/lib/pry/commands/ls/grep.rb | 21 + .../lib/pry/commands/ls/instance_vars.rb | 39 + .../lib/pry/commands/ls/interrogatable.rb | 18 + .../lib/pry/commands/ls/jruby_hacks.rb | 49 + .../lib/pry/commands/ls/local_names.rb | 35 + .../lib/pry/commands/ls/local_vars.rb | 39 + .../lib/pry/commands/ls/ls_entity.rb | 70 + .../pry-0.10.2/lib/pry/commands/ls/methods.rb | 57 + .../lib/pry/commands/ls/methods_helper.rb | 46 + .../lib/pry/commands/ls/self_methods.rb | 32 + .../pry-0.10.2/lib/pry/commands/nesting.rb | 25 + .../gems/pry-0.10.2/lib/pry/commands/play.rb | 103 + .../lib/pry/commands/pry_backtrace.rb | 25 + .../lib/pry/commands/pry_version.rb | 17 + .../pry-0.10.2/lib/pry/commands/raise_up.rb | 32 + .../lib/pry/commands/reload_code.rb | 62 + .../gems/pry-0.10.2/lib/pry/commands/reset.rb | 18 + .../gems/pry-0.10.2/lib/pry/commands/ri.rb | 60 + .../pry-0.10.2/lib/pry/commands/save_file.rb | 61 + .../lib/pry/commands/shell_command.rb | 48 + .../pry-0.10.2/lib/pry/commands/shell_mode.rb | 25 + .../pry-0.10.2/lib/pry/commands/show_doc.rb | 83 + .../pry-0.10.2/lib/pry/commands/show_info.rb | 195 ++ .../pry-0.10.2/lib/pry/commands/show_input.rb | 17 + .../lib/pry/commands/show_source.rb | 50 + .../lib/pry/commands/simple_prompt.rb | 22 + .../gems/pry-0.10.2/lib/pry/commands/stat.rb | 40 + .../pry-0.10.2/lib/pry/commands/switch_to.rb | 23 + .../lib/pry/commands/toggle_color.rb | 24 + .../lib/pry/commands/watch_expression.rb | 105 + .../commands/watch_expression/expression.rb | 38 + .../pry-0.10.2/lib/pry/commands/whereami.rb | 190 ++ .../gems/pry-0.10.2/lib/pry/commands/wtf.rb | 57 + .bundle/gems/pry-0.10.2/lib/pry/config.rb | 24 + .../pry-0.10.2/lib/pry/config/behavior.rb | 139 ++ .../pry-0.10.2/lib/pry/config/convenience.rb | 25 + .../gems/pry-0.10.2/lib/pry/config/default.rb | 161 ++ .../pry-0.10.2/lib/pry/core_extensions.rb | 131 ++ .bundle/gems/pry-0.10.2/lib/pry/editor.rb | 135 ++ .bundle/gems/pry-0.10.2/lib/pry/exceptions.rb | 78 + .bundle/gems/pry-0.10.2/lib/pry/helpers.rb | 5 + .../lib/pry/helpers/base_helpers.rb | 113 + .../lib/pry/helpers/command_helpers.rb | 156 ++ .../lib/pry/helpers/documentation_helpers.rb | 75 + .../lib/pry/helpers/options_helpers.rb | 27 + .../gems/pry-0.10.2/lib/pry/helpers/table.rb | 109 + .../gems/pry-0.10.2/lib/pry/helpers/text.rb | 107 + .bundle/gems/pry-0.10.2/lib/pry/history.rb | 127 ++ .../gems/pry-0.10.2/lib/pry/history_array.rb | 121 ++ .bundle/gems/pry-0.10.2/lib/pry/hooks.rb | 230 ++ .bundle/gems/pry-0.10.2/lib/pry/indent.rb | 406 ++++ .../pry-0.10.2/lib/pry/input_completer.rb | 242 +++ .bundle/gems/pry-0.10.2/lib/pry/input_lock.rb | 132 ++ .bundle/gems/pry-0.10.2/lib/pry/inspector.rb | 27 + .../gems/pry-0.10.2/lib/pry/last_exception.rb | 61 + .bundle/gems/pry-0.10.2/lib/pry/method.rb | 546 +++++ .../pry-0.10.2/lib/pry/method/disowned.rb | 53 + .../gems/pry-0.10.2/lib/pry/method/patcher.rb | 125 ++ .../lib/pry/method/weird_method_locator.rb | 188 ++ .../pry-0.10.2/lib/pry/module_candidate.rb | 136 ++ .../gems/pry-0.10.2/lib/pry/object_path.rb | 82 + .bundle/gems/pry-0.10.2/lib/pry/output.rb | 50 + .bundle/gems/pry-0.10.2/lib/pry/pager.rb | 236 +++ .bundle/gems/pry-0.10.2/lib/pry/plugins.rb | 103 + .bundle/gems/pry-0.10.2/lib/pry/prompt.rb | 26 + .bundle/gems/pry-0.10.2/lib/pry/pry_class.rb | 375 ++++ .../gems/pry-0.10.2/lib/pry/pry_instance.rb | 664 ++++++ .bundle/gems/pry-0.10.2/lib/pry/rbx_path.rb | 22 + .bundle/gems/pry-0.10.2/lib/pry/repl.rb | 202 ++ .../pry-0.10.2/lib/pry/repl_file_loader.rb | 74 + .bundle/gems/pry-0.10.2/lib/pry/rubygem.rb | 82 + .bundle/gems/pry-0.10.2/lib/pry/terminal.rb | 79 + .../gems/pry-0.10.2/lib/pry/test/helper.rb | 170 ++ .bundle/gems/pry-0.10.2/lib/pry/version.rb | 3 + .../gems/pry-0.10.2/lib/pry/wrapped_module.rb | 377 ++++ .bundle/gems/rspec-3.3.0/License.txt | 24 + .bundle/gems/rspec-3.3.0/README.md | 34 + .bundle/gems/rspec-3.3.0/lib/rspec.rb | 3 + .bundle/gems/rspec-3.3.0/lib/rspec/version.rb | 5 + .bundle/gems/rspec-core-3.3.2/.document | 5 + .bundle/gems/rspec-core-3.3.2/.yardopts | 8 + .bundle/gems/rspec-core-3.3.2/Changelog.md | 1856 +++++++++++++++++ .bundle/gems/rspec-core-3.3.2/License.txt | 25 + .bundle/gems/rspec-core-3.3.2/README.md | 369 ++++ .bundle/gems/rspec-core-3.3.2/exe/rspec | 4 + .../rspec-core-3.3.2/lib/rspec/autorun.rb | 3 + .../gems/rspec-core-3.3.2/lib/rspec/core.rb | 181 ++ .../lib/rspec/core/backtrace_formatter.rb | 64 + .../lib/rspec/core/bisect/coordinator.rb | 66 + .../rspec/core/bisect/example_minimizer.rb | 130 ++ .../lib/rspec/core/bisect/runner.rb | 139 ++ .../lib/rspec/core/bisect/server.rb | 61 + .../rspec/core/bisect/subset_enumerator.rb | 39 + .../lib/rspec/core/configuration.rb | 1807 ++++++++++++++++ .../lib/rspec/core/configuration_options.rb | 191 ++ .../rspec-core-3.3.2/lib/rspec/core/drb.rb | 111 + .../rspec-core-3.3.2/lib/rspec/core/dsl.rb | 96 + .../lib/rspec/core/example.rb | 573 +++++ .../lib/rspec/core/example_group.rb | 796 +++++++ .../rspec/core/example_status_persister.rb | 235 +++ .../lib/rspec/core/filter_manager.rb | 231 ++ .../lib/rspec/core/flat_map.rb | 20 + .../lib/rspec/core/formatters.rb | 254 +++ .../rspec/core/formatters/base_formatter.rb | 70 + .../core/formatters/base_text_formatter.rb | 77 + .../rspec/core/formatters/bisect_formatter.rb | 68 + .../formatters/bisect_progress_formatter.rb | 115 + .../rspec/core/formatters/console_codes.rb | 65 + .../core/formatters/deprecation_formatter.rb | 223 ++ .../formatters/documentation_formatter.rb | 70 + .../core/formatters/exception_presenter.rb | 393 ++++ .../formatters/fallback_message_formatter.rb | 28 + .../lib/rspec/core/formatters/helpers.rb | 109 + .../rspec/core/formatters/html_formatter.rb | 151 ++ .../lib/rspec/core/formatters/html_printer.rb | 415 ++++ .../rspec/core/formatters/json_formatter.rb | 96 + .../core/formatters/profile_formatter.rb | 68 + .../core/formatters/progress_formatter.rb | 28 + .../lib/rspec/core/formatters/protocol.rb | 172 ++ .../core/formatters/snippet_extractor.rb | 116 ++ .../rspec-core-3.3.2/lib/rspec/core/hooks.rb | 638 ++++++ .../lib/rspec/core/memoized_helpers.rb | 532 +++++ .../lib/rspec/core/metadata.rb | 490 +++++ .../lib/rspec/core/metadata_filter.rb | 235 +++ .../rspec/core/minitest_assertions_adapter.rb | 31 + .../rspec/core/mocking_adapters/flexmock.rb | 31 + .../lib/rspec/core/mocking_adapters/mocha.rb | 57 + .../lib/rspec/core/mocking_adapters/null.rb | 14 + .../lib/rspec/core/mocking_adapters/rr.rb | 31 + .../lib/rspec/core/mocking_adapters/rspec.rb | 32 + .../rspec-core-3.3.2/lib/rspec/core/mutex.rb | 63 + .../lib/rspec/core/notifications.rb | 498 +++++ .../lib/rspec/core/option_parser.rb | 301 +++ .../lib/rspec/core/ordering.rb | 158 ++ .../lib/rspec/core/pending.rb | 165 ++ .../lib/rspec/core/profiler.rb | 32 + .../lib/rspec/core/project_initializer.rb | 48 + .../lib/rspec/core/project_initializer/.rspec | 2 + .../project_initializer/spec/spec_helper.rb | 96 + .../lib/rspec/core/rake_task.rb | 158 ++ .../lib/rspec/core/reentrant_mutex.rb | 52 + .../lib/rspec/core/reporter.rb | 220 ++ .../lib/rspec/core/ruby_project.rb | 53 + .../rspec-core-3.3.2/lib/rspec/core/runner.rb | 179 ++ .../lib/rspec/core/sandbox.rb | 37 + .../rspec-core-3.3.2/lib/rspec/core/set.rb | 49 + .../lib/rspec/core/shared_context.rb | 55 + .../lib/rspec/core/shared_example_group.rb | 210 ++ .../lib/rspec/core/shell_escape.rb | 49 + .../core/test_unit_assertions_adapter.rb | 30 + .../lib/rspec/core/version.rb | 9 + .../lib/rspec/core/warnings.rb | 40 + .../rspec-core-3.3.2/lib/rspec/core/world.rb | 178 ++ .../gems/rspec-expectations-3.3.1/.document | 5 + .../gems/rspec-expectations-3.3.1/.yardopts | 6 + .../rspec-expectations-3.3.1/Changelog.md | 953 +++++++++ .../gems/rspec-expectations-3.3.1/License.txt | 24 + .../gems/rspec-expectations-3.3.1/README.md | 289 +++ .../lib/rspec/expectations.rb | 81 + .../lib/rspec/expectations/configuration.rb | 164 ++ .../rspec/expectations/expectation_target.rb | 113 + .../lib/rspec/expectations/fail_with.rb | 31 + .../rspec/expectations/failure_aggregator.rb | 194 ++ .../lib/rspec/expectations/handler.rb | 170 ++ .../expectations/minitest_integration.rb | 31 + .../lib/rspec/expectations/syntax.rb | 132 ++ .../lib/rspec/expectations/version.rb | 8 + .../lib/rspec/matchers.rb | 1009 +++++++++ .../lib/rspec/matchers/aliased_matcher.rb | 116 ++ .../lib/rspec/matchers/built_in.rb | 52 + .../lib/rspec/matchers/built_in/all.rb | 85 + .../rspec/matchers/built_in/base_matcher.rb | 181 ++ .../lib/rspec/matchers/built_in/be.rb | 285 +++ .../lib/rspec/matchers/built_in/be_between.rb | 77 + .../rspec/matchers/built_in/be_instance_of.rb | 22 + .../lib/rspec/matchers/built_in/be_kind_of.rb | 16 + .../lib/rspec/matchers/built_in/be_within.rb | 72 + .../lib/rspec/matchers/built_in/change.rb | 337 +++ .../lib/rspec/matchers/built_in/compound.rb | 293 +++ .../matchers/built_in/contain_exactly.rb | 253 +++ .../lib/rspec/matchers/built_in/cover.rb | 24 + .../lib/rspec/matchers/built_in/eq.rb | 40 + .../lib/rspec/matchers/built_in/eql.rb | 34 + .../lib/rspec/matchers/built_in/equal.rb | 81 + .../lib/rspec/matchers/built_in/exist.rb | 86 + .../lib/rspec/matchers/built_in/has.rb | 103 + .../matchers/built_in/have_attributes.rb | 114 + .../lib/rspec/matchers/built_in/include.rb | 130 ++ .../lib/rspec/matchers/built_in/match.rb | 37 + .../lib/rspec/matchers/built_in/operators.rb | 128 ++ .../lib/rspec/matchers/built_in/output.rb | 200 ++ .../rspec/matchers/built_in/raise_error.rb | 216 ++ .../lib/rspec/matchers/built_in/respond_to.rb | 90 + .../lib/rspec/matchers/built_in/satisfy.rb | 37 + .../matchers/built_in/start_or_end_with.rb | 94 + .../rspec/matchers/built_in/throw_symbol.rb | 132 ++ .../lib/rspec/matchers/built_in/yield.rb | 418 ++++ .../lib/rspec/matchers/composable.rb | 184 ++ .../lib/rspec/matchers/dsl.rb | 453 ++++ .../lib/rspec/matchers/english_phrasing.rb | 42 + .../matchers/expecteds_for_multiple_diffs.rb | 73 + .../lib/rspec/matchers/fail_matchers.rb | 42 + .../rspec/matchers/generated_descriptions.rb | 42 + .../lib/rspec/matchers/matcher_delegator.rb | 35 + .../lib/rspec/matchers/matcher_protocol.rb | 99 + .bundle/gems/rspec-mocks-3.3.2/.document | 5 + .bundle/gems/rspec-mocks-3.3.2/.yardopts | 6 + .bundle/gems/rspec-mocks-3.3.2/Changelog.md | 965 +++++++++ .bundle/gems/rspec-mocks-3.3.2/License.txt | 24 + .bundle/gems/rspec-mocks-3.3.2/README.md | 430 ++++ .../gems/rspec-mocks-3.3.2/lib/rspec/mocks.rb | 126 ++ .../lib/rspec/mocks/any_instance.rb | 11 + .../lib/rspec/mocks/any_instance/chain.rb | 110 + .../mocks/any_instance/error_generator.rb | 31 + .../mocks/any_instance/expect_chain_chain.rb | 35 + .../mocks/any_instance/expectation_chain.rb | 48 + .../mocks/any_instance/message_chains.rb | 83 + .../lib/rspec/mocks/any_instance/proxy.rb | 116 ++ .../lib/rspec/mocks/any_instance/recorder.rb | 264 +++ .../rspec/mocks/any_instance/stub_chain.rb | 46 + .../mocks/any_instance/stub_chain_chain.rb | 27 + .../lib/rspec/mocks/argument_list_matcher.rb | 100 + .../lib/rspec/mocks/argument_matchers.rb | 320 +++ .../lib/rspec/mocks/configuration.rb | 188 ++ .../lib/rspec/mocks/error_generator.rb | 362 ++++ .../lib/rspec/mocks/example_methods.rb | 421 ++++ .../rspec/mocks/instance_method_stasher.rb | 135 ++ .../lib/rspec/mocks/marshal_extension.rb | 41 + .../matchers/expectation_customization.rb | 20 + .../lib/rspec/mocks/matchers/have_received.rb | 116 ++ .../lib/rspec/mocks/matchers/receive.rb | 130 ++ .../mocks/matchers/receive_message_chain.rb | 80 + .../rspec/mocks/matchers/receive_messages.rb | 75 + .../lib/rspec/mocks/message_chain.rb | 87 + .../lib/rspec/mocks/message_expectation.rb | 717 +++++++ .../lib/rspec/mocks/method_double.rb | 287 +++ .../lib/rspec/mocks/method_reference.rb | 192 ++ .../lib/rspec/mocks/mutate_const.rb | 335 +++ .../lib/rspec/mocks/mutex.rb | 73 + .../lib/rspec/mocks/object_reference.rb | 149 ++ .../lib/rspec/mocks/order_group.rb | 81 + .../lib/rspec/mocks/proxy.rb | 439 ++++ .../lib/rspec/mocks/reentrant_mutex.rb | 53 + .../lib/rspec/mocks/space.rb | 238 +++ .../lib/rspec/mocks/standalone.rb | 3 + .../lib/rspec/mocks/syntax.rb | 325 +++ .../lib/rspec/mocks/targets.rb | 97 + .../lib/rspec/mocks/test_double.rb | 170 ++ .../lib/rspec/mocks/verifying_double.rb | 129 ++ .../mocks/verifying_message_expecation.rb | 54 + .../lib/rspec/mocks/verifying_proxy.rb | 213 ++ .../lib/rspec/mocks/version.rb | 9 + .bundle/gems/rspec-support-3.3.0/Changelog.md | 125 ++ .bundle/gems/rspec-support-3.3.0/LICENSE.txt | 22 + .bundle/gems/rspec-support-3.3.0/README.md | 26 + .../rspec-support-3.3.0/lib/rspec/support.rb | 111 + .../lib/rspec/support/caller_filter.rb | 83 + .../lib/rspec/support/differ.rb | 215 ++ .../lib/rspec/support/directory_maker.rb | 63 + .../lib/rspec/support/encoded_string.rb | 155 ++ .../lib/rspec/support/fuzzy_matcher.rb | 48 + .../lib/rspec/support/hunk_generator.rb | 47 + .../lib/rspec/support/matcher_definition.rb | 42 + .../support/method_signature_verifier.rb | 273 +++ .../lib/rspec/support/object_formatter.rb | 93 + .../rspec/support/recursive_const_methods.rb | 76 + .../lib/rspec/support/ruby_features.rb | 118 ++ .../lib/rspec/support/spec.rb | 81 + .../rspec/support/spec/deprecation_helpers.rb | 64 + .../rspec/support/spec/formatting_support.rb | 9 + .../lib/rspec/support/spec/in_sub_process.rb | 52 + .../rspec/support/spec/library_wide_checks.rb | 145 ++ .../lib/rspec/support/spec/shell_out.rb | 71 + .../lib/rspec/support/spec/stderr_splitter.rb | 63 + .../lib/rspec/support/spec/string_matcher.rb | 46 + .../support/spec/with_isolated_directory.rb | 9 + .../support/spec/with_isolated_stderr.rb | 13 + .../lib/rspec/support/version.rb | 7 + .../lib/rspec/support/version_checker.rb | 53 + .../lib/rspec/support/warnings.rb | 39 + .bundle/gems/slop-3.6.0/.gitignore | 7 + .bundle/gems/slop-3.6.0/.travis.yml | 9 + .bundle/gems/slop-3.6.0/CHANGES.md | 309 +++ .bundle/gems/slop-3.6.0/Gemfile | 3 + .bundle/gems/slop-3.6.0/LICENSE | 20 + .bundle/gems/slop-3.6.0/README.md | 202 ++ .bundle/gems/slop-3.6.0/Rakefile | 29 + .bundle/gems/slop-3.6.0/lib/slop.rb | 687 ++++++ .bundle/gems/slop-3.6.0/lib/slop/commands.rb | 196 ++ .bundle/gems/slop-3.6.0/lib/slop/option.rb | 214 ++ .bundle/gems/slop-3.6.0/slop.gemspec | 17 + .bundle/gems/slop-3.6.0/test/commands_test.rb | 26 + .bundle/gems/slop-3.6.0/test/helper.rb | 12 + .bundle/gems/slop-3.6.0/test/option_test.rb | 145 ++ .bundle/gems/slop-3.6.0/test/slop_test.rb | 518 +++++ .bundle/specifications/coderay-1.1.0.gemspec | 26 + .bundle/specifications/diff-lcs-1.2.5.gemspec | 68 + .../method_source-0.8.2.gemspec | 34 + .bundle/specifications/pry-0.10.2.gemspec | 43 + .bundle/specifications/rspec-3.3.0.gemspec | 42 + .../specifications/rspec-core-3.3.2.gemspec | 68 + .../rspec-expectations-3.3.1.gemspec | 50 + .../specifications/rspec-mocks-3.3.2.gemspec | 53 + .../rspec-support-3.3.0.gemspec | 38 + .bundle/specifications/slop-3.6.0.gemspec | 36 + edit-me.txt | 1 + 509 files changed, 65555 insertions(+) create mode 100755 .bundle/bin/coderay create mode 100755 .bundle/bin/htmldiff create mode 100755 .bundle/bin/ldiff create mode 100755 .bundle/bin/pry create mode 100755 .bundle/bin/rspec create mode 100755 .bundle/binstubs/coderay create mode 100755 .bundle/binstubs/htmldiff create mode 100755 .bundle/binstubs/ldiff create mode 100755 .bundle/binstubs/pry create mode 100755 .bundle/binstubs/rspec create mode 100644 .bundle/cache/coderay-1.1.0.gem create mode 100644 .bundle/cache/diff-lcs-1.2.5.gem create mode 100644 .bundle/cache/method_source-0.8.2.gem create mode 100644 .bundle/cache/pry-0.10.2.gem create mode 100644 .bundle/cache/rspec-3.3.0.gem create mode 100644 .bundle/cache/rspec-core-3.3.2.gem create mode 100644 .bundle/cache/rspec-expectations-3.3.1.gem create mode 100644 .bundle/cache/rspec-mocks-3.3.2.gem create mode 100644 .bundle/cache/rspec-support-3.3.0.gem create mode 100644 .bundle/cache/slop-3.6.0.gem create mode 100644 .bundle/config create mode 100644 .bundle/gems/coderay-1.1.0/README_INDEX.rdoc create mode 100644 .bundle/gems/coderay-1.1.0/Rakefile create mode 100755 .bundle/gems/coderay-1.1.0/bin/coderay create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/duo.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/encoder.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/encoders/_map.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/encoders/comment_filter.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/encoders/count.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/encoders/debug.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/encoders/debug_lint.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/encoders/div.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/encoders/filter.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/encoders/html.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/encoders/html/css.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/encoders/html/numbering.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/encoders/html/output.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/encoders/json.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/encoders/lines_of_code.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/encoders/lint.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/encoders/null.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/encoders/page.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/encoders/span.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/encoders/statistic.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/encoders/terminal.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/encoders/text.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/encoders/token_kind_filter.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/encoders/xml.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/encoders/yaml.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/for_redcloth.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/helpers/file_type.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/helpers/plugin.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/helpers/word_list.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanner.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanners/_map.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanners/c.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanners/clojure.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanners/cpp.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanners/css.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanners/debug.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanners/delphi.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanners/diff.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanners/erb.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanners/go.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanners/groovy.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanners/haml.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanners/html.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanners/java.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanners/java/builtin_types.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanners/java_script.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanners/json.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanners/lua.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanners/php.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanners/python.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanners/raydebug.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanners/ruby.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanners/ruby/patterns.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanners/ruby/string_state.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanners/sass.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanners/sql.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanners/taskpaper.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanners/text.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanners/xml.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/scanners/yaml.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/style.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/styles/_map.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/styles/alpha.rb create mode 100755 .bundle/gems/coderay-1.1.0/lib/coderay/token_kinds.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/tokens.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/tokens_proxy.rb create mode 100644 .bundle/gems/coderay-1.1.0/lib/coderay/version.rb create mode 100755 .bundle/gems/coderay-1.1.0/test/functional/basic.rb create mode 100755 .bundle/gems/coderay-1.1.0/test/functional/examples.rb create mode 100644 .bundle/gems/coderay-1.1.0/test/functional/for_redcloth.rb create mode 100755 .bundle/gems/coderay-1.1.0/test/functional/suite.rb create mode 100644 .bundle/gems/diff-lcs-1.2.5/.autotest create mode 100644 .bundle/gems/diff-lcs-1.2.5/.gemtest create mode 100644 .bundle/gems/diff-lcs-1.2.5/.hoerc create mode 100644 .bundle/gems/diff-lcs-1.2.5/.rspec create mode 100644 .bundle/gems/diff-lcs-1.2.5/.travis.yml create mode 100644 .bundle/gems/diff-lcs-1.2.5/Contributing.rdoc create mode 100644 .bundle/gems/diff-lcs-1.2.5/Gemfile create mode 100644 .bundle/gems/diff-lcs-1.2.5/History.rdoc create mode 100644 .bundle/gems/diff-lcs-1.2.5/License.rdoc create mode 100644 .bundle/gems/diff-lcs-1.2.5/Manifest.txt create mode 100644 .bundle/gems/diff-lcs-1.2.5/README.rdoc create mode 100644 .bundle/gems/diff-lcs-1.2.5/Rakefile create mode 100644 .bundle/gems/diff-lcs-1.2.5/autotest/discover.rb create mode 100755 .bundle/gems/diff-lcs-1.2.5/bin/htmldiff create mode 100755 .bundle/gems/diff-lcs-1.2.5/bin/ldiff create mode 100644 .bundle/gems/diff-lcs-1.2.5/docs/COPYING.txt create mode 100644 .bundle/gems/diff-lcs-1.2.5/docs/artistic.txt create mode 100644 .bundle/gems/diff-lcs-1.2.5/lib/diff-lcs.rb create mode 100644 .bundle/gems/diff-lcs-1.2.5/lib/diff/lcs.rb create mode 100644 .bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/array.rb create mode 100644 .bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/block.rb create mode 100644 .bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/callbacks.rb create mode 100644 .bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/change.rb create mode 100644 .bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/htmldiff.rb create mode 100644 .bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/hunk.rb create mode 100644 .bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/internals.rb create mode 100644 .bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/ldiff.rb create mode 100644 .bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/string.rb create mode 100644 .bundle/gems/diff-lcs-1.2.5/spec/change_spec.rb create mode 100644 .bundle/gems/diff-lcs-1.2.5/spec/diff_spec.rb create mode 100644 .bundle/gems/diff-lcs-1.2.5/spec/hunk_spec.rb create mode 100644 .bundle/gems/diff-lcs-1.2.5/spec/issues_spec.rb create mode 100644 .bundle/gems/diff-lcs-1.2.5/spec/lcs_spec.rb create mode 100644 .bundle/gems/diff-lcs-1.2.5/spec/patch_spec.rb create mode 100644 .bundle/gems/diff-lcs-1.2.5/spec/sdiff_spec.rb create mode 100644 .bundle/gems/diff-lcs-1.2.5/spec/spec_helper.rb create mode 100644 .bundle/gems/diff-lcs-1.2.5/spec/traverse_balanced_spec.rb create mode 100644 .bundle/gems/diff-lcs-1.2.5/spec/traverse_sequences_spec.rb create mode 100644 .bundle/gems/method_source-0.8.2/.gemtest create mode 100644 .bundle/gems/method_source-0.8.2/.travis.yml create mode 100644 .bundle/gems/method_source-0.8.2/.yardopts create mode 100644 .bundle/gems/method_source-0.8.2/Gemfile create mode 100644 .bundle/gems/method_source-0.8.2/LICENSE create mode 100644 .bundle/gems/method_source-0.8.2/README.markdown create mode 100644 .bundle/gems/method_source-0.8.2/Rakefile create mode 100644 .bundle/gems/method_source-0.8.2/lib/method_source.rb create mode 100644 .bundle/gems/method_source-0.8.2/lib/method_source/code_helpers.rb create mode 100644 .bundle/gems/method_source-0.8.2/lib/method_source/source_location.rb create mode 100644 .bundle/gems/method_source-0.8.2/lib/method_source/version.rb create mode 100644 .bundle/gems/method_source-0.8.2/method_source.gemspec create mode 100644 .bundle/gems/method_source-0.8.2/test/test.rb create mode 100644 .bundle/gems/method_source-0.8.2/test/test_code_helpers.rb create mode 100644 .bundle/gems/method_source-0.8.2/test/test_helper.rb create mode 100644 .bundle/gems/pry-0.10.2/CHANGELOG.md create mode 100644 .bundle/gems/pry-0.10.2/LICENSE create mode 100644 .bundle/gems/pry-0.10.2/README.md create mode 100755 .bundle/gems/pry-0.10.2/bin/pry create mode 100644 .bundle/gems/pry-0.10.2/lib/pry.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/cli.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/code.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/code/code_file.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/code/code_range.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/code/loc.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/code_object.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/color_printer.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/command.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/command_set.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/amend_line.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/bang.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/bang_pry.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/cat.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/cat/abstract_formatter.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/cat/exception_formatter.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/cat/file_formatter.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/cat/input_expression_formatter.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/cd.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/change_inspector.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/change_prompt.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/code_collector.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/disable_pry.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/disabled_commands.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/easter_eggs.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/edit.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/edit/exception_patcher.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/edit/file_and_line_locator.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/exit.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/exit_all.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/exit_program.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/find_method.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/fix_indent.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/gem_cd.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/gem_install.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/gem_list.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/gem_open.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/gist.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/help.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/hist.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/import_set.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/install_command.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/jump_to.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/list_inspectors.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/list_prompts.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/ls.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/ls/constants.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/ls/formatter.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/ls/globals.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/ls/grep.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/ls/instance_vars.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/ls/interrogatable.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/ls/jruby_hacks.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/ls/local_names.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/ls/local_vars.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/ls/ls_entity.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/ls/methods.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/ls/methods_helper.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/ls/self_methods.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/nesting.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/play.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/pry_backtrace.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/pry_version.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/raise_up.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/reload_code.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/reset.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/ri.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/save_file.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/shell_command.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/shell_mode.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/show_doc.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/show_info.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/show_input.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/show_source.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/simple_prompt.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/stat.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/switch_to.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/toggle_color.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/watch_expression.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/watch_expression/expression.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/whereami.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/commands/wtf.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/config.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/config/behavior.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/config/convenience.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/config/default.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/core_extensions.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/editor.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/exceptions.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/helpers.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/helpers/base_helpers.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/helpers/command_helpers.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/helpers/documentation_helpers.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/helpers/options_helpers.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/helpers/table.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/helpers/text.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/history.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/history_array.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/hooks.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/indent.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/input_completer.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/input_lock.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/inspector.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/last_exception.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/method.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/method/disowned.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/method/patcher.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/method/weird_method_locator.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/module_candidate.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/object_path.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/output.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/pager.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/plugins.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/prompt.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/pry_class.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/pry_instance.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/rbx_path.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/repl.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/repl_file_loader.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/rubygem.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/terminal.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/test/helper.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/version.rb create mode 100644 .bundle/gems/pry-0.10.2/lib/pry/wrapped_module.rb create mode 100644 .bundle/gems/rspec-3.3.0/License.txt create mode 100644 .bundle/gems/rspec-3.3.0/README.md create mode 100644 .bundle/gems/rspec-3.3.0/lib/rspec.rb create mode 100644 .bundle/gems/rspec-3.3.0/lib/rspec/version.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/.document create mode 100644 .bundle/gems/rspec-core-3.3.2/.yardopts create mode 100644 .bundle/gems/rspec-core-3.3.2/Changelog.md create mode 100644 .bundle/gems/rspec-core-3.3.2/License.txt create mode 100644 .bundle/gems/rspec-core-3.3.2/README.md create mode 100755 .bundle/gems/rspec-core-3.3.2/exe/rspec create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/autorun.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/backtrace_formatter.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/bisect/coordinator.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/bisect/example_minimizer.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/bisect/runner.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/bisect/server.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/bisect/subset_enumerator.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/configuration.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/configuration_options.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/drb.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/dsl.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/example.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/example_group.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/example_status_persister.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/filter_manager.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/flat_map.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/base_formatter.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/base_text_formatter.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/bisect_formatter.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/bisect_progress_formatter.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/console_codes.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/deprecation_formatter.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/documentation_formatter.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/exception_presenter.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/fallback_message_formatter.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/helpers.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/html_formatter.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/html_printer.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/json_formatter.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/profile_formatter.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/progress_formatter.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/protocol.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/snippet_extractor.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/hooks.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/memoized_helpers.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/metadata.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/metadata_filter.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/minitest_assertions_adapter.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/mocking_adapters/flexmock.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/mocking_adapters/mocha.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/mocking_adapters/null.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/mocking_adapters/rr.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/mocking_adapters/rspec.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/mutex.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/notifications.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/option_parser.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/ordering.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/pending.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/profiler.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/project_initializer.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/project_initializer/.rspec create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/project_initializer/spec/spec_helper.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/rake_task.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/reentrant_mutex.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/reporter.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/ruby_project.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/runner.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/sandbox.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/set.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/shared_context.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/shared_example_group.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/shell_escape.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/test_unit_assertions_adapter.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/version.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/warnings.rb create mode 100644 .bundle/gems/rspec-core-3.3.2/lib/rspec/core/world.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/.document create mode 100644 .bundle/gems/rspec-expectations-3.3.1/.yardopts create mode 100644 .bundle/gems/rspec-expectations-3.3.1/Changelog.md create mode 100644 .bundle/gems/rspec-expectations-3.3.1/License.txt create mode 100644 .bundle/gems/rspec-expectations-3.3.1/README.md create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/configuration.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/expectation_target.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/fail_with.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/failure_aggregator.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/handler.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/minitest_integration.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/syntax.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/version.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/aliased_matcher.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/all.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/base_matcher.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/be.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/be_between.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/be_instance_of.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/be_kind_of.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/be_within.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/change.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/compound.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/contain_exactly.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/cover.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/eq.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/eql.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/equal.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/exist.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/has.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/have_attributes.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/include.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/match.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/operators.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/output.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/raise_error.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/respond_to.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/satisfy.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/start_or_end_with.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/throw_symbol.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/yield.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/composable.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/dsl.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/english_phrasing.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/expecteds_for_multiple_diffs.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/fail_matchers.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/generated_descriptions.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/matcher_delegator.rb create mode 100644 .bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/matcher_protocol.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/.document create mode 100644 .bundle/gems/rspec-mocks-3.3.2/.yardopts create mode 100644 .bundle/gems/rspec-mocks-3.3.2/Changelog.md create mode 100644 .bundle/gems/rspec-mocks-3.3.2/License.txt create mode 100644 .bundle/gems/rspec-mocks-3.3.2/README.md create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/chain.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/error_generator.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/expect_chain_chain.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/expectation_chain.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/message_chains.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/proxy.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/recorder.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/stub_chain.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/stub_chain_chain.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/argument_list_matcher.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/argument_matchers.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/configuration.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/error_generator.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/example_methods.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/instance_method_stasher.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/marshal_extension.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/matchers/expectation_customization.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/matchers/have_received.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/matchers/receive.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/matchers/receive_message_chain.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/matchers/receive_messages.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/message_chain.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/message_expectation.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/method_double.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/method_reference.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/mutate_const.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/mutex.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/object_reference.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/order_group.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/proxy.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/reentrant_mutex.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/space.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/standalone.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/syntax.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/targets.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/test_double.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/verifying_double.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/verifying_message_expecation.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/verifying_proxy.rb create mode 100644 .bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/version.rb create mode 100644 .bundle/gems/rspec-support-3.3.0/Changelog.md create mode 100644 .bundle/gems/rspec-support-3.3.0/LICENSE.txt create mode 100644 .bundle/gems/rspec-support-3.3.0/README.md create mode 100644 .bundle/gems/rspec-support-3.3.0/lib/rspec/support.rb create mode 100644 .bundle/gems/rspec-support-3.3.0/lib/rspec/support/caller_filter.rb create mode 100644 .bundle/gems/rspec-support-3.3.0/lib/rspec/support/differ.rb create mode 100644 .bundle/gems/rspec-support-3.3.0/lib/rspec/support/directory_maker.rb create mode 100644 .bundle/gems/rspec-support-3.3.0/lib/rspec/support/encoded_string.rb create mode 100644 .bundle/gems/rspec-support-3.3.0/lib/rspec/support/fuzzy_matcher.rb create mode 100644 .bundle/gems/rspec-support-3.3.0/lib/rspec/support/hunk_generator.rb create mode 100644 .bundle/gems/rspec-support-3.3.0/lib/rspec/support/matcher_definition.rb create mode 100644 .bundle/gems/rspec-support-3.3.0/lib/rspec/support/method_signature_verifier.rb create mode 100644 .bundle/gems/rspec-support-3.3.0/lib/rspec/support/object_formatter.rb create mode 100644 .bundle/gems/rspec-support-3.3.0/lib/rspec/support/recursive_const_methods.rb create mode 100644 .bundle/gems/rspec-support-3.3.0/lib/rspec/support/ruby_features.rb create mode 100644 .bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec.rb create mode 100644 .bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/deprecation_helpers.rb create mode 100644 .bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/formatting_support.rb create mode 100644 .bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/in_sub_process.rb create mode 100644 .bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/library_wide_checks.rb create mode 100644 .bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/shell_out.rb create mode 100644 .bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/stderr_splitter.rb create mode 100644 .bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/string_matcher.rb create mode 100644 .bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/with_isolated_directory.rb create mode 100644 .bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/with_isolated_stderr.rb create mode 100644 .bundle/gems/rspec-support-3.3.0/lib/rspec/support/version.rb create mode 100644 .bundle/gems/rspec-support-3.3.0/lib/rspec/support/version_checker.rb create mode 100644 .bundle/gems/rspec-support-3.3.0/lib/rspec/support/warnings.rb create mode 100644 .bundle/gems/slop-3.6.0/.gitignore create mode 100644 .bundle/gems/slop-3.6.0/.travis.yml create mode 100644 .bundle/gems/slop-3.6.0/CHANGES.md create mode 100644 .bundle/gems/slop-3.6.0/Gemfile create mode 100644 .bundle/gems/slop-3.6.0/LICENSE create mode 100644 .bundle/gems/slop-3.6.0/README.md create mode 100644 .bundle/gems/slop-3.6.0/Rakefile create mode 100644 .bundle/gems/slop-3.6.0/lib/slop.rb create mode 100644 .bundle/gems/slop-3.6.0/lib/slop/commands.rb create mode 100644 .bundle/gems/slop-3.6.0/lib/slop/option.rb create mode 100644 .bundle/gems/slop-3.6.0/slop.gemspec create mode 100644 .bundle/gems/slop-3.6.0/test/commands_test.rb create mode 100644 .bundle/gems/slop-3.6.0/test/helper.rb create mode 100644 .bundle/gems/slop-3.6.0/test/option_test.rb create mode 100644 .bundle/gems/slop-3.6.0/test/slop_test.rb create mode 100644 .bundle/specifications/coderay-1.1.0.gemspec create mode 100644 .bundle/specifications/diff-lcs-1.2.5.gemspec create mode 100644 .bundle/specifications/method_source-0.8.2.gemspec create mode 100644 .bundle/specifications/pry-0.10.2.gemspec create mode 100644 .bundle/specifications/rspec-3.3.0.gemspec create mode 100644 .bundle/specifications/rspec-core-3.3.2.gemspec create mode 100644 .bundle/specifications/rspec-expectations-3.3.1.gemspec create mode 100644 .bundle/specifications/rspec-mocks-3.3.2.gemspec create mode 100644 .bundle/specifications/rspec-support-3.3.0.gemspec create mode 100644 .bundle/specifications/slop-3.6.0.gemspec diff --git a/.bundle/bin/coderay b/.bundle/bin/coderay new file mode 100755 index 0000000..08d501f --- /dev/null +++ b/.bundle/bin/coderay @@ -0,0 +1,23 @@ +#!/usr/bin/env ruby +# +# This file was generated by RubyGems. +# +# The application 'coderay' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'rubygems' + +version = ">= 0" + +if ARGV.first + str = ARGV.first + str = str.dup.force_encoding("BINARY") if str.respond_to? :force_encoding + if str =~ /\A_(.*)_\z/ and Gem::Version.correct?($1) then + version = $1 + ARGV.shift + end +end + +gem 'coderay', version +load Gem.bin_path('coderay', 'coderay', version) diff --git a/.bundle/bin/htmldiff b/.bundle/bin/htmldiff new file mode 100755 index 0000000..b39c99d --- /dev/null +++ b/.bundle/bin/htmldiff @@ -0,0 +1,25 @@ +#!/bin/sh +'exec' "ruby" '-x' "$0" "$@" +#!/usr/local/opt/rbenv/versions/2.1.5/bin/ruby +# +# This file was generated by RubyGems. +# +# The application 'diff-lcs' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'rubygems' + +version = ">= 0" + +if ARGV.first + str = ARGV.first + str = str.dup.force_encoding("BINARY") if str.respond_to? :force_encoding + if str =~ /\A_(.*)_\z/ and Gem::Version.correct?($1) then + version = $1 + ARGV.shift + end +end + +gem 'diff-lcs', version +load Gem.bin_path('diff-lcs', 'htmldiff', version) diff --git a/.bundle/bin/ldiff b/.bundle/bin/ldiff new file mode 100755 index 0000000..1da6891 --- /dev/null +++ b/.bundle/bin/ldiff @@ -0,0 +1,25 @@ +#!/bin/sh +'exec' "ruby" '-x' "$0" "$@" +#!/usr/local/opt/rbenv/versions/2.1.5/bin/ruby +# +# This file was generated by RubyGems. +# +# The application 'diff-lcs' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'rubygems' + +version = ">= 0" + +if ARGV.first + str = ARGV.first + str = str.dup.force_encoding("BINARY") if str.respond_to? :force_encoding + if str =~ /\A_(.*)_\z/ and Gem::Version.correct?($1) then + version = $1 + ARGV.shift + end +end + +gem 'diff-lcs', version +load Gem.bin_path('diff-lcs', 'ldiff', version) diff --git a/.bundle/bin/pry b/.bundle/bin/pry new file mode 100755 index 0000000..27a22a8 --- /dev/null +++ b/.bundle/bin/pry @@ -0,0 +1,23 @@ +#!/usr/bin/env ruby +# +# This file was generated by RubyGems. +# +# The application 'pry' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'rubygems' + +version = ">= 0" + +if ARGV.first + str = ARGV.first + str = str.dup.force_encoding("BINARY") if str.respond_to? :force_encoding + if str =~ /\A_(.*)_\z/ and Gem::Version.correct?($1) then + version = $1 + ARGV.shift + end +end + +gem 'pry', version +load Gem.bin_path('pry', 'pry', version) diff --git a/.bundle/bin/rspec b/.bundle/bin/rspec new file mode 100755 index 0000000..1df29e9 --- /dev/null +++ b/.bundle/bin/rspec @@ -0,0 +1,23 @@ +#!/usr/bin/env ruby +# +# This file was generated by RubyGems. +# +# The application 'rspec-core' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'rubygems' + +version = ">= 0" + +if ARGV.first + str = ARGV.first + str = str.dup.force_encoding("BINARY") if str.respond_to? :force_encoding + if str =~ /\A_(.*)_\z/ and Gem::Version.correct?($1) then + version = $1 + ARGV.shift + end +end + +gem 'rspec-core', version +load Gem.bin_path('rspec-core', 'rspec', version) diff --git a/.bundle/binstubs/coderay b/.bundle/binstubs/coderay new file mode 100755 index 0000000..0123250 --- /dev/null +++ b/.bundle/binstubs/coderay @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# +# This file was generated by Bundler. +# +# The application 'coderay' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../../Gemfile", + Pathname.new(__FILE__).realpath) + +require 'rubygems' +require 'bundler/setup' + +load Gem.bin_path('coderay', 'coderay') diff --git a/.bundle/binstubs/htmldiff b/.bundle/binstubs/htmldiff new file mode 100755 index 0000000..157c97f --- /dev/null +++ b/.bundle/binstubs/htmldiff @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# +# This file was generated by Bundler. +# +# The application 'htmldiff' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../../Gemfile", + Pathname.new(__FILE__).realpath) + +require 'rubygems' +require 'bundler/setup' + +load Gem.bin_path('diff-lcs', 'htmldiff') diff --git a/.bundle/binstubs/ldiff b/.bundle/binstubs/ldiff new file mode 100755 index 0000000..28a9cb6 --- /dev/null +++ b/.bundle/binstubs/ldiff @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# +# This file was generated by Bundler. +# +# The application 'ldiff' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../../Gemfile", + Pathname.new(__FILE__).realpath) + +require 'rubygems' +require 'bundler/setup' + +load Gem.bin_path('diff-lcs', 'ldiff') diff --git a/.bundle/binstubs/pry b/.bundle/binstubs/pry new file mode 100755 index 0000000..6a9994f --- /dev/null +++ b/.bundle/binstubs/pry @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# +# This file was generated by Bundler. +# +# The application 'pry' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../../Gemfile", + Pathname.new(__FILE__).realpath) + +require 'rubygems' +require 'bundler/setup' + +load Gem.bin_path('pry', 'pry') diff --git a/.bundle/binstubs/rspec b/.bundle/binstubs/rspec new file mode 100755 index 0000000..cb010fd --- /dev/null +++ b/.bundle/binstubs/rspec @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# +# This file was generated by Bundler. +# +# The application 'rspec' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../../Gemfile", + Pathname.new(__FILE__).realpath) + +require 'rubygems' +require 'bundler/setup' + +load Gem.bin_path('rspec-core', 'rspec') diff --git a/.bundle/cache/coderay-1.1.0.gem b/.bundle/cache/coderay-1.1.0.gem new file mode 100644 index 0000000000000000000000000000000000000000..20f291162a5048979723ce4ffc8041a0b72ab77e GIT binary patch literal 95232 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Ƶ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 Ie^>+m3Hg0=Q~&?~ literal 0 HcmV?d00001 diff --git a/.bundle/cache/diff-lcs-1.2.5.gem b/.bundle/cache/diff-lcs-1.2.5.gem new file mode 100644 index 0000000000000000000000000000000000000000..e4436ccc54911911961bcc89113b273459102fcf GIT binary patch literal 49152 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 B|9k)d literal 0 HcmV?d00001 diff --git a/.bundle/cache/method_source-0.8.2.gem b/.bundle/cache/method_source-0.8.2.gem new file mode 100644 index 0000000000000000000000000000000000000000..842453a334b7708bfe6e619c4e284aa254ea7294 GIT binary patch literal 13312 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 E4MH$$rT_o{ literal 0 HcmV?d00001 diff --git a/.bundle/cache/pry-0.10.2.gem b/.bundle/cache/pry-0.10.2.gem new file mode 100644 index 0000000000000000000000000000000000000000..7711e9a5969d6e959634a12ac8786888090740d8 GIT binary patch literal 135680 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 bqrwF5sf!o~Q>=`-Wi$jvLtr!nXdeOq!m;yx literal 0 HcmV?d00001 diff --git a/.bundle/cache/rspec-3.3.0.gem b/.bundle/cache/rspec-3.3.0.gem new file mode 100644 index 0000000000000000000000000000000000000000..3a9ad2b7beb4fc7aba504a6e7a4d576c9673e25d GIT binary patch literal 10240 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 literal 0 HcmV?d00001 diff --git a/.bundle/cache/rspec-core-3.3.2.gem b/.bundle/cache/rspec-core-3.3.2.gem new file mode 100644 index 0000000000000000000000000000000000000000..978694e7f9a90f55fa45c937703768f577ab6b73 GIT binary patch literal 139264 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 z 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

lnP%$&AsQ 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�rjGgypv;)AQ4#^BX-W(^k;rc9RyXb=K9Qb2M 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 KHv<1i1pWoFq(5f> literal 0 HcmV?d00001 diff --git a/.bundle/cache/rspec-mocks-3.3.2.gem b/.bundle/cache/rspec-mocks-3.3.2.gem new file mode 100644 index 0000000000000000000000000000000000000000..81e6e94d81abce66715bb69efb308e80caa37f2d GIT binary patch literal 74752 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≷(mTAU6NFSVq#Y*d3z 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 J{8xJ5e*j@G!fyZo literal 0 HcmV?d00001 diff --git a/.bundle/cache/rspec-support-3.3.0.gem b/.bundle/cache/rspec-support-3.3.0.gem new file mode 100644 index 0000000000000000000000000000000000000000..9b9e7067cb69464a43520c88499c52cc5e040e5e GIT binary patch literal 28672 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 literal 0 HcmV?d00001 diff --git a/.bundle/cache/slop-3.6.0.gem b/.bundle/cache/slop-3.6.0.gem new file mode 100644 index 0000000000000000000000000000000000000000..153a673db3c76d98cb3e03d9fccf92398dd0c748 GIT binary patch literal 23552 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 P{+qzx1pX%QejKQ5} literal 0 HcmV?d00001 diff --git a/.bundle/config b/.bundle/config new file mode 100644 index 0000000..df11c75 --- /dev/null +++ b/.bundle/config @@ -0,0 +1,2 @@ +--- +BUNDLE_DISABLE_SHARED_GEMS: '1' diff --git a/.bundle/gems/coderay-1.1.0/README_INDEX.rdoc b/.bundle/gems/coderay-1.1.0/README_INDEX.rdoc new file mode 100644 index 0000000..7332653 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/README_INDEX.rdoc @@ -0,0 +1,123 @@ += CodeRay + +Tired of blue'n'gray? Try the original version of this documentation on +coderay.rubychan.de[http://coderay.rubychan.de/doc/] :-) + +== About + +CodeRay is a Ruby library for syntax highlighting. + +You put your code in, and you get it back colored; Keywords, strings, +floats, comments - all in different colors. And with line numbers. + +*Syntax* *Highlighting*... +* makes code easier to read and maintain +* lets you detect syntax errors faster +* helps you to understand the syntax of a language +* looks nice +* is what everybody wants to have on their website +* solves all your problems and makes the girls run after you + + +== Installation + + % gem install coderay + + +=== Dependencies + +CodeRay needs Ruby 1.8.7+ or 1.9.2+. It also runs on Rubinius and JRuby. + + +== Example Usage + + require 'coderay' + + html = CodeRay.scan("puts 'Hello, world!'", :ruby).div(:line_numbers => :table) + + +== Documentation + +See CodeRay. + + +== Credits + +=== Special Thanks to + +* licenser (Heinz N. Gies) for ending my QBasic career, inventing the Coder + project and the input/output plugin system. + CodeRay would not exist without him. +* bovi (Daniel Bovensiepen) for helping me out on various occasions. + +=== Thanks to + +* Caleb Clausen for writing RubyLexer (see + http://rubyforge.org/projects/rubylexer) and lots of very interesting mail + traffic +* birkenfeld (Georg Brandl) and mitsuhiku (Arnim Ronacher) for PyKleur, now pygments. + You guys rock! +* Jamis Buck for writing Syntax (see http://rubyforge.org/projects/syntax) + I got some useful ideas from it. +* Doug Kearns and everyone else who worked on ruby.vim - it not only helped me + coding CodeRay, but also gave me a wonderful target to reach for the Ruby + scanner. +* everyone who uses CodeBB on http://www.rubyforen.de and http://www.python-forum.de +* iGEL, magichisoka, manveru, WoNáDo and everyone I forgot from rubyforen.de +* Dethix from ruby-mine.de +* zickzackw +* Dookie (who is no longer with us...) and Leonidas from http://www.python-forum.de +* Andreas Schwarz for finding out that CaseIgnoringWordList was not case + ignoring! Such things really make you write tests. +* closure for the first version of the Scheme scanner. +* Stefan Walk for the first version of the JavaScript and PHP scanners. +* Josh Goebel for another version of the JavaScript scanner, a SQL and a Diff scanner. +* Jonathan Younger for pointing out the licence confusion caused by wrong LICENSE file. +* Jeremy Hinegardner for finding the shebang-on-empty-file bug in FileType. +* Charles Oliver Nutter and Yehuda Katz for helping me benchmark CodeRay on JRuby. +* Andreas Neuhaus for pointing out a markup bug in coderay/for_redcloth. +* 0xf30fc7 for the FileType patch concerning Delphi file extensions. +* The folks at redmine.org - thank you for using and fixing CodeRay! +* Keith Pitt for his SQL scanners +* Rob Aldred for the terminal encoder +* Trans for pointing out $DEBUG dependencies +* Flameeyes for finding that Term::ANSIColor was obsolete +* matz and all Ruby gods and gurus +* The inventors of: the computer, the internet, the true color display, HTML & + CSS, VIM, Ruby, pizza, microwaves, guitars, scouting, programming, anime, + manga, coke and green ice tea. + +Where would we be without all those people? + +=== Created using + +* Ruby[http://ruby-lang.org/] +* Chihiro (my Sony VAIO laptop); Henrietta (my old MacBook); + Triella, born Rico (my new MacBook); as well as + Seras and Hikari (my PCs) +* RDE[http://homepage2.nifty.com/sakazuki/rde_e.html], + VIM[http://vim.org] and TextMate[http://macromates.com] +* Subversion[http://subversion.tigris.org/] +* Redmine[http://redmine.org/] +* Firefox[http://www.mozilla.org/products/firefox/], + Firebug[http://getfirebug.com/], Safari[http://www.apple.com/safari/], and + Thunderbird[http://www.mozilla.org/products/thunderbird/] +* RubyGems[http://docs.rubygems.org/] and Rake[http://rake.rubyforge.org/] +* TortoiseSVN[http://tortoisesvn.tigris.org/] using Apache via + XAMPP[http://www.apachefriends.org/en/xampp.html] +* RDoc (though I'm quite unsatisfied with it) +* Microsoft Windows (yes, I confess!) and MacOS X +* GNUWin32, MinGW and some other tools to make the shell under windows a bit + less useless +* Term::ANSIColor[http://term-ansicolor.rubyforge.org/] +* PLEAC[http://pleac.sourceforge.net/] code examples +* Github +* Travis CI (http://travis-ci.org/rubychan/github) + +=== Free + +* As you can see, CodeRay was created under heavy use of *free* software. +* So CodeRay is also *free*. +* If you use CodeRay to create software, think about making this software + *free*, too. +* Thanks :) diff --git a/.bundle/gems/coderay-1.1.0/Rakefile b/.bundle/gems/coderay-1.1.0/Rakefile new file mode 100644 index 0000000..c9b1e8a --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/Rakefile @@ -0,0 +1,37 @@ +require 'bundler/gem_tasks' + +$:.unshift File.dirname(__FILE__) unless $:.include? '.' + +ROOT = '.' +LIB_ROOT = File.join ROOT, 'lib' + +task :default => :test + +if File.directory? 'rake_tasks' + + # load rake tasks from subfolder + for task_file in Dir['rake_tasks/*.rake'].sort + load task_file + end + +else + + # fallback tasks when rake_tasks folder is not present (eg. in the distribution package) + desc 'Run CodeRay tests (basic)' + task :test do + ruby './test/functional/suite.rb' + ruby './test/functional/for_redcloth.rb' + end + + gem 'rdoc' if defined? gem + require 'rdoc/task' + desc 'Generate documentation for CodeRay' + Rake::RDocTask.new :doc do |rd| + rd.title = 'CodeRay Documentation' + rd.main = 'README_INDEX.rdoc' + rd.rdoc_files.add Dir['lib'] + rd.rdoc_files.add rd.main + rd.rdoc_dir = 'doc' + end + +end diff --git a/.bundle/gems/coderay-1.1.0/bin/coderay b/.bundle/gems/coderay-1.1.0/bin/coderay new file mode 100755 index 0000000..889ae72 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/bin/coderay @@ -0,0 +1,215 @@ +#!/usr/bin/env ruby +require 'coderay' + +$options, args = ARGV.partition { |arg| arg[/^-[hv]$|--\w+/] } +subcommand = args.first if /^\w/ === args.first +subcommand = nil if subcommand && File.exist?(subcommand) +args.delete subcommand + +def option? *options + !($options & options).empty? +end + +def tty? + $stdout.tty? || option?('--tty') +end + +def version + puts <<-USAGE +CodeRay #{CodeRay::VERSION} + USAGE +end + +def help + puts <<-HELP +This is CodeRay #{CodeRay::VERSION}, a syntax highlighting tool for selected languages. + +usage: + coderay [-language] [input] [-format] [output] + +defaults: + language detect from input file name or shebang; fall back to plain text + input STDIN + format detect from output file name or use terminal; fall back to HTML + output STDOUT + +common: + coderay file.rb # highlight file to terminal + coderay file.rb > file.html # highlight file to HTML page + coderay file.rb -div > file.html # highlight file to HTML snippet + +configure output: + coderay file.py output.json # output tokens as JSON + coderay file.py -loc # count lines of code in Python file + +configure input: + coderay -python file # specify the input language + coderay -ruby # take input from STDIN + +more: + coderay stylesheet [style] # print CSS stylesheet + HELP +end + +def commands + puts <<-COMMANDS + general: + highlight code highlighting (default command, optional) + stylesheet print the CSS stylesheet with the given name (aliases: style, css) + + about: + list [of] list all available plugins (or just the scanners|encoders|styles|filetypes) + commands print this list + help show some help + version print CodeRay version + COMMANDS +end + +def print_list_of plugin_host + plugins = plugin_host.all_plugins.map do |plugin| + info = " #{plugin.plugin_id}: #{plugin.title}" + + aliases = (plugin.aliases - [:default]).map { |key| "-#{key}" }.sort_by { |key| key.size } + if plugin.respond_to?(:file_extension) || !aliases.empty? + additional_info = [] + additional_info << aliases.join(', ') unless aliases.empty? + info << " (#{additional_info.join('; ')})" + end + + info << ' <-- default' if plugin.aliases.include? :default + + info + end + puts plugins.sort +end + +if option? '-v', '--version' + version +end + +if option? '-h', '--help' + help +end + +case subcommand +when 'highlight', nil + if ARGV.empty? + version + help + else + signature = args.map { |arg| arg[/^-/] ? '-' : 'f' }.join + names = args.map { |arg| arg.sub(/^-/, '') } + case signature + when /^$/ + exit + when /^ff?$/ + input_file, output_file, = *names + when /^f-f?$/ + input_file, output_format, output_file, = *names + when /^-ff?$/ + input_lang, input_file, output_file, = *names + when /^-f-f?$/ + input_lang, input_file, output_format, output_file, = *names + when /^--?f?$/ + input_lang, output_format, output_file, = *names + else + $stdout = $stderr + help + puts + puts "Unknown parameter order: #{args.join ' '}, expected: [-language] [input] [-format] [output]" + exit 1 + end + + if input_file + input_lang ||= CodeRay::FileType.fetch input_file, :text, true + end + + if output_file + output_format ||= CodeRay::FileType[output_file] || :plain + else + output_format ||= :terminal + end + + output_format = :page if output_format.to_s == 'html' + + if input_file + input = File.read input_file + else + input = $stdin.read + end + + begin + file = + if output_file + File.open output_file, 'w' + else + $stdout + end + CodeRay.encode(input, input_lang, output_format, :out => file) + file.puts + rescue CodeRay::PluginHost::PluginNotFound => boom + $stdout = $stderr + if boom.message[/CodeRay::(\w+)s could not load plugin :?(.*?): /] + puts "I don't know the #$1 \"#$2\"." + else + puts boom.message + end + # puts "I don't know this plugin: #{boom.message[/Could not load plugin (.*?): /, 1]}." + rescue CodeRay::Scanners::Scanner::ScanError + # this is sometimes raised by pagers; ignore + # FIXME: rescue Errno::EPIPE + ensure + file.close if output_file + end + end +when 'li', 'list' + arg = args.first && args.first.downcase + if [nil, 's', 'sc', 'scanner', 'scanners'].include? arg + puts 'input languages (Scanners):' + print_list_of CodeRay::Scanners + end + + if [nil, 'e', 'en', 'enc', 'encoder', 'encoders'].include? arg + puts 'output formats (Encoders):' + print_list_of CodeRay::Encoders + end + + if [nil, 'st', 'style', 'styles'].include? arg + puts 'CSS themes for HTML output (Styles):' + print_list_of CodeRay::Styles + end + + if [nil, 'f', 'ft', 'file', 'filetype', 'filetypes'].include? arg + puts 'recognized file types:' + + filetypes = Hash.new { |h, k| h[k] = [] } + CodeRay::FileType::TypeFromExt.inject filetypes do |types, (ext, type)| + types[type.to_s] << ".#{ext}" + types + end + CodeRay::FileType::TypeFromName.inject filetypes do |types, (name, type)| + types[type.to_s] << name + types + end + + filetypes.sort.each do |type, exts| + puts " #{type}: #{exts.sort_by { |ext| ext.size }.join(', ')}" + end + end +when 'stylesheet', 'style', 'css' + puts CodeRay::Encoders[:html]::CSS.new(args.first || :default).stylesheet +when 'commands' + commands +when 'help' + help +else + $stdout = $stderr + help + puts + if subcommand[/\A\w+\z/] + puts "Unknown command: #{subcommand}" + else + puts "File not found: #{subcommand}" + end + exit 1 +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay.rb b/.bundle/gems/coderay-1.1.0/lib/coderay.rb new file mode 100644 index 0000000..f759ed6 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay.rb @@ -0,0 +1,284 @@ +# encoding: utf-8 +# Encoding.default_internal = 'UTF-8' + +# = CodeRay Library +# +# CodeRay is a Ruby library for syntax highlighting. +# +# I try to make CodeRay easy to use and intuitive, but at the same time fully +# featured, complete, fast and efficient. +# +# See README. +# +# It consists mainly of +# * the main engine: CodeRay (Scanners::Scanner, Tokens, Encoders::Encoder) +# * the plugin system: PluginHost, Plugin +# * the scanners in CodeRay::Scanners +# * the encoders in CodeRay::Encoders +# * the styles in CodeRay::Styles +# +# Here's a fancy graphic to light up this gray docu: +# +# http://cycnus.de/raindark/coderay/scheme.png +# +# == Documentation +# +# See CodeRay, Encoders, Scanners, Tokens. +# +# == Usage +# +# Remember you need RubyGems to use CodeRay, unless you have it in your load +# path. Run Ruby with -rubygems option if required. +# +# === Highlight Ruby code in a string as html +# +# require 'coderay' +# print CodeRay.scan('puts "Hello, world!"', :ruby).html +# +# # prints something like this: +# puts "Hello, world!" +# +# +# === Highlight C code from a file in a html div +# +# require 'coderay' +# print CodeRay.scan(File.read('ruby.h'), :c).div +# print CodeRay.scan_file('ruby.h').html.div +# +# You can include this div in your page. The used CSS styles can be printed with +# +# % coderay_stylesheet +# +# === Highlight without typing too much +# +# If you are one of the hasty (or lazy, or extremely curious) people, just run this file: +# +# % ruby -rubygems /path/to/coderay/coderay.rb > example.html +# +# and look at the file it created in your browser. +# +# = CodeRay Module +# +# The CodeRay module provides convenience methods for the engine. +# +# * The +lang+ and +format+ arguments select Scanner and Encoder to use. These are +# simply lower-case symbols, like :python or :html. +# * All methods take an optional hash as last parameter, +options+, that is send to +# the Encoder / Scanner. +# * Input and language are always sorted in this order: +code+, +lang+. +# (This is in alphabetical order, if you need a mnemonic ;) +# +# You should be able to highlight everything you want just using these methods; +# so there is no need to dive into CodeRay's deep class hierarchy. +# +# The examples in the demo directory demonstrate common cases using this interface. +# +# = Basic Access Ways +# +# Read this to get a general view what CodeRay provides. +# +# == Scanning +# +# Scanning means analysing an input string, splitting it up into Tokens. +# Each Token knows about what type it is: string, comment, class name, etc. +# +# Each +lang+ (language) has its own Scanner; for example, :ruby code is +# handled by CodeRay::Scanners::Ruby. +# +# CodeRay.scan:: Scan a string in a given language into Tokens. +# This is the most common method to use. +# CodeRay.scan_file:: Scan a file and guess the language using FileType. +# +# The Tokens object you get from these methods can encode itself; see Tokens. +# +# == Encoding +# +# Encoding means compiling Tokens into an output. This can be colored HTML or +# LaTeX, a textual statistic or just the number of non-whitespace tokens. +# +# Each Encoder provides output in a specific +format+, so you select Encoders via +# formats like :html or :statistic. +# +# CodeRay.encode:: Scan and encode a string in a given language. +# CodeRay.encode_tokens:: Encode the given tokens. +# CodeRay.encode_file:: Scan a file, guess the language using FileType and encode it. +# +# == All-in-One Encoding +# +# CodeRay.encode:: Highlight a string with a given input and output format. +# +# == Instanciating +# +# You can use an Encoder instance to highlight multiple inputs. This way, the setup +# for this Encoder must only be done once. +# +# CodeRay.encoder:: Create an Encoder instance with format and options. +# CodeRay.scanner:: Create an Scanner instance for lang, with '' as default code. +# +# To make use of CodeRay.scanner, use CodeRay::Scanner::code=. +# +# The scanning methods provide more flexibility; we recommend to use these. +# +# == Reusing Scanners and Encoders +# +# If you want to re-use scanners and encoders (because that is faster), see +# CodeRay::Duo for the most convenient (and recommended) interface. +module CodeRay + + $CODERAY_DEBUG ||= false + + CODERAY_PATH = File.expand_path('../coderay', __FILE__) + + # Assuming the path is a subpath of lib/coderay/ + def self.coderay_path *path + File.join CODERAY_PATH, *path + end + + require 'coderay/version' + + # helpers + autoload :FileType, coderay_path('helpers', 'file_type') + + # Tokens + autoload :Tokens, coderay_path('tokens') + autoload :TokensProxy, coderay_path('tokens_proxy') + autoload :TokenKinds, coderay_path('token_kinds') + + # Plugin system + autoload :PluginHost, coderay_path('helpers', 'plugin') + autoload :Plugin, coderay_path('helpers', 'plugin') + + # Plugins + autoload :Scanners, coderay_path('scanner') + autoload :Encoders, coderay_path('encoder') + autoload :Styles, coderay_path('style') + + # convenience access and reusable Encoder/Scanner pair + autoload :Duo, coderay_path('duo') + + class << self + + # Scans the given +code+ (a String) with the Scanner for +lang+. + # + # This is a simple way to use CodeRay. Example: + # require 'coderay' + # page = CodeRay.scan("puts 'Hello, world!'", :ruby).html + # + # See also demo/demo_simple. + def scan code, lang, options = {}, &block + TokensProxy.new code, lang, options, block + end + + # Scans +filename+ (a path to a code file) with the Scanner for +lang+. + # + # If +lang+ is :auto or omitted, the CodeRay::FileType module is used to + # determine it. If it cannot find out what type it is, it uses + # CodeRay::Scanners::Text. + # + # Calls CodeRay.scan. + # + # Example: + # require 'coderay' + # page = CodeRay.scan_file('some_c_code.c').html + def scan_file filename, lang = :auto, options = {}, &block + lang = FileType.fetch filename, :text, true if lang == :auto + code = File.read filename + scan code, lang, options, &block + end + + # Encode a string. + # + # This scans +code+ with the the Scanner for +lang+ and then + # encodes it with the Encoder for +format+. + # +options+ will be passed to the Encoder. + # + # See CodeRay::Encoder.encode. + def encode code, lang, format, options = {} + encoder(format, options).encode code, lang, options + end + + # Encode pre-scanned Tokens. + # Use this together with CodeRay.scan: + # + # require 'coderay' + # + # # Highlight a short Ruby code example in a HTML span + # tokens = CodeRay.scan '1 + 2', :ruby + # puts CodeRay.encode_tokens(tokens, :span) + # + def encode_tokens tokens, format, options = {} + encoder(format, options).encode_tokens tokens, options + end + + # Encodes +filename+ (a path to a code file) with the Scanner for +lang+. + # + # See CodeRay.scan_file. + # Notice that the second argument is the output +format+, not the input language. + # + # Example: + # require 'coderay' + # page = CodeRay.encode_file 'some_c_code.c', :html + def encode_file filename, format, options = {} + tokens = scan_file filename, :auto, get_scanner_options(options) + encode_tokens tokens, format, options + end + + # Highlight a string into a HTML

. + # + # CSS styles use classes, so you have to include a stylesheet + # in your output. + # + # See encode. + def highlight code, lang, options = { :css => :class }, format = :div + encode code, lang, format, options + end + + # Highlight a file into a HTML
. + # + # CSS styles use classes, so you have to include a stylesheet + # in your output. + # + # See encode. + def highlight_file filename, options = { :css => :class }, format = :div + encode_file filename, format, options + end + + # Finds the Encoder class for +format+ and creates an instance, passing + # +options+ to it. + # + # Example: + # require 'coderay' + # + # stats = CodeRay.encoder(:statistic) + # stats.encode("puts 17 + 4\n", :ruby) + # + # puts '%d out of %d tokens have the kind :integer.' % [ + # stats.type_stats[:integer].count, + # stats.real_token_count + # ] + # #-> 2 out of 4 tokens have the kind :integer. + def encoder format, options = {} + Encoders[format].new options + end + + # Finds the Scanner class for +lang+ and creates an instance, passing + # +options+ to it. + # + # See Scanner.new. + def scanner lang, options = {}, &block + Scanners[lang].new '', options, &block + end + + # Extract the options for the scanner from the +options+ hash. + # + # Returns an empty Hash if :scanner_options is not set. + # + # This is used if a method like CodeRay.encode has to provide options + # for Encoder _and_ scanner. + def get_scanner_options options + options.fetch :scanner_options, {} + end + + end + +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/duo.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/duo.rb new file mode 100644 index 0000000..cb3f8ee --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/duo.rb @@ -0,0 +1,81 @@ +module CodeRay + + # = Duo + # + # A Duo is a convenient way to use CodeRay. You just create a Duo, + # giving it a lang (language of the input code) and a format (desired + # output format), and call Duo#highlight with the code. + # + # Duo makes it easy to re-use both scanner and encoder for a repetitive + # task. It also provides a very easy interface syntax: + # + # require 'coderay' + # CodeRay::Duo[:python, :div].highlight 'import this' + # + # Until you want to do uncommon things with CodeRay, I recommend to use + # this method, since it takes care of everything. + class Duo + + attr_accessor :lang, :format, :options + + # Create a new Duo, holding a lang and a format to highlight code. + # + # simple: + # CodeRay::Duo[:ruby, :html].highlight 'bla 42' + # + # with options: + # CodeRay::Duo[:ruby, :html, :hint => :debug].highlight '????::??' + # + # alternative syntax without options: + # CodeRay::Duo[:ruby => :statistic].encode 'class << self; end' + # + # alternative syntax with options: + # CodeRay::Duo[{ :ruby => :statistic }, :do => :something].encode 'abc' + # + # The options are forwarded to scanner and encoder + # (see CodeRay.get_scanner_options). + def initialize lang = nil, format = nil, options = {} + if format.nil? && lang.is_a?(Hash) && lang.size == 1 + @lang = lang.keys.first + @format = lang[@lang] + else + @lang = lang + @format = format + end + @options = options + end + + class << self + # To allow calls like Duo[:ruby, :html].highlight. + alias [] new + end + + # The scanner of the duo. Only created once. + def scanner + @scanner ||= CodeRay.scanner @lang, CodeRay.get_scanner_options(@options) + end + + # The encoder of the duo. Only created once. + def encoder + @encoder ||= CodeRay.encoder @format, @options + end + + # Tokenize and highlight the code using +scanner+ and +encoder+. + def encode code, options = {} + options = @options.merge options + encoder.encode(code, @lang, options) + end + alias highlight encode + + # Allows to use Duo like a proc object: + # + # CodeRay::Duo[:python => :yaml].call(code) + # + # or, in Ruby 1.9 and later: + # + # CodeRay::Duo[:python => :yaml].(code) + alias call encode + + end + +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/encoder.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/encoder.rb new file mode 100644 index 0000000..d2d6c7e --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/encoder.rb @@ -0,0 +1,201 @@ +module CodeRay + + # This module holds the Encoder class and its subclasses. + # For example, the HTML encoder is named CodeRay::Encoders::HTML + # can be found in coderay/encoders/html. + # + # Encoders also provides methods and constants for the register + # mechanism and the [] method that returns the Encoder class + # belonging to the given format. + module Encoders + + extend PluginHost + plugin_path File.dirname(__FILE__), 'encoders' + + # = Encoder + # + # The Encoder base class. Together with Scanner and + # Tokens, it forms the highlighting triad. + # + # Encoder instances take a Tokens object and do something with it. + # + # The most common Encoder is surely the HTML encoder + # (CodeRay::Encoders::HTML). It highlights the code in a colorful + # html page. + # If you want the highlighted code in a div or a span instead, + # use its subclasses Div and Span. + class Encoder + extend Plugin + plugin_host Encoders + + class << self + + # If FILE_EXTENSION isn't defined, this method returns the + # downcase class name instead. + def const_missing sym + if sym == :FILE_EXTENSION + (defined?(@plugin_id) && @plugin_id || name[/\w+$/].downcase).to_s + else + super + end + end + + # The default file extension for output file of this encoder class. + def file_extension + self::FILE_EXTENSION + end + + end + + # Subclasses are to store their default options in this constant. + DEFAULT_OPTIONS = { } + + # The options you gave the Encoder at creating. + attr_accessor :options, :scanner + + # Creates a new Encoder. + # +options+ is saved and used for all encode operations, as long + # as you don't overwrite it there by passing additional options. + # + # Encoder objects provide three encode methods: + # - encode simply takes a +code+ string and a +lang+ + # - encode_tokens expects a +tokens+ object instead + # + # Each method has an optional +options+ parameter. These are + # added to the options you passed at creation. + def initialize options = {} + @options = self.class::DEFAULT_OPTIONS.merge options + @@CODERAY_TOKEN_INTERFACE_DEPRECATION_WARNING_GIVEN = false + end + + # Encode a Tokens object. + def encode_tokens tokens, options = {} + options = @options.merge options + @scanner = tokens.scanner if tokens.respond_to? :scanner + setup options + compile tokens, options + finish options + end + + # Encode the given +code+ using the Scanner for +lang+. + def encode code, lang, options = {} + options = @options.merge options + @scanner = Scanners[lang].new code, CodeRay.get_scanner_options(options).update(:tokens => self) + setup options + @scanner.tokenize + finish options + end + + # You can use highlight instead of encode, if that seems + # more clear to you. + alias highlight encode + + # The default file extension for this encoder. + def file_extension + self.class.file_extension + end + + def << token + unless @@CODERAY_TOKEN_INTERFACE_DEPRECATION_WARNING_GIVEN + warn 'Using old Tokens#<< interface.' + @@CODERAY_TOKEN_INTERFACE_DEPRECATION_WARNING_GIVEN = true + end + self.token(*token) + end + + # Called with +content+ and +kind+ of the currently scanned token. + # For simple scanners, it's enougth to implement this method. + # + # By default, it calls text_token, begin_group, end_group, begin_line, + # or end_line, depending on the +content+. + def token content, kind + case content + when String + text_token content, kind + when :begin_group + begin_group kind + when :end_group + end_group kind + when :begin_line + begin_line kind + when :end_line + end_line kind + else + raise ArgumentError, 'Unknown token content type: %p, kind = %p' % [content, kind] + end + end + + # Called for each text token ([text, kind]), where text is a String. + def text_token text, kind + @out << text + end + + # Starts a token group with the given +kind+. + def begin_group kind + end + + # Ends a token group with the given +kind+. + def end_group kind + end + + # Starts a new line token group with the given +kind+. + def begin_line kind + end + + # Ends a new line token group with the given +kind+. + def end_line kind + end + + protected + + # Called with merged options before encoding starts. + # Sets @out to an empty string. + # + # See the HTML Encoder for an example of option caching. + def setup options + @out = get_output(options) + end + + def get_output options + options[:out] || '' + end + + # Append data.to_s to the output. Returns the argument. + def output data + @out << data.to_s + data + end + + # Called with merged options after encoding starts. + # The return value is the result of encoding, typically @out. + def finish options + @out + end + + # Do the encoding. + # + # The already created +tokens+ object must be used; it must be a + # Tokens object. + def compile tokens, options = {} + content = nil + for item in tokens + if item.is_a? Array + raise ArgumentError, 'Two-element array tokens are no longer supported.' + end + if content + token content, item + content = nil + else + content = item + end + end + raise 'odd number list for Tokens' if content + end + + alias tokens compile + public :tokens + + end + + end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/_map.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/_map.rb new file mode 100644 index 0000000..4cca196 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/_map.rb @@ -0,0 +1,17 @@ +module CodeRay +module Encoders + + map \ + :loc => :lines_of_code, + :plain => :text, + :plaintext => :text, + :remove_comments => :comment_filter, + :stats => :statistic, + :term => :terminal, + :tty => :terminal, + :yml => :yaml + + # No default because Tokens#nonsense should raise NoMethodError. + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/comment_filter.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/comment_filter.rb new file mode 100644 index 0000000..28336b3 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/comment_filter.rb @@ -0,0 +1,25 @@ +module CodeRay +module Encoders + + load :token_kind_filter + + # A simple Filter that removes all tokens of the :comment kind. + # + # Alias: +remove_comments+ + # + # Usage: + # CodeRay.scan('print # foo', :ruby).comment_filter.text + # #-> "print " + # + # See also: TokenKindFilter, LinesOfCode + class CommentFilter < TokenKindFilter + + register_for :comment_filter + + DEFAULT_OPTIONS = superclass::DEFAULT_OPTIONS.merge \ + :exclude => [:comment, :docstring] + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/count.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/count.rb new file mode 100644 index 0000000..98a427e --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/count.rb @@ -0,0 +1,39 @@ +module CodeRay +module Encoders + + # Returns the number of tokens. + # + # Text and block tokens are counted. + class Count < Encoder + + register_for :count + + protected + + def setup options + super + + @count = 0 + end + + def finish options + output @count + end + + public + + def text_token text, kind + @count += 1 + end + + def begin_group kind + @count += 1 + end + alias end_group begin_group + alias begin_line begin_group + alias end_line begin_group + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/debug.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/debug.rb new file mode 100644 index 0000000..f4db330 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/debug.rb @@ -0,0 +1,49 @@ +module CodeRay +module Encoders + + # = Debug Encoder + # + # Fast encoder producing simple debug output. + # + # It is readable and diff-able and is used for testing. + # + # You cannot fully restore the tokens information from the + # output, because consecutive :space tokens are merged. + # + # See also: Scanners::Debug + class Debug < Encoder + + register_for :debug + + FILE_EXTENSION = 'raydebug' + + def text_token text, kind + if kind == :space + @out << text + else + text = text.gsub('\\', '\\\\\\\\') if text.index('\\') + text = text.gsub(')', '\\\\)') if text.index(')') + @out << "#{kind}(#{text})" + end + end + + def begin_group kind + @out << "#{kind}<" + end + + def end_group kind + @out << '>' + end + + def begin_line kind + @out << "#{kind}[" + end + + def end_line kind + @out << ']' + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/debug_lint.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/debug_lint.rb new file mode 100644 index 0000000..a4eba2c --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/debug_lint.rb @@ -0,0 +1,63 @@ +module CodeRay +module Encoders + + load :lint + + # = Debug Lint Encoder + # + # Debug encoder with additional checks for: + # + # - empty tokens + # - incorrect nesting + # + # It will raise an InvalidTokenStream exception when any of the above occurs. + # + # See also: Encoders::Debug + class DebugLint < Debug + + register_for :debug_lint + + def text_token text, kind + raise Lint::EmptyToken, 'empty token for %p' % [kind] if text.empty? + raise Lint::UnknownTokenKind, 'unknown token kind %p (text was %p)' % [kind, text] unless TokenKinds.has_key? kind + super + end + + def begin_group kind + @opened << kind + super + end + + def end_group kind + raise Lint::IncorrectTokenGroupNesting, 'We are inside %s, not %p (end_group)' % [@opened.reverse.map(&:inspect).join(' < '), kind] if @opened.last != kind + @opened.pop + super + end + + def begin_line kind + @opened << kind + super + end + + def end_line kind + raise Lint::IncorrectTokenGroupNesting, 'We are inside %s, not %p (end_line)' % [@opened.reverse.map(&:inspect).join(' < '), kind] if @opened.last != kind + @opened.pop + super + end + + protected + + def setup options + super + @opened = [] + end + + def finish options + raise 'Some tokens still open at end of token stream: %p' % [@opened] unless @opened.empty? + super + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/div.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/div.rb new file mode 100644 index 0000000..efd9435 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/div.rb @@ -0,0 +1,23 @@ +module CodeRay +module Encoders + + load :html + + # Wraps HTML output into a DIV element, using inline styles by default. + # + # See Encoders::HTML for available options. + class Div < HTML + + FILE_EXTENSION = 'div.html' + + register_for :div + + DEFAULT_OPTIONS = HTML::DEFAULT_OPTIONS.merge \ + :css => :style, + :wrap => :div, + :line_numbers => false + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/filter.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/filter.rb new file mode 100644 index 0000000..e7f34d6 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/filter.rb @@ -0,0 +1,58 @@ +module CodeRay +module Encoders + + # A Filter encoder has another Tokens instance as output. + # It can be subclass to select, remove, or modify tokens in the stream. + # + # Subclasses of Filter are called "Filters" and can be chained. + # + # == Options + # + # === :tokens + # + # The Tokens object which will receive the output. + # + # Default: Tokens.new + # + # See also: TokenKindFilter + class Filter < Encoder + + register_for :filter + + protected + def setup options + super + + @tokens = options[:tokens] || Tokens.new + end + + def finish options + output @tokens + end + + public + + def text_token text, kind # :nodoc: + @tokens.text_token text, kind + end + + def begin_group kind # :nodoc: + @tokens.begin_group kind + end + + def begin_line kind # :nodoc: + @tokens.begin_line kind + end + + def end_group kind # :nodoc: + @tokens.end_group kind + end + + def end_line kind # :nodoc: + @tokens.end_line kind + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/html.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/html.rb new file mode 100644 index 0000000..d2ebb5a --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/html.rb @@ -0,0 +1,332 @@ +require 'set' + +module CodeRay +module Encoders + + # = HTML Encoder + # + # This is CodeRay's most important highlighter: + # It provides save, fast XHTML generation and CSS support. + # + # == Usage + # + # require 'coderay' + # puts CodeRay.scan('Some /code/', :ruby).html #-> a HTML page + # puts CodeRay.scan('Some /code/', :ruby).html(:wrap => :span) + # #-> Some /code/ + # puts CodeRay.scan('Some /code/', :ruby).span #-> the same + # + # puts CodeRay.scan('Some code', :ruby).html( + # :wrap => nil, + # :line_numbers => :inline, + # :css => :style + # ) + # + # == Options + # + # === :tab_width + # Convert \t characters to +n+ spaces (a number.) + # + # Default: 8 + # + # === :css + # How to include the styles; can be :class or :style. + # + # Default: :class + # + # === :wrap + # Wrap in :page, :div, :span or nil. + # + # You can also use Encoders::Div and Encoders::Span. + # + # Default: nil + # + # === :title + # + # The title of the HTML page (works only when :wrap is set to :page.) + # + # Default: 'CodeRay output' + # + # === :break_lines + # + # Split multiline blocks at line breaks. + # Forced to true if :line_numbers option is set to :inline. + # + # Default: false + # + # === :line_numbers + # Include line numbers in :table, :inline, or nil (no line numbers) + # + # Default: nil + # + # === :line_number_anchors + # Adds anchors and links to the line numbers. Can be false (off), true (on), + # or a prefix string that will be prepended to the anchor name. + # + # The prefix must consist only of letters, digits, and underscores. + # + # Default: true, default prefix name: "line" + # + # === :line_number_start + # Where to start with line number counting. + # + # Default: 1 + # + # === :bold_every + # Make every +n+-th number appear bold. + # + # Default: 10 + # + # === :highlight_lines + # + # Highlights certain line numbers. + # Can be any Enumerable, typically just an Array or Range, of numbers. + # + # Bolding is deactivated when :highlight_lines is set. It only makes sense + # in combination with :line_numbers. + # + # Default: nil + # + # === :hint + # Include some information into the output using the title attribute. + # Can be :info (show token kind on mouse-over), :info_long (with full path) + # or :debug (via inspect). + # + # Default: false + class HTML < Encoder + + register_for :html + + FILE_EXTENSION = 'snippet.html' + + DEFAULT_OPTIONS = { + :tab_width => 8, + + :css => :class, + :style => :alpha, + :wrap => nil, + :title => 'CodeRay output', + + :break_lines => false, + + :line_numbers => nil, + :line_number_anchors => 'n', + :line_number_start => 1, + :bold_every => 10, + :highlight_lines => nil, + + :hint => false, + } + + autoload :Output, CodeRay.coderay_path('encoders', 'html', 'output') + autoload :CSS, CodeRay.coderay_path('encoders', 'html', 'css') + autoload :Numbering, CodeRay.coderay_path('encoders', 'html', 'numbering') + + attr_reader :css + + protected + + def self.make_html_escape_hash + { + '&' => '&', + '"' => '"', + '>' => '>', + '<' => '<', + # "\t" => will be set to ' ' * options[:tab_width] during setup + }.tap do |hash| + # Escape ASCII control codes except \x9 == \t and \xA == \n. + (Array(0x00..0x8) + Array(0xB..0x1F)).each { |invalid| hash[invalid.chr] = ' ' } + end + end + + HTML_ESCAPE = make_html_escape_hash + HTML_ESCAPE_PATTERN = /[\t"&><\0-\x8\xB-\x1F]/ + + TOKEN_KIND_TO_INFO = Hash.new do |h, kind| + h[kind] = kind.to_s.gsub(/_/, ' ').gsub(/\b\w/) { $&.capitalize } + end + + TRANSPARENT_TOKEN_KINDS = Set[ + :delimiter, :modifier, :content, :escape, :inline_delimiter, + ] + + # Generate a hint about the given +kinds+ in a +hint+ style. + # + # +hint+ may be :info, :info_long or :debug. + def self.token_path_to_hint hint, kinds + kinds = Array kinds + title = + case hint + when :info + kinds = kinds[1..-1] if TRANSPARENT_TOKEN_KINDS.include? kinds.first + TOKEN_KIND_TO_INFO[kinds.first] + when :info_long + kinds.reverse.map { |kind| TOKEN_KIND_TO_INFO[kind] }.join('/') + when :debug + kinds.inspect + end + title ? " title=\"#{title}\"" : '' + end + + def setup options + super + + check_options! options + + if options[:wrap] || options[:line_numbers] + @real_out = @out + @out = '' + end + + @break_lines = (options[:break_lines] == true) + + @HTML_ESCAPE = HTML_ESCAPE.merge("\t" => ' ' * options[:tab_width]) + + @opened = [] + @last_opened = nil + @css = CSS.new options[:style] + + @span_for_kinds = make_span_for_kinds(options[:css], options[:hint]) + + @set_last_opened = options[:hint] || options[:css] == :style + end + + def finish options + unless @opened.empty? + @out << '' while @opened.pop + @last_opened = nil + end + + if @out.respond_to? :to_str + @out.extend Output + @out.css = @css + if options[:line_numbers] + Numbering.number! @out, options[:line_numbers], options + end + @out.wrap! options[:wrap] + @out.apply_title! options[:title] + end + + if defined?(@real_out) && @real_out + @real_out << @out + @out = @real_out + end + + super + end + + public + + def text_token text, kind + style = @span_for_kinds[@last_opened ? [kind, *@opened] : kind] + + text = text.gsub(/#{HTML_ESCAPE_PATTERN}/o) { |m| @HTML_ESCAPE[m] } if text =~ /#{HTML_ESCAPE_PATTERN}/o + text = break_lines(text, style) if @break_lines && (style || @opened.size > 0) && text.index("\n") + + if style + @out << style << text << '' + else + @out << text + end + end + + # token groups, eg. strings + def begin_group kind + @out << (@span_for_kinds[@last_opened ? [kind, *@opened] : kind] || '') + @opened << kind + @last_opened = kind if @set_last_opened + end + + def end_group kind + check_group_nesting 'token group', kind if $CODERAY_DEBUG + close_span + end + + # whole lines to be highlighted, eg. a deleted line in a diff + def begin_line kind + if style = @span_for_kinds[@last_opened ? [kind, *@opened] : kind] + if style['class="'] + @out << style.sub('class="', 'class="line ') + else + @out << style.sub('>', ' class="line">') + end + else + @out << '' + end + @opened << kind + @last_opened = kind if @options[:css] == :style + end + + def end_line kind + check_group_nesting 'line', kind if $CODERAY_DEBUG + close_span + end + + protected + + def check_options! options + unless [false, nil, :debug, :info, :info_long].include? options[:hint] + raise ArgumentError, "Unknown value %p for :hint; expected :info, :info_long, :debug, false, or nil." % [options[:hint]] + end + + unless [:class, :style].include? options[:css] + raise ArgumentError, 'Unknown value %p for :css.' % [options[:css]] + end + + options[:break_lines] = true if options[:line_numbers] == :inline + end + + def css_class_for_kinds kinds + TokenKinds[kinds.is_a?(Symbol) ? kinds : kinds.first] + end + + def style_for_kinds kinds + css_classes = kinds.is_a?(Array) ? kinds.map { |c| TokenKinds[c] } : [TokenKinds[kinds]] + @css.get_style_for_css_classes css_classes + end + + def make_span_for_kinds method, hint + Hash.new do |h, kinds| + begin + css_class = css_class_for_kinds(kinds) + title = HTML.token_path_to_hint hint, kinds if hint + + if css_class || title + if method == :style + style = style_for_kinds(kinds) + "" + else + "" + end + end + end.tap do |span| + h.clear if h.size >= 100 + h[kinds] = span + end + end + end + + def check_group_nesting name, kind + if @opened.empty? || @opened.last != kind + warn "Malformed token stream: Trying to close a #{name} (%p) that is not open. Open are: %p." % [kind, @opened[1..-1]] + end + end + + def break_lines text, style + reopen = '' + @opened.each_with_index do |kind, index| + reopen << (@span_for_kinds[index > 0 ? [kind, *@opened[0...index]] : kind] || '') + end + text.gsub("\n", "#{'' * @opened.size}#{'' if style}\n#{reopen}#{style}") + end + + def close_span + if @opened.pop + @out << '' + @last_opened = @opened.last if @last_opened + end + end + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/html/css.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/html/css.rb new file mode 100644 index 0000000..164d7f8 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/html/css.rb @@ -0,0 +1,65 @@ +module CodeRay +module Encoders + + class HTML + class CSS # :nodoc: + + attr :stylesheet + + def CSS.load_stylesheet style = nil + CodeRay::Styles[style] + end + + def initialize style = :default + @styles = Hash.new + style = CSS.load_stylesheet style + @stylesheet = [ + style::CSS_MAIN_STYLES, + style::TOKEN_COLORS.gsub(/^(?!$)/, '.CodeRay ') + ].join("\n") + parse style::TOKEN_COLORS + end + + def get_style_for_css_classes css_classes + cl = @styles[css_classes.first] + return '' unless cl + style = '' + 1.upto css_classes.size do |offset| + break if style = cl[css_classes[offset .. -1]] + end + # warn 'Style not found: %p' % [styles] if style.empty? + return style + end + + private + + CSS_CLASS_PATTERN = / + ( # $1 = selectors + (?: + (?: \s* \. [-\w]+ )+ + \s* ,? + )+ + ) + \s* \{ \s* + ( [^\}]+ )? # $2 = style + \s* \} \s* + | + ( [^\n]+ ) # $3 = error + /mx + def parse stylesheet + stylesheet.scan CSS_CLASS_PATTERN do |selectors, style, error| + raise "CSS parse error: '#{error.inspect}' not recognized" if error + for selector in selectors.split(',') + classes = selector.scan(/[-\w]+/) + cl = classes.pop + @styles[cl] ||= Hash.new + @styles[cl][classes] = style.to_s.strip.delete(' ').chomp(';') + end + end + end + + end + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/html/numbering.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/html/numbering.rb new file mode 100644 index 0000000..a1b9c04 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/html/numbering.rb @@ -0,0 +1,108 @@ +module CodeRay +module Encoders + + class HTML + + module Numbering # :nodoc: + + def self.number! output, mode = :table, options = {} + return self unless mode + + options = DEFAULT_OPTIONS.merge options + + start = options[:line_number_start] + unless start.is_a? Integer + raise ArgumentError, "Invalid value %p for :line_number_start; Integer expected." % start + end + + anchor_prefix = options[:line_number_anchors] + anchor_prefix = 'line' if anchor_prefix == true + anchor_prefix = anchor_prefix.to_s[/[\w-]+/] if anchor_prefix + anchoring = + if anchor_prefix + proc do |line| + line = line.to_s + anchor = anchor_prefix + line + "#{line}" + end + else + :to_s.to_proc + end + + bold_every = options[:bold_every] + highlight_lines = options[:highlight_lines] + bolding = + if bold_every == false && highlight_lines == nil + anchoring + elsif highlight_lines.is_a? Enumerable + highlight_lines = highlight_lines.to_set + proc do |line| + if highlight_lines.include? line + "#{anchoring[line]}" # highlighted line numbers in bold + else + anchoring[line] + end + end + elsif bold_every.is_a? Integer + raise ArgumentError, ":bolding can't be 0." if bold_every == 0 + proc do |line| + if line % bold_every == 0 + "#{anchoring[line]}" # every bold_every-th number in bold + else + anchoring[line] + end + end + else + raise ArgumentError, 'Invalid value %p for :bolding; false or Integer expected.' % bold_every + end + + if position_of_last_newline = output.rindex(RUBY_VERSION >= '1.9' ? /\n/ : ?\n) + after_last_newline = output[position_of_last_newline + 1 .. -1] + ends_with_newline = after_last_newline[/\A(?:<\/span>)*\z/] + + if ends_with_newline + line_count = output.count("\n") + else + line_count = output.count("\n") + 1 + end + else + line_count = 1 + end + + case mode + when :inline + max_width = (start + line_count).to_s.size + line_number = start + output.gsub!(/^.*$\n?/) do |line| + line_number_text = bolding.call line_number + indent = ' ' * (max_width - line_number.to_s.size) + line_number += 1 + "#{indent}#{line_number_text}#{line}" + end + + when :table + line_numbers = (start ... start + line_count).map(&bolding).join("\n") + line_numbers << "\n" + line_numbers_table_template = Output::TABLE.apply('LINE_NUMBERS', line_numbers) + + output.gsub!(/<\/div>\n/, '
') + output.wrap_in! line_numbers_table_template + output.wrapped_in = :div + + when :list + raise NotImplementedError, 'The :list option is no longer available. Use :table.' + + else + raise ArgumentError, 'Unknown value %p for mode: expected one of %p' % + [mode, [:table, :inline]] + end + + output + end + + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/html/output.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/html/output.rb new file mode 100644 index 0000000..de6f6ea --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/html/output.rb @@ -0,0 +1,166 @@ +module CodeRay +module Encoders + + class HTML + + # This module is included in the output String of the HTML Encoder. + # + # It provides methods like wrap, div, page etc. + # + # Remember to use #clone instead of #dup to keep the modules the object was + # extended with. + # + # TODO: Rewrite this without monkey patching. + module Output + + attr_accessor :css + + class << self + + # Raises an exception if an object that doesn't respond to to_str is extended by Output, + # to prevent users from misuse. Use Module#remove_method to disable. + def extended o # :nodoc: + warn "The Output module is intended to extend instances of String, not #{o.class}." unless o.respond_to? :to_str + end + + def make_stylesheet css, in_tag = false # :nodoc: + sheet = css.stylesheet + sheet = <<-'CSS' if in_tag + + CSS + sheet + end + + def page_template_for_css css # :nodoc: + sheet = make_stylesheet css + PAGE.apply 'CSS', sheet + end + + end + + def wrapped_in? element + wrapped_in == element + end + + def wrapped_in + @wrapped_in ||= nil + end + attr_writer :wrapped_in + + def wrap_in! template + Template.wrap! self, template, 'CONTENT' + self + end + + def apply_title! title + self.sub!(/()(<\/title>)/) { $1 + title + $2 } + self + end + + def wrap! element, *args + return self if not element or element == wrapped_in + case element + when :div + raise "Can't wrap %p in %p" % [wrapped_in, element] unless wrapped_in? nil + wrap_in! DIV + when :span + raise "Can't wrap %p in %p" % [wrapped_in, element] unless wrapped_in? nil + wrap_in! SPAN + when :page + wrap! :div if wrapped_in? nil + raise "Can't wrap %p in %p" % [wrapped_in, element] unless wrapped_in? :div + wrap_in! Output.page_template_for_css(@css) + if args.first.is_a?(Hash) && title = args.first[:title] + apply_title! title + end + self + when nil + return self + else + raise "Unknown value %p for :wrap" % element + end + @wrapped_in = element + self + end + + def stylesheet in_tag = false + Output.make_stylesheet @css, in_tag + end + +#-- don't include the templates in docu + + class Template < String # :nodoc: + + def self.wrap! str, template, target + target = Regexp.new(Regexp.escape("<%#{target}%>")) + if template =~ target + str[0,0] = $` + str << $' + else + raise "Template target <%%%p%%> not found" % target + end + end + + def apply target, replacement + target = Regexp.new(Regexp.escape("<%#{target}%>")) + if self =~ target + Template.new($` + replacement + $') + else + raise "Template target <%%%p%%> not found" % target + end + end + + end + + SPAN = Template.new '<span class="CodeRay"><%CONTENT%></span>' + + DIV = Template.new <<-DIV +<div class="CodeRay"> + <div class="code"><pre><%CONTENT%></pre></div> +</div> + DIV + + TABLE = Template.new <<-TABLE +<table class="CodeRay"><tr> + <td class="line-numbers"><pre><%LINE_NUMBERS%></pre></td> + <td class="code"><pre><%CONTENT%></pre></td> +</tr></table> + TABLE + + PAGE = Template.new <<-PAGE +<!DOCTYPE html> +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <title> + + + + +<%CONTENT%> + + + PAGE + + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/json.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/json.rb new file mode 100644 index 0000000..a9e40dc --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/json.rb @@ -0,0 +1,83 @@ +module CodeRay +module Encoders + + # A simple JSON Encoder. + # + # Example: + # CodeRay.scan('puts "Hello world!"', :ruby).json + # yields + # [ + # {"type"=>"text", "text"=>"puts", "kind"=>"ident"}, + # {"type"=>"text", "text"=>" ", "kind"=>"space"}, + # {"type"=>"block", "action"=>"open", "kind"=>"string"}, + # {"type"=>"text", "text"=>"\"", "kind"=>"delimiter"}, + # {"type"=>"text", "text"=>"Hello world!", "kind"=>"content"}, + # {"type"=>"text", "text"=>"\"", "kind"=>"delimiter"}, + # {"type"=>"block", "action"=>"close", "kind"=>"string"}, + # ] + class JSON < Encoder + + begin + require 'json' + rescue LoadError + begin + require 'rubygems' unless defined? Gem + gem 'json' + require 'json' + rescue LoadError + $stderr.puts "The JSON encoder needs the JSON library.\n" \ + "Please gem install json." + raise + end + end + + register_for :json + FILE_EXTENSION = 'json' + + protected + def setup options + super + + @first = true + @out << '[' + end + + def finish options + @out << ']' + end + + def append data + if @first + @first = false + else + @out << ',' + end + + @out << data.to_json + end + + public + def text_token text, kind + append :type => 'text', :text => text, :kind => kind + end + + def begin_group kind + append :type => 'block', :action => 'open', :kind => kind + end + + def end_group kind + append :type => 'block', :action => 'close', :kind => kind + end + + def begin_line kind + append :type => 'block', :action => 'begin_line', :kind => kind + end + + def end_line kind + append :type => 'block', :action => 'end_line', :kind => kind + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/lines_of_code.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/lines_of_code.rb new file mode 100644 index 0000000..5f8422f --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/lines_of_code.rb @@ -0,0 +1,45 @@ +module CodeRay +module Encoders + + # Counts the LoC (Lines of Code). Returns an Integer >= 0. + # + # Alias: +loc+ + # + # Everything that is not comment, markup, doctype/shebang, or an empty line, + # is considered to be code. + # + # For example, + # * HTML files not containing JavaScript have 0 LoC + # * in a Java class without comments, LoC is the number of non-empty lines + # + # A Scanner class should define the token kinds that are not code in the + # KINDS_NOT_LOC constant, which defaults to [:comment, :doctype]. + class LinesOfCode < TokenKindFilter + + register_for :lines_of_code + + NON_EMPTY_LINE = /^\s*\S.*$/ + + protected + + def setup options + if scanner + kinds_not_loc = scanner.class::KINDS_NOT_LOC + else + warn "Tokens have no associated scanner, counting all nonempty lines." if $VERBOSE + kinds_not_loc = CodeRay::Scanners::Scanner::KINDS_NOT_LOC + end + + options[:exclude] = kinds_not_loc + + super options + end + + def finish options + output @tokens.text.scan(NON_EMPTY_LINE).size + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/lint.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/lint.rb new file mode 100644 index 0000000..88c8bd1 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/lint.rb @@ -0,0 +1,59 @@ +module CodeRay +module Encoders + + # = Lint Encoder + # + # Checks for: + # + # - empty tokens + # - incorrect nesting + # + # It will raise an InvalidTokenStream exception when any of the above occurs. + # + # See also: Encoders::DebugLint + class Lint < Debug + + register_for :lint + + InvalidTokenStream = Class.new StandardError + EmptyToken = Class.new InvalidTokenStream + UnknownTokenKind = Class.new InvalidTokenStream + IncorrectTokenGroupNesting = Class.new InvalidTokenStream + + def text_token text, kind + raise EmptyToken, 'empty token for %p' % [kind] if text.empty? + raise UnknownTokenKind, 'unknown token kind %p (text was %p)' % [kind, text] unless TokenKinds.has_key? kind + end + + def begin_group kind + @opened << kind + end + + def end_group kind + raise IncorrectTokenGroupNesting, 'We are inside %s, not %p (end_group)' % [@opened.reverse.map(&:inspect).join(' < '), kind] if @opened.last != kind + @opened.pop + end + + def begin_line kind + @opened << kind + end + + def end_line kind + raise IncorrectTokenGroupNesting, 'We are inside %s, not %p (end_line)' % [@opened.reverse.map(&:inspect).join(' < '), kind] if @opened.last != kind + @opened.pop + end + + protected + + def setup options + @opened = [] + end + + def finish options + raise 'Some tokens still open at end of token stream: %p' % [@opened] unless @opened.empty? + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/null.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/null.rb new file mode 100644 index 0000000..73ba47d --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/null.rb @@ -0,0 +1,18 @@ +module CodeRay +module Encoders + + # = Null Encoder + # + # Does nothing and returns an empty string. + class Null < Encoder + + register_for :null + + def text_token text, kind + # do nothing + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/page.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/page.rb new file mode 100644 index 0000000..800e73f --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/page.rb @@ -0,0 +1,24 @@ +module CodeRay +module Encoders + + load :html + + # Wraps the output into a HTML page, using CSS classes and + # line numbers in the table format by default. + # + # See Encoders::HTML for available options. + class Page < HTML + + FILE_EXTENSION = 'html' + + register_for :page + + DEFAULT_OPTIONS = HTML::DEFAULT_OPTIONS.merge \ + :css => :class, + :wrap => :page, + :line_numbers => :table + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/span.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/span.rb new file mode 100644 index 0000000..da705bd --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/span.rb @@ -0,0 +1,23 @@ +module CodeRay +module Encoders + + load :html + + # Wraps HTML output into a SPAN element, using inline styles by default. + # + # See Encoders::HTML for available options. + class Span < HTML + + FILE_EXTENSION = 'span.html' + + register_for :span + + DEFAULT_OPTIONS = HTML::DEFAULT_OPTIONS.merge \ + :css => :style, + :wrap => :span, + :line_numbers => false + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/statistic.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/statistic.rb new file mode 100644 index 0000000..b2f8b83 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/statistic.rb @@ -0,0 +1,95 @@ +module CodeRay +module Encoders + + # Makes a statistic for the given tokens. + # + # Alias: +stats+ + class Statistic < Encoder + + register_for :statistic + + attr_reader :type_stats, :real_token_count # :nodoc: + + TypeStats = Struct.new :count, :size # :nodoc: + + protected + + def setup options + super + + @type_stats = Hash.new { |h, k| h[k] = TypeStats.new 0, 0 } + @real_token_count = 0 + end + + STATS = <<-STATS # :nodoc: + +Code Statistics + +Tokens %8d + Non-Whitespace %8d +Bytes Total %8d + +Token Types (%d): + type count ratio size (average) +------------------------------------------------------------- +%s + STATS + + TOKEN_TYPES_ROW = <<-TKR # :nodoc: + %-20s %8d %6.2f %% %5.1f + TKR + + def finish options + all = @type_stats['TOTAL'] + all_count, all_size = all.count, all.size + @type_stats.each do |type, stat| + stat.size /= stat.count.to_f + end + types_stats = @type_stats.sort_by { |k, v| [-v.count, k.to_s] }.map do |k, v| + TOKEN_TYPES_ROW % [k, v.count, 100.0 * v.count / all_count, v.size] + end.join + @out << STATS % [ + all_count, @real_token_count, all_size, + @type_stats.delete_if { |k, v| k.is_a? String }.size, + types_stats + ] + + super + end + + public + + def text_token text, kind + @real_token_count += 1 unless kind == :space + @type_stats[kind].count += 1 + @type_stats[kind].size += text.size + @type_stats['TOTAL'].size += text.size + @type_stats['TOTAL'].count += 1 + end + + def begin_group kind + block_token ':begin_group', kind + end + + def end_group kind + block_token ':end_group', kind + end + + def begin_line kind + block_token ':begin_line', kind + end + + def end_line kind + block_token ':end_line', kind + end + + def block_token action, kind + @type_stats['TOTAL'].count += 1 + @type_stats[action].count += 1 + @type_stats[kind].count += 1 + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/terminal.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/terminal.rb new file mode 100644 index 0000000..c7ae014 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/terminal.rb @@ -0,0 +1,195 @@ +module CodeRay + module Encoders + + # Outputs code highlighted for a color terminal. + # + # Note: This encoder is in beta. It currently doesn't use the Styles. + # + # Alias: +term+ + # + # == Authors & License + # + # By Rob Aldred (http://robaldred.co.uk) + # + # Based on idea by Nathan Weizenbaum (http://nex-3.com) + # + # MIT License (http://www.opensource.org/licenses/mit-license.php) + class Terminal < Encoder + + register_for :terminal + + TOKEN_COLORS = { + :debug => "\e[1;37;44m", + + :annotation => "\e[34m", + :attribute_name => "\e[35m", + :attribute_value => "\e[31m", + :binary => { + :self => "\e[31m", + :char => "\e[1;31m", + :delimiter => "\e[1;31m", + }, + :char => { + :self => "\e[35m", + :delimiter => "\e[1;35m" + }, + :class => "\e[1;35;4m", + :class_variable => "\e[36m", + :color => "\e[32m", + :comment => { + :self => "\e[1;30m", + :char => "\e[37m", + :delimiter => "\e[37m", + }, + :constant => "\e[1;34;4m", + :decorator => "\e[35m", + :definition => "\e[1;33m", + :directive => "\e[33m", + :docstring => "\e[31m", + :doctype => "\e[1;34m", + :done => "\e[1;30;2m", + :entity => "\e[31m", + :error => "\e[1;37;41m", + :exception => "\e[1;31m", + :float => "\e[1;35m", + :function => "\e[1;34m", + :global_variable => "\e[1;32m", + :hex => "\e[1;36m", + :id => "\e[1;34m", + :include => "\e[31m", + :integer => "\e[1;34m", + :imaginary => "\e[1;34m", + :important => "\e[1;31m", + :key => { + :self => "\e[35m", + :char => "\e[1;35m", + :delimiter => "\e[1;35m", + }, + :keyword => "\e[32m", + :label => "\e[1;33m", + :local_variable => "\e[33m", + :namespace => "\e[1;35m", + :octal => "\e[1;34m", + :predefined => "\e[36m", + :predefined_constant => "\e[1;36m", + :predefined_type => "\e[1;32m", + :preprocessor => "\e[1;36m", + :pseudo_class => "\e[1;34m", + :regexp => { + :self => "\e[35m", + :delimiter => "\e[1;35m", + :modifier => "\e[35m", + :char => "\e[1;35m", + }, + :reserved => "\e[32m", + :shell => { + :self => "\e[33m", + :char => "\e[1;33m", + :delimiter => "\e[1;33m", + :escape => "\e[1;33m", + }, + :string => { + :self => "\e[31m", + :modifier => "\e[1;31m", + :char => "\e[1;35m", + :delimiter => "\e[1;31m", + :escape => "\e[1;31m", + }, + :symbol => { + :self => "\e[33m", + :delimiter => "\e[1;33m", + }, + :tag => "\e[32m", + :type => "\e[1;34m", + :value => "\e[36m", + :variable => "\e[34m", + + :insert => { + :self => "\e[42m", + :insert => "\e[1;32;42m", + :eyecatcher => "\e[102m", + }, + :delete => { + :self => "\e[41m", + :delete => "\e[1;31;41m", + :eyecatcher => "\e[101m", + }, + :change => { + :self => "\e[44m", + :change => "\e[37;44m", + }, + :head => { + :self => "\e[45m", + :filename => "\e[37;45m" + }, + } + + TOKEN_COLORS[:keyword] = TOKEN_COLORS[:reserved] + TOKEN_COLORS[:method] = TOKEN_COLORS[:function] + TOKEN_COLORS[:escape] = TOKEN_COLORS[:delimiter] + + protected + + def setup(options) + super + @opened = [] + @color_scopes = [TOKEN_COLORS] + end + + public + + def text_token text, kind + if color = @color_scopes.last[kind] + color = color[:self] if color.is_a? Hash + + @out << color + @out << (text.index("\n") ? text.gsub("\n", "\e[0m\n" + color) : text) + @out << "\e[0m" + if outer_color = @color_scopes.last[:self] + @out << outer_color + end + else + @out << text + end + end + + def begin_group kind + @opened << kind + @out << open_token(kind) + end + alias begin_line begin_group + + def end_group kind + if @opened.pop + @color_scopes.pop + @out << "\e[0m" + if outer_color = @color_scopes.last[:self] + @out << outer_color + end + end + end + + def end_line kind + @out << (@line_filler ||= "\t" * 100) + end_group kind + end + + private + + def open_token kind + if color = @color_scopes.last[kind] + if color.is_a? Hash + @color_scopes << color + color[:self] + else + @color_scopes << @color_scopes.last + color + end + else + @color_scopes << @color_scopes.last + '' + end + end + end + end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/text.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/text.rb new file mode 100644 index 0000000..15c66f9 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/text.rb @@ -0,0 +1,46 @@ +module CodeRay +module Encoders + + # Concats the tokens into a single string, resulting in the original + # code string if no tokens were removed. + # + # Alias: +plain+, +plaintext+ + # + # == Options + # + # === :separator + # A separator string to join the tokens. + # + # Default: empty String + class Text < Encoder + + register_for :text + + FILE_EXTENSION = 'txt' + + DEFAULT_OPTIONS = { + :separator => nil + } + + def text_token text, kind + super + + if @first + @first = false + else + @out << @sep + end if @sep + end + + protected + def setup options + super + + @first = true + @sep = options[:separator] + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/token_kind_filter.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/token_kind_filter.rb new file mode 100644 index 0000000..4773ea3 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/token_kind_filter.rb @@ -0,0 +1,111 @@ +module CodeRay +module Encoders + + load :filter + + # A Filter that selects tokens based on their token kind. + # + # == Options + # + # === :exclude + # + # One or many symbols (in an Array) which shall be excluded. + # + # Default: [] + # + # === :include + # + # One or many symbols (in an array) which shall be included. + # + # Default: :all, which means all tokens are included. + # + # Exclusion wins over inclusion. + # + # See also: CommentFilter + class TokenKindFilter < Filter + + register_for :token_kind_filter + + DEFAULT_OPTIONS = { + :exclude => [], + :include => :all + } + + protected + def setup options + super + + @group_excluded = false + @exclude = options[:exclude] + @exclude = Array(@exclude) unless @exclude == :all + @include = options[:include] + @include = Array(@include) unless @include == :all + end + + def include_text_token? text, kind + include_group? kind + end + + def include_group? kind + (@include == :all || @include.include?(kind)) && + !(@exclude == :all || @exclude.include?(kind)) + end + + public + + # Add the token to the output stream if +kind+ matches the conditions. + def text_token text, kind + super if !@group_excluded && include_text_token?(text, kind) + end + + # Add the token group to the output stream if +kind+ matches the + # conditions. + # + # If it does not, all tokens inside the group are excluded from the + # stream, even if their kinds match. + def begin_group kind + if @group_excluded + @group_excluded += 1 + elsif include_group? kind + super + else + @group_excluded = 1 + end + end + + # See +begin_group+. + def begin_line kind + if @group_excluded + @group_excluded += 1 + elsif include_group? kind + super + else + @group_excluded = 1 + end + end + + # Take care of re-enabling the delegation of tokens to the output stream + # if an exluded group has ended. + def end_group kind + if @group_excluded + @group_excluded -= 1 + @group_excluded = false if @group_excluded.zero? + else + super + end + end + + # See +end_group+. + def end_line kind + if @group_excluded + @group_excluded -= 1 + @group_excluded = false if @group_excluded.zero? + else + super + end + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/xml.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/xml.rb new file mode 100644 index 0000000..3d306a6 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/xml.rb @@ -0,0 +1,72 @@ +module CodeRay +module Encoders + + # = XML Encoder + # + # Uses REXML. Very slow. + class XML < Encoder + + register_for :xml + + FILE_EXTENSION = 'xml' + + autoload :REXML, 'rexml/document' + + DEFAULT_OPTIONS = { + :tab_width => 8, + :pretty => -1, + :transitive => false, + } + + protected + def setup options + super + + @doc = REXML::Document.new + @doc << REXML::XMLDecl.new + @tab_width = options[:tab_width] + @root = @node = @doc.add_element('coderay-tokens') + end + + def finish options + @doc.write @out, options[:pretty], options[:transitive], true + + super + end + + public + def text_token text, kind + if kind == :space + token = @node + else + token = @node.add_element kind.to_s + end + text.scan(/(\x20+)|(\t+)|(\n)|[^\x20\t\n]+/) do |space, tab, nl| + case + when space + token << REXML::Text.new(space, true) + when tab + token << REXML::Text.new(tab, true) + when nl + token << REXML::Text.new(nl, true) + else + token << REXML::Text.new($&) + end + end + end + + def begin_group kind + @node = @node.add_element kind.to_s + end + + def end_group kind + if @node == @root + raise 'no token to close!' + end + @node = @node.parent + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/yaml.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/yaml.rb new file mode 100644 index 0000000..ba6e715 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/encoders/yaml.rb @@ -0,0 +1,50 @@ +autoload :YAML, 'yaml' + +module CodeRay +module Encoders + + # = YAML Encoder + # + # Slow. + class YAML < Encoder + + register_for :yaml + + FILE_EXTENSION = 'yaml' + + protected + def setup options + super + + @data = [] + end + + def finish options + output ::YAML.dump(@data) + end + + public + def text_token text, kind + @data << [text, kind] + end + + def begin_group kind + @data << [:begin_group, kind] + end + + def end_group kind + @data << [:end_group, kind] + end + + def begin_line kind + @data << [:begin_line, kind] + end + + def end_line kind + @data << [:end_line, kind] + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/for_redcloth.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/for_redcloth.rb new file mode 100644 index 0000000..f9df32b --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/for_redcloth.rb @@ -0,0 +1,95 @@ +module CodeRay + + # A little hack to enable CodeRay highlighting in RedCloth. + # + # Usage: + # require 'coderay' + # require 'coderay/for_redcloth' + # RedCloth.new('@[ruby]puts "Hello, World!"@').to_html + # + # Make sure you have RedCloth 4.0.3 activated, for example by calling + # require 'rubygems' + # before RedCloth is loaded and before calling CodeRay.for_redcloth. + module ForRedCloth + + def self.install + gem 'RedCloth', '>= 4.0.3' if defined? gem + require 'redcloth' + unless RedCloth::VERSION.to_s >= '4.0.3' + if defined? gem + raise 'CodeRay.for_redcloth needs RedCloth version 4.0.3 or later. ' + + "You have #{RedCloth::VERSION}. Please gem install RedCloth." + else + $".delete 'redcloth.rb' # sorry, but it works + require 'rubygems' + return install # retry + end + end + unless RedCloth::VERSION.to_s >= '4.2.2' + warn 'CodeRay.for_redcloth works best with RedCloth version 4.2.2 or later.' + end + RedCloth::TextileDoc.send :include, ForRedCloth::TextileDoc + RedCloth::Formatters::HTML.module_eval do + def unescape(html) # :nodoc: + replacements = { + '&' => '&', + '"' => '"', + '>' => '>', + '<' => '<', + } + html.gsub(/&(?:amp|quot|[gl]t);/) { |entity| replacements[entity] } + end + undef code, bc_open, bc_close, escape_pre + def code(opts) # :nodoc: + opts[:block] = true + if !opts[:lang] && RedCloth::VERSION.to_s >= '4.2.0' + # simulating pre-4.2 behavior + if opts[:text].sub!(/\A\[(\w+)\]/, '') + if CodeRay::Scanners[$1].lang == :text + opts[:text] = $& + opts[:text] + else + opts[:lang] = $1 + end + end + end + if opts[:lang] && !filter_coderay + require 'coderay' + @in_bc ||= nil + format = @in_bc ? :div : :span + opts[:text] = unescape(opts[:text]) unless @in_bc + highlighted_code = CodeRay.encode opts[:text], opts[:lang], format + highlighted_code.sub!(/\A<(span|div)/) { |m| m + pba(@in_bc || opts) } + highlighted_code + else + "#{opts[:text]}" + end + end + def bc_open(opts) # :nodoc: + opts[:block] = true + @in_bc = opts + opts[:lang] ? '' : "" + end + def bc_close(opts) # :nodoc: + opts = @in_bc + @in_bc = nil + opts[:lang] ? '' : "\n" + end + def escape_pre(text) # :nodoc: + if @in_bc ||= nil + text + else + html_esc(text, :html_escape_preformatted) + end + end + end + end + + module TextileDoc # :nodoc: + attr_accessor :filter_coderay + end + + end + +end + +CodeRay::ForRedCloth.install \ No newline at end of file diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/helpers/file_type.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/helpers/file_type.rb new file mode 100644 index 0000000..7de34d5 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/helpers/file_type.rb @@ -0,0 +1,151 @@ +module CodeRay + + # = FileType + # + # A simple filetype recognizer. + # + # == Usage + # + # # determine the type of the given + # lang = FileType[file_name] + # + # # return :text if the file type is unknown + # lang = FileType.fetch file_name, :text + # + # # try the shebang line, too + # lang = FileType.fetch file_name, :text, true + module FileType + + UnknownFileType = Class.new Exception + + class << self + + # Try to determine the file type of the file. + # + # +filename+ is a relative or absolute path to a file. + # + # The file itself is only accessed when +read_shebang+ is set to true. + # That means you can get filetypes from files that don't exist. + def [] filename, read_shebang = false + name = File.basename filename + ext = File.extname(name).sub(/^\./, '') # from last dot, delete the leading dot + ext2 = filename.to_s[/\.(.*)/, 1] # from first dot + + type = + TypeFromExt[ext] || + TypeFromExt[ext.downcase] || + (TypeFromExt[ext2] if ext2) || + (TypeFromExt[ext2.downcase] if ext2) || + TypeFromName[name] || + TypeFromName[name.downcase] + type ||= type_from_shebang(filename) if read_shebang + + type + end + + # This works like Hash#fetch. + # + # If the filetype cannot be found, the +default+ value + # is returned. + def fetch filename, default = nil, read_shebang = false + if default && block_given? + warn 'Block supersedes default value argument; use either.' + end + + if type = self[filename, read_shebang] + type + else + return yield if block_given? + return default if default + raise UnknownFileType, 'Could not determine type of %p.' % filename + end + end + + protected + + def type_from_shebang filename + return unless File.exist? filename + File.open filename, 'r' do |f| + if first_line = f.gets + if type = first_line[TypeFromShebang] + type.to_sym + end + end + end + end + + end + + TypeFromExt = { + 'c' => :c, + 'cfc' => :xml, + 'cfm' => :xml, + 'clj' => :clojure, + 'css' => :css, + 'diff' => :diff, + 'dpr' => :delphi, + 'erb' => :erb, + 'gemspec' => :ruby, + 'go' => :go, + 'groovy' => :groovy, + 'gvy' => :groovy, + 'h' => :c, + 'haml' => :haml, + 'htm' => :html, + 'html' => :html, + 'html.erb' => :erb, + 'java' => :java, + 'js' => :java_script, + 'json' => :json, + 'lua' => :lua, + 'mab' => :ruby, + 'pas' => :delphi, + 'patch' => :diff, + 'phtml' => :php, + 'php' => :php, + 'php3' => :php, + 'php4' => :php, + 'php5' => :php, + 'prawn' => :ruby, + 'py' => :python, + 'py3' => :python, + 'pyw' => :python, + 'rake' => :ruby, + 'raydebug' => :raydebug, + 'rb' => :ruby, + 'rbw' => :ruby, + 'rhtml' => :erb, + 'rjs' => :ruby, + 'rpdf' => :ruby, + 'ru' => :ruby, # config.ru + 'rxml' => :ruby, + 'sass' => :sass, + 'sql' => :sql, + 'taskpaper' => :taskpaper, + 'template' => :json, # AWS CloudFormation template + 'tmproj' => :xml, + 'xaml' => :xml, + 'xhtml' => :html, + 'xml' => :xml, + 'yaml' => :yaml, + 'yml' => :yaml, + } + for cpp_alias in %w[cc cpp cp cxx c++ C hh hpp h++ cu] + TypeFromExt[cpp_alias] = :cpp + end + + TypeFromShebang = /\b(?:ruby|perl|python|sh)\b/ + + TypeFromName = { + 'Capfile' => :ruby, + 'Rakefile' => :ruby, + 'Rantfile' => :ruby, + 'Gemfile' => :ruby, + 'Guardfile' => :ruby, + 'Vagrantfile' => :ruby, + 'Appraisals' => :ruby + } + + end + +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/helpers/plugin.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/helpers/plugin.rb new file mode 100644 index 0000000..9a724ff --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/helpers/plugin.rb @@ -0,0 +1,274 @@ +module CodeRay + + # = PluginHost + # + # A simple subclass/subfolder plugin system. + # + # Example: + # class Generators + # extend PluginHost + # plugin_path 'app/generators' + # end + # + # class Generator + # extend Plugin + # PLUGIN_HOST = Generators + # end + # + # class FancyGenerator < Generator + # register_for :fancy + # end + # + # Generators[:fancy] #-> FancyGenerator + # # or + # CodeRay.require_plugin 'Generators/fancy' + # # or + # Generators::Fancy + module PluginHost + + # Raised if Encoders::[] fails because: + # * a file could not be found + # * the requested Plugin is not registered + PluginNotFound = Class.new LoadError + HostNotFound = Class.new LoadError + + PLUGIN_HOSTS = [] + PLUGIN_HOSTS_BY_ID = {} # dummy hash + + # Loads all plugins using list and load. + def load_all + for plugin in list + load plugin + end + end + + # Returns the Plugin for +id+. + # + # Example: + # yaml_plugin = MyPluginHost[:yaml] + def [] id, *args, &blk + plugin = validate_id(id) + begin + plugin = plugin_hash.[](plugin, *args, &blk) + end while plugin.is_a? String + plugin + end + + alias load [] + + # Tries to +load+ the missing plugin by translating +const+ to the + # underscore form (eg. LinesOfCode becomes lines_of_code). + def const_missing const + id = const.to_s. + gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). + gsub(/([a-z\d])([A-Z])/,'\1_\2'). + downcase + load id + end + + class << self + + # Adds the module/class to the PLUGIN_HOSTS list. + def extended mod + PLUGIN_HOSTS << mod + end + + end + + # The path where the plugins can be found. + def plugin_path *args + unless args.empty? + @plugin_path = File.expand_path File.join(*args) + end + @plugin_path ||= '' + end + + # Map a plugin_id to another. + # + # Usage: Put this in a file plugin_path/_map.rb. + # + # class MyColorHost < PluginHost + # map :navy => :dark_blue, + # :maroon => :brown, + # :luna => :moon + # end + def map hash + for from, to in hash + from = validate_id from + to = validate_id to + plugin_hash[from] = to unless plugin_hash.has_key? from + end + end + + # Define the default plugin to use when no plugin is found + # for a given id, or return the default plugin. + # + # See also map. + # + # class MyColorHost < PluginHost + # map :navy => :dark_blue + # default :gray + # end + # + # MyColorHost.default # loads and returns the Gray plugin + def default id = nil + if id + id = validate_id id + raise "The default plugin can't be named \"default\"." if id == :default + plugin_hash[:default] = id + else + load :default + end + end + + # Every plugin must register itself for +id+ by calling register_for, + # which calls this method. + # + # See Plugin#register_for. + def register plugin, id + plugin_hash[validate_id(id)] = plugin + end + + # A Hash of plugion_id => Plugin pairs. + def plugin_hash + @plugin_hash ||= (@plugin_hash = make_plugin_hash).tap { load_plugin_map } + end + + # Returns an array of all .rb files in the plugin path. + # + # The extension .rb is not included. + def list + Dir[path_to('*')].select do |file| + File.basename(file)[/^(?!_)\w+\.rb$/] + end.map do |file| + File.basename(file, '.rb').to_sym + end + end + + # Returns an array of all Plugins. + # + # Note: This loads all plugins using load_all. + def all_plugins + load_all + plugin_hash.values.grep(Class) + end + + # Loads the map file (see map). + # + # This is done automatically when plugin_path is called. + def load_plugin_map + mapfile = path_to '_map' + if File.exist? mapfile + require mapfile + true + else + false + end + end + + protected + + # Return a plugin hash that automatically loads plugins. + def make_plugin_hash + Hash.new do |h, plugin_id| + id = validate_id(plugin_id) + path = path_to id + begin + require path + rescue LoadError => boom + if h.has_key?(:default) + h[:default] + else + raise PluginNotFound, '%p could not load plugin %p: %s' % [self, id, boom] + end + else + # Plugin should have registered by now + if h.has_key? id + h[id] + else + raise PluginNotFound, "No #{self.name} plugin for #{id.inspect} found in #{path}." + end + end + end + end + + # Returns the expected path to the plugin file for the given id. + def path_to plugin_id + File.join plugin_path, "#{plugin_id}.rb" + end + + # Converts +id+ to a valid plugin ID String, or returns +nil+. + # + # Raises +ArgumentError+ for all other objects, or if the + # given String includes non-alphanumeric characters (\W). + def validate_id id + case id + when Symbol + id.to_s + when String + if id[/\w+/] == id + id.downcase + else + raise ArgumentError, "Invalid id given: #{id}" + end + else + raise ArgumentError, "Symbol or String expected, but #{id.class} given." + end + end + + end + + + # = Plugin + # + # Plugins have to include this module. + # + # IMPORTANT: Use extend for this module. + # + # See CodeRay::PluginHost for examples. + module Plugin + + attr_reader :plugin_id + + # Register this class for the given +id+. + # + # Example: + # class MyPlugin < PluginHost::BaseClass + # register_for :my_id + # ... + # end + # + # See PluginHost.register. + def register_for id + @plugin_id = id + plugin_host.register self, id + end + + # Returns the title of the plugin, or sets it to the + # optional argument +title+. + def title title = nil + if title + @title = title.to_s + else + @title ||= name[/([^:]+)$/, 1] + end + end + + # The PluginHost for this Plugin class. + def plugin_host host = nil + if host.is_a? PluginHost + const_set :PLUGIN_HOST, host + end + self::PLUGIN_HOST + end + + def aliases + plugin_host.plugin_hash.inject [] do |aliases, (key, _)| + aliases << key if plugin_host[key] == self + aliases + end + end + + end + +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/helpers/word_list.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/helpers/word_list.rb new file mode 100644 index 0000000..4a42c4a --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/helpers/word_list.rb @@ -0,0 +1,72 @@ +module CodeRay + + # = WordList + # + # A Hash subclass designed for mapping word lists to token types. + # + # A WordList is a Hash with some additional features. + # It is intended to be used for keyword recognition. + # + # WordList is optimized to be used in Scanners, + # typically to decide whether a given ident is a special token. + # + # For case insensitive words use WordList::CaseIgnoring. + # + # Example: + # + # # define word arrays + # RESERVED_WORDS = %w[ + # asm break case continue default do else + # ] + # + # PREDEFINED_TYPES = %w[ + # int long short char void + # ] + # + # # make a WordList + # IDENT_KIND = WordList.new(:ident). + # add(RESERVED_WORDS, :reserved). + # add(PREDEFINED_TYPES, :predefined_type) + # + # ... + # + # def scan_tokens tokens, options + # ... + # + # elsif scan(/[A-Za-z_][A-Za-z_0-9]*/) + # # use it + # kind = IDENT_KIND[match] + # ... + class WordList < Hash + + # Create a new WordList with +default+ as default value. + def initialize default = false + super default + end + + # Add words to the list and associate them with +value+. + # + # Returns +self+, so you can concat add calls. + def add words, value = true + words.each { |word| self[word] = value } + self + end + + end + + + # A CaseIgnoring WordList is like a WordList, only that + # keys are compared case-insensitively (normalizing keys using +downcase+). + class WordList::CaseIgnoring < WordList + + def [] key + super key.downcase + end + + def []= key, value + super key.downcase, value + end + + end + +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanner.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanner.rb new file mode 100644 index 0000000..b3f7e17 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanner.rb @@ -0,0 +1,355 @@ +# encoding: utf-8 +require 'strscan' + +module CodeRay + + autoload :WordList, coderay_path('helpers', 'word_list') + + # = Scanners + # + # This module holds the Scanner class and its subclasses. + # For example, the Ruby scanner is named CodeRay::Scanners::Ruby + # can be found in coderay/scanners/ruby. + # + # Scanner also provides methods and constants for the register + # mechanism and the [] method that returns the Scanner class + # belonging to the given lang. + # + # See PluginHost. + module Scanners + extend PluginHost + plugin_path File.dirname(__FILE__), 'scanners' + + + # = Scanner + # + # The base class for all Scanners. + # + # It is a subclass of Ruby's great +StringScanner+, which + # makes it easy to access the scanning methods inside. + # + # It is also +Enumerable+, so you can use it like an Array of + # Tokens: + # + # require 'coderay' + # + # c_scanner = CodeRay::Scanners[:c].new "if (*p == '{') nest++;" + # + # for text, kind in c_scanner + # puts text if kind == :operator + # end + # + # # prints: (*==)++; + # + # OK, this is a very simple example :) + # You can also use +map+, +any?+, +find+ and even +sort_by+, + # if you want. + class Scanner < StringScanner + + extend Plugin + plugin_host Scanners + + # Raised if a Scanner fails while scanning + ScanError = Class.new StandardError + + # The default options for all scanner classes. + # + # Define @default_options for subclasses. + DEFAULT_OPTIONS = { } + + KINDS_NOT_LOC = [:comment, :doctype, :docstring] + + attr_accessor :state + + class << self + + # Normalizes the given code into a string with UNIX newlines, in the + # scanner's internal encoding, with invalid and undefined charachters + # replaced by placeholders. Always returns a new object. + def normalize code + # original = code + code = code.to_s unless code.is_a? ::String + return code if code.empty? + + if code.respond_to? :encoding + code = encode_with_encoding code, self.encoding + else + code = to_unix code + end + # code = code.dup if code.eql? original + code + end + + # The typical filename suffix for this scanner's language. + def file_extension extension = lang + @file_extension ||= extension.to_s + end + + # The encoding used internally by this scanner. + def encoding name = 'UTF-8' + @encoding ||= defined?(Encoding.find) && Encoding.find(name) + end + + # The lang of this Scanner class, which is equal to its Plugin ID. + def lang + @plugin_id + end + + protected + + def encode_with_encoding code, target_encoding + if code.encoding == target_encoding + if code.valid_encoding? + return to_unix(code) + else + source_encoding = guess_encoding code + end + else + source_encoding = code.encoding + end + # print "encode_with_encoding from #{source_encoding} to #{target_encoding}" + code.encode target_encoding, source_encoding, :universal_newline => true, :undef => :replace, :invalid => :replace + end + + def to_unix code + code.index(?\r) ? code.gsub(/\r\n?/, "\n") : code + end + + def guess_encoding s + #:nocov: + IO.popen("file -b --mime -", "w+") do |file| + file.write s[0, 1024] + file.close_write + begin + Encoding.find file.gets[/charset=([-\w]+)/, 1] + rescue ArgumentError + Encoding::BINARY + end + end + #:nocov: + end + + end + + # Create a new Scanner. + # + # * +code+ is the input String and is handled by the superclass + # StringScanner. + # * +options+ is a Hash with Symbols as keys. + # It is merged with the default options of the class (you can + # overwrite default options here.) + # + # Else, a Tokens object is used. + def initialize code = '', options = {} + if self.class == Scanner + raise NotImplementedError, "I am only the basic Scanner class. I can't scan anything. :( Use my subclasses." + end + + @options = self.class::DEFAULT_OPTIONS.merge options + + super self.class.normalize(code) + + @tokens = options[:tokens] || Tokens.new + @tokens.scanner = self if @tokens.respond_to? :scanner= + + setup + end + + # Sets back the scanner. Subclasses should redefine the reset_instance + # method instead of this one. + def reset + super + reset_instance + end + + # Set a new string to be scanned. + def string= code + code = self.class.normalize(code) + super code + reset_instance + end + + # the Plugin ID for this scanner + def lang + self.class.lang + end + + # the default file extension for this scanner + def file_extension + self.class.file_extension + end + + # Scan the code and returns all tokens in a Tokens object. + def tokenize source = nil, options = {} + options = @options.merge(options) + + set_tokens_from_options options + set_string_from_source source + + begin + scan_tokens @tokens, options + rescue => e + message = "Error in %s#scan_tokens, initial state was: %p" % [self.class, defined?(state) && state] + raise_inspect e.message, @tokens, message, 30, e.backtrace + end + + @cached_tokens = @tokens + if source.is_a? Array + @tokens.split_into_parts(*source.map { |part| part.size }) + else + @tokens + end + end + + # Cache the result of tokenize. + def tokens + @cached_tokens ||= tokenize + end + + # Traverse the tokens. + def each &block + tokens.each(&block) + end + include Enumerable + + # The current line position of the scanner, starting with 1. + # See also: #column. + # + # Beware, this is implemented inefficiently. It should be used + # for debugging only. + def line pos = self.pos + return 1 if pos <= 0 + binary_string[0...pos].count("\n") + 1 + end + + # The current column position of the scanner, starting with 1. + # See also: #line. + def column pos = self.pos + return 1 if pos <= 0 + pos - (binary_string.rindex(?\n, pos - 1) || -1) + end + + # The string in binary encoding. + # + # To be used with #pos, which is the index of the byte the scanner + # will scan next. + def binary_string + @binary_string ||= + if string.respond_to?(:bytesize) && string.bytesize != string.size + #:nocov: + string.dup.force_encoding('binary') + #:nocov: + else + string + end + end + + protected + + # Can be implemented by subclasses to do some initialization + # that has to be done once per instance. + # + # Use reset for initialization that has to be done once per + # scan. + def setup # :doc: + end + + def set_string_from_source source + case source + when Array + self.string = self.class.normalize(source.join) + when nil + reset + else + self.string = self.class.normalize(source) + end + end + + def set_tokens_from_options options + @tokens = options[:tokens] || @tokens || Tokens.new + @tokens.scanner = self if @tokens.respond_to? :scanner= + end + + # This is the central method, and commonly the only one a + # subclass implements. + # + # Subclasses must implement this method; it must return +tokens+ + # and must only use Tokens#<< for storing scanned tokens! + def scan_tokens tokens, options # :doc: + raise NotImplementedError, "#{self.class}#scan_tokens not implemented." + end + + # Resets the scanner. + def reset_instance + @tokens.clear if @tokens.respond_to?(:clear) && !@options[:keep_tokens] + @cached_tokens = nil + @binary_string = nil if defined? @binary_string + end + + SCAN_ERROR_MESSAGE = <<-MESSAGE + + +***ERROR in %s: %s (after %s tokens) + +tokens: +%s + +%s + +surrounding code: +%p ~~ %p + + +***ERROR*** + + MESSAGE + + def raise_inspect_arguments message, tokens, state, ambit + return File.basename(caller[0]), + message, + tokens_size(tokens), + tokens_last(tokens, 10).map(&:inspect).join("\n"), + scanner_state_info(state), + binary_string[pos - ambit, ambit], + binary_string[pos, ambit] + end + + SCANNER_STATE_INFO = <<-INFO +current line: %d column: %d pos: %d +matched: %p state: %p +bol?: %p, eos?: %p + INFO + + def scanner_state_info state + SCANNER_STATE_INFO % [ + line, column, pos, + matched, state || 'No state given!', + bol?, eos?, + ] + end + + # Scanner error with additional status information + def raise_inspect message, tokens, state = self.state, ambit = 30, backtrace = caller + raise ScanError, SCAN_ERROR_MESSAGE % raise_inspect_arguments(message, tokens, state, ambit), backtrace + end + + def tokens_size tokens + tokens.size if tokens.respond_to?(:size) + end + + def tokens_last tokens, n + tokens.respond_to?(:last) ? tokens.last(n) : [] + end + + # Shorthand for scan_until(/\z/). + # This method also avoids a JRuby 1.9 mode bug. + def scan_rest + rest = self.rest + terminate + rest + end + + end + + end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/_map.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/_map.rb new file mode 100644 index 0000000..a240298 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/_map.rb @@ -0,0 +1,24 @@ +module CodeRay +module Scanners + + map \ + :'c++' => :cpp, + :cplusplus => :cpp, + :ecmascript => :java_script, + :ecma_script => :java_script, + :rhtml => :erb, + :eruby => :erb, + :irb => :ruby, + :javascript => :java_script, + :js => :java_script, + :pascal => :delphi, + :patch => :diff, + :plain => :text, + :plaintext => :text, + :xhtml => :html, + :yml => :yaml + + default :text + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/c.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/c.rb new file mode 100644 index 0000000..84b6e8e --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/c.rb @@ -0,0 +1,189 @@ +module CodeRay +module Scanners + + # Scanner for C. + class C < Scanner + + register_for :c + file_extension 'c' + + KEYWORDS = [ + 'asm', 'break', 'case', 'continue', 'default', 'do', + 'else', 'enum', 'for', 'goto', 'if', 'return', + 'sizeof', 'struct', 'switch', 'typedef', 'union', 'while', + 'restrict', # added in C99 + ] # :nodoc: + + PREDEFINED_TYPES = [ + 'int', 'long', 'short', 'char', + 'signed', 'unsigned', 'float', 'double', + 'bool', 'complex', # added in C99 + ] # :nodoc: + + PREDEFINED_CONSTANTS = [ + 'EOF', 'NULL', + 'true', 'false', # added in C99 + ] # :nodoc: + DIRECTIVES = [ + 'auto', 'extern', 'register', 'static', 'void', + 'const', 'volatile', # added in C89 + 'inline', # added in C99 + ] # :nodoc: + + IDENT_KIND = WordList.new(:ident). + add(KEYWORDS, :keyword). + add(PREDEFINED_TYPES, :predefined_type). + add(DIRECTIVES, :directive). + add(PREDEFINED_CONSTANTS, :predefined_constant) # :nodoc: + + ESCAPE = / [rbfntv\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x # :nodoc: + UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x # :nodoc: + + protected + + def scan_tokens encoder, options + + state = :initial + label_expected = true + case_expected = false + label_expected_before_preproc_line = nil + in_preproc_line = false + + until eos? + + case state + + when :initial + + if match = scan(/ \s+ | \\\n /x) + if in_preproc_line && match != "\\\n" && match.index(?\n) + in_preproc_line = false + label_expected = label_expected_before_preproc_line + end + encoder.text_token match, :space + + elsif match = scan(%r! // [^\n\\]* (?: \\. [^\n\\]* )* | /\* (?: .*? \*/ | .* ) !mx) + encoder.text_token match, :comment + + elsif match = scan(/ [-+*=<>?:;,!&^|()\[\]{}~%]+ | \/=? | \.(?!\d) /x) + label_expected = match =~ /[;\{\}]/ + if case_expected + label_expected = true if match == ':' + case_expected = false + end + encoder.text_token match, :operator + + elsif match = scan(/ [A-Za-z_][A-Za-z_0-9]* /x) + kind = IDENT_KIND[match] + if kind == :ident && label_expected && !in_preproc_line && scan(/:(?!:)/) + kind = :label + match << matched + else + label_expected = false + if kind == :keyword + case match + when 'case', 'default' + case_expected = true + end + end + end + encoder.text_token match, kind + + elsif match = scan(/L?"/) + encoder.begin_group :string + if match[0] == ?L + encoder.text_token 'L', :modifier + match = '"' + end + encoder.text_token match, :delimiter + state = :string + + elsif match = scan(/ \# \s* if \s* 0 /x) + match << scan_until(/ ^\# (?:elif|else|endif) .*? $ | \z /xm) unless eos? + encoder.text_token match, :comment + + elsif match = scan(/#[ \t]*(\w*)/) + encoder.text_token match, :preprocessor + in_preproc_line = true + label_expected_before_preproc_line = label_expected + state = :include_expected if self[1] == 'include' + + elsif match = scan(/ L?' (?: [^\'\n\\] | \\ #{ESCAPE} )? '? /ox) + label_expected = false + encoder.text_token match, :char + + elsif match = scan(/\$/) + encoder.text_token match, :ident + + elsif match = scan(/0[xX][0-9A-Fa-f]+/) + label_expected = false + encoder.text_token match, :hex + + elsif match = scan(/(?:0[0-7]+)(?![89.eEfF])/) + label_expected = false + encoder.text_token match, :octal + + elsif match = scan(/(?:\d+)(?![.eEfF])L?L?/) + label_expected = false + encoder.text_token match, :integer + + elsif match = scan(/\d[fF]?|\d*\.\d+(?:[eE][+-]?\d+)?[fF]?|\d+[eE][+-]?\d+[fF]?/) + label_expected = false + encoder.text_token match, :float + + else + encoder.text_token getch, :error + + end + + when :string + if match = scan(/[^\\\n"]+/) + encoder.text_token match, :content + elsif match = scan(/"/) + encoder.text_token match, :delimiter + encoder.end_group :string + state = :initial + label_expected = false + elsif match = scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox) + encoder.text_token match, :char + elsif match = scan(/ \\ | $ /x) + encoder.end_group :string + encoder.text_token match, :error unless match.empty? + state = :initial + label_expected = false + else + raise_inspect "else case \" reached; %p not handled." % peek(1), encoder + end + + when :include_expected + if match = scan(/<[^>\n]+>?|"[^"\n\\]*(?:\\.[^"\n\\]*)*"?/) + encoder.text_token match, :include + state = :initial + + elsif match = scan(/\s+/) + encoder.text_token match, :space + state = :initial if match.index ?\n + + else + state = :initial + + end + + else + raise_inspect 'Unknown state', encoder + + end + + end + + if state == :string + encoder.end_group :string + end + + encoder + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/clojure.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/clojure.rb new file mode 100644 index 0000000..f8fbf65 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/clojure.rb @@ -0,0 +1,217 @@ +# encoding: utf-8 +module CodeRay + module Scanners + + # Clojure scanner by Licenser. + class Clojure < Scanner + + register_for :clojure + file_extension 'clj' + + SPECIAL_FORMS = %w[ + def if do let quote var fn loop recur throw try catch monitor-enter monitor-exit . + new + ] # :nodoc: + + CORE_FORMS = %w[ + + - -> ->> .. / * <= < = == >= > accessor aclone add-classpath add-watch + agent agent-error agent-errors aget alength alias all-ns alter alter-meta! + alter-var-root amap ancestors and apply areduce array-map aset aset-boolean + aset-byte aset-char aset-double aset-float aset-int aset-long aset-short + assert assoc assoc! assoc-in associative? atom await await-for bases bean + bigdec bigint binding bit-and bit-and-not bit-clear bit-flip bit-not bit-or + bit-set bit-shift-left bit-shift-right bit-test bit-xor boolean boolean-array + booleans bound-fn bound-fn* bound? butlast byte byte-array bytes case cast char + char-array char-escape-string char-name-string char? chars class class? + clear-agent-errors clojure-version coll? comment commute comp comparator + compare compare-and-set! compile complement concat cond condp conj conj! + cons constantly construct-proxy contains? count counted? create-ns + create-struct cycle dec decimal? declare definline defmacro defmethod defmulti + defn defn- defonce defprotocol defrecord defstruct deftype delay delay? + deliver denominator deref derive descendants disj disj! dissoc dissoc! + distinct distinct? doall doc dorun doseq dosync dotimes doto double + double-array doubles drop drop-last drop-while empty empty? ensure + enumeration-seq error-handler error-mode eval even? every? extend + extend-protocol extend-type extenders extends? false? ffirst file-seq + filter find find-doc find-ns find-var first float float-array float? + floats flush fn fn? fnext for force format future future-call future-cancel + future-cancelled? future-done? future? gen-class gen-interface gensym get + get-in get-method get-proxy-class get-thread-bindings get-validator hash + hash-map hash-set identical? identity if-let if-not ifn? import in-ns + inc init-proxy instance? int int-array integer? interleave intern + interpose into into-array ints io! isa? iterate iterator-seq juxt key + keys keyword keyword? last lazy-cat lazy-seq let letfn line-seq list list* + list? load load-file load-reader load-string loaded-libs locking long + long-array longs loop macroexpand macroexpand-1 make-array make-hierarchy + map map? mapcat max max-key memfn memoize merge merge-with meta methods + min min-key mod name namespace neg? newline next nfirst nil? nnext not + not-any? not-empty not-every? not= ns ns-aliases ns-imports ns-interns + ns-map ns-name ns-publics ns-refers ns-resolve ns-unalias ns-unmap nth + nthnext num number? numerator object-array odd? or parents partial + partition pcalls peek persistent! pmap pop pop! pop-thread-bindings + pos? pr pr-str prefer-method prefers print print-namespace-doc + print-str printf println println-str prn prn-str promise proxy + proxy-mappings proxy-super push-thread-bindings pvalues quot rand + rand-int range ratio? rationalize re-find re-groups re-matcher + re-matches re-pattern re-seq read read-line read-string reduce ref + ref-history-count ref-max-history ref-min-history ref-set refer + refer-clojure reify release-pending-sends rem remove remove-all-methods + remove-method remove-ns remove-watch repeat repeatedly replace replicate + require reset! reset-meta! resolve rest restart-agent resultset-seq + reverse reversible? rseq rsubseq satisfies? second select-keys send + send-off seq seq? seque sequence sequential? set set-error-handler! + set-error-mode! set-validator! set? short short-array shorts + shutdown-agents slurp some sort sort-by sorted-map sorted-map-by + sorted-set sorted-set-by sorted? special-form-anchor special-symbol? + split-at split-with str string? struct struct-map subs subseq subvec + supers swap! symbol symbol? sync syntax-symbol-anchor take take-last + take-nth take-while test the-ns thread-bound? time to-array to-array-2d + trampoline transient tree-seq true? type unchecked-add unchecked-dec + unchecked-divide unchecked-inc unchecked-multiply unchecked-negate + unchecked-remainder unchecked-subtract underive update-in update-proxy + use val vals var-get var-set var? vary-meta vec vector vector-of vector? + when when-first when-let when-not while with-bindings with-bindings* + with-in-str with-local-vars with-meta with-open with-out-str + with-precision xml-seq zero? zipmap + ] # :nodoc: + + PREDEFINED_CONSTANTS = %w[ + true false nil *1 *2 *3 *agent* *clojure-version* *command-line-args* + *compile-files* *compile-path* *e *err* *file* *flush-on-newline* + *in* *ns* *out* *print-dup* *print-length* *print-level* *print-meta* + *print-readably* *read-eval* *warn-on-reflection* + ] # :nodoc: + + IDENT_KIND = WordList.new(:ident). + add(SPECIAL_FORMS, :keyword). + add(CORE_FORMS, :keyword). + add(PREDEFINED_CONSTANTS, :predefined_constant) + + KEYWORD_NEXT_TOKEN_KIND = WordList.new(nil). + add(%w[ def defn defn- definline defmacro defmulti defmethod defstruct defonce declare ], :function). + add(%w[ ns ], :namespace). + add(%w[ defprotocol defrecord ], :class) + + BASIC_IDENTIFIER = /[a-zA-Z$%*\/_+!?&<>\-=]=?[a-zA-Z0-9$&*+!\/_?<>\-\#]*/ + IDENTIFIER = /(?!-\d)(?:(?:#{BASIC_IDENTIFIER}\.)*#{BASIC_IDENTIFIER}(?:\/#{BASIC_IDENTIFIER})?\.?)|\.\.?/ + SYMBOL = /::?#{IDENTIFIER}/o + DIGIT = /\d/ + DIGIT10 = DIGIT + DIGIT16 = /[0-9a-f]/i + DIGIT8 = /[0-7]/ + DIGIT2 = /[01]/ + RADIX16 = /\#x/i + RADIX8 = /\#o/i + RADIX2 = /\#b/i + RADIX10 = /\#d/i + EXACTNESS = /#i|#e/i + SIGN = /[\+-]?/ + EXP_MARK = /[esfdl]/i + EXP = /#{EXP_MARK}#{SIGN}#{DIGIT}+/ + SUFFIX = /#{EXP}?/ + PREFIX10 = /#{RADIX10}?#{EXACTNESS}?|#{EXACTNESS}?#{RADIX10}?/ + PREFIX16 = /#{RADIX16}#{EXACTNESS}?|#{EXACTNESS}?#{RADIX16}/ + PREFIX8 = /#{RADIX8}#{EXACTNESS}?|#{EXACTNESS}?#{RADIX8}/ + PREFIX2 = /#{RADIX2}#{EXACTNESS}?|#{EXACTNESS}?#{RADIX2}/ + UINT10 = /#{DIGIT10}+#*/ + UINT16 = /#{DIGIT16}+#*/ + UINT8 = /#{DIGIT8}+#*/ + UINT2 = /#{DIGIT2}+#*/ + DECIMAL = /#{DIGIT10}+#+\.#*#{SUFFIX}|#{DIGIT10}+\.#{DIGIT10}*#*#{SUFFIX}|\.#{DIGIT10}+#*#{SUFFIX}|#{UINT10}#{EXP}/ + UREAL10 = /#{UINT10}\/#{UINT10}|#{DECIMAL}|#{UINT10}/ + UREAL16 = /#{UINT16}\/#{UINT16}|#{UINT16}/ + UREAL8 = /#{UINT8}\/#{UINT8}|#{UINT8}/ + UREAL2 = /#{UINT2}\/#{UINT2}|#{UINT2}/ + REAL10 = /#{SIGN}#{UREAL10}/ + REAL16 = /#{SIGN}#{UREAL16}/ + REAL8 = /#{SIGN}#{UREAL8}/ + REAL2 = /#{SIGN}#{UREAL2}/ + IMAG10 = /i|#{UREAL10}i/ + IMAG16 = /i|#{UREAL16}i/ + IMAG8 = /i|#{UREAL8}i/ + IMAG2 = /i|#{UREAL2}i/ + COMPLEX10 = /#{REAL10}@#{REAL10}|#{REAL10}\+#{IMAG10}|#{REAL10}-#{IMAG10}|\+#{IMAG10}|-#{IMAG10}|#{REAL10}/ + COMPLEX16 = /#{REAL16}@#{REAL16}|#{REAL16}\+#{IMAG16}|#{REAL16}-#{IMAG16}|\+#{IMAG16}|-#{IMAG16}|#{REAL16}/ + COMPLEX8 = /#{REAL8}@#{REAL8}|#{REAL8}\+#{IMAG8}|#{REAL8}-#{IMAG8}|\+#{IMAG8}|-#{IMAG8}|#{REAL8}/ + COMPLEX2 = /#{REAL2}@#{REAL2}|#{REAL2}\+#{IMAG2}|#{REAL2}-#{IMAG2}|\+#{IMAG2}|-#{IMAG2}|#{REAL2}/ + NUM10 = /#{PREFIX10}?#{COMPLEX10}/ + NUM16 = /#{PREFIX16}#{COMPLEX16}/ + NUM8 = /#{PREFIX8}#{COMPLEX8}/ + NUM2 = /#{PREFIX2}#{COMPLEX2}/ + NUM = /#{NUM10}|#{NUM16}|#{NUM8}|#{NUM2}/ + + protected + + def scan_tokens encoder, options + + state = :initial + kind = nil + + until eos? + + case state + when :initial + if match = scan(/ \s+ | \\\n | , /x) + encoder.text_token match, :space + elsif match = scan(/['`\(\[\)\]\{\}]|\#[({]|~@?|[@\^]/) + encoder.text_token match, :operator + elsif match = scan(/;.*/) + encoder.text_token match, :comment # TODO: recognize (comment ...) too + elsif match = scan(/\#?\\(?:newline|space|.?)/) + encoder.text_token match, :char + elsif match = scan(/\#[ft]/) + encoder.text_token match, :predefined_constant + elsif match = scan(/#{IDENTIFIER}/o) + kind = IDENT_KIND[match] + encoder.text_token match, kind + if rest? && kind == :keyword + if kind = KEYWORD_NEXT_TOKEN_KIND[match] + encoder.text_token match, :space if match = scan(/\s+/o) + encoder.text_token match, kind if match = scan(/#{IDENTIFIER}/o) + end + end + elsif match = scan(/#{SYMBOL}/o) + encoder.text_token match, :symbol + elsif match = scan(/\./) + encoder.text_token match, :operator + elsif match = scan(/ \# \^ #{IDENTIFIER} /ox) + encoder.text_token match, :type + elsif match = scan(/ (\#)? " /x) + state = self[1] ? :regexp : :string + encoder.begin_group state + encoder.text_token match, :delimiter + elsif match = scan(/#{NUM}/o) and not matched.empty? + encoder.text_token match, match[/[.e\/]/i] ? :float : :integer + else + encoder.text_token getch, :error + end + + when :string, :regexp + if match = scan(/[^"\\]+|\\.?/) + encoder.text_token match, :content + elsif match = scan(/"/) + encoder.text_token match, :delimiter + encoder.end_group state + state = :initial + else + raise_inspect "else case \" reached; %p not handled." % peek(1), + encoder, state + end + + else + raise 'else case reached' + + end + + end + + if [:string, :regexp].include? state + encoder.end_group state + end + + encoder + + end + end + end +end \ No newline at end of file diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/cpp.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/cpp.rb new file mode 100644 index 0000000..e61f56f --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/cpp.rb @@ -0,0 +1,215 @@ +module CodeRay +module Scanners + + # Scanner for C++. + # + # Aliases: +cplusplus+, c++ + class CPlusPlus < Scanner + + register_for :cpp + file_extension 'cpp' + title 'C++' + + #-- http://www.cppreference.com/wiki/keywords/start + KEYWORDS = [ + 'and', 'and_eq', 'asm', 'bitand', 'bitor', 'break', + 'case', 'catch', 'class', 'compl', 'const_cast', + 'continue', 'default', 'delete', 'do', 'dynamic_cast', 'else', + 'enum', 'export', 'for', 'goto', 'if', 'namespace', 'new', + 'not', 'not_eq', 'or', 'or_eq', 'reinterpret_cast', 'return', + 'sizeof', 'static_cast', 'struct', 'switch', 'template', + 'throw', 'try', 'typedef', 'typeid', 'typename', 'union', + 'while', 'xor', 'xor_eq', + ] # :nodoc: + + PREDEFINED_TYPES = [ + 'bool', 'char', 'double', 'float', 'int', 'long', + 'short', 'signed', 'unsigned', 'wchar_t', 'string', + ] # :nodoc: + PREDEFINED_CONSTANTS = [ + 'false', 'true', + 'EOF', 'NULL', + ] # :nodoc: + PREDEFINED_VARIABLES = [ + 'this', + ] # :nodoc: + DIRECTIVES = [ + 'auto', 'const', 'explicit', 'extern', 'friend', 'inline', 'mutable', 'operator', + 'private', 'protected', 'public', 'register', 'static', 'using', 'virtual', 'void', + 'volatile', + ] # :nodoc: + + IDENT_KIND = WordList.new(:ident). + add(KEYWORDS, :keyword). + add(PREDEFINED_TYPES, :predefined_type). + add(PREDEFINED_VARIABLES, :local_variable). + add(DIRECTIVES, :directive). + add(PREDEFINED_CONSTANTS, :predefined_constant) # :nodoc: + + ESCAPE = / [rbfntv\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x # :nodoc: + UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x # :nodoc: + + protected + + def scan_tokens encoder, options + + state = :initial + label_expected = true + case_expected = false + label_expected_before_preproc_line = nil + in_preproc_line = false + + until eos? + + case state + + when :initial + + if match = scan(/ \s+ | \\\n /x) + if in_preproc_line && match != "\\\n" && match.index(?\n) + in_preproc_line = false + label_expected = label_expected_before_preproc_line + end + encoder.text_token match, :space + + elsif match = scan(%r! // [^\n\\]* (?: \\. [^\n\\]* )* | /\* (?: .*? \*/ | .* ) !mx) + encoder.text_token match, :comment + + elsif match = scan(/ \# \s* if \s* 0 /x) + match << scan_until(/ ^\# (?:elif|else|endif) .*? $ | \z /xm) unless eos? + encoder.text_token match, :comment + + elsif match = scan(/ [-+*=<>?:;,!&^|()\[\]{}~%]+ | \/=? | \.(?!\d) /x) + label_expected = match =~ /[;\{\}]/ + if case_expected + label_expected = true if match == ':' + case_expected = false + end + encoder.text_token match, :operator + + elsif match = scan(/ [A-Za-z_][A-Za-z_0-9]* /x) + kind = IDENT_KIND[match] + if kind == :ident && label_expected && !in_preproc_line && scan(/:(?!:)/) + kind = :label + match << matched + else + label_expected = false + if kind == :keyword + case match + when 'class' + state = :class_name_expected + when 'case', 'default' + case_expected = true + end + end + end + encoder.text_token match, kind + + elsif match = scan(/\$/) + encoder.text_token match, :ident + + elsif match = scan(/L?"/) + encoder.begin_group :string + if match[0] == ?L + encoder.text_token match, 'L', :modifier + match = '"' + end + state = :string + encoder.text_token match, :delimiter + + elsif match = scan(/#[ \t]*(\w*)/) + encoder.text_token match, :preprocessor + in_preproc_line = true + label_expected_before_preproc_line = label_expected + state = :include_expected if self[1] == 'include' + + elsif match = scan(/ L?' (?: [^\'\n\\] | \\ #{ESCAPE} )? '? /ox) + label_expected = false + encoder.text_token match, :char + + elsif match = scan(/0[xX][0-9A-Fa-f]+/) + label_expected = false + encoder.text_token match, :hex + + elsif match = scan(/(?:0[0-7]+)(?![89.eEfF])/) + label_expected = false + encoder.text_token match, :octal + + elsif match = scan(/(?:\d+)(?![.eEfF])L?L?/) + label_expected = false + encoder.text_token match, :integer + + elsif match = scan(/\d[fF]?|\d*\.\d+(?:[eE][+-]?\d+)?[fF]?|\d+[eE][+-]?\d+[fF]?/) + label_expected = false + encoder.text_token match, :float + + else + encoder.text_token getch, :error + + end + + when :string + if match = scan(/[^\\"]+/) + encoder.text_token match, :content + elsif match = scan(/"/) + encoder.text_token match, :delimiter + encoder.end_group :string + state = :initial + label_expected = false + elsif match = scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox) + encoder.text_token match, :char + elsif match = scan(/ \\ | $ /x) + encoder.end_group :string + encoder.text_token match, :error unless match.empty? + state = :initial + label_expected = false + else + raise_inspect "else case \" reached; %p not handled." % peek(1), encoder + end + + when :include_expected + if match = scan(/<[^>\n]+>?|"[^"\n\\]*(?:\\.[^"\n\\]*)*"?/) + encoder.text_token match, :include + state = :initial + + elsif match = scan(/\s+/) + encoder.text_token match, :space + state = :initial if match.index ?\n + + else + state = :initial + + end + + when :class_name_expected + if match = scan(/ [A-Za-z_][A-Za-z_0-9]* /x) + encoder.text_token match, :class + state = :initial + + elsif match = scan(/\s+/) + encoder.text_token match, :space + + else + encoder.text_token getch, :error + state = :initial + + end + + else + raise_inspect 'Unknown state', encoder + + end + + end + + if state == :string + encoder.end_group :string + end + + encoder + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/css.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/css.rb new file mode 100644 index 0000000..55d5239 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/css.rb @@ -0,0 +1,196 @@ +module CodeRay +module Scanners + + class CSS < Scanner + + register_for :css + + KINDS_NOT_LOC = [ + :comment, + :class, :pseudo_class, :tag, + :id, :directive, + :key, :value, :operator, :color, :float, :string, + :error, :important, :type, + ] # :nodoc: + + module RE # :nodoc: + Hex = /[0-9a-fA-F]/ + Unicode = /\\#{Hex}{1,6}\b/ # differs from standard because it allows uppercase hex too + Escape = /#{Unicode}|\\[^\n0-9a-fA-F]/ + NMChar = /[-_a-zA-Z0-9]/ + NMStart = /[_a-zA-Z]/ + String1 = /"(?:[^\n\\"]+|\\\n|#{Escape})*"?/ # TODO: buggy regexp + String2 = /'(?:[^\n\\']+|\\\n|#{Escape})*'?/ # TODO: buggy regexp + String = /#{String1}|#{String2}/ + + HexColor = /#(?:#{Hex}{6}|#{Hex}{3})/ + + Num = /-?(?:[0-9]*\.[0-9]+|[0-9]+)n?/ + Name = /#{NMChar}+/ + Ident = /-?#{NMStart}#{NMChar}*/ + AtKeyword = /@#{Ident}/ + Percentage = /#{Num}%/ + + reldimensions = %w[em ex px] + absdimensions = %w[in cm mm pt pc] + Unit = Regexp.union(*(reldimensions + absdimensions + %w[s dpi dppx deg])) + + Dimension = /#{Num}#{Unit}/ + + Function = /(?:url|alpha|attr|counters?)\((?:[^)\n]|\\\))*\)?/ + + Id = /(?!#{HexColor}\b(?!-))##{Name}/ + Class = /\.#{Name}/ + PseudoClass = /::?#{Ident}/ + AttributeSelector = /\[[^\]]*\]?/ + end + + protected + + def setup + @state = :initial + @value_expected = false + end + + def scan_tokens encoder, options + states = Array(options[:state] || @state).dup + value_expected = @value_expected + + until eos? + + if match = scan(/\s+/) + encoder.text_token match, :space + + elsif case states.last + when :initial, :media + if match = scan(/(?>#{RE::Ident})(?!\()|\*/ox) + encoder.text_token match, :tag + next + elsif match = scan(RE::Class) + encoder.text_token match, :class + next + elsif match = scan(RE::Id) + encoder.text_token match, :id + next + elsif match = scan(RE::PseudoClass) + encoder.text_token match, :pseudo_class + next + elsif match = scan(RE::AttributeSelector) + # TODO: Improve highlighting inside of attribute selectors. + encoder.text_token match[0,1], :operator + encoder.text_token match[1..-2], :attribute_name if match.size > 2 + encoder.text_token match[-1,1], :operator if match[-1] == ?] + next + elsif match = scan(/@media/) + encoder.text_token match, :directive + states.push :media_before_name + next + end + + when :block + if match = scan(/(?>#{RE::Ident})(?!\()/ox) + if value_expected + encoder.text_token match, :value + else + encoder.text_token match, :key + end + next + end + + when :media_before_name + if match = scan(RE::Ident) + encoder.text_token match, :type + states[-1] = :media_after_name + next + end + + when :media_after_name + if match = scan(/\{/) + encoder.text_token match, :operator + states[-1] = :media + next + end + + else + #:nocov: + raise_inspect 'Unknown state', encoder + #:nocov: + + end + + elsif match = scan(/\/\*(?:.*?\*\/|\z)/m) + encoder.text_token match, :comment + + elsif match = scan(/\{/) + value_expected = false + encoder.text_token match, :operator + states.push :block + + elsif match = scan(/\}/) + value_expected = false + encoder.text_token match, :operator + if states.last == :block || states.last == :media + states.pop + end + + elsif match = scan(/#{RE::String}/o) + encoder.begin_group :string + encoder.text_token match[0, 1], :delimiter + encoder.text_token match[1..-2], :content if match.size > 2 + encoder.text_token match[-1, 1], :delimiter if match.size >= 2 + encoder.end_group :string + + elsif match = scan(/#{RE::Function}/o) + encoder.begin_group :function + start = match[/^\w+\(/] + encoder.text_token start, :delimiter + if match[-1] == ?) + encoder.text_token match[start.size..-2], :content if match.size > start.size + 1 + encoder.text_token ')', :delimiter + else + encoder.text_token match[start.size..-1], :content if match.size > start.size + end + encoder.end_group :function + + elsif match = scan(/(?: #{RE::Dimension} | #{RE::Percentage} | #{RE::Num} )/ox) + encoder.text_token match, :float + + elsif match = scan(/#{RE::HexColor}/o) + encoder.text_token match, :color + + elsif match = scan(/! *important/) + encoder.text_token match, :important + + elsif match = scan(/(?:rgb|hsl)a?\([^()\n]*\)?/) + encoder.text_token match, :color + + elsif match = scan(RE::AtKeyword) + encoder.text_token match, :directive + + elsif match = scan(/ [+>~:;,.=()\/] /x) + if match == ':' + value_expected = true + elsif match == ';' + value_expected = false + end + encoder.text_token match, :operator + + else + encoder.text_token getch, :error + + end + + end + + if options[:keep_state] + @state = states + @value_expected = value_expected + end + + encoder + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/debug.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/debug.rb new file mode 100644 index 0000000..83ede9a --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/debug.rb @@ -0,0 +1,75 @@ +require 'set' + +module CodeRay +module Scanners + + # = Debug Scanner + # + # Interprets the output of the Encoders::Debug encoder (basically the inverse function). + class Debug < Scanner + + register_for :debug + title 'CodeRay Token Dump Import' + + protected + + def setup + super + @known_token_kinds = TokenKinds.keys.map(&:to_s).to_set + end + + def scan_tokens encoder, options + + opened_tokens = [] + + until eos? + + if match = scan(/\s+/) + encoder.text_token match, :space + + elsif match = scan(/ (\w+) \( ( [^\)\\]* ( \\. [^\)\\]* )* ) \)? /x) + if @known_token_kinds.include? self[1] + encoder.text_token self[2].gsub(/\\(.)/m, '\1'), self[1].to_sym + else + encoder.text_token matched, :unknown + end + + elsif match = scan(/ (\w+) ([<\[]) /x) + if @known_token_kinds.include? self[1] + kind = self[1].to_sym + else + kind = :unknown + end + + opened_tokens << kind + case self[2] + when '<' + encoder.begin_group kind + when '[' + encoder.begin_line kind + else + raise 'CodeRay bug: This case should not be reached.' + end + + elsif !opened_tokens.empty? && match = scan(/ > /x) + encoder.end_group opened_tokens.pop + + elsif !opened_tokens.empty? && match = scan(/ \] /x) + encoder.end_line opened_tokens.pop + + else + encoder.text_token getch, :space + + end + + end + + encoder.end_group opened_tokens.pop until opened_tokens.empty? + + encoder + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/delphi.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/delphi.rb new file mode 100644 index 0000000..b328155 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/delphi.rb @@ -0,0 +1,144 @@ +module CodeRay +module Scanners + + # Scanner for the Delphi language (Object Pascal). + # + # Alias: +pascal+ + class Delphi < Scanner + + register_for :delphi + file_extension 'pas' + + KEYWORDS = [ + 'and', 'array', 'as', 'at', 'asm', 'at', 'begin', 'case', 'class', + 'const', 'constructor', 'destructor', 'dispinterface', 'div', 'do', + 'downto', 'else', 'end', 'except', 'exports', 'file', 'finalization', + 'finally', 'for', 'function', 'goto', 'if', 'implementation', 'in', + 'inherited', 'initialization', 'inline', 'interface', 'is', 'label', + 'library', 'mod', 'nil', 'not', 'object', 'of', 'or', 'out', 'packed', + 'procedure', 'program', 'property', 'raise', 'record', 'repeat', + 'resourcestring', 'set', 'shl', 'shr', 'string', 'then', 'threadvar', + 'to', 'try', 'type', 'unit', 'until', 'uses', 'var', 'while', 'with', + 'xor', 'on', + ] # :nodoc: + + DIRECTIVES = [ + 'absolute', 'abstract', 'assembler', 'at', 'automated', 'cdecl', + 'contains', 'deprecated', 'dispid', 'dynamic', 'export', + 'external', 'far', 'forward', 'implements', 'local', + 'near', 'nodefault', 'on', 'overload', 'override', + 'package', 'pascal', 'platform', 'private', 'protected', 'public', + 'published', 'read', 'readonly', 'register', 'reintroduce', + 'requires', 'resident', 'safecall', 'stdcall', 'stored', 'varargs', + 'virtual', 'write', 'writeonly', + ] # :nodoc: + + IDENT_KIND = WordList::CaseIgnoring.new(:ident). + add(KEYWORDS, :keyword). + add(DIRECTIVES, :directive) # :nodoc: + + NAME_FOLLOWS = WordList::CaseIgnoring.new(false). + add(%w(procedure function .)) # :nodoc: + + protected + + def scan_tokens encoder, options + + state = :initial + last_token = '' + + until eos? + + if state == :initial + + if match = scan(/ \s+ /x) + encoder.text_token match, :space + next + + elsif match = scan(%r! \{ \$ [^}]* \}? | \(\* \$ (?: .*? \*\) | .* ) !mx) + encoder.text_token match, :preprocessor + next + + elsif match = scan(%r! // [^\n]* | \{ [^}]* \}? | \(\* (?: .*? \*\) | .* ) !mx) + encoder.text_token match, :comment + next + + elsif match = scan(/ <[>=]? | >=? | :=? | [-+=*\/;,@\^|\(\)\[\]] | \.\. /x) + encoder.text_token match, :operator + + elsif match = scan(/\./) + encoder.text_token match, :operator + next if last_token == 'end' + + elsif match = scan(/ [A-Za-z_][A-Za-z_0-9]* /x) + encoder.text_token match, NAME_FOLLOWS[last_token] ? :ident : IDENT_KIND[match] + + elsif match = skip(/ ' ( [^\n']|'' ) (?:'|$) /x) + encoder.begin_group :char + encoder.text_token "'", :delimiter + encoder.text_token self[1], :content + encoder.text_token "'", :delimiter + encoder.end_group :char + next + + elsif match = scan(/ ' /x) + encoder.begin_group :string + encoder.text_token match, :delimiter + state = :string + + elsif match = scan(/ \# (?: \d+ | \$[0-9A-Fa-f]+ ) /x) + encoder.text_token match, :char + + elsif match = scan(/ \$ [0-9A-Fa-f]+ /x) + encoder.text_token match, :hex + + elsif match = scan(/ (?: \d+ ) (?![eE]|\.[^.]) /x) + encoder.text_token match, :integer + + elsif match = scan(/ \d+ (?: \.\d+ (?: [eE][+-]? \d+ )? | [eE][+-]? \d+ ) /x) + encoder.text_token match, :float + + else + encoder.text_token getch, :error + next + + end + + elsif state == :string + if match = scan(/[^\n']+/) + encoder.text_token match, :content + elsif match = scan(/''/) + encoder.text_token match, :char + elsif match = scan(/'/) + encoder.text_token match, :delimiter + encoder.end_group :string + state = :initial + next + elsif match = scan(/\n/) + encoder.end_group :string + encoder.text_token match, :space + state = :initial + else + raise "else case \' reached; %p not handled." % peek(1), encoder + end + + else + raise 'else-case reached', encoder + + end + + last_token = match + + end + + if state == :string + encoder.end_group state + end + + encoder + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/diff.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/diff.rb new file mode 100644 index 0000000..fd1aed6 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/diff.rb @@ -0,0 +1,221 @@ +module CodeRay +module Scanners + + # Scanner for output of the diff command. + # + # Alias: +patch+ + class Diff < Scanner + + register_for :diff + title 'diff output' + + DEFAULT_OPTIONS = { + :highlight_code => true, + :inline_diff => true, + } + + protected + + def scan_tokens encoder, options + + line_kind = nil + state = :initial + deleted_lines_count = 0 + scanners = Hash.new do |h, lang| + h[lang] = Scanners[lang].new '', :keep_tokens => true, :keep_state => true + end + content_scanner = scanners[:plain] + content_scanner_entry_state = nil + + until eos? + + if match = scan(/\n/) + deleted_lines_count = 0 unless line_kind == :delete + if line_kind + encoder.end_line line_kind + line_kind = nil + end + encoder.text_token match, :space + next + end + + case state + + when :initial + if match = scan(/--- |\+\+\+ |=+|_+/) + encoder.begin_line line_kind = :head + encoder.text_token match, :head + if match = scan(/[^\x00\n]+?(?=$|[\t\n]| \(revision)/) + encoder.text_token match, :filename + if options[:highlight_code] && match != '/dev/null' + file_type = CodeRay::FileType.fetch(match, :text) + file_type = :text if file_type == :diff + content_scanner = scanners[file_type] + content_scanner_entry_state = nil + end + end + next unless match = scan(/.+/) + encoder.text_token match, :plain + elsif match = scan(/Index: |Property changes on: /) + encoder.begin_line line_kind = :head + encoder.text_token match, :head + next unless match = scan(/.+/) + encoder.text_token match, :plain + elsif match = scan(/Added: /) + encoder.begin_line line_kind = :head + encoder.text_token match, :head + next unless match = scan(/.+/) + encoder.text_token match, :plain + state = :added + elsif match = scan(/\\ .*/) + encoder.text_token match, :comment + elsif match = scan(/@@(?>[^@\n]+)@@/) + content_scanner.state = :initial unless match?(/\n\+/) + content_scanner_entry_state = nil + if check(/\n|$/) + encoder.begin_line line_kind = :change + else + encoder.begin_group :change + end + encoder.text_token match[0,2], :change + encoder.text_token match[2...-2], :plain + encoder.text_token match[-2,2], :change + encoder.end_group :change unless line_kind + next unless match = scan(/.+/) + if options[:highlight_code] + content_scanner.tokenize match, :tokens => encoder + else + encoder.text_token match, :plain + end + next + elsif match = scan(/\+/) + encoder.begin_line line_kind = :insert + encoder.text_token match, :insert + next unless match = scan(/.+/) + if options[:highlight_code] + content_scanner.tokenize match, :tokens => encoder + else + encoder.text_token match, :plain + end + next + elsif match = scan(/-/) + deleted_lines_count += 1 + if options[:inline_diff] && deleted_lines_count == 1 && (changed_lines_count = 1 + check(/.*(?:\n\-.*)*/).count("\n")) && match?(/(?>.*(?:\n\-.*){#{changed_lines_count - 1}}(?:\n\+.*){#{changed_lines_count}})$(?!\n\+)/) + deleted_lines = Array.new(changed_lines_count) { |i| skip(/\n\-/) if i > 0; scan(/.*/) } + inserted_lines = Array.new(changed_lines_count) { |i| skip(/\n\+/) ; scan(/.*/) } + + deleted_lines_tokenized = [] + inserted_lines_tokenized = [] + for deleted_line, inserted_line in deleted_lines.zip(inserted_lines) + pre, deleted_part, inserted_part, post = diff deleted_line, inserted_line + content_scanner_entry_state = content_scanner.state + deleted_lines_tokenized << content_scanner.tokenize([pre, deleted_part, post], :tokens => Tokens.new) + content_scanner.state = content_scanner_entry_state || :initial + inserted_lines_tokenized << content_scanner.tokenize([pre, inserted_part, post], :tokens => Tokens.new) + end + + for pre, deleted_part, post in deleted_lines_tokenized + encoder.begin_line :delete + encoder.text_token '-', :delete + encoder.tokens pre + unless deleted_part.empty? + encoder.begin_group :eyecatcher + encoder.tokens deleted_part + encoder.end_group :eyecatcher + end + encoder.tokens post + encoder.end_line :delete + encoder.text_token "\n", :space + end + + for pre, inserted_part, post in inserted_lines_tokenized + encoder.begin_line :insert + encoder.text_token '+', :insert + encoder.tokens pre + unless inserted_part.empty? + encoder.begin_group :eyecatcher + encoder.tokens inserted_part + encoder.end_group :eyecatcher + end + encoder.tokens post + changed_lines_count -= 1 + if changed_lines_count > 0 + encoder.end_line :insert + encoder.text_token "\n", :space + end + end + + line_kind = :insert + + elsif match = scan(/.*/) + encoder.begin_line line_kind = :delete + encoder.text_token '-', :delete + if options[:highlight_code] + if deleted_lines_count == 1 + content_scanner_entry_state = content_scanner.state + end + content_scanner.tokenize match, :tokens => encoder unless match.empty? + if !match?(/\n-/) + if match?(/\n\+/) + content_scanner.state = content_scanner_entry_state || :initial + end + content_scanner_entry_state = nil + end + else + encoder.text_token match, :plain + end + end + next + elsif match = scan(/ .*/) + if options[:highlight_code] + content_scanner.tokenize match, :tokens => encoder + else + encoder.text_token match, :plain + end + next + elsif match = scan(/.+/) + encoder.begin_line line_kind = :comment + encoder.text_token match, :plain + else + raise_inspect 'else case rached' + end + + when :added + if match = scan(/ \+/) + encoder.begin_line line_kind = :insert + encoder.text_token match, :insert + next unless match = scan(/.+/) + encoder.text_token match, :plain + else + state = :initial + next + end + end + + end + + encoder.end_line line_kind if line_kind + + encoder + end + + private + + def diff a, b + # i will be the index of the leftmost difference from the left. + i_max = [a.size, b.size].min + i = 0 + i += 1 while i < i_max && a[i] == b[i] + # j_min will be the index of the leftmost difference from the right. + j_min = i - i_max + # j will be the index of the rightmost difference from the right which + # does not precede the leftmost one from the left. + j = -1 + j -= 1 while j >= j_min && a[j] == b[j] + return a[0...i], a[i..j], b[i..j], (j < -1) ? a[j+1..-1] : '' + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/erb.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/erb.rb new file mode 100644 index 0000000..727a993 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/erb.rb @@ -0,0 +1,81 @@ +module CodeRay +module Scanners + + load :html + load :ruby + + # Scanner for HTML ERB templates. + class ERB < Scanner + + register_for :erb + title 'HTML ERB Template' + + KINDS_NOT_LOC = HTML::KINDS_NOT_LOC + + ERB_RUBY_BLOCK = / + (<%(?!%)[-=\#]?) + ((?> + [^\-%]* # normal* + (?> # special + (?: %(?!>) | -(?!%>) ) + [^\-%]* # normal* + )* + )) + ((?: -?%> )?) + /x # :nodoc: + + START_OF_ERB = / + <%(?!%) + /x # :nodoc: + + protected + + def setup + @ruby_scanner = CodeRay.scanner :ruby, :tokens => @tokens, :keep_tokens => true + @html_scanner = CodeRay.scanner :html, :tokens => @tokens, :keep_tokens => true, :keep_state => true + end + + def reset_instance + super + @html_scanner.reset + end + + def scan_tokens encoder, options + + until eos? + + if (match = scan_until(/(?=#{START_OF_ERB})/o) || scan_rest) and not match.empty? + @html_scanner.tokenize match, :tokens => encoder + + elsif match = scan(/#{ERB_RUBY_BLOCK}/o) + start_tag = self[1] + code = self[2] + end_tag = self[3] + + encoder.begin_group :inline + encoder.text_token start_tag, :inline_delimiter + + if start_tag == '<%#' + encoder.text_token code, :comment + else + @ruby_scanner.tokenize code, :tokens => encoder + end unless code.empty? + + encoder.text_token end_tag, :inline_delimiter unless end_tag.empty? + encoder.end_group :inline + + else + raise_inspect 'else-case reached!', encoder + + end + + end + + encoder + + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/go.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/go.rb new file mode 100644 index 0000000..99fdd63 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/go.rb @@ -0,0 +1,208 @@ +module CodeRay +module Scanners + + class Go < Scanner + + register_for :go + file_extension 'go' + + # http://golang.org/ref/spec#Keywords + KEYWORDS = [ + 'break', 'default', 'func', 'interface', 'select', + 'case', 'defer', 'go', 'map', 'struct', + 'chan', 'else', 'goto', 'package', 'switch', + 'const', 'fallthrough', 'if', 'range', 'type', + 'continue', 'for', 'import', 'return', 'var', + ] # :nodoc: + + # http://golang.org/ref/spec#Types + PREDEFINED_TYPES = [ + 'bool', + 'uint8', 'uint16', 'uint32', 'uint64', + 'int8', 'int16', 'int32', 'int64', + 'float32', 'float64', + 'complex64', 'complex128', + 'byte', 'rune', 'string', 'error', + 'uint', 'int', 'uintptr', + ] # :nodoc: + + PREDEFINED_CONSTANTS = [ + 'nil', 'iota', + 'true', 'false', + ] # :nodoc: + + PREDEFINED_FUNCTIONS = %w[ + append cap close complex copy delete imag len + make new panic print println real recover + ] # :nodoc: + + IDENT_KIND = WordList.new(:ident). + add(KEYWORDS, :keyword). + add(PREDEFINED_TYPES, :predefined_type). + add(PREDEFINED_CONSTANTS, :predefined_constant). + add(PREDEFINED_FUNCTIONS, :predefined) # :nodoc: + + ESCAPE = / [rbfntv\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x # :nodoc: + UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x # :nodoc: + + protected + + def scan_tokens encoder, options + + state = :initial + label_expected = true + case_expected = false + label_expected_before_preproc_line = nil + in_preproc_line = false + + until eos? + + case state + + when :initial + + if match = scan(/ \s+ | \\\n /x) + if in_preproc_line && match != "\\\n" && match.index(?\n) + in_preproc_line = false + case_expected = false + label_expected = label_expected_before_preproc_line + end + encoder.text_token match, :space + + elsif match = scan(%r! // [^\n\\]* (?: \\. [^\n\\]* )* | /\* (?: .*? \*/ | .* ) !mx) + encoder.text_token match, :comment + + elsif match = scan(/ ?:;,!&^|()\[\]{}~%]+ | \/=? | \.(?!\d) /x) + if case_expected + label_expected = true if match == ':' + case_expected = false + end + encoder.text_token match, :operator + + elsif match = scan(/ [A-Za-z_][A-Za-z_0-9]* /x) + kind = IDENT_KIND[match] + if kind == :ident && label_expected && !in_preproc_line && scan(/:(?!:)/) + kind = :label + label_expected = false + match << matched + else + label_expected = false + if kind == :keyword + case match + when 'case', 'default' + case_expected = true + end + end + end + encoder.text_token match, kind + + elsif match = scan(/L?"/) + encoder.begin_group :string + if match[0] == ?L + encoder.text_token 'L', :modifier + match = '"' + end + encoder.text_token match, :delimiter + state = :string + + elsif match = scan(/ ` ([^`]+)? (`)? /x) + encoder.begin_group :shell + encoder.text_token '`', :delimiter + encoder.text_token self[1], :content if self[1] + encoder.text_token self[2], :delimiter if self[2] + encoder.end_group :shell + + elsif match = scan(/ \# \s* if \s* 0 /x) + match << scan_until(/ ^\# (?:elif|else|endif) .*? $ | \z /xm) unless eos? + encoder.text_token match, :comment + + elsif match = scan(/#[ \t]*(\w*)/) + encoder.text_token match, :preprocessor + in_preproc_line = true + label_expected_before_preproc_line = label_expected + state = :include_expected if self[1] == 'include' + + elsif match = scan(/ L?' (?: [^\'\n\\] | \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) )? '? /ox) + label_expected = false + encoder.text_token match, :char + + elsif match = scan(/\$/) + encoder.text_token match, :ident + + elsif match = scan(/-?\d*(\.\d*)?([eE][+-]?\d+)?i/) + label_expected = false + encoder.text_token match, :imaginary + + elsif match = scan(/-?0[xX][0-9A-Fa-f]+/) + label_expected = false + encoder.text_token match, :hex + + elsif match = scan(/-?(?:0[0-7]+)(?![89.eEfF])/) + label_expected = false + encoder.text_token match, :octal + + elsif match = scan(/-?(?:\d*\.\d+|\d+\.)(?:[eE][+-]?\d+)?|\d+[eE][+-]?\d+/) + label_expected = false + encoder.text_token match, :float + + elsif match = scan(/-?(?:\d+)(?![.eEfF])L?L?/) + label_expected = false + encoder.text_token match, :integer + + else + encoder.text_token getch, :error + + end + + when :string + if match = scan(/[^\\\n"]+/) + encoder.text_token match, :content + elsif match = scan(/"/) + encoder.text_token match, :delimiter + encoder.end_group :string + state = :initial + label_expected = false + elsif match = scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox) + encoder.text_token match, :char + elsif match = scan(/ \\ /x) + encoder.text_token match, :error + elsif match = scan(/$/) + encoder.end_group :string + state = :initial + label_expected = false + else + raise_inspect "else case \" reached; %p not handled." % peek(1), encoder + end + + when :include_expected + if match = scan(/<[^>\n]+>?|"[^"\n\\]*(?:\\.[^"\n\\]*)*"?/) + encoder.text_token match, :include + state = :initial + + elsif match = scan(/\s+/) + encoder.text_token match, :space + state = :initial if match.index ?\n + + else + state = :initial + + end + + else + raise_inspect 'Unknown state', encoder + + end + + end + + if state == :string + encoder.end_group :string + end + + encoder + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/groovy.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/groovy.rb new file mode 100644 index 0000000..c64454f --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/groovy.rb @@ -0,0 +1,268 @@ +module CodeRay +module Scanners + + load :java + + # Scanner for Groovy. + class Groovy < Java + + register_for :groovy + + # TODO: check list of keywords + GROOVY_KEYWORDS = %w[ + as assert def in + ] # :nodoc: + KEYWORDS_EXPECTING_VALUE = WordList.new.add %w[ + case instanceof new return throw typeof while as assert in + ] # :nodoc: + GROOVY_MAGIC_VARIABLES = %w[ it ] # :nodoc: + + IDENT_KIND = Java::IDENT_KIND.dup. + add(GROOVY_KEYWORDS, :keyword). + add(GROOVY_MAGIC_VARIABLES, :local_variable) # :nodoc: + + ESCAPE = / [bfnrtv$\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x # :nodoc: + UNICODE_ESCAPE = / u[a-fA-F0-9]{4} /x # :nodoc: no 4-byte unicode chars? U[a-fA-F0-9]{8} + REGEXP_ESCAPE = / [bfnrtv\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} | \d | [bBdDsSwW\/] /x # :nodoc: + + # TODO: interpretation inside ', ", / + STRING_CONTENT_PATTERN = { + "'" => /(?>\\[^\\'\n]+|[^\\'\n]+)+/, + '"' => /[^\\$"\n]+/, + "'''" => /(?>[^\\']+|'(?!''))+/, + '"""' => /(?>[^\\$"]+|"(?!""))+/, + '/' => /[^\\$\/\n]+/, + } # :nodoc: + + protected + + def setup + @state = :initial + end + + def scan_tokens encoder, options + state = options[:state] || @state + inline_block_stack = [] + inline_block_paren_depth = nil + string_delimiter = nil + import_clause = class_name_follows = last_token = after_def = false + value_expected = true + + until eos? + + case state + + when :initial + + if match = scan(/ \s+ | \\\n /x) + encoder.text_token match, :space + if match.index ?\n + import_clause = after_def = false + value_expected = true unless value_expected + end + next + + elsif match = scan(%r! // [^\n\\]* (?: \\. [^\n\\]* )* | /\* (?: .*? \*/ | .* ) !mx) + value_expected = true + after_def = false + encoder.text_token match, :comment + + elsif bol? && match = scan(/ \#!.* /x) + encoder.text_token match, :doctype + + elsif import_clause && match = scan(/ (?!as) #{IDENT} (?: \. #{IDENT} )* (?: \.\* )? /ox) + after_def = value_expected = false + encoder.text_token match, :include + + elsif match = scan(/ #{IDENT} | \[\] /ox) + kind = IDENT_KIND[match] + value_expected = (kind == :keyword) && KEYWORDS_EXPECTING_VALUE[match] + if last_token == '.' + kind = :ident + elsif class_name_follows + kind = :class + class_name_follows = false + elsif after_def && check(/\s*[({]/) + kind = :method + after_def = false + elsif kind == :ident && last_token != '?' && check(/:/) + kind = :key + else + class_name_follows = true if match == 'class' || (import_clause && match == 'as') + import_clause = match == 'import' + after_def = true if match == 'def' + end + encoder.text_token match, kind + + elsif match = scan(/;/) + import_clause = after_def = false + value_expected = true + encoder.text_token match, :operator + + elsif match = scan(/\{/) + class_name_follows = after_def = false + value_expected = true + encoder.text_token match, :operator + if !inline_block_stack.empty? + inline_block_paren_depth += 1 + end + + # TODO: ~'...', ~"..." and ~/.../ style regexps + elsif match = scan(/ \.\.] | \+\+ | + && | \|\| | \*\*=? | ==?~ | <=?>? | [-+*%^~&|>=!]=? | <<>>?=? /x) + value_expected = true + value_expected = :regexp if match == '~' + after_def = false + encoder.text_token match, :operator + + elsif match = scan(/ [)\]}] /x) + value_expected = after_def = false + if !inline_block_stack.empty? && match == '}' + inline_block_paren_depth -= 1 + if inline_block_paren_depth == 0 # closing brace of inline block reached + encoder.text_token match, :inline_delimiter + encoder.end_group :inline + state, string_delimiter, inline_block_paren_depth = inline_block_stack.pop + next + end + end + encoder.text_token match, :operator + + elsif check(/[\d.]/) + after_def = value_expected = false + if match = scan(/0[xX][0-9A-Fa-f]+/) + encoder.text_token match, :hex + elsif match = scan(/(?>0[0-7]+)(?![89.eEfF])/) + encoder.text_token match, :octal + elsif match = scan(/\d+[fFdD]|\d*\.\d+(?:[eE][+-]?\d+)?[fFdD]?|\d+[eE][+-]?\d+[fFdD]?/) + encoder.text_token match, :float + elsif match = scan(/\d+[lLgG]?/) + encoder.text_token match, :integer + end + + elsif match = scan(/'''|"""/) + after_def = value_expected = false + state = :multiline_string + encoder.begin_group :string + string_delimiter = match + encoder.text_token match, :delimiter + + # TODO: record.'name' syntax + elsif match = scan(/["']/) + after_def = value_expected = false + state = match == '/' ? :regexp : :string + encoder.begin_group state + string_delimiter = match + encoder.text_token match, :delimiter + + elsif value_expected && match = scan(/\//) + after_def = value_expected = false + encoder.begin_group :regexp + state = :regexp + string_delimiter = '/' + encoder.text_token match, :delimiter + + elsif match = scan(/ @ #{IDENT} /ox) + after_def = value_expected = false + encoder.text_token match, :annotation + + elsif match = scan(/\//) + after_def = false + value_expected = true + encoder.text_token match, :operator + + else + encoder.text_token getch, :error + + end + + when :string, :regexp, :multiline_string + if match = scan(STRING_CONTENT_PATTERN[string_delimiter]) + encoder.text_token match, :content + + elsif match = scan(state == :multiline_string ? /'''|"""/ : /["'\/]/) + encoder.text_token match, :delimiter + if state == :regexp + # TODO: regexp modifiers? s, m, x, i? + modifiers = scan(/[ix]+/) + encoder.text_token modifiers, :modifier if modifiers && !modifiers.empty? + end + state = :string if state == :multiline_string + encoder.end_group state + string_delimiter = nil + after_def = value_expected = false + state = :initial + next + + elsif (state == :string || state == :multiline_string) && + (match = scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox)) + if string_delimiter[0] == ?' && !(match == "\\\\" || match == "\\'") + encoder.text_token match, :content + else + encoder.text_token match, :char + end + elsif state == :regexp && match = scan(/ \\ (?: #{REGEXP_ESCAPE} | #{UNICODE_ESCAPE} ) /mox) + encoder.text_token match, :char + + elsif match = scan(/ \$ #{IDENT} /mox) + encoder.begin_group :inline + encoder.text_token '$', :inline_delimiter + match = match[1..-1] + encoder.text_token match, IDENT_KIND[match] + encoder.end_group :inline + next + elsif match = scan(/ \$ \{ /x) + encoder.begin_group :inline + encoder.text_token match, :inline_delimiter + inline_block_stack << [state, string_delimiter, inline_block_paren_depth] + inline_block_paren_depth = 1 + state = :initial + next + + elsif match = scan(/ \$ /mx) + encoder.text_token match, :content + + elsif match = scan(/ \\. /mx) + encoder.text_token match, :content # TODO: Shouldn't this be :error? + + elsif match = scan(/ \\ | \n /x) + encoder.end_group state == :regexp ? :regexp : :string + encoder.text_token match, :error + after_def = value_expected = false + state = :initial + + else + raise_inspect "else case \" reached; %p not handled." % peek(1), encoder + + end + + else + raise_inspect 'Unknown state', encoder + + end + + last_token = match unless [:space, :comment, :doctype].include? kind + + end + + if [:multiline_string, :string, :regexp].include? state + encoder.end_group state == :regexp ? :regexp : :string + end + + if options[:keep_state] + @state = state + end + + until inline_block_stack.empty? + state, = *inline_block_stack.pop + encoder.end_group :inline + encoder.end_group state == :regexp ? :regexp : :string + end + + encoder + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/haml.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/haml.rb new file mode 100644 index 0000000..5433790 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/haml.rb @@ -0,0 +1,168 @@ +module CodeRay +module Scanners + + load :ruby + load :html + load :java_script + + class HAML < Scanner + + register_for :haml + title 'HAML Template' + + KINDS_NOT_LOC = HTML::KINDS_NOT_LOC + + protected + + def setup + super + @ruby_scanner = CodeRay.scanner :ruby, :tokens => @tokens, :keep_tokens => true + @embedded_ruby_scanner = CodeRay.scanner :ruby, :tokens => @tokens, :keep_tokens => true, :state => @ruby_scanner.interpreted_string_state + @html_scanner = CodeRay.scanner :html, :tokens => @tokens, :keep_tokens => true + end + + def scan_tokens encoder, options + + match = nil + code = '' + + until eos? + + if bol? + if match = scan(/!!!.*/) + encoder.text_token match, :doctype + next + end + + if match = scan(/(?>( *)(\/(?!\[if)|-\#|:javascript|:ruby|:\w+) *)(?=\n)/) + encoder.text_token match, :comment + + code = self[2] + if match = scan(/(?:\n+#{self[1]} .*)+/) + case code + when '/', '-#' + encoder.text_token match, :comment + when ':javascript' + # TODO: recognize #{...} snippets inside JavaScript + @java_script_scanner ||= CodeRay.scanner :java_script, :tokens => @tokens, :keep_tokens => true + @java_script_scanner.tokenize match, :tokens => encoder + when ':ruby' + @ruby_scanner.tokenize match, :tokens => encoder + when /:\w+/ + encoder.text_token match, :comment + else + raise 'else-case reached: %p' % [code] + end + end + end + + if match = scan(/ +/) + encoder.text_token match, :space + end + + if match = scan(/\/.*/) + encoder.text_token match, :comment + next + end + + if match = scan(/\\/) + encoder.text_token match, :plain + if match = scan(/.+/) + @html_scanner.tokenize match, :tokens => encoder + end + next + end + + tag = false + + if match = scan(/%[\w:]+\/?/) + encoder.text_token match, :tag + # if match = scan(/( +)(.+)/) + # encoder.text_token self[1], :space + # @embedded_ruby_scanner.tokenize self[2], :tokens => encoder + # end + tag = true + end + + while match = scan(/([.#])[-\w]*\w/) + encoder.text_token match, self[1] == '#' ? :constant : :class + tag = true + end + + if tag && match = scan(/(\()([^)]+)?(\))?/) + # TODO: recognize title=@title, class="widget_#{@widget.number}" + encoder.text_token self[1], :plain + @html_scanner.tokenize self[2], :tokens => encoder, :state => :attribute if self[2] + encoder.text_token self[3], :plain if self[3] + end + + if tag && match = scan(/\{/) + encoder.text_token match, :plain + + code = '' + level = 1 + while true + code << scan(/([^\{\},\n]|, *\n?)*/) + case match = getch + when '{' + level += 1 + code << match + when '}' + level -= 1 + if level > 0 + code << match + else + break + end + when "\n", ",", nil + break + end + end + @ruby_scanner.tokenize code, :tokens => encoder unless code.empty? + + encoder.text_token match, :plain if match + end + + if tag && match = scan(/(\[)([^\]\n]+)?(\])?/) + encoder.text_token self[1], :plain + @ruby_scanner.tokenize self[2], :tokens => encoder if self[2] + encoder.text_token self[3], :plain if self[3] + end + + if tag && match = scan(/\//) + encoder.text_token match, :tag + end + + if scan(/(>? encoder + else + @ruby_scanner.tokenize self[4], :tokens => encoder + end + end + elsif match = scan(/((?:<|> encoder if self[2] + end + + elsif match = scan(/.+/) + @html_scanner.tokenize match, :tokens => encoder + + end + + if match = scan(/\n/) + encoder.text_token match, :space + end + end + + encoder + + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/html.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/html.rb new file mode 100644 index 0000000..ebe7b01 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/html.rb @@ -0,0 +1,275 @@ +module CodeRay +module Scanners + + # HTML Scanner + # + # Alias: +xhtml+ + # + # See also: Scanners::XML + class HTML < Scanner + + register_for :html + + KINDS_NOT_LOC = [ + :comment, :doctype, :preprocessor, + :tag, :attribute_name, :operator, + :attribute_value, :string, + :plain, :entity, :error, + ] # :nodoc: + + EVENT_ATTRIBUTES = %w( + onabort onafterprint onbeforeprint onbeforeunload onblur oncanplay + oncanplaythrough onchange onclick oncontextmenu oncuechange ondblclick + ondrag ondragdrop ondragend ondragenter ondragleave ondragover + ondragstart ondrop ondurationchange onemptied onended onerror onfocus + onformchange onforminput onhashchange oninput oninvalid onkeydown + onkeypress onkeyup onload onloadeddata onloadedmetadata onloadstart + onmessage onmousedown onmousemove onmouseout onmouseover onmouseup + onmousewheel onmove onoffline ononline onpagehide onpageshow onpause + onplay onplaying onpopstate onprogress onratechange onreadystatechange + onredo onreset onresize onscroll onseeked onseeking onselect onshow + onstalled onstorage onsubmit onsuspend ontimeupdate onundo onunload + onvolumechange onwaiting + ) + + IN_ATTRIBUTE = WordList::CaseIgnoring.new(nil). + add(EVENT_ATTRIBUTES, :script). + add(['style'], :style) + + ATTR_NAME = /[\w.:-]+/ # :nodoc: + TAG_END = /\/?>/ # :nodoc: + HEX = /[0-9a-fA-F]/ # :nodoc: + ENTITY = / + & + (?: + \w+ + | + \# + (?: + \d+ + | + x#{HEX}+ + ) + ) + ; + /ox # :nodoc: + + PLAIN_STRING_CONTENT = { + "'" => /[^&'>\n]+/, + '"' => /[^&">\n]+/, + } # :nodoc: + + def reset + super + @state = :initial + @plain_string_content = nil + end + + protected + + def setup + @state = :initial + @plain_string_content = nil + @in_tag = nil + end + + def scan_java_script encoder, code + if code && !code.empty? + @java_script_scanner ||= Scanners::JavaScript.new '', :keep_tokens => true + @java_script_scanner.tokenize code, :tokens => encoder + end + end + + def scan_css encoder, code, state = [:initial] + if code && !code.empty? + @css_scanner ||= Scanners::CSS.new '', :keep_tokens => true + @css_scanner.tokenize code, :tokens => encoder, :state => state + end + end + + def scan_tokens encoder, options + state = options[:state] || @state + plain_string_content = @plain_string_content + in_tag = @in_tag + in_attribute = nil + + encoder.begin_group :string if state == :attribute_value_string + + until eos? + + if state != :in_special_tag && match = scan(/\s+/m) + encoder.text_token match, :space + + else + + case state + + when :initial + if match = scan(//m) + encoder.text_token match[0..-4], :plain + encoder.text_token ']]>', :inline_delimiter + elsif match = scan(/.+/) + encoder.text_token match, :error + end + elsif match = scan(/|.*)/m) + encoder.text_token match, :comment + elsif match = scan(/|.*)|\]>/m) + encoder.text_token match, :doctype + elsif match = scan(/<\?xml(?:.*?\?>|.*)/m) + encoder.text_token match, :preprocessor + elsif match = scan(/<\?(?:.*?\?>|.*)/m) + encoder.text_token match, :comment + elsif match = scan(/<\/[-\w.:]*>?/m) + in_tag = nil + encoder.text_token match, :tag + elsif match = scan(/<(?:(script|style)|[-\w.:]+)(>)?/m) + encoder.text_token match, :tag + in_tag = self[1] + if self[2] + state = :in_special_tag if in_tag + else + state = :attribute + end + elsif match = scan(/[^<>&]+/) + encoder.text_token match, :plain + elsif match = scan(/#{ENTITY}/ox) + encoder.text_token match, :entity + elsif match = scan(/[<>&]/) + in_tag = nil + encoder.text_token match, :error + else + raise_inspect '[BUG] else-case reached with state %p' % [state], encoder + end + + when :attribute + if match = scan(/#{TAG_END}/o) + encoder.text_token match, :tag + in_attribute = nil + if in_tag + state = :in_special_tag + else + state = :initial + end + elsif match = scan(/#{ATTR_NAME}/o) + in_attribute = IN_ATTRIBUTE[match] + encoder.text_token match, :attribute_name + state = :attribute_equal + else + in_tag = nil + encoder.text_token getch, :error + end + + when :attribute_equal + if match = scan(/=/) #/ + encoder.text_token match, :operator + state = :attribute_value + else + state = :attribute + next + end + + when :attribute_value + if match = scan(/#{ATTR_NAME}/o) + encoder.text_token match, :attribute_value + state = :attribute + elsif match = scan(/["']/) + if in_attribute == :script || in_attribute == :style + encoder.begin_group :string + encoder.text_token match, :delimiter + if scan(/javascript:[ \t]*/) + encoder.text_token matched, :comment + end + code = scan_until(match == '"' ? /(?="|\z)/ : /(?='|\z)/) + if in_attribute == :script + scan_java_script encoder, code + else + scan_css encoder, code, [:block] + end + match = scan(/["']/) + encoder.text_token match, :delimiter if match + encoder.end_group :string + state = :attribute + in_attribute = nil + else + encoder.begin_group :string + state = :attribute_value_string + plain_string_content = PLAIN_STRING_CONTENT[match] + encoder.text_token match, :delimiter + end + elsif match = scan(/#{TAG_END}/o) + encoder.text_token match, :tag + state = :initial + else + encoder.text_token getch, :error + end + + when :attribute_value_string + if match = scan(plain_string_content) + encoder.text_token match, :content + elsif match = scan(/['"]/) + encoder.text_token match, :delimiter + encoder.end_group :string + state = :attribute + elsif match = scan(/#{ENTITY}/ox) + encoder.text_token match, :entity + elsif match = scan(/&/) + encoder.text_token match, :content + elsif match = scan(/[\n>]/) + encoder.end_group :string + state = :initial + encoder.text_token match, :error + end + + when :in_special_tag + case in_tag + when 'script', 'style' + encoder.text_token match, :space if match = scan(/[ \t]*\n/) + if scan(/(\s*)|(.*))/m) + code = self[2] || self[4] + closing = self[3] + encoder.text_token self[1], :comment + else + code = scan_until(/(?=(?:\n\s*)?<\/#{in_tag}>)|\z/) + closing = false + end + unless code.empty? + encoder.begin_group :inline + if in_tag == 'script' + scan_java_script encoder, code + else + scan_css encoder, code + end + encoder.end_group :inline + end + encoder.text_token closing, :comment if closing + state = :initial + else + raise 'unknown special tag: %p' % [in_tag] + end + + else + raise_inspect 'Unknown state: %p' % [state], encoder + + end + + end + + end + + if options[:keep_state] + @state = state + @plain_string_content = plain_string_content + @in_tag = in_tag + end + + encoder.end_group :string if state == :attribute_value_string + + encoder + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/java.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/java.rb new file mode 100644 index 0000000..b282864 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/java.rb @@ -0,0 +1,174 @@ +module CodeRay +module Scanners + + # Scanner for Java. + class Java < Scanner + + register_for :java + + autoload :BuiltinTypes, CodeRay.coderay_path('scanners', 'java', 'builtin_types') + + # http://java.sun.com/docs/books/tutorial/java/nutsandbolts/_keywords.html + KEYWORDS = %w[ + assert break case catch continue default do else + finally for if instanceof import new package + return switch throw try typeof while + debugger export + ] # :nodoc: + RESERVED = %w[ const goto ] # :nodoc: + CONSTANTS = %w[ false null true ] # :nodoc: + MAGIC_VARIABLES = %w[ this super ] # :nodoc: + TYPES = %w[ + boolean byte char class double enum float int interface long + short void + ] << '[]' # :nodoc: because int[] should be highlighted as a type + DIRECTIVES = %w[ + abstract extends final implements native private protected public + static strictfp synchronized throws transient volatile + ] # :nodoc: + + IDENT_KIND = WordList.new(:ident). + add(KEYWORDS, :keyword). + add(RESERVED, :reserved). + add(CONSTANTS, :predefined_constant). + add(MAGIC_VARIABLES, :local_variable). + add(TYPES, :type). + add(BuiltinTypes::List, :predefined_type). + add(BuiltinTypes::List.select { |builtin| builtin[/(Error|Exception)$/] }, :exception). + add(DIRECTIVES, :directive) # :nodoc: + + ESCAPE = / [bfnrtv\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x # :nodoc: + UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x # :nodoc: + STRING_CONTENT_PATTERN = { + "'" => /[^\\']+/, + '"' => /[^\\"]+/, + '/' => /[^\\\/]+/, + } # :nodoc: + IDENT = /[a-zA-Z_][A-Za-z_0-9]*/ # :nodoc: + + protected + + def scan_tokens encoder, options + + state = :initial + string_delimiter = nil + package_name_expected = false + class_name_follows = false + last_token_dot = false + + until eos? + + case state + + when :initial + + if match = scan(/ \s+ | \\\n /x) + encoder.text_token match, :space + next + + elsif match = scan(%r! // [^\n\\]* (?: \\. [^\n\\]* )* | /\* (?: .*? \*/ | .* ) !mx) + encoder.text_token match, :comment + next + + elsif package_name_expected && match = scan(/ #{IDENT} (?: \. #{IDENT} )* /ox) + encoder.text_token match, package_name_expected + + elsif match = scan(/ #{IDENT} | \[\] /ox) + kind = IDENT_KIND[match] + if last_token_dot + kind = :ident + elsif class_name_follows + kind = :class + class_name_follows = false + else + case match + when 'import' + package_name_expected = :include + when 'package' + package_name_expected = :namespace + when 'class', 'interface' + class_name_follows = true + end + end + encoder.text_token match, kind + + elsif match = scan(/ \.(?!\d) | [,?:()\[\]}] | -- | \+\+ | && | \|\| | \*\*=? | [-+*\/%^~&|<>=!]=? | <<>>?=? /x) + encoder.text_token match, :operator + + elsif match = scan(/;/) + package_name_expected = false + encoder.text_token match, :operator + + elsif match = scan(/\{/) + class_name_follows = false + encoder.text_token match, :operator + + elsif check(/[\d.]/) + if match = scan(/0[xX][0-9A-Fa-f]+/) + encoder.text_token match, :hex + elsif match = scan(/(?>0[0-7]+)(?![89.eEfF])/) + encoder.text_token match, :octal + elsif match = scan(/\d+[fFdD]|\d*\.\d+(?:[eE][+-]?\d+)?[fFdD]?|\d+[eE][+-]?\d+[fFdD]?/) + encoder.text_token match, :float + elsif match = scan(/\d+[lL]?/) + encoder.text_token match, :integer + end + + elsif match = scan(/["']/) + state = :string + encoder.begin_group state + string_delimiter = match + encoder.text_token match, :delimiter + + elsif match = scan(/ @ #{IDENT} /ox) + encoder.text_token match, :annotation + + else + encoder.text_token getch, :error + + end + + when :string + if match = scan(STRING_CONTENT_PATTERN[string_delimiter]) + encoder.text_token match, :content + elsif match = scan(/["'\/]/) + encoder.text_token match, :delimiter + encoder.end_group state + state = :initial + string_delimiter = nil + elsif state == :string && (match = scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox)) + if string_delimiter == "'" && !(match == "\\\\" || match == "\\'") + encoder.text_token match, :content + else + encoder.text_token match, :char + end + elsif match = scan(/\\./m) + encoder.text_token match, :content + elsif match = scan(/ \\ | $ /x) + encoder.end_group state + state = :initial + encoder.text_token match, :error unless match.empty? + else + raise_inspect "else case \" reached; %p not handled." % peek(1), encoder + end + + else + raise_inspect 'Unknown state', encoder + + end + + last_token_dot = match == '.' + + end + + if state == :string + encoder.end_group state + end + + encoder + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/java/builtin_types.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/java/builtin_types.rb new file mode 100644 index 0000000..d1b8b73 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/java/builtin_types.rb @@ -0,0 +1,421 @@ +module CodeRay +module Scanners + + module Java::BuiltinTypes # :nodoc: + + #:nocov: + List = %w[ + AbstractAction AbstractBorder AbstractButton AbstractCellEditor AbstractCollection + AbstractColorChooserPanel AbstractDocument AbstractExecutorService AbstractInterruptibleChannel + AbstractLayoutCache AbstractList AbstractListModel AbstractMap AbstractMethodError AbstractPreferences + AbstractQueue AbstractQueuedSynchronizer AbstractSelectableChannel AbstractSelectionKey AbstractSelector + AbstractSequentialList AbstractSet AbstractSpinnerModel AbstractTableModel AbstractUndoableEdit + AbstractWriter AccessControlContext AccessControlException AccessController AccessException Accessible + AccessibleAction AccessibleAttributeSequence AccessibleBundle AccessibleComponent AccessibleContext + AccessibleEditableText AccessibleExtendedComponent AccessibleExtendedTable AccessibleExtendedText + AccessibleHyperlink AccessibleHypertext AccessibleIcon AccessibleKeyBinding AccessibleObject + AccessibleRelation AccessibleRelationSet AccessibleResourceBundle AccessibleRole AccessibleSelection + AccessibleState AccessibleStateSet AccessibleStreamable AccessibleTable AccessibleTableModelChange + AccessibleText AccessibleTextSequence AccessibleValue AccountException AccountExpiredException + AccountLockedException AccountNotFoundException Acl AclEntry AclNotFoundException Action ActionEvent + ActionListener ActionMap ActionMapUIResource Activatable ActivateFailedException ActivationDesc + ActivationException ActivationGroup ActivationGroupDesc ActivationGroupID ActivationGroup_Stub + ActivationID ActivationInstantiator ActivationMonitor ActivationSystem Activator ActiveEvent + ActivityCompletedException ActivityRequiredException Adjustable AdjustmentEvent AdjustmentListener + Adler32 AffineTransform AffineTransformOp AlgorithmParameterGenerator AlgorithmParameterGeneratorSpi + AlgorithmParameters AlgorithmParameterSpec AlgorithmParametersSpi AllPermission AlphaComposite + AlreadyBoundException AlreadyConnectedException AncestorEvent AncestorListener AnnotatedElement + Annotation AnnotationFormatError AnnotationTypeMismatchException AppConfigurationEntry Appendable Applet + AppletContext AppletInitializer AppletStub Arc2D Area AreaAveragingScaleFilter ArithmeticException Array + ArrayBlockingQueue ArrayIndexOutOfBoundsException ArrayList Arrays ArrayStoreException ArrayType + AssertionError AsyncBoxView AsynchronousCloseException AtomicBoolean AtomicInteger AtomicIntegerArray + AtomicIntegerFieldUpdater AtomicLong AtomicLongArray AtomicLongFieldUpdater AtomicMarkableReference + AtomicReference AtomicReferenceArray AtomicReferenceFieldUpdater AtomicStampedReference Attribute + AttributeChangeNotification AttributeChangeNotificationFilter AttributedCharacterIterator + AttributedString AttributeException AttributeInUseException AttributeList AttributeModificationException + AttributeNotFoundException Attributes AttributeSet AttributeSetUtilities AttributeValueExp AudioClip + AudioFileFormat AudioFileReader AudioFileWriter AudioFormat AudioInputStream AudioPermission AudioSystem + AuthenticationException AuthenticationNotSupportedException Authenticator AuthorizeCallback + AuthPermission AuthProvider Autoscroll AWTError AWTEvent AWTEventListener AWTEventListenerProxy + AWTEventMulticaster AWTException AWTKeyStroke AWTPermission BackingStoreException + BadAttributeValueExpException BadBinaryOpValueExpException BadLocationException BadPaddingException + BadStringOperationException BandCombineOp BandedSampleModel BaseRowSet BasicArrowButton BasicAttribute + BasicAttributes BasicBorders BasicButtonListener BasicButtonUI BasicCheckBoxMenuItemUI BasicCheckBoxUI + BasicColorChooserUI BasicComboBoxEditor BasicComboBoxRenderer BasicComboBoxUI BasicComboPopup + BasicControl BasicDesktopIconUI BasicDesktopPaneUI BasicDirectoryModel BasicEditorPaneUI + BasicFileChooserUI BasicFormattedTextFieldUI BasicGraphicsUtils BasicHTML BasicIconFactory + BasicInternalFrameTitlePane BasicInternalFrameUI BasicLabelUI BasicListUI BasicLookAndFeel + BasicMenuBarUI BasicMenuItemUI BasicMenuUI BasicOptionPaneUI BasicPanelUI BasicPasswordFieldUI + BasicPermission BasicPopupMenuSeparatorUI BasicPopupMenuUI BasicProgressBarUI BasicRadioButtonMenuItemUI + BasicRadioButtonUI BasicRootPaneUI BasicScrollBarUI BasicScrollPaneUI BasicSeparatorUI BasicSliderUI + BasicSpinnerUI BasicSplitPaneDivider BasicSplitPaneUI BasicStroke BasicTabbedPaneUI BasicTableHeaderUI + BasicTableUI BasicTextAreaUI BasicTextFieldUI BasicTextPaneUI BasicTextUI BasicToggleButtonUI + BasicToolBarSeparatorUI BasicToolBarUI BasicToolTipUI BasicTreeUI BasicViewportUI BatchUpdateException + BeanContext BeanContextChild BeanContextChildComponentProxy BeanContextChildSupport + BeanContextContainerProxy BeanContextEvent BeanContextMembershipEvent BeanContextMembershipListener + BeanContextProxy BeanContextServiceAvailableEvent BeanContextServiceProvider + BeanContextServiceProviderBeanInfo BeanContextServiceRevokedEvent BeanContextServiceRevokedListener + BeanContextServices BeanContextServicesListener BeanContextServicesSupport BeanContextSupport + BeanDescriptor BeanInfo Beans BevelBorder Bidi BigDecimal BigInteger BinaryRefAddr BindException Binding + BitSet Blob BlockingQueue BlockView BMPImageWriteParam Book Boolean BooleanControl Border BorderFactory + BorderLayout BorderUIResource BoundedRangeModel Box BoxLayout BoxView BreakIterator + BrokenBarrierException Buffer BufferCapabilities BufferedImage BufferedImageFilter BufferedImageOp + BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter BufferOverflowException + BufferStrategy BufferUnderflowException Button ButtonGroup ButtonModel ButtonUI Byte + ByteArrayInputStream ByteArrayOutputStream ByteBuffer ByteChannel ByteLookupTable ByteOrder CachedRowSet + CacheRequest CacheResponse Calendar Callable CallableStatement Callback CallbackHandler + CancelablePrintJob CancellationException CancelledKeyException CannotProceedException + CannotRedoException CannotUndoException Canvas CardLayout Caret CaretEvent CaretListener CellEditor + CellEditorListener CellRendererPane Certificate CertificateEncodingException CertificateException + CertificateExpiredException CertificateFactory CertificateFactorySpi CertificateNotYetValidException + CertificateParsingException CertPath CertPathBuilder CertPathBuilderException CertPathBuilderResult + CertPathBuilderSpi CertPathParameters CertPathTrustManagerParameters CertPathValidator + CertPathValidatorException CertPathValidatorResult CertPathValidatorSpi CertSelector CertStore + CertStoreException CertStoreParameters CertStoreSpi ChangedCharSetException ChangeEvent ChangeListener + Channel Channels Character CharacterCodingException CharacterIterator CharArrayReader CharArrayWriter + CharBuffer CharConversionException CharSequence Charset CharsetDecoder CharsetEncoder CharsetProvider + Checkbox CheckboxGroup CheckboxMenuItem CheckedInputStream CheckedOutputStream Checksum Choice + ChoiceCallback ChoiceFormat Chromaticity Cipher CipherInputStream CipherOutputStream CipherSpi Class + ClassCastException ClassCircularityError ClassDefinition ClassDesc ClassFileTransformer ClassFormatError + ClassLoader ClassLoaderRepository ClassLoadingMXBean ClassNotFoundException Clip Clipboard + ClipboardOwner Clob Cloneable CloneNotSupportedException Closeable ClosedByInterruptException + ClosedChannelException ClosedSelectorException CMMException CoderMalfunctionError CoderResult CodeSigner + CodeSource CodingErrorAction CollationElementIterator CollationKey Collator Collection + CollectionCertStoreParameters Collections Color ColorChooserComponentFactory ColorChooserUI + ColorConvertOp ColorModel ColorSelectionModel ColorSpace ColorSupported ColorType ColorUIResource + ComboBoxEditor ComboBoxModel ComboBoxUI ComboPopup CommunicationException Comparable Comparator + CompilationMXBean Compiler CompletionService Component ComponentAdapter ComponentColorModel + ComponentEvent ComponentInputMap ComponentInputMapUIResource ComponentListener ComponentOrientation + ComponentSampleModel ComponentUI ComponentView Composite CompositeContext CompositeData + CompositeDataSupport CompositeName CompositeType CompositeView CompoundBorder CompoundControl + CompoundEdit CompoundName Compression ConcurrentHashMap ConcurrentLinkedQueue ConcurrentMap + ConcurrentModificationException Condition Configuration ConfigurationException ConfirmationCallback + ConnectException ConnectIOException Connection ConnectionEvent ConnectionEventListener + ConnectionPendingException ConnectionPoolDataSource ConsoleHandler Constructor Container + ContainerAdapter ContainerEvent ContainerListener ContainerOrderFocusTraversalPolicy ContentHandler + ContentHandlerFactory ContentModel Context ContextNotEmptyException ContextualRenderedImageFactory + Control ControlFactory ControllerEventListener ConvolveOp CookieHandler Copies CopiesSupported + CopyOnWriteArrayList CopyOnWriteArraySet CountDownLatch CounterMonitor CounterMonitorMBean CRC32 + CredentialException CredentialExpiredException CredentialNotFoundException CRL CRLException CRLSelector + CropImageFilter CSS CubicCurve2D Currency Cursor Customizer CyclicBarrier DatabaseMetaData DataBuffer + DataBufferByte DataBufferDouble DataBufferFloat DataBufferInt DataBufferShort DataBufferUShort + DataFlavor DataFormatException DatagramChannel DatagramPacket DatagramSocket DatagramSocketImpl + DatagramSocketImplFactory DataInput DataInputStream DataLine DataOutput DataOutputStream DataSource + DataTruncation DatatypeConfigurationException DatatypeConstants DatatypeFactory Date DateFormat + DateFormatSymbols DateFormatter DateTimeAtCompleted DateTimeAtCreation DateTimeAtProcessing + DateTimeSyntax DebugGraphics DecimalFormat DecimalFormatSymbols DefaultBoundedRangeModel + DefaultButtonModel DefaultCaret DefaultCellEditor DefaultColorSelectionModel DefaultComboBoxModel + DefaultDesktopManager DefaultEditorKit DefaultFocusManager DefaultFocusTraversalPolicy DefaultFormatter + DefaultFormatterFactory DefaultHighlighter DefaultKeyboardFocusManager DefaultListCellRenderer + DefaultListModel DefaultListSelectionModel DefaultLoaderRepository DefaultMenuLayout DefaultMetalTheme + DefaultMutableTreeNode DefaultPersistenceDelegate DefaultSingleSelectionModel DefaultStyledDocument + DefaultTableCellRenderer DefaultTableColumnModel DefaultTableModel DefaultTextUI DefaultTreeCellEditor + DefaultTreeCellRenderer DefaultTreeModel DefaultTreeSelectionModel Deflater DeflaterOutputStream Delayed + DelayQueue DelegationPermission Deprecated Descriptor DescriptorAccess DescriptorSupport DESedeKeySpec + DesignMode DESKeySpec DesktopIconUI DesktopManager DesktopPaneUI Destination Destroyable + DestroyFailedException DGC DHGenParameterSpec DHKey DHParameterSpec DHPrivateKey DHPrivateKeySpec + DHPublicKey DHPublicKeySpec Dialog Dictionary DigestException DigestInputStream DigestOutputStream + Dimension Dimension2D DimensionUIResource DirContext DirectColorModel DirectoryManager DirObjectFactory + DirStateFactory DisplayMode DnDConstants Doc DocAttribute DocAttributeSet DocFlavor DocPrintJob Document + DocumentBuilder DocumentBuilderFactory Documented DocumentEvent DocumentFilter DocumentListener + DocumentName DocumentParser DomainCombiner DOMLocator DOMResult DOMSource Double DoubleBuffer + DragGestureEvent DragGestureListener DragGestureRecognizer DragSource DragSourceAdapter + DragSourceContext DragSourceDragEvent DragSourceDropEvent DragSourceEvent DragSourceListener + DragSourceMotionListener Driver DriverManager DriverPropertyInfo DropTarget DropTargetAdapter + DropTargetContext DropTargetDragEvent DropTargetDropEvent DropTargetEvent DropTargetListener DSAKey + DSAKeyPairGenerator DSAParameterSpec DSAParams DSAPrivateKey DSAPrivateKeySpec DSAPublicKey + DSAPublicKeySpec DTD DTDConstants DuplicateFormatFlagsException Duration DynamicMBean ECField ECFieldF2m + ECFieldFp ECGenParameterSpec ECKey ECParameterSpec ECPoint ECPrivateKey ECPrivateKeySpec ECPublicKey + ECPublicKeySpec EditorKit Element ElementIterator ElementType Ellipse2D EllipticCurve EmptyBorder + EmptyStackException EncodedKeySpec Encoder EncryptedPrivateKeyInfo Entity Enum + EnumConstantNotPresentException EnumControl Enumeration EnumMap EnumSet EnumSyntax EOFException Error + ErrorListener ErrorManager EtchedBorder Event EventContext EventDirContext EventHandler EventListener + EventListenerList EventListenerProxy EventObject EventQueue EventSetDescriptor Exception + ExceptionInInitializerError ExceptionListener Exchanger ExecutionException Executor + ExecutorCompletionService Executors ExecutorService ExemptionMechanism ExemptionMechanismException + ExemptionMechanismSpi ExpandVetoException ExportException Expression ExtendedRequest ExtendedResponse + Externalizable FactoryConfigurationError FailedLoginException FeatureDescriptor Fidelity Field + FieldPosition FieldView File FileCacheImageInputStream FileCacheImageOutputStream FileChannel + FileChooserUI FileDescriptor FileDialog FileFilter FileHandler FileImageInputStream + FileImageOutputStream FileInputStream FileLock FileLockInterruptionException FilenameFilter FileNameMap + FileNotFoundException FileOutputStream FilePermission FileReader FileSystemView FileView FileWriter + Filter FilteredImageSource FilteredRowSet FilterInputStream FilterOutputStream FilterReader FilterWriter + Finishings FixedHeightLayoutCache FlatteningPathIterator FlavorEvent FlavorException FlavorListener + FlavorMap FlavorTable Float FloatBuffer FloatControl FlowLayout FlowView Flushable FocusAdapter + FocusEvent FocusListener FocusManager FocusTraversalPolicy Font FontFormatException FontMetrics + FontRenderContext FontUIResource Format FormatConversionProvider FormatFlagsConversionMismatchException + Formattable FormattableFlags Formatter FormatterClosedException FormSubmitEvent FormView Frame Future + FutureTask GapContent GarbageCollectorMXBean GatheringByteChannel GaugeMonitor GaugeMonitorMBean + GeneralPath GeneralSecurityException GenericArrayType GenericDeclaration GenericSignatureFormatError + GlyphJustificationInfo GlyphMetrics GlyphVector GlyphView GradientPaint GraphicAttribute Graphics + Graphics2D GraphicsConfigTemplate GraphicsConfiguration GraphicsDevice GraphicsEnvironment GrayFilter + GregorianCalendar GridBagConstraints GridBagLayout GridLayout Group Guard GuardedObject GZIPInputStream + GZIPOutputStream Handler HandshakeCompletedEvent HandshakeCompletedListener HasControls HashAttributeSet + HashDocAttributeSet HashMap HashPrintJobAttributeSet HashPrintRequestAttributeSet + HashPrintServiceAttributeSet HashSet Hashtable HeadlessException HierarchyBoundsAdapter + HierarchyBoundsListener HierarchyEvent HierarchyListener Highlighter HostnameVerifier HTML HTMLDocument + HTMLEditorKit HTMLFrameHyperlinkEvent HTMLWriter HttpRetryException HttpsURLConnection HttpURLConnection + HyperlinkEvent HyperlinkListener ICC_ColorSpace ICC_Profile ICC_ProfileGray ICC_ProfileRGB Icon + IconUIResource IconView Identity IdentityHashMap IdentityScope IIOByteBuffer IIOException IIOImage + IIOInvalidTreeException IIOMetadata IIOMetadataController IIOMetadataFormat IIOMetadataFormatImpl + IIOMetadataNode IIOParam IIOParamController IIOReadProgressListener IIOReadUpdateListener + IIOReadWarningListener IIORegistry IIOServiceProvider IIOWriteProgressListener IIOWriteWarningListener + IllegalAccessError IllegalAccessException IllegalArgumentException IllegalBlockingModeException + IllegalBlockSizeException IllegalCharsetNameException IllegalClassFormatException + IllegalComponentStateException IllegalFormatCodePointException IllegalFormatConversionException + IllegalFormatException IllegalFormatFlagsException IllegalFormatPrecisionException + IllegalFormatWidthException IllegalMonitorStateException IllegalPathStateException + IllegalSelectorException IllegalStateException IllegalThreadStateException Image ImageCapabilities + ImageConsumer ImageFilter ImageGraphicAttribute ImageIcon ImageInputStream ImageInputStreamImpl + ImageInputStreamSpi ImageIO ImageObserver ImageOutputStream ImageOutputStreamImpl ImageOutputStreamSpi + ImageProducer ImageReader ImageReaderSpi ImageReaderWriterSpi ImageReadParam ImageTranscoder + ImageTranscoderSpi ImageTypeSpecifier ImageView ImageWriteParam ImageWriter ImageWriterSpi + ImagingOpException IncompatibleClassChangeError IncompleteAnnotationException IndexColorModel + IndexedPropertyChangeEvent IndexedPropertyDescriptor IndexOutOfBoundsException Inet4Address Inet6Address + InetAddress InetSocketAddress Inflater InflaterInputStream InheritableThreadLocal Inherited + InitialContext InitialContextFactory InitialContextFactoryBuilder InitialDirContext InitialLdapContext + InlineView InputContext InputEvent InputMap InputMapUIResource InputMethod InputMethodContext + InputMethodDescriptor InputMethodEvent InputMethodHighlight InputMethodListener InputMethodRequests + InputMismatchException InputStream InputStreamReader InputSubset InputVerifier Insets InsetsUIResource + InstanceAlreadyExistsException InstanceNotFoundException InstantiationError InstantiationException + Instrument Instrumentation InsufficientResourcesException IntBuffer Integer IntegerSyntax InternalError + InternalFrameAdapter InternalFrameEvent InternalFrameFocusTraversalPolicy InternalFrameListener + InternalFrameUI InternationalFormatter InterruptedException InterruptedIOException + InterruptedNamingException InterruptibleChannel IntrospectionException Introspector + InvalidActivityException InvalidAlgorithmParameterException InvalidApplicationException + InvalidAttributeIdentifierException InvalidAttributesException InvalidAttributeValueException + InvalidClassException InvalidDnDOperationException InvalidKeyException InvalidKeySpecException + InvalidMarkException InvalidMidiDataException InvalidNameException InvalidObjectException + InvalidOpenTypeException InvalidParameterException InvalidParameterSpecException + InvalidPreferencesFormatException InvalidPropertiesFormatException InvalidRelationIdException + InvalidRelationServiceException InvalidRelationTypeException InvalidRoleInfoException + InvalidRoleValueException InvalidSearchControlsException InvalidSearchFilterException + InvalidTargetObjectTypeException InvalidTransactionException InvocationEvent InvocationHandler + InvocationTargetException IOException ItemEvent ItemListener ItemSelectable Iterable Iterator + IvParameterSpec JApplet JarEntry JarException JarFile JarInputStream JarOutputStream JarURLConnection + JButton JCheckBox JCheckBoxMenuItem JColorChooser JComboBox JComponent JdbcRowSet JDesktopPane JDialog + JEditorPane JFileChooser JFormattedTextField JFrame JInternalFrame JLabel JLayeredPane JList JMenu + JMenuBar JMenuItem JMException JMRuntimeException JMXAuthenticator JMXConnectionNotification + JMXConnector JMXConnectorFactory JMXConnectorProvider JMXConnectorServer JMXConnectorServerFactory + JMXConnectorServerMBean JMXConnectorServerProvider JMXPrincipal JMXProviderException + JMXServerErrorException JMXServiceURL JobAttributes JobHoldUntil JobImpressions JobImpressionsCompleted + JobImpressionsSupported JobKOctets JobKOctetsProcessed JobKOctetsSupported JobMediaSheets + JobMediaSheetsCompleted JobMediaSheetsSupported JobMessageFromOperator JobName JobOriginatingUserName + JobPriority JobPrioritySupported JobSheets JobState JobStateReason JobStateReasons Joinable JoinRowSet + JOptionPane JPanel JPasswordField JPEGHuffmanTable JPEGImageReadParam JPEGImageWriteParam JPEGQTable + JPopupMenu JProgressBar JRadioButton JRadioButtonMenuItem JRootPane JScrollBar JScrollPane JSeparator + JSlider JSpinner JSplitPane JTabbedPane JTable JTableHeader JTextArea JTextComponent JTextField + JTextPane JToggleButton JToolBar JToolTip JTree JViewport JWindow KerberosKey KerberosPrincipal + KerberosTicket Kernel Key KeyAdapter KeyAgreement KeyAgreementSpi KeyAlreadyExistsException + KeyboardFocusManager KeyEvent KeyEventDispatcher KeyEventPostProcessor KeyException KeyFactory + KeyFactorySpi KeyGenerator KeyGeneratorSpi KeyListener KeyManagementException KeyManager + KeyManagerFactory KeyManagerFactorySpi Keymap KeyPair KeyPairGenerator KeyPairGeneratorSpi KeyRep + KeySpec KeyStore KeyStoreBuilderParameters KeyStoreException KeyStoreSpi KeyStroke Label LabelUI + LabelView LanguageCallback LastOwnerException LayeredHighlighter LayoutFocusTraversalPolicy + LayoutManager LayoutManager2 LayoutQueue LDAPCertStoreParameters LdapContext LdapName + LdapReferralException Lease Level LimitExceededException Line Line2D LineBorder LineBreakMeasurer + LineEvent LineListener LineMetrics LineNumberInputStream LineNumberReader LineUnavailableException + LinkageError LinkedBlockingQueue LinkedHashMap LinkedHashSet LinkedList LinkException LinkLoopException + LinkRef List ListCellRenderer ListDataEvent ListDataListener ListenerNotFoundException ListIterator + ListModel ListResourceBundle ListSelectionEvent ListSelectionListener ListSelectionModel ListUI ListView + LoaderHandler Locale LocateRegistry Lock LockSupport Logger LoggingMXBean LoggingPermission LoginContext + LoginException LoginModule LogManager LogRecord LogStream Long LongBuffer LookAndFeel LookupOp + LookupTable Mac MacSpi MalformedInputException MalformedLinkException MalformedObjectNameException + MalformedParameterizedTypeException MalformedURLException ManagementFactory ManagementPermission + ManageReferralControl ManagerFactoryParameters Manifest Map MappedByteBuffer MarshalException + MarshalledObject MaskFormatter Matcher MatchResult Math MathContext MatteBorder MBeanAttributeInfo + MBeanConstructorInfo MBeanException MBeanFeatureInfo MBeanInfo MBeanNotificationInfo MBeanOperationInfo + MBeanParameterInfo MBeanPermission MBeanRegistration MBeanRegistrationException MBeanServer + MBeanServerBuilder MBeanServerConnection MBeanServerDelegate MBeanServerDelegateMBean MBeanServerFactory + MBeanServerForwarder MBeanServerInvocationHandler MBeanServerNotification MBeanServerNotificationFilter + MBeanServerPermission MBeanTrustPermission Media MediaName MediaPrintableArea MediaSize MediaSizeName + MediaTracker MediaTray Member MemoryCacheImageInputStream MemoryCacheImageOutputStream MemoryHandler + MemoryImageSource MemoryManagerMXBean MemoryMXBean MemoryNotificationInfo MemoryPoolMXBean MemoryType + MemoryUsage Menu MenuBar MenuBarUI MenuComponent MenuContainer MenuDragMouseEvent MenuDragMouseListener + MenuElement MenuEvent MenuItem MenuItemUI MenuKeyEvent MenuKeyListener MenuListener MenuSelectionManager + MenuShortcut MessageDigest MessageDigestSpi MessageFormat MetaEventListener MetalBorders MetalButtonUI + MetalCheckBoxIcon MetalCheckBoxUI MetalComboBoxButton MetalComboBoxEditor MetalComboBoxIcon + MetalComboBoxUI MetalDesktopIconUI MetalFileChooserUI MetalIconFactory MetalInternalFrameTitlePane + MetalInternalFrameUI MetalLabelUI MetalLookAndFeel MetalMenuBarUI MetalPopupMenuSeparatorUI + MetalProgressBarUI MetalRadioButtonUI MetalRootPaneUI MetalScrollBarUI MetalScrollButton + MetalScrollPaneUI MetalSeparatorUI MetalSliderUI MetalSplitPaneUI MetalTabbedPaneUI MetalTextFieldUI + MetalTheme MetalToggleButtonUI MetalToolBarUI MetalToolTipUI MetalTreeUI MetaMessage Method + MethodDescriptor MGF1ParameterSpec MidiChannel MidiDevice MidiDeviceProvider MidiEvent MidiFileFormat + MidiFileReader MidiFileWriter MidiMessage MidiSystem MidiUnavailableException MimeTypeParseException + MinimalHTMLWriter MissingFormatArgumentException MissingFormatWidthException MissingResourceException + Mixer MixerProvider MLet MLetMBean ModelMBean ModelMBeanAttributeInfo ModelMBeanConstructorInfo + ModelMBeanInfo ModelMBeanInfoSupport ModelMBeanNotificationBroadcaster ModelMBeanNotificationInfo + ModelMBeanOperationInfo ModificationItem Modifier Monitor MonitorMBean MonitorNotification + MonitorSettingException MouseAdapter MouseDragGestureRecognizer MouseEvent MouseInfo MouseInputAdapter + MouseInputListener MouseListener MouseMotionAdapter MouseMotionListener MouseWheelEvent + MouseWheelListener MultiButtonUI MulticastSocket MultiColorChooserUI MultiComboBoxUI MultiDesktopIconUI + MultiDesktopPaneUI MultiDoc MultiDocPrintJob MultiDocPrintService MultiFileChooserUI + MultiInternalFrameUI MultiLabelUI MultiListUI MultiLookAndFeel MultiMenuBarUI MultiMenuItemUI + MultiOptionPaneUI MultiPanelUI MultiPixelPackedSampleModel MultipleDocumentHandling MultipleMaster + MultiPopupMenuUI MultiProgressBarUI MultiRootPaneUI MultiScrollBarUI MultiScrollPaneUI MultiSeparatorUI + MultiSliderUI MultiSpinnerUI MultiSplitPaneUI MultiTabbedPaneUI MultiTableHeaderUI MultiTableUI + MultiTextUI MultiToolBarUI MultiToolTipUI MultiTreeUI MultiViewportUI MutableAttributeSet + MutableComboBoxModel MutableTreeNode Name NameAlreadyBoundException NameCallback NameClassPair + NameNotFoundException NameParser NamespaceChangeListener NamespaceContext Naming NamingEnumeration + NamingEvent NamingException NamingExceptionEvent NamingListener NamingManager NamingSecurityException + NavigationFilter NegativeArraySizeException NetPermission NetworkInterface NoClassDefFoundError + NoConnectionPendingException NodeChangeEvent NodeChangeListener NoInitialContextException + NoninvertibleTransformException NonReadableChannelException NonWritableChannelException + NoPermissionException NoRouteToHostException NoSuchAlgorithmException NoSuchAttributeException + NoSuchElementException NoSuchFieldError NoSuchFieldException NoSuchMethodError NoSuchMethodException + NoSuchObjectException NoSuchPaddingException NoSuchProviderException NotActiveException + NotBoundException NotCompliantMBeanException NotContextException Notification NotificationBroadcaster + NotificationBroadcasterSupport NotificationEmitter NotificationFilter NotificationFilterSupport + NotificationListener NotificationResult NotOwnerException NotSerializableException NotYetBoundException + NotYetConnectedException NullCipher NullPointerException Number NumberFormat NumberFormatException + NumberFormatter NumberOfDocuments NumberOfInterveningJobs NumberUp NumberUpSupported NumericShaper + OAEPParameterSpec Object ObjectChangeListener ObjectFactory ObjectFactoryBuilder ObjectInput + ObjectInputStream ObjectInputValidation ObjectInstance ObjectName ObjectOutput ObjectOutputStream + ObjectStreamClass ObjectStreamConstants ObjectStreamException ObjectStreamField ObjectView ObjID + Observable Observer OceanTheme OpenDataException OpenMBeanAttributeInfo OpenMBeanAttributeInfoSupport + OpenMBeanConstructorInfo OpenMBeanConstructorInfoSupport OpenMBeanInfo OpenMBeanInfoSupport + OpenMBeanOperationInfo OpenMBeanOperationInfoSupport OpenMBeanParameterInfo + OpenMBeanParameterInfoSupport OpenType OperatingSystemMXBean Operation OperationNotSupportedException + OperationsException Option OptionalDataException OptionPaneUI OrientationRequested OutOfMemoryError + OutputDeviceAssigned OutputKeys OutputStream OutputStreamWriter OverlappingFileLockException + OverlayLayout Override Owner Pack200 Package PackedColorModel Pageable PageAttributes + PagedResultsControl PagedResultsResponseControl PageFormat PageRanges PagesPerMinute PagesPerMinuteColor + Paint PaintContext PaintEvent Panel PanelUI Paper ParagraphView ParameterBlock ParameterDescriptor + ParameterizedType ParameterMetaData ParseException ParsePosition Parser ParserConfigurationException + ParserDelegator PartialResultException PasswordAuthentication PasswordCallback PasswordView Patch + PathIterator Pattern PatternSyntaxException PBEKey PBEKeySpec PBEParameterSpec PDLOverrideSupported + Permission PermissionCollection Permissions PersistenceDelegate PersistentMBean PhantomReference Pipe + PipedInputStream PipedOutputStream PipedReader PipedWriter PixelGrabber PixelInterleavedSampleModel + PKCS8EncodedKeySpec PKIXBuilderParameters PKIXCertPathBuilderResult PKIXCertPathChecker + PKIXCertPathValidatorResult PKIXParameters PlainDocument PlainView Point Point2D PointerInfo Policy + PolicyNode PolicyQualifierInfo Polygon PooledConnection Popup PopupFactory PopupMenu PopupMenuEvent + PopupMenuListener PopupMenuUI Port PortableRemoteObject PortableRemoteObjectDelegate + PortUnreachableException Position Predicate PreferenceChangeEvent PreferenceChangeListener Preferences + PreferencesFactory PreparedStatement PresentationDirection Principal Printable PrinterAbortException + PrinterException PrinterGraphics PrinterInfo PrinterIOException PrinterIsAcceptingJobs PrinterJob + PrinterLocation PrinterMakeAndModel PrinterMessageFromOperator PrinterMoreInfo + PrinterMoreInfoManufacturer PrinterName PrinterResolution PrinterState PrinterStateReason + PrinterStateReasons PrinterURI PrintEvent PrintException PrintGraphics PrintJob PrintJobAdapter + PrintJobAttribute PrintJobAttributeEvent PrintJobAttributeListener PrintJobAttributeSet PrintJobEvent + PrintJobListener PrintQuality PrintRequestAttribute PrintRequestAttributeSet PrintService + PrintServiceAttribute PrintServiceAttributeEvent PrintServiceAttributeListener PrintServiceAttributeSet + PrintServiceLookup PrintStream PrintWriter PriorityBlockingQueue PriorityQueue PrivateClassLoader + PrivateCredentialPermission PrivateKey PrivateMLet PrivilegedAction PrivilegedActionException + PrivilegedExceptionAction Process ProcessBuilder ProfileDataException ProgressBarUI ProgressMonitor + ProgressMonitorInputStream Properties PropertyChangeEvent PropertyChangeListener + PropertyChangeListenerProxy PropertyChangeSupport PropertyDescriptor PropertyEditor + PropertyEditorManager PropertyEditorSupport PropertyPermission PropertyResourceBundle + PropertyVetoException ProtectionDomain ProtocolException Provider ProviderException Proxy ProxySelector + PSource PSSParameterSpec PublicKey PushbackInputStream PushbackReader QName QuadCurve2D Query QueryEval + QueryExp Queue QueuedJobCount Random RandomAccess RandomAccessFile Raster RasterFormatException RasterOp + RC2ParameterSpec RC5ParameterSpec Rdn Readable ReadableByteChannel Reader ReadOnlyBufferException + ReadWriteLock RealmCallback RealmChoiceCallback Receiver Rectangle Rectangle2D RectangularShape + ReentrantLock ReentrantReadWriteLock Ref RefAddr Reference Referenceable ReferenceQueue + ReferenceUriSchemesSupported ReferralException ReflectionException ReflectPermission Refreshable + RefreshFailedException Region RegisterableService Registry RegistryHandler RejectedExecutionException + RejectedExecutionHandler Relation RelationException RelationNotFoundException RelationNotification + RelationService RelationServiceMBean RelationServiceNotRegisteredException RelationSupport + RelationSupportMBean RelationType RelationTypeNotFoundException RelationTypeSupport Remote RemoteCall + RemoteException RemoteObject RemoteObjectInvocationHandler RemoteRef RemoteServer RemoteStub + RenderableImage RenderableImageOp RenderableImageProducer RenderContext RenderedImage + RenderedImageFactory Renderer RenderingHints RepaintManager ReplicateScaleFilter RequestingUserName + RequiredModelMBean RescaleOp ResolutionSyntax Resolver ResolveResult ResourceBundle ResponseCache Result + ResultSet ResultSetMetaData Retention RetentionPolicy ReverbType RGBImageFilter RMIClassLoader + RMIClassLoaderSpi RMIClientSocketFactory RMIConnection RMIConnectionImpl RMIConnectionImpl_Stub + RMIConnector RMIConnectorServer RMIFailureHandler RMIIIOPServerImpl RMIJRMPServerImpl + RMISecurityException RMISecurityManager RMIServer RMIServerImpl RMIServerImpl_Stub + RMIServerSocketFactory RMISocketFactory Robot Role RoleInfo RoleInfoNotFoundException RoleList + RoleNotFoundException RoleResult RoleStatus RoleUnresolved RoleUnresolvedList RootPaneContainer + RootPaneUI RoundingMode RoundRectangle2D RowMapper RowSet RowSetEvent RowSetInternal RowSetListener + RowSetMetaData RowSetMetaDataImpl RowSetReader RowSetWarning RowSetWriter RSAKey RSAKeyGenParameterSpec + RSAMultiPrimePrivateCrtKey RSAMultiPrimePrivateCrtKeySpec RSAOtherPrimeInfo RSAPrivateCrtKey + RSAPrivateCrtKeySpec RSAPrivateKey RSAPrivateKeySpec RSAPublicKey RSAPublicKeySpec RTFEditorKit + RuleBasedCollator Runnable Runtime RuntimeErrorException RuntimeException RuntimeMBeanException + RuntimeMXBean RuntimeOperationsException RuntimePermission SampleModel Sasl SaslClient SaslClientFactory + SaslException SaslServer SaslServerFactory Savepoint SAXParser SAXParserFactory SAXResult SAXSource + SAXTransformerFactory Scanner ScatteringByteChannel ScheduledExecutorService ScheduledFuture + ScheduledThreadPoolExecutor Schema SchemaFactory SchemaFactoryLoader SchemaViolationException Scrollable + Scrollbar ScrollBarUI ScrollPane ScrollPaneAdjustable ScrollPaneConstants ScrollPaneLayout ScrollPaneUI + SealedObject SearchControls SearchResult SecretKey SecretKeyFactory SecretKeyFactorySpi SecretKeySpec + SecureCacheResponse SecureClassLoader SecureRandom SecureRandomSpi Security SecurityException + SecurityManager SecurityPermission Segment SelectableChannel SelectionKey Selector SelectorProvider + Semaphore SeparatorUI Sequence SequenceInputStream Sequencer SerialArray SerialBlob SerialClob + SerialDatalink SerialException Serializable SerializablePermission SerialJavaObject SerialRef + SerialStruct ServerCloneException ServerError ServerException ServerNotActiveException ServerRef + ServerRuntimeException ServerSocket ServerSocketChannel ServerSocketFactory ServiceNotFoundException + ServicePermission ServiceRegistry ServiceUI ServiceUIFactory ServiceUnavailableException Set + SetOfIntegerSyntax Severity Shape ShapeGraphicAttribute SheetCollate Short ShortBuffer + ShortBufferException ShortLookupTable ShortMessage Sides Signature SignatureException SignatureSpi + SignedObject Signer SimpleAttributeSet SimpleBeanInfo SimpleDateFormat SimpleDoc SimpleFormatter + SimpleTimeZone SimpleType SinglePixelPackedSampleModel SingleSelectionModel Size2DSyntax + SizeLimitExceededException SizeRequirements SizeSequence Skeleton SkeletonMismatchException + SkeletonNotFoundException SliderUI Socket SocketAddress SocketChannel SocketException SocketFactory + SocketHandler SocketImpl SocketImplFactory SocketOptions SocketPermission SocketSecurityException + SocketTimeoutException SoftBevelBorder SoftReference SortControl SortedMap SortedSet + SortingFocusTraversalPolicy SortKey SortResponseControl Soundbank SoundbankReader SoundbankResource + Source SourceDataLine SourceLocator SpinnerDateModel SpinnerListModel SpinnerModel SpinnerNumberModel + SpinnerUI SplitPaneUI Spring SpringLayout SQLData SQLException SQLInput SQLInputImpl SQLOutput + SQLOutputImpl SQLPermission SQLWarning SSLContext SSLContextSpi SSLEngine SSLEngineResult SSLException + SSLHandshakeException SSLKeyException SSLPeerUnverifiedException SSLPermission SSLProtocolException + SslRMIClientSocketFactory SslRMIServerSocketFactory SSLServerSocket SSLServerSocketFactory SSLSession + SSLSessionBindingEvent SSLSessionBindingListener SSLSessionContext SSLSocket SSLSocketFactory Stack + StackOverflowError StackTraceElement StandardMBean StartTlsRequest StartTlsResponse StateEdit + StateEditable StateFactory Statement StreamCorruptedException StreamHandler StreamPrintService + StreamPrintServiceFactory StreamResult StreamSource StreamTokenizer StrictMath String StringBuffer + StringBufferInputStream StringBuilder StringCharacterIterator StringContent + StringIndexOutOfBoundsException StringMonitor StringMonitorMBean StringReader StringRefAddr + StringSelection StringTokenizer StringValueExp StringWriter Stroke Struct Stub StubDelegate + StubNotFoundException Style StyleConstants StyleContext StyledDocument StyledEditorKit StyleSheet + Subject SubjectDelegationPermission SubjectDomainCombiner SupportedValuesAttribute SuppressWarnings + SwingConstants SwingPropertyChangeSupport SwingUtilities SyncFactory SyncFactoryException + SyncFailedException SynchronousQueue SyncProvider SyncProviderException SyncResolver SynthConstants + SynthContext Synthesizer SynthGraphicsUtils SynthLookAndFeel SynthPainter SynthStyle SynthStyleFactory + SysexMessage System SystemColor SystemFlavorMap TabableView TabbedPaneUI TabExpander TableCellEditor + TableCellRenderer TableColumn TableColumnModel TableColumnModelEvent TableColumnModelListener + TableHeaderUI TableModel TableModelEvent TableModelListener TableUI TableView TabSet TabStop TabularData + TabularDataSupport TabularType TagElement Target TargetDataLine TargetedNotification Templates + TemplatesHandler TextAction TextArea TextAttribute TextComponent TextEvent TextField TextHitInfo + TextInputCallback TextLayout TextListener TextMeasurer TextOutputCallback TextSyntax TextUI TexturePaint + Thread ThreadDeath ThreadFactory ThreadGroup ThreadInfo ThreadLocal ThreadMXBean ThreadPoolExecutor + Throwable Tie TileObserver Time TimeLimitExceededException TimeoutException Timer + TimerAlarmClockNotification TimerMBean TimerNotification TimerTask Timestamp TimeUnit TimeZone + TitledBorder ToolBarUI Toolkit ToolTipManager ToolTipUI TooManyListenersException Track + TransactionalWriter TransactionRequiredException TransactionRolledbackException Transferable + TransferHandler TransformAttribute Transformer TransformerConfigurationException TransformerException + TransformerFactory TransformerFactoryConfigurationError TransformerHandler Transmitter Transparency + TreeCellEditor TreeCellRenderer TreeExpansionEvent TreeExpansionListener TreeMap TreeModel + TreeModelEvent TreeModelListener TreeNode TreePath TreeSelectionEvent TreeSelectionListener + TreeSelectionModel TreeSet TreeUI TreeWillExpandListener TrustAnchor TrustManager TrustManagerFactory + TrustManagerFactorySpi Type TypeInfoProvider TypeNotPresentException Types TypeVariable UID UIDefaults + UIManager UIResource UndeclaredThrowableException UndoableEdit UndoableEditEvent UndoableEditListener + UndoableEditSupport UndoManager UnexpectedException UnicastRemoteObject UnknownError + UnknownFormatConversionException UnknownFormatFlagsException UnknownGroupException UnknownHostException + UnknownObjectException UnknownServiceException UnmappableCharacterException UnmarshalException + UnmodifiableClassException UnmodifiableSetException UnrecoverableEntryException + UnrecoverableKeyException Unreferenced UnresolvedAddressException UnresolvedPermission + UnsatisfiedLinkError UnsolicitedNotification UnsolicitedNotificationEvent + UnsolicitedNotificationListener UnsupportedAddressTypeException UnsupportedAudioFileException + UnsupportedCallbackException UnsupportedCharsetException UnsupportedClassVersionError + UnsupportedEncodingException UnsupportedFlavorException UnsupportedLookAndFeelException + UnsupportedOperationException URI URIException URIResolver URISyntax URISyntaxException URL + URLClassLoader URLConnection URLDecoder URLEncoder URLStreamHandler URLStreamHandlerFactory + UTFDataFormatException Util UtilDelegate Utilities UUID Validator ValidatorHandler ValueExp ValueHandler + ValueHandlerMultiFormat VariableHeightLayoutCache Vector VerifyError VetoableChangeListener + VetoableChangeListenerProxy VetoableChangeSupport View ViewFactory ViewportLayout ViewportUI + VirtualMachineError Visibility VMID VoiceStatus Void VolatileImage WeakHashMap WeakReference WebRowSet + WildcardType Window WindowAdapter WindowConstants WindowEvent WindowFocusListener WindowListener + WindowStateListener WrappedPlainView WritableByteChannel WritableRaster WritableRenderedImage + WriteAbortedException Writer X500Principal X500PrivateCredential X509Certificate X509CertSelector + X509CRL X509CRLEntry X509CRLSelector X509EncodedKeySpec X509ExtendedKeyManager X509Extension + X509KeyManager X509TrustManager XAConnection XADataSource XAException XAResource Xid XMLConstants + XMLDecoder XMLEncoder XMLFormatter XMLGregorianCalendar XMLParseException XmlReader XmlWriter XPath + XPathConstants XPathException XPathExpression XPathExpressionException XPathFactory + XPathFactoryConfigurationException XPathFunction XPathFunctionException XPathFunctionResolver + XPathVariableResolver ZipEntry ZipException ZipFile ZipInputStream ZipOutputStream ZoneView + ] + #:nocov: + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/java_script.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/java_script.rb new file mode 100644 index 0000000..9eb0a0a --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/java_script.rb @@ -0,0 +1,237 @@ +module CodeRay +module Scanners + + # Scanner for JavaScript. + # + # Aliases: +ecmascript+, +ecma_script+, +javascript+ + class JavaScript < Scanner + + register_for :java_script + file_extension 'js' + + # The actual JavaScript keywords. + KEYWORDS = %w[ + break case catch continue default delete do else + finally for function if in instanceof new + return switch throw try typeof var void while with + ] # :nodoc: + PREDEFINED_CONSTANTS = %w[ + false null true undefined NaN Infinity + ] # :nodoc: + + MAGIC_VARIABLES = %w[ this arguments ] # :nodoc: arguments was introduced in JavaScript 1.4 + + KEYWORDS_EXPECTING_VALUE = WordList.new.add %w[ + case delete in instanceof new return throw typeof with + ] # :nodoc: + + # Reserved for future use. + RESERVED_WORDS = %w[ + abstract boolean byte char class debugger double enum export extends + final float goto implements import int interface long native package + private protected public short static super synchronized throws transient + volatile + ] # :nodoc: + + IDENT_KIND = WordList.new(:ident). + add(RESERVED_WORDS, :reserved). + add(PREDEFINED_CONSTANTS, :predefined_constant). + add(MAGIC_VARIABLES, :local_variable). + add(KEYWORDS, :keyword) # :nodoc: + + ESCAPE = / [bfnrtv\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x # :nodoc: + UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x # :nodoc: + REGEXP_ESCAPE = / [bBdDsSwW] /x # :nodoc: + STRING_CONTENT_PATTERN = { + "'" => /[^\\']+/, + '"' => /[^\\"]+/, + '/' => /[^\\\/]+/, + } # :nodoc: + KEY_CHECK_PATTERN = { + "'" => / (?> [^\\']* (?: \\. [^\\']* )* ) ' \s* : /mx, + '"' => / (?> [^\\"]* (?: \\. [^\\"]* )* ) " \s* : /mx, + } # :nodoc: + + protected + + def setup + @state = :initial + end + + def scan_tokens encoder, options + + state, string_delimiter = options[:state] || @state + if string_delimiter + encoder.begin_group state + end + + value_expected = true + key_expected = false + function_expected = false + + until eos? + + case state + + when :initial + + if match = scan(/ \s+ | \\\n /x) + value_expected = true if !value_expected && match.index(?\n) + encoder.text_token match, :space + + elsif match = scan(%r! // [^\n\\]* (?: \\. [^\n\\]* )* | /\* (?: .*? \*/ | .*() ) !mx) + value_expected = true + encoder.text_token match, :comment + state = :open_multi_line_comment if self[1] + + elsif check(/\.?\d/) + key_expected = value_expected = false + if match = scan(/0[xX][0-9A-Fa-f]+/) + encoder.text_token match, :hex + elsif match = scan(/(?>0[0-7]+)(?![89.eEfF])/) + encoder.text_token match, :octal + elsif match = scan(/\d+[fF]|\d*\.\d+(?:[eE][+-]?\d+)?[fF]?|\d+[eE][+-]?\d+[fF]?/) + encoder.text_token match, :float + elsif match = scan(/\d+/) + encoder.text_token match, :integer + end + + elsif value_expected && match = scan(/<([[:alpha:]]\w*) (?: [^\/>]*\/> | .*?<\/\1>)/xim) + # TODO: scan over nested tags + xml_scanner.tokenize match, :tokens => encoder + value_expected = false + next + + elsif match = scan(/ [-+*=<>?:;,!&^|(\[{~%]+ | \.(?!\d) /x) + value_expected = true + last_operator = match[-1] + key_expected = (last_operator == ?{) || (last_operator == ?,) + function_expected = false + encoder.text_token match, :operator + + elsif match = scan(/ [)\]}]+ /x) + function_expected = key_expected = value_expected = false + encoder.text_token match, :operator + + elsif match = scan(/ [$a-zA-Z_][A-Za-z_0-9$]* /x) + kind = IDENT_KIND[match] + value_expected = (kind == :keyword) && KEYWORDS_EXPECTING_VALUE[match] + # TODO: labels + if kind == :ident + if match.index(?$) # $ allowed inside an identifier + kind = :predefined + elsif function_expected + kind = :function + elsif check(/\s*[=:]\s*function\b/) + kind = :function + elsif key_expected && check(/\s*:/) + kind = :key + end + end + function_expected = (kind == :keyword) && (match == 'function') + key_expected = false + encoder.text_token match, kind + + elsif match = scan(/["']/) + if key_expected && check(KEY_CHECK_PATTERN[match]) + state = :key + else + state = :string + end + encoder.begin_group state + string_delimiter = match + encoder.text_token match, :delimiter + + elsif value_expected && (match = scan(/\//)) + encoder.begin_group :regexp + state = :regexp + string_delimiter = '/' + encoder.text_token match, :delimiter + + elsif match = scan(/ \/ /x) + value_expected = true + key_expected = false + encoder.text_token match, :operator + + else + encoder.text_token getch, :error + + end + + when :string, :regexp, :key + if match = scan(STRING_CONTENT_PATTERN[string_delimiter]) + encoder.text_token match, :content + elsif match = scan(/["'\/]/) + encoder.text_token match, :delimiter + if state == :regexp + modifiers = scan(/[gim]+/) + encoder.text_token modifiers, :modifier if modifiers && !modifiers.empty? + end + encoder.end_group state + string_delimiter = nil + key_expected = value_expected = false + state = :initial + elsif state != :regexp && (match = scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox)) + if string_delimiter == "'" && !(match == "\\\\" || match == "\\'") + encoder.text_token match, :content + else + encoder.text_token match, :char + end + elsif state == :regexp && match = scan(/ \\ (?: #{ESCAPE} | #{REGEXP_ESCAPE} | #{UNICODE_ESCAPE} ) /mox) + encoder.text_token match, :char + elsif match = scan(/\\./m) + encoder.text_token match, :content + elsif match = scan(/ \\ | $ /x) + encoder.end_group state + encoder.text_token match, :error unless match.empty? + string_delimiter = nil + key_expected = value_expected = false + state = :initial + else + raise_inspect "else case #{string_delimiter} reached; %p not handled." % peek(1), encoder + end + + when :open_multi_line_comment + if match = scan(%r! .*? \*/ !mx) + state = :initial + else + match = scan(%r! .+ !mx) + end + value_expected = true + encoder.text_token match, :comment if match + + else + #:nocov: + raise_inspect 'Unknown state: %p' % [state], encoder + #:nocov: + + end + + end + + if options[:keep_state] + @state = state, string_delimiter + end + + if [:string, :regexp].include? state + encoder.end_group state + end + + encoder + end + + protected + + def reset_instance + super + @xml_scanner.reset if defined? @xml_scanner + end + + def xml_scanner + @xml_scanner ||= CodeRay.scanner :xml, :tokens => @tokens, :keep_tokens => true, :keep_state => false + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/json.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/json.rb new file mode 100644 index 0000000..b09970c --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/json.rb @@ -0,0 +1,98 @@ +module CodeRay +module Scanners + + # Scanner for JSON (JavaScript Object Notation). + class JSON < Scanner + + register_for :json + file_extension 'json' + + KINDS_NOT_LOC = [ + :float, :char, :content, :delimiter, + :error, :integer, :operator, :value, + ] # :nodoc: + + ESCAPE = / [bfnrt\\"\/] /x # :nodoc: + UNICODE_ESCAPE = / u[a-fA-F0-9]{4} /x # :nodoc: + KEY = / (?> (?: [^\\"]+ | \\. )* ) " \s* : /x + + protected + + def setup + @state = :initial + end + + # See http://json.org/ for a definition of the JSON lexic/grammar. + def scan_tokens encoder, options + state = options[:state] || @state + + if [:string, :key].include? state + encoder.begin_group state + end + + until eos? + + case state + + when :initial + if match = scan(/ \s+ /x) + encoder.text_token match, :space + elsif match = scan(/"/) + state = check(/#{KEY}/o) ? :key : :string + encoder.begin_group state + encoder.text_token match, :delimiter + elsif match = scan(/ [:,\[{\]}] /x) + encoder.text_token match, :operator + elsif match = scan(/ true | false | null /x) + encoder.text_token match, :value + elsif match = scan(/ -? (?: 0 | [1-9]\d* ) /x) + if scan(/ \.\d+ (?:[eE][-+]?\d+)? | [eE][-+]? \d+ /x) + match << matched + encoder.text_token match, :float + else + encoder.text_token match, :integer + end + else + encoder.text_token getch, :error + end + + when :string, :key + if match = scan(/[^\\"]+/) + encoder.text_token match, :content + elsif match = scan(/"/) + encoder.text_token match, :delimiter + encoder.end_group state + state = :initial + elsif match = scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox) + encoder.text_token match, :char + elsif match = scan(/\\./m) + encoder.text_token match, :content + elsif match = scan(/ \\ | $ /x) + encoder.end_group state + encoder.text_token match, :error unless match.empty? + state = :initial + else + raise_inspect "else case \" reached; %p not handled." % peek(1), encoder + end + + else + raise_inspect 'Unknown state: %p' % [state], encoder + + end + end + + if options[:keep_state] + @state = state + end + + if [:string, :key].include? state + encoder.end_group state + end + + encoder + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/lua.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/lua.rb new file mode 100644 index 0000000..fb1e45a --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/lua.rb @@ -0,0 +1,280 @@ +# encoding: utf-8 + +module CodeRay +module Scanners + + # Scanner for the Lua[http://lua.org] programming lanuage. + # + # The language’s complete syntax is defined in + # {the Lua manual}[http://www.lua.org/manual/5.2/manual.html], + # which is what this scanner tries to conform to. + class Lua < Scanner + + register_for :lua + file_extension 'lua' + title 'Lua' + + # Keywords used in Lua. + KEYWORDS = %w[and break do else elseif end + for function goto if in + local not or repeat return + then until while + ] + + # Constants set by the Lua core. + PREDEFINED_CONSTANTS = %w[false true nil] + + # The expressions contained in this array are parts of Lua’s `basic' + # library. Although it’s not entirely necessary to load that library, + # it is highly recommended and one would have to provide own implementations + # of some of these expressions if one does not do so. They however aren’t + # keywords, neither are they constants, but nearly predefined, so they + # get tagged as `predefined' rather than anything else. + # + # This list excludes values of form `_UPPERCASE' because the Lua manual + # requires such identifiers to be reserved by Lua anyway and they are + # highlighted directly accordingly, without the need for specific + # identifiers to be listed here. + PREDEFINED_EXPRESSIONS = %w[ + assert collectgarbage dofile error getmetatable + ipairs load loadfile next pairs pcall print + rawequal rawget rawlen rawset select setmetatable + tonumber tostring type xpcall + ] + + # Automatic token kind selection for normal words. + IDENT_KIND = CodeRay::WordList.new(:ident). + add(KEYWORDS, :keyword). + add(PREDEFINED_CONSTANTS, :predefined_constant). + add(PREDEFINED_EXPRESSIONS, :predefined) + + protected + + # Scanner initialization. + def setup + @state = :initial + @brace_depth = 0 + end + + # CodeRay entry hook. Starts parsing. + def scan_tokens(encoder, options) + state = options[:state] || @state + brace_depth = @brace_depth + num_equals = nil + + until eos? + case state + + when :initial + if match = scan(/\-\-\[\=*\[/) #--[[ long (possibly multiline) comment ]] + num_equals = match.count("=") # Number must match for comment end + encoder.begin_group(:comment) + encoder.text_token(match, :delimiter) + state = :long_comment + + elsif match = scan(/--.*$/) # --Lua comment + encoder.text_token(match, :comment) + + elsif match = scan(/\[=*\[/) # [[ long (possibly multiline) string ]] + num_equals = match.count("=") # Number must match for comment end + encoder.begin_group(:string) + encoder.text_token(match, :delimiter) + state = :long_string + + elsif match = scan(/::\s*[a-zA-Z_][a-zA-Z0-9_]+\s*::/) # ::goto_label:: + encoder.text_token(match, :label) + + elsif match = scan(/_[A-Z]+/) # _UPPERCASE are names reserved for Lua + encoder.text_token(match, :predefined) + + elsif match = scan(/[a-zA-Z_][a-zA-Z0-9_]*/) # Normal letters (or letters followed by digits) + kind = IDENT_KIND[match] + + # Extra highlighting for entities following certain keywords + if kind == :keyword and match == "function" + state = :function_expected + elsif kind == :keyword and match == "goto" + state = :goto_label_expected + elsif kind == :keyword and match == "local" + state = :local_var_expected + end + + encoder.text_token(match, kind) + + elsif match = scan(/\{/) # Opening table brace { + encoder.begin_group(:map) + encoder.text_token(match, brace_depth >= 1 ? :inline_delimiter : :delimiter) + brace_depth += 1 + state = :map + + elsif match = scan(/\}/) # Closing table brace } + if brace_depth == 1 + brace_depth = 0 + encoder.text_token(match, :delimiter) + encoder.end_group(:map) + elsif brace_depth == 0 # Mismatched brace + encoder.text_token(match, :error) + else + brace_depth -= 1 + encoder.text_token(match, :inline_delimiter) + encoder.end_group(:map) + state = :map + end + + elsif match = scan(/["']/) # String delimiters " and ' + encoder.begin_group(:string) + encoder.text_token(match, :delimiter) + start_delim = match + state = :string + + # ↓Prefix hex number ←|→ decimal number + elsif match = scan(/-? (?:0x\h* \. \h+ (?:p[+\-]?\d+)? | \d*\.\d+ (?:e[+\-]?\d+)?)/ix) # hexadecimal constants have no E power, decimal ones no P power + encoder.text_token(match, :float) + + # ↓Prefix hex number ←|→ decimal number + elsif match = scan(/-? (?:0x\h+ (?:p[+\-]?\d+)? | \d+ (?:e[+\-]?\d+)?)/ix) # hexadecimal constants have no E power, decimal ones no P power + encoder.text_token(match, :integer) + + elsif match = scan(/[\+\-\*\/%^\#=~<>\(\)\[\]:;,] | \.(?!\d)/x) # Operators + encoder.text_token(match, :operator) + + elsif match = scan(/\s+/) # Space + encoder.text_token(match, :space) + + else # Invalid stuff. Note that Lua doesn’t accept multibyte chars outside of strings, hence these are also errors. + encoder.text_token(getch, :error) + end + + # It may be that we’re scanning a full-blown subexpression of a table + # (tables can contain full expressions in parts). + # If this is the case, return to :map scanning state. + state = :map if state == :initial && brace_depth >= 1 + + when :function_expected + if match = scan(/\(.*?\)/m) # x = function() # "Anonymous" function without explicit name + encoder.text_token(match, :operator) + state = :initial + elsif match = scan(/[a-zA-Z_] (?:[a-zA-Z0-9_\.] (?!\.\d))* [\.\:]/x) # function tbl.subtbl.foo() | function tbl:foo() # Colon only allowed as last separator + encoder.text_token(match, :ident) + elsif match = scan(/[a-zA-Z_][a-zA-Z0-9_]*/) # function foo() + encoder.text_token(match, :function) + state = :initial + elsif match = scan(/\s+/) # Between the `function' keyword and the ident may be any amount of whitespace + encoder.text_token(match, :space) + else + encoder.text_token(getch, :error) + state = :initial + end + + when :goto_label_expected + if match = scan(/[a-zA-Z_][a-zA-Z0-9_]*/) + encoder.text_token(match, :label) + state = :initial + elsif match = scan(/\s+/) # Between the `goto' keyword and the label may be any amount of whitespace + encoder.text_token(match, :space) + else + encoder.text_token(getch, :error) + end + + when :local_var_expected + if match = scan(/function/) # local function ... + encoder.text_token(match, :keyword) + state = :function_expected + elsif match = scan(/[a-zA-Z_][a-zA-Z0-9_]*/) + encoder.text_token(match, :local_variable) + elsif match = scan(/,/) + encoder.text_token(match, :operator) + elsif match = scan(/\=/) + encoder.text_token(match, :operator) + # After encountering the equal sign, arbitrary expressions are + # allowed again, so just return to the main state for further + # parsing. + state = :initial + elsif match = scan(/\n/) + encoder.text_token(match, :space) + state = :initial + elsif match = scan(/\s+/) + encoder.text_token(match, :space) + else + encoder.text_token(getch, :error) + end + + when :long_comment + if match = scan(/.*?(?=\]={#{num_equals}}\])/m) + encoder.text_token(match, :content) + + delim = scan(/\]={#{num_equals}}\]/) + encoder.text_token(delim, :delimiter) + else # No terminator found till EOF + encoder.text_token(rest, :error) + terminate + end + encoder.end_group(:comment) + state = :initial + + when :long_string + if match = scan(/.*?(?=\]={#{num_equals}}\])/m) # Long strings do not interpret any escape sequences + encoder.text_token(match, :content) + + delim = scan(/\]={#{num_equals}}\]/) + encoder.text_token(delim, :delimiter) + else # No terminator found till EOF + encoder.text_token(rest, :error) + terminate + end + encoder.end_group(:string) + state = :initial + + when :string + if match = scan(/[^\\#{start_delim}\n]+/) # Everything except \ and the start delimiter character is string content (newlines are only allowed if preceeded by \ or \z) + encoder.text_token(match, :content) + elsif match = scan(/\\(?:['"abfnrtv\\]|z\s*|x\h\h|\d{1,3}|\n)/m) + encoder.text_token(match, :char) + elsif match = scan(Regexp.compile(start_delim)) + encoder.text_token(match, :delimiter) + encoder.end_group(:string) + state = :initial + elsif match = scan(/\n/) # Lua forbids unescaped newlines in normal non-long strings + encoder.text_token("\\n\n", :error) # Visually appealing error indicator--otherwise users may wonder whether the highlighter cannot highlight multine strings + encoder.end_group(:string) + state = :initial + else + encoder.text_token(getch, :error) + end + + when :map + if match = scan(/[,;]/) + encoder.text_token(match, :operator) + elsif match = scan(/[a-zA-Z_][a-zA-Z0-9_]* (?=\s*=)/x) + encoder.text_token(match, :key) + encoder.text_token(scan(/\s+/), :space) if check(/\s+/) + encoder.text_token(scan(/\=/), :operator) + state = :initial + elsif match = scan(/\s+/m) + encoder.text_token(match, :space) + else + # Note this clause doesn’t advance the scan pointer, it’s a kind of + # "retry with other options" (the :initial state then of course + # advances the pointer). + state = :initial + end + else + raise + end + + end + + if options[:keep_state] + @state = state + end + + encoder.end_group :string if [:string].include? state + brace_depth.times { encoder.end_group :map } + + encoder + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/php.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/php.rb new file mode 100644 index 0000000..7a8d75d --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/php.rb @@ -0,0 +1,527 @@ +# encoding: utf-8 +module CodeRay +module Scanners + + load :html + + # Scanner for PHP. + # + # Original by Stefan Walk. + class PHP < Scanner + + register_for :php + file_extension 'php' + + KINDS_NOT_LOC = HTML::KINDS_NOT_LOC + + protected + + def setup + @html_scanner = CodeRay.scanner :html, :tokens => @tokens, :keep_tokens => true, :keep_state => true + end + + def reset_instance + super + @html_scanner.reset + end + + module Words # :nodoc: + + # according to http://www.php.net/manual/en/reserved.keywords.php + KEYWORDS = %w[ + abstract and array as break case catch class clone const continue declare default do else elseif + enddeclare endfor endforeach endif endswitch endwhile extends final for foreach function global + goto if implements interface instanceof namespace new or private protected public static switch + throw try use var while xor + cfunction old_function + ] + + TYPES = %w[ int integer float double bool boolean string array object resource ] + + LANGUAGE_CONSTRUCTS = %w[ + die echo empty exit eval include include_once isset list + require require_once return print unset + ] + + CLASSES = %w[ Directory stdClass __PHP_Incomplete_Class exception php_user_filter Closure ] + + # according to http://php.net/quickref.php on 2009-04-21; + # all functions with _ excluded (module functions) and selected additional functions + BUILTIN_FUNCTIONS = %w[ + abs acos acosh addcslashes addslashes aggregate array arsort ascii2ebcdic asin asinh asort assert atan atan2 + atanh basename bcadd bccomp bcdiv bcmod bcmul bcpow bcpowmod bcscale bcsqrt bcsub bin2hex bindec + bindtextdomain bzclose bzcompress bzdecompress bzerrno bzerror bzerrstr bzflush bzopen bzread bzwrite + calculhmac ceil chdir checkdate checkdnsrr chgrp chmod chop chown chr chroot clearstatcache closedir closelog + compact constant copy cos cosh count crc32 crypt current date dcgettext dcngettext deaggregate decbin dechex + decoct define defined deg2rad delete dgettext die dirname diskfreespace dl dngettext doubleval each + ebcdic2ascii echo empty end ereg eregi escapeshellarg escapeshellcmd eval exec exit exp explode expm1 extract + fclose feof fflush fgetc fgetcsv fgets fgetss file fileatime filectime filegroup fileinode filemtime fileowner + fileperms filepro filesize filetype floatval flock floor flush fmod fnmatch fopen fpassthru fprintf fputcsv + fputs fread frenchtojd fscanf fseek fsockopen fstat ftell ftok ftruncate fwrite getallheaders getcwd getdate + getenv gethostbyaddr gethostbyname gethostbynamel getimagesize getlastmod getmxrr getmygid getmyinode getmypid + getmyuid getopt getprotobyname getprotobynumber getrandmax getrusage getservbyname getservbyport gettext + gettimeofday gettype glob gmdate gmmktime gmstrftime gregoriantojd gzclose gzcompress gzdecode gzdeflate + gzencode gzeof gzfile gzgetc gzgets gzgetss gzinflate gzopen gzpassthru gzputs gzread gzrewind gzseek gztell + gzuncompress gzwrite hash header hebrev hebrevc hexdec htmlentities htmlspecialchars hypot iconv idate + implode include intval ip2long iptcembed iptcparse isset + jddayofweek jdmonthname jdtofrench jdtogregorian jdtojewish jdtojulian jdtounix jewishtojd join jpeg2wbmp + juliantojd key krsort ksort lcfirst lchgrp lchown levenshtein link linkinfo list localeconv localtime log + log10 log1p long2ip lstat ltrim mail main max md5 metaphone mhash microtime min mkdir mktime msql natcasesort + natsort next ngettext nl2br nthmac octdec opendir openlog + ord overload pack passthru pathinfo pclose pfsockopen phpcredits phpinfo phpversion pi png2wbmp popen pos pow + prev print printf putenv quotemeta rad2deg rand range rawurldecode rawurlencode readdir readfile readgzfile + readline readlink realpath recode rename require reset rewind rewinddir rmdir round rsort rtrim scandir + serialize setcookie setlocale setrawcookie settype sha1 shuffle signeurlpaiement sin sinh sizeof sleep snmpget + snmpgetnext snmprealwalk snmpset snmpwalk snmpwalkoid sort soundex split spliti sprintf sqrt srand sscanf stat + strcasecmp strchr strcmp strcoll strcspn strftime stripcslashes stripos stripslashes stristr strlen + strnatcasecmp strnatcmp strncasecmp strncmp strpbrk strpos strptime strrchr strrev strripos strrpos strspn + strstr strtok strtolower strtotime strtoupper strtr strval substr symlink syslog system tan tanh tempnam + textdomain time tmpfile touch trim uasort ucfirst ucwords uksort umask uniqid unixtojd unlink unpack + unserialize unset urldecode urlencode usleep usort vfprintf virtual vprintf vsprintf wordwrap + array_change_key_case array_chunk array_combine array_count_values array_diff array_diff_assoc + array_diff_key array_diff_uassoc array_diff_ukey array_fill array_fill_keys array_filter array_flip + array_intersect array_intersect_assoc array_intersect_key array_intersect_uassoc array_intersect_ukey + array_key_exists array_keys array_map array_merge array_merge_recursive array_multisort array_pad + array_pop array_product array_push array_rand array_reduce array_reverse array_search array_shift + array_slice array_splice array_sum array_udiff array_udiff_assoc array_udiff_uassoc array_uintersect + array_uintersect_assoc array_uintersect_uassoc array_unique array_unshift array_values array_walk + array_walk_recursive + assert_options base_convert base64_decode base64_encode + chunk_split class_exists class_implements class_parents + count_chars debug_backtrace debug_print_backtrace debug_zval_dump + error_get_last error_log error_reporting extension_loaded + file_exists file_get_contents file_put_contents load_file + func_get_arg func_get_args func_num_args function_exists + get_browser get_called_class get_cfg_var get_class get_class_methods get_class_vars + get_current_user get_declared_classes get_declared_interfaces get_defined_constants + get_defined_functions get_defined_vars get_extension_funcs get_headers get_html_translation_table + get_include_path get_included_files get_loaded_extensions get_magic_quotes_gpc get_magic_quotes_runtime + get_meta_tags get_object_vars get_parent_class get_required_filesget_resource_type + gc_collect_cycles gc_disable gc_enable gc_enabled + halt_compiler headers_list headers_sent highlight_file highlight_string + html_entity_decode htmlspecialchars_decode + in_array include_once inclued_get_data + is_a is_array is_binary is_bool is_buffer is_callable is_dir is_double is_executable is_file is_finite + is_float is_infinite is_int is_integer is_link is_long is_nan is_null is_numeric is_object is_readable + is_real is_resource is_scalar is_soap_fault is_string is_subclass_of is_unicode is_uploaded_file + is_writable is_writeable + locale_get_default locale_set_default + number_format override_function parse_str parse_url + php_check_syntax php_ini_loaded_file php_ini_scanned_files php_logo_guid php_sapi_name + php_strip_whitespace php_uname + preg_filter preg_grep preg_last_error preg_match preg_match_all preg_quote preg_replace + preg_replace_callback preg_split print_r + require_once register_shutdown_function register_tick_function + set_error_handler set_exception_handler set_file_buffer set_include_path + set_magic_quotes_runtime set_time_limit shell_exec + str_getcsv str_ireplace str_pad str_repeat str_replace str_rot13 str_shuffle str_split str_word_count + strip_tags substr_compare substr_count substr_replace + time_nanosleep time_sleep_until + token_get_all token_name trigger_error + unregister_tick_function use_soap_error_handler user_error + utf8_decode utf8_encode var_dump var_export + version_compare + zend_logo_guid zend_thread_id zend_version + create_function call_user_func_array + posix_access posix_ctermid posix_get_last_error posix_getcwd posix_getegid + posix_geteuid posix_getgid posix_getgrgid posix_getgrnam posix_getgroups + posix_getlogin posix_getpgid posix_getpgrp posix_getpid posix_getppid + posix_getpwnam posix_getpwuid posix_getrlimit posix_getsid posix_getuid + posix_initgroups posix_isatty posix_kill posix_mkfifo posix_mknod + posix_setegid posix_seteuid posix_setgid posix_setpgid posix_setsid + posix_setuid posix_strerror posix_times posix_ttyname posix_uname + pcntl_alarm pcntl_exec pcntl_fork pcntl_getpriority pcntl_setpriority + pcntl_signal pcntl_signal_dispatch pcntl_sigprocmask pcntl_sigtimedwait + pcntl_sigwaitinfo pcntl_wait pcntl_waitpid pcntl_wexitstatus pcntl_wifexited + pcntl_wifsignaled pcntl_wifstopped pcntl_wstopsig pcntl_wtermsig + ] + # TODO: more built-in PHP functions? + + EXCEPTIONS = %w[ + E_ERROR E_WARNING E_PARSE E_NOTICE E_CORE_ERROR E_CORE_WARNING E_COMPILE_ERROR E_COMPILE_WARNING + E_USER_ERROR E_USER_WARNING E_USER_NOTICE E_DEPRECATED E_USER_DEPRECATED E_ALL E_STRICT + ] + + CONSTANTS = %w[ + null true false self parent + __LINE__ __DIR__ __FILE__ __LINE__ + __CLASS__ __NAMESPACE__ __METHOD__ __FUNCTION__ + PHP_VERSION PHP_MAJOR_VERSION PHP_MINOR_VERSION PHP_RELEASE_VERSION PHP_VERSION_ID PHP_EXTRA_VERSION PHP_ZTS + PHP_DEBUG PHP_MAXPATHLEN PHP_OS PHP_SAPI PHP_EOL PHP_INT_MAX PHP_INT_SIZE DEFAULT_INCLUDE_PATH + PEAR_INSTALL_DIR PEAR_EXTENSION_DIR PHP_EXTENSION_DIR PHP_PREFIX PHP_BINDIR PHP_LIBDIR PHP_DATADIR + PHP_SYSCONFDIR PHP_LOCALSTATEDIR PHP_CONFIG_FILE_PATH PHP_CONFIG_FILE_SCAN_DIR PHP_SHLIB_SUFFIX + PHP_OUTPUT_HANDLER_START PHP_OUTPUT_HANDLER_CONT PHP_OUTPUT_HANDLER_END + __COMPILER_HALT_OFFSET__ + EXTR_OVERWRITE EXTR_SKIP EXTR_PREFIX_SAME EXTR_PREFIX_ALL EXTR_PREFIX_INVALID EXTR_PREFIX_IF_EXISTS + EXTR_IF_EXISTS SORT_ASC SORT_DESC SORT_REGULAR SORT_NUMERIC SORT_STRING CASE_LOWER CASE_UPPER COUNT_NORMAL + COUNT_RECURSIVE ASSERT_ACTIVE ASSERT_CALLBACK ASSERT_BAIL ASSERT_WARNING ASSERT_QUIET_EVAL CONNECTION_ABORTED + CONNECTION_NORMAL CONNECTION_TIMEOUT INI_USER INI_PERDIR INI_SYSTEM INI_ALL M_E M_LOG2E M_LOG10E M_LN2 M_LN10 + M_PI M_PI_2 M_PI_4 M_1_PI M_2_PI M_2_SQRTPI M_SQRT2 M_SQRT1_2 CRYPT_SALT_LENGTH CRYPT_STD_DES CRYPT_EXT_DES + CRYPT_MD5 CRYPT_BLOWFISH DIRECTORY_SEPARATOR SEEK_SET SEEK_CUR SEEK_END LOCK_SH LOCK_EX LOCK_UN LOCK_NB + HTML_SPECIALCHARS HTML_ENTITIES ENT_COMPAT ENT_QUOTES ENT_NOQUOTES INFO_GENERAL INFO_CREDITS + INFO_CONFIGURATION INFO_MODULES INFO_ENVIRONMENT INFO_VARIABLES INFO_LICENSE INFO_ALL CREDITS_GROUP + CREDITS_GENERAL CREDITS_SAPI CREDITS_MODULES CREDITS_DOCS CREDITS_FULLPAGE CREDITS_QA CREDITS_ALL STR_PAD_LEFT + STR_PAD_RIGHT STR_PAD_BOTH PATHINFO_DIRNAME PATHINFO_BASENAME PATHINFO_EXTENSION PATH_SEPARATOR CHAR_MAX + LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_ALL LC_MESSAGES ABDAY_1 ABDAY_2 ABDAY_3 ABDAY_4 ABDAY_5 + ABDAY_6 ABDAY_7 DAY_1 DAY_2 DAY_3 DAY_4 DAY_5 DAY_6 DAY_7 ABMON_1 ABMON_2 ABMON_3 ABMON_4 ABMON_5 ABMON_6 + ABMON_7 ABMON_8 ABMON_9 ABMON_10 ABMON_11 ABMON_12 MON_1 MON_2 MON_3 MON_4 MON_5 MON_6 MON_7 MON_8 MON_9 + MON_10 MON_11 MON_12 AM_STR PM_STR D_T_FMT D_FMT T_FMT T_FMT_AMPM ERA ERA_YEAR ERA_D_T_FMT ERA_D_FMT ERA_T_FMT + ALT_DIGITS INT_CURR_SYMBOL CURRENCY_SYMBOL CRNCYSTR MON_DECIMAL_POINT MON_THOUSANDS_SEP MON_GROUPING + POSITIVE_SIGN NEGATIVE_SIGN INT_FRAC_DIGITS FRAC_DIGITS P_CS_PRECEDES P_SEP_BY_SPACE N_CS_PRECEDES + N_SEP_BY_SPACE P_SIGN_POSN N_SIGN_POSN DECIMAL_POINT RADIXCHAR THOUSANDS_SEP THOUSEP GROUPING YESEXPR NOEXPR + YESSTR NOSTR CODESET LOG_EMERG LOG_ALERT LOG_CRIT LOG_ERR LOG_WARNING LOG_NOTICE LOG_INFO LOG_DEBUG LOG_KERN + LOG_USER LOG_MAIL LOG_DAEMON LOG_AUTH LOG_SYSLOG LOG_LPR LOG_NEWS LOG_UUCP LOG_CRON LOG_AUTHPRIV LOG_LOCAL0 + LOG_LOCAL1 LOG_LOCAL2 LOG_LOCAL3 LOG_LOCAL4 LOG_LOCAL5 LOG_LOCAL6 LOG_LOCAL7 LOG_PID LOG_CONS LOG_ODELAY + LOG_NDELAY LOG_NOWAIT LOG_PERROR + ] + + PREDEFINED = %w[ + $GLOBALS $_SERVER $_GET $_POST $_FILES $_REQUEST $_SESSION $_ENV + $_COOKIE $php_errormsg $HTTP_RAW_POST_DATA $http_response_header + $argc $argv + ] + + IDENT_KIND = WordList::CaseIgnoring.new(:ident). + add(KEYWORDS, :keyword). + add(TYPES, :predefined_type). + add(LANGUAGE_CONSTRUCTS, :keyword). + add(BUILTIN_FUNCTIONS, :predefined). + add(CLASSES, :predefined_constant). + add(EXCEPTIONS, :exception). + add(CONSTANTS, :predefined_constant) + + VARIABLE_KIND = WordList.new(:local_variable). + add(PREDEFINED, :predefined) + end + + module RE # :nodoc: + + PHP_START = / + ]*?language\s*=\s*"php"[^>]*?> | + ]*?language\s*=\s*'php'[^>]*?> | + <\?php\d? | + <\?(?!xml) + /xi + + PHP_END = %r! + | + \?> + !xi + + HTML_INDICATOR = / ]/i + + IDENTIFIER = 'ä'[/[[:alpha:]]/] == 'ä' ? Regexp.new('[[:alpha:]_[^\0-\177]][[:alnum:]_[^\0-\177]]*') : Regexp.new('[a-z_\x7f-\xFF][a-z0-9_\x7f-\xFF]*', true) + VARIABLE = /\$#{IDENTIFIER}/ + + OPERATOR = / + \.(?!\d)=? | # dot that is not decimal point, string concatenation + && | \|\| | # logic + :: | -> | => | # scope, member, dictionary + \\(?!\n) | # namespace + \+\+ | -- | # increment, decrement + [,;?:()\[\]{}] | # simple delimiters + [-+*\/%&|^]=? | # ordinary math, binary logic, assignment shortcuts + [~$] | # whatever + =& | # reference assignment + [=!]=?=? | <> | # comparison and assignment + <<=? | >>=? | [<>]=? # comparison and shift + /x + + end + + protected + + def scan_tokens encoder, options + + if check(RE::PHP_START) || # starts with #{RE::IDENTIFIER}/o) + encoder.begin_group :inline + encoder.text_token match, :local_variable + encoder.text_token scan(/->/), :operator + encoder.text_token scan(/#{RE::IDENTIFIER}/o), :ident + encoder.end_group :inline + elsif check(/->/) + match << scan(/->/) + encoder.text_token match, :error + else + encoder.text_token match, :local_variable + end + elsif match = scan(/\{/) + if check(/\$/) + encoder.begin_group :inline + states[-1] = [states.last, delimiter] + delimiter = nil + states.push :php_inline + encoder.text_token match, :delimiter + else + encoder.text_token match, :content + end + elsif match = scan(/\$\{#{RE::IDENTIFIER}\}/o) + encoder.text_token match, :local_variable + elsif match = scan(/\$/) + encoder.text_token match, :content + else + encoder.end_group :string + states.pop + end + + when :class_expected + if match = scan(/\s+/) + encoder.text_token match, :space + elsif match = scan(/#{RE::IDENTIFIER}/o) + encoder.text_token match, :class + states.pop + else + states.pop + end + + when :function_expected + if match = scan(/\s+/) + encoder.text_token match, :space + elsif match = scan(/&/) + encoder.text_token match, :operator + elsif match = scan(/#{RE::IDENTIFIER}/o) + encoder.text_token match, :function + states.pop + else + states.pop + end + + else + raise_inspect 'Unknown state!', encoder, states + end + + end + + while state = states.pop + encoder.end_group :string if [:sqstring, :dqstring].include? state + if state.is_a? Array + encoder.end_group :inline + encoder.end_group :string if [:sqstring, :dqstring].include? state.first + end + end + + encoder + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/python.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/python.rb new file mode 100644 index 0000000..09c8b6e --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/python.rb @@ -0,0 +1,287 @@ +module CodeRay +module Scanners + + # Scanner for Python. Supports Python 3. + # + # Based on pygments' PythonLexer, see + # http://dev.pocoo.org/projects/pygments/browser/pygments/lexers/agile.py. + class Python < Scanner + + register_for :python + file_extension 'py' + + KEYWORDS = [ + 'and', 'as', 'assert', 'break', 'class', 'continue', 'def', + 'del', 'elif', 'else', 'except', 'finally', 'for', + 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'not', + 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield', + 'nonlocal', # new in Python 3 + ] # :nodoc: + + OLD_KEYWORDS = [ + 'exec', 'print', # gone in Python 3 + ] # :nodoc: + + PREDEFINED_METHODS_AND_TYPES = %w[ + __import__ abs all any apply basestring bin bool buffer + bytearray bytes callable chr classmethod cmp coerce compile + complex delattr dict dir divmod enumerate eval execfile exit + file filter float frozenset getattr globals hasattr hash hex id + input int intern isinstance issubclass iter len list locals + long map max min next object oct open ord pow property range + raw_input reduce reload repr reversed round set setattr slice + sorted staticmethod str sum super tuple type unichr unicode + vars xrange zip + ] # :nodoc: + + PREDEFINED_EXCEPTIONS = %w[ + ArithmeticError AssertionError AttributeError + BaseException DeprecationWarning EOFError EnvironmentError + Exception FloatingPointError FutureWarning GeneratorExit IOError + ImportError ImportWarning IndentationError IndexError KeyError + KeyboardInterrupt LookupError MemoryError NameError + NotImplemented NotImplementedError OSError OverflowError + OverflowWarning PendingDeprecationWarning ReferenceError + RuntimeError RuntimeWarning StandardError StopIteration + SyntaxError SyntaxWarning SystemError SystemExit TabError + TypeError UnboundLocalError UnicodeDecodeError + UnicodeEncodeError UnicodeError UnicodeTranslateError + UnicodeWarning UserWarning ValueError Warning ZeroDivisionError + ] # :nodoc: + + PREDEFINED_VARIABLES_AND_CONSTANTS = [ + 'False', 'True', 'None', # "keywords" since Python 3 + 'self', 'Ellipsis', 'NotImplemented', + ] # :nodoc: + + IDENT_KIND = WordList.new(:ident). + add(KEYWORDS, :keyword). + add(OLD_KEYWORDS, :old_keyword). + add(PREDEFINED_METHODS_AND_TYPES, :predefined). + add(PREDEFINED_VARIABLES_AND_CONSTANTS, :predefined_constant). + add(PREDEFINED_EXCEPTIONS, :exception) # :nodoc: + + NAME = / [[:alpha:]_] \w* /x # :nodoc: + ESCAPE = / [abfnrtv\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x # :nodoc: + UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} | N\{[-\w ]+\} /x # :nodoc: + + OPERATOR = / + \.\.\. | # ellipsis + \.(?!\d) | # dot but not decimal point + [,;:()\[\]{}] | # simple delimiters + \/\/=? | \*\*=? | # special math + [-+*\/%&|^]=? | # ordinary math and binary logic + [~`] | # binary complement and inspection + <<=? | >>=? | [<>=]=? | != # comparison and assignment + /x # :nodoc: + + STRING_DELIMITER_REGEXP = Hash.new { |h, delimiter| + h[delimiter] = Regexp.union delimiter # :nodoc: + } + + STRING_CONTENT_REGEXP = Hash.new { |h, delimiter| + h[delimiter] = / [^\\\n]+? (?= \\ | $ | #{Regexp.escape(delimiter)} ) /x # :nodoc: + } + + DEF_NEW_STATE = WordList.new(:initial). + add(%w(def), :def_expected). + add(%w(import from), :include_expected). + add(%w(class), :class_expected) # :nodoc: + + DESCRIPTOR = / + #{NAME} + (?: \. #{NAME} )* + | \* + /x # :nodoc: + + DOCSTRING_COMING = / + [ \t]* u?r? ("""|''') + /x # :nodoc: + + protected + + def scan_tokens encoder, options + + state = :initial + string_delimiter = nil + string_raw = false + string_type = nil + docstring_coming = match?(/#{DOCSTRING_COMING}/o) + last_token_dot = false + unicode = string.respond_to?(:encoding) && string.encoding.name == 'UTF-8' + from_import_state = [] + + until eos? + + if state == :string + if match = scan(STRING_DELIMITER_REGEXP[string_delimiter]) + encoder.text_token match, :delimiter + encoder.end_group string_type + string_type = nil + state = :initial + next + elsif string_delimiter.size == 3 && match = scan(/\n/) + encoder.text_token match, :content + elsif match = scan(STRING_CONTENT_REGEXP[string_delimiter]) + encoder.text_token match, :content + elsif !string_raw && match = scan(/ \\ #{ESCAPE} /ox) + encoder.text_token match, :char + elsif match = scan(/ \\ #{UNICODE_ESCAPE} /ox) + encoder.text_token match, :char + elsif match = scan(/ \\ . /x) + encoder.text_token match, :content + elsif match = scan(/ \\ | $ /x) + encoder.end_group string_type + string_type = nil + encoder.text_token match, :error unless match.empty? + state = :initial + else + raise_inspect "else case \" reached; %p not handled." % peek(1), encoder, state + end + + elsif match = scan(/ [ \t]+ | \\?\n /x) + encoder.text_token match, :space + if match == "\n" + state = :initial if state == :include_expected + docstring_coming = true if match?(/#{DOCSTRING_COMING}/o) + end + next + + elsif match = scan(/ \# [^\n]* /mx) + encoder.text_token match, :comment + next + + elsif state == :initial + + if match = scan(/#{OPERATOR}/o) + encoder.text_token match, :operator + + elsif match = scan(/(u?r?|b)?("""|"|'''|')/i) + modifiers = self[1] + string_delimiter = self[2] + string_type = docstring_coming ? :docstring : (modifiers == 'b' ? :binary : :string) + docstring_coming = false if docstring_coming + encoder.begin_group string_type + string_raw = false + unless modifiers.empty? + string_raw = !!modifiers.index(?r) + encoder.text_token modifiers, :modifier + match = string_delimiter + end + state = :string + encoder.text_token match, :delimiter + + # TODO: backticks + + elsif match = scan(unicode ? /#{NAME}/uo : /#{NAME}/o) + kind = IDENT_KIND[match] + # TODO: keyword arguments + kind = :ident if last_token_dot + if kind == :old_keyword + kind = check(/\(/) ? :ident : :keyword + elsif kind == :predefined && check(/ *=/) + kind = :ident + elsif kind == :keyword + state = DEF_NEW_STATE[match] + from_import_state << match.to_sym if state == :include_expected + end + encoder.text_token match, kind + + elsif match = scan(/@[a-zA-Z0-9_.]+[lL]?/) + encoder.text_token match, :decorator + + elsif match = scan(/0[xX][0-9A-Fa-f]+[lL]?/) + encoder.text_token match, :hex + + elsif match = scan(/0[bB][01]+[lL]?/) + encoder.text_token match, :binary + + elsif match = scan(/(?:\d*\.\d+|\d+\.\d*)(?:[eE][+-]?\d+)?|\d+[eE][+-]?\d+/) + if scan(/[jJ]/) + match << matched + encoder.text_token match, :imaginary + else + encoder.text_token match, :float + end + + elsif match = scan(/0[oO][0-7]+|0[0-7]+(?![89.eE])[lL]?/) + encoder.text_token match, :octal + + elsif match = scan(/\d+([lL])?/) + if self[1] == nil && scan(/[jJ]/) + match << matched + encoder.text_token match, :imaginary + else + encoder.text_token match, :integer + end + + else + encoder.text_token getch, :error + + end + + elsif state == :def_expected + state = :initial + if match = scan(unicode ? /#{NAME}/uo : /#{NAME}/o) + encoder.text_token match, :method + else + next + end + + elsif state == :class_expected + state = :initial + if match = scan(unicode ? /#{NAME}/uo : /#{NAME}/o) + encoder.text_token match, :class + else + next + end + + elsif state == :include_expected + if match = scan(unicode ? /#{DESCRIPTOR}/uo : /#{DESCRIPTOR}/o) + if match == 'as' + encoder.text_token match, :keyword + from_import_state << :as + elsif from_import_state.first == :from && match == 'import' + encoder.text_token match, :keyword + from_import_state << :import + elsif from_import_state.last == :as + # encoder.text_token match, match[0,1][unicode ? /[[:upper:]]/u : /[[:upper:]]/] ? :class : :method + encoder.text_token match, :ident + from_import_state.pop + elsif IDENT_KIND[match] == :keyword + unscan + match = nil + state = :initial + next + else + encoder.text_token match, :include + end + elsif match = scan(/,/) + from_import_state.pop if from_import_state.last == :as + encoder.text_token match, :operator + else + from_import_state = [] + state = :initial + next + end + + else + raise_inspect 'Unknown state', encoder, state + + end + + last_token_dot = match == '.' + + end + + if state == :string + encoder.end_group string_type + end + + encoder + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/raydebug.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/raydebug.rb new file mode 100644 index 0000000..1effdc8 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/raydebug.rb @@ -0,0 +1,75 @@ +require 'set' + +module CodeRay +module Scanners + + # = Raydebug Scanner + # + # Highlights the output of the Encoders::Debug encoder. + class Raydebug < Scanner + + register_for :raydebug + file_extension 'raydebug' + title 'CodeRay Token Dump' + + protected + + def setup + super + @known_token_kinds = TokenKinds.keys.map(&:to_s).to_set + end + + def scan_tokens encoder, options + + opened_tokens = [] + + until eos? + + if match = scan(/\s+/) + encoder.text_token match, :space + + elsif match = scan(/ (\w+) \( ( [^\)\\]* ( \\. [^\)\\]* )* ) /x) + kind = self[1] + encoder.text_token kind, :class + encoder.text_token '(', :operator + match = self[2] + unless match.empty? + if @known_token_kinds.include? kind + encoder.text_token match, kind.to_sym + else + encoder.text_token match, :plain + end + end + encoder.text_token match, :operator if match = scan(/\)/) + + elsif match = scan(/ (\w+) ([<\[]) /x) + encoder.text_token self[1], :class + if @known_token_kinds.include? self[1] + kind = self[1].to_sym + else + kind = :unknown + end + opened_tokens << kind + encoder.begin_group kind + encoder.text_token self[2], :operator + + elsif !opened_tokens.empty? && match = scan(/ [>\]] /x) + encoder.text_token match, :operator + encoder.end_group opened_tokens.pop + + else + encoder.text_token getch, :space + + end + + end + + encoder.end_group opened_tokens.pop until opened_tokens.empty? + + encoder + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/ruby.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/ruby.rb new file mode 100644 index 0000000..80165ca --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/ruby.rb @@ -0,0 +1,470 @@ +module CodeRay +module Scanners + + # This scanner is really complex, since Ruby _is_ a complex language! + # + # It tries to highlight 100% of all common code, + # and 90% of strange codes. + # + # It is optimized for HTML highlighting, and is not very useful for + # parsing or pretty printing. + class Ruby < Scanner + + register_for :ruby + file_extension 'rb' + + autoload :Patterns, CodeRay.coderay_path('scanners', 'ruby', 'patterns') + autoload :StringState, CodeRay.coderay_path('scanners', 'ruby', 'string_state') + + def interpreted_string_state + StringState.new :string, true, '"' + end + + protected + + def setup + @state = :initial + end + + def scan_tokens encoder, options + state, heredocs = options[:state] || @state + heredocs = heredocs.dup if heredocs.is_a?(Array) + + if state && state.instance_of?(StringState) + encoder.begin_group state.type + end + + last_state = nil + + method_call_expected = false + value_expected = true + + inline_block_stack = nil + inline_block_curly_depth = 0 + + if heredocs + state = heredocs.shift + encoder.begin_group state.type + heredocs = nil if heredocs.empty? + end + + # def_object_stack = nil + # def_object_paren_depth = 0 + + patterns = Patterns # avoid constant lookup + + unicode = string.respond_to?(:encoding) && string.encoding.name == 'UTF-8' + + until eos? + + if state.instance_of? ::Symbol + + if match = scan(/[ \t\f\v]+/) + encoder.text_token match, :space + + elsif match = scan(/\n/) + if heredocs + unscan # heredoc scanning needs \n at start + state = heredocs.shift + encoder.begin_group state.type + heredocs = nil if heredocs.empty? + else + state = :initial if state == :undef_comma_expected + encoder.text_token match, :space + value_expected = true + end + + elsif match = scan(bol? ? / \#(!)?.* | #{patterns::RUBYDOC_OR_DATA} /ox : /\#.*/) + encoder.text_token match, self[1] ? :doctype : :comment + + elsif match = scan(/\\\n/) + if heredocs + unscan # heredoc scanning needs \n at start + encoder.text_token scan(/\\/), :space + state = heredocs.shift + encoder.begin_group state.type + heredocs = nil if heredocs.empty? + else + encoder.text_token match, :space + end + + elsif state == :initial + + # IDENTS # + if !method_call_expected && + match = scan(unicode ? /#{patterns::METHOD_NAME}/uo : + /#{patterns::METHOD_NAME}/o) + + kind = patterns::IDENT_KIND[match] + if value_expected != :colon_expected && scan(/:(?!:)/) + value_expected = true + encoder.text_token match, :key + encoder.text_token ':', :operator + else + value_expected = false + if kind == :ident + if match[/\A[A-Z]/] && !(match[/[!?]$/] || match?(/\(/)) + kind = :constant + end + elsif kind == :keyword + state = patterns::KEYWORD_NEW_STATE[match] + if patterns::KEYWORDS_EXPECTING_VALUE[match] + value_expected = match == 'when' ? :colon_expected : true + end + end + value_expected = true if !value_expected && check(/#{patterns::VALUE_FOLLOWS}/o) + encoder.text_token match, kind + end + + elsif method_call_expected && + match = scan(unicode ? /#{patterns::METHOD_AFTER_DOT}/uo : + /#{patterns::METHOD_AFTER_DOT}/o) + if method_call_expected == '::' && match[/\A[A-Z]/] && !match?(/\(/) + encoder.text_token match, :constant + else + encoder.text_token match, :ident + end + method_call_expected = false + value_expected = check(/#{patterns::VALUE_FOLLOWS}/o) + + # OPERATORS # + elsif !method_call_expected && match = scan(/ (\.(?!\.)|::) | ( \.\.\.? | ==?=? | [,\(\[\{] ) | [\)\]\}] /x) + method_call_expected = self[1] + value_expected = !method_call_expected && !!self[2] + if inline_block_stack + case match + when '{' + inline_block_curly_depth += 1 + when '}' + inline_block_curly_depth -= 1 + if inline_block_curly_depth == 0 # closing brace of inline block reached + state, inline_block_curly_depth, heredocs = inline_block_stack.pop + inline_block_stack = nil if inline_block_stack.empty? + heredocs = nil if heredocs && heredocs.empty? + encoder.text_token match, :inline_delimiter + encoder.end_group :inline + next + end + end + end + encoder.text_token match, :operator + + elsif match = scan(unicode ? /#{patterns::SYMBOL}/uo : + /#{patterns::SYMBOL}/o) + case delim = match[1] + when ?', ?" + encoder.begin_group :symbol + encoder.text_token ':', :symbol + match = delim.chr + encoder.text_token match, :delimiter + state = self.class::StringState.new :symbol, delim == ?", match + else + encoder.text_token match, :symbol + value_expected = false + end + + elsif match = scan(/ ' (?:(?>[^'\\]*) ')? | " (?:(?>[^"\\\#]*) ")? /mx) + encoder.begin_group :string + if match.size == 1 + encoder.text_token match, :delimiter + state = self.class::StringState.new :string, match == '"', match # important for streaming + else + encoder.text_token match[0,1], :delimiter + encoder.text_token match[1..-2], :content if match.size > 2 + encoder.text_token match[-1,1], :delimiter + encoder.end_group :string + value_expected = false + end + + elsif match = scan(unicode ? /#{patterns::INSTANCE_VARIABLE}/uo : + /#{patterns::INSTANCE_VARIABLE}/o) + value_expected = false + encoder.text_token match, :instance_variable + + elsif value_expected && match = scan(/\//) + encoder.begin_group :regexp + encoder.text_token match, :delimiter + state = self.class::StringState.new :regexp, true, '/' + + elsif match = scan(value_expected ? /[-+]?#{patterns::NUMERIC}/o : /#{patterns::NUMERIC}/o) + if method_call_expected + encoder.text_token match, :error + method_call_expected = false + else + encoder.text_token match, self[1] ? :float : :integer # TODO: send :hex/:octal/:binary + end + value_expected = false + + elsif match = scan(/ [-+!~^\/]=? | [:;] | [*|&]{1,2}=? | >>? /x) + value_expected = true + encoder.text_token match, :operator + + elsif value_expected && match = scan(/#{patterns::HEREDOC_OPEN}/o) + quote = self[3] + delim = self[quote ? 4 : 2] + kind = patterns::QUOTE_TO_TYPE[quote] + encoder.begin_group kind + encoder.text_token match, :delimiter + encoder.end_group kind + heredocs ||= [] # create heredocs if empty + heredocs << self.class::StringState.new(kind, quote != "'", delim, + self[1] == '-' ? :indented : :linestart) + value_expected = false + + elsif value_expected && match = scan(/#{patterns::FANCY_STRING_START}/o) + kind = patterns::FANCY_STRING_KIND[self[1]] + encoder.begin_group kind + state = self.class::StringState.new kind, patterns::FANCY_STRING_INTERPRETED[self[1]], self[2] + encoder.text_token match, :delimiter + + elsif value_expected && match = scan(/#{patterns::CHARACTER}/o) + value_expected = false + encoder.text_token match, :integer + + elsif match = scan(/ %=? | <(?:<|=>?)? | \? /x) + value_expected = match == '?' ? :colon_expected : true + encoder.text_token match, :operator + + elsif match = scan(/`/) + encoder.begin_group :shell + encoder.text_token match, :delimiter + state = self.class::StringState.new :shell, true, match + + elsif match = scan(unicode ? /#{patterns::GLOBAL_VARIABLE}/uo : + /#{patterns::GLOBAL_VARIABLE}/o) + encoder.text_token match, :global_variable + value_expected = false + + elsif match = scan(unicode ? /#{patterns::CLASS_VARIABLE}/uo : + /#{patterns::CLASS_VARIABLE}/o) + encoder.text_token match, :class_variable + value_expected = false + + elsif match = scan(/\\\z/) + encoder.text_token match, :space + + else + if method_call_expected + method_call_expected = false + next + end + unless unicode + # check for unicode + $DEBUG_BEFORE, $DEBUG = $DEBUG, false + begin + if check(/./mu).size > 1 + # seems like we should try again with unicode + unicode = true + end + rescue + # bad unicode char; use getch + ensure + $DEBUG = $DEBUG_BEFORE + end + next if unicode + end + + encoder.text_token getch, :error + + end + + if last_state + state = last_state unless state.is_a?(StringState) # otherwise, a simple 'def"' results in unclosed tokens + last_state = nil + end + + elsif state == :def_expected + if match = scan(unicode ? /(?>#{patterns::METHOD_NAME_EX})(?!\.|::)/uo : + /(?>#{patterns::METHOD_NAME_EX})(?!\.|::)/o) + encoder.text_token match, :method + state = :initial + else + last_state = :dot_expected + state = :initial + end + + elsif state == :dot_expected + if match = scan(/\.|::/) + # invalid definition + state = :def_expected + encoder.text_token match, :operator + else + state = :initial + end + + elsif state == :module_expected + if match = scan(/<#{patterns::METHOD_NAME_EX})(?!\.|::)/uo : + /(?>#{patterns::METHOD_NAME_EX})(?!\.|::)/o) + encoder.text_token match, :method + elsif match = scan(/#{patterns::SYMBOL}/o) + case delim = match[1] + when ?', ?" + encoder.begin_group :symbol + encoder.text_token ':', :symbol + match = delim.chr + encoder.text_token match, :delimiter + state = self.class::StringState.new :symbol, delim == ?", match + state.next_state = :undef_comma_expected + else + encoder.text_token match, :symbol + end + else + state = :initial + end + + elsif state == :undef_comma_expected + if match = scan(/,/) + encoder.text_token match, :operator + state = :undef_expected + else + state = :initial + end + + elsif state == :alias_expected + match = scan(unicode ? /(#{patterns::METHOD_NAME_OR_SYMBOL})([ \t]+)(#{patterns::METHOD_NAME_OR_SYMBOL})/uo : + /(#{patterns::METHOD_NAME_OR_SYMBOL})([ \t]+)(#{patterns::METHOD_NAME_OR_SYMBOL})/o) + + if match + encoder.text_token self[1], (self[1][0] == ?: ? :symbol : :method) + encoder.text_token self[2], :space + encoder.text_token self[3], (self[3][0] == ?: ? :symbol : :method) + end + state = :initial + + else + #:nocov: + raise_inspect 'Unknown state: %p' % [state], encoder + #:nocov: + end + + else # StringState + + match = scan_until(state.pattern) || scan_rest + unless match.empty? + encoder.text_token match, :content + break if eos? + end + + if state.heredoc && self[1] # end of heredoc + match = getch + match << scan_until(/$/) unless eos? + encoder.text_token match, :delimiter unless match.empty? + encoder.end_group state.type + state = state.next_state + next + end + + case match = getch + + when state.delim + if state.paren_depth + state.paren_depth -= 1 + if state.paren_depth > 0 + encoder.text_token match, :content + next + end + end + encoder.text_token match, :delimiter + if state.type == :regexp && !eos? + match = scan(/#{patterns::REGEXP_MODIFIERS}/o) + encoder.text_token match, :modifier unless match.empty? + end + encoder.end_group state.type + value_expected = false + state = state.next_state + + when '\\' + if state.interpreted + if esc = scan(/#{patterns::ESCAPE}/o) + encoder.text_token match + esc, :char + else + encoder.text_token match, :error + end + else + case esc = getch + when nil + encoder.text_token match, :content + when state.delim, '\\' + encoder.text_token match + esc, :char + else + encoder.text_token match + esc, :content + end + end + + when '#' + case peek(1) + when '{' + inline_block_stack ||= [] + inline_block_stack << [state, inline_block_curly_depth, heredocs] + value_expected = true + state = :initial + inline_block_curly_depth = 1 + encoder.begin_group :inline + encoder.text_token match + getch, :inline_delimiter + when '$', '@' + encoder.text_token match, :escape + last_state = state + state = :initial + else + #:nocov: + raise_inspect 'else-case # reached; #%p not handled' % [peek(1)], encoder + #:nocov: + end + + when state.opening_paren + state.paren_depth += 1 + encoder.text_token match, :content + + else + #:nocov + raise_inspect 'else-case " reached; %p not handled, state = %p' % [match, state], encoder + #:nocov: + + end + + end + + end + + # cleaning up + if state.is_a? StringState + encoder.end_group state.type + end + + if options[:keep_state] + if state.is_a?(StringState) && state.heredoc + (heredocs ||= []).unshift state + state = :initial + elsif heredocs && heredocs.empty? + heredocs = nil + end + @state = state, heredocs + end + + if inline_block_stack + until inline_block_stack.empty? + state, = *inline_block_stack.pop + encoder.end_group :inline + encoder.end_group state.type + end + end + + encoder + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/ruby/patterns.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/ruby/patterns.rb new file mode 100644 index 0000000..0b36e13 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/ruby/patterns.rb @@ -0,0 +1,178 @@ +# encoding: utf-8 +module CodeRay +module Scanners + + module Ruby::Patterns # :nodoc: all + + KEYWORDS = %w[ + and def end in or unless begin + defined? ensure module redo super until + BEGIN break do next rescue then + when END case else for retry + while alias class elsif if not return + undef yield + ] + + # See http://murfy.de/ruby-constants. + PREDEFINED_CONSTANTS = %w[ + nil true false self + DATA ARGV ARGF ENV + FALSE TRUE NIL + STDERR STDIN STDOUT + TOPLEVEL_BINDING + RUBY_COPYRIGHT RUBY_DESCRIPTION RUBY_ENGINE RUBY_PATCHLEVEL + RUBY_PLATFORM RUBY_RELEASE_DATE RUBY_REVISION RUBY_VERSION + __FILE__ __LINE__ __ENCODING__ + ] + + IDENT_KIND = WordList.new(:ident). + add(KEYWORDS, :keyword). + add(PREDEFINED_CONSTANTS, :predefined_constant) + + KEYWORD_NEW_STATE = WordList.new(:initial). + add(%w[ def ], :def_expected). + add(%w[ undef ], :undef_expected). + add(%w[ alias ], :alias_expected). + add(%w[ class module ], :module_expected) + + IDENT = 'ä'[/[[:alpha:]]/] == 'ä' ? Regexp.new('[[:alpha:]_[^\0-\177]][[:alnum:]_[^\0-\177]]*') : /[^\W\d]\w*/ + + METHOD_NAME = / #{IDENT} [?!]? /ox + METHOD_NAME_OPERATOR = / + \*\*? # multiplication and power + | [-+~]@? # plus, minus, tilde with and without at sign + | [\/%&|^`] # division, modulo or format strings, and, or, xor, system + | \[\]=? # array getter and setter + | << | >> # append or shift left, shift right + | <=?>? | >=? # comparison, rocket operator + | ===? | =~ # simple equality, case equality, match + | ![~=@]? # negation with and without at sign, not-equal and not-match + /ox + METHOD_SUFFIX = / (?: [?!] | = (?![~>]|=(?!>)) ) /x + METHOD_NAME_EX = / #{IDENT} #{METHOD_SUFFIX}? | #{METHOD_NAME_OPERATOR} /ox + METHOD_AFTER_DOT = / #{IDENT} [?!]? | #{METHOD_NAME_OPERATOR} /ox + INSTANCE_VARIABLE = / @ #{IDENT} /ox + CLASS_VARIABLE = / @@ #{IDENT} /ox + OBJECT_VARIABLE = / @@? #{IDENT} /ox + GLOBAL_VARIABLE = / \$ (?: #{IDENT} | [1-9]\d* | 0\w* | [~&+`'=\/,;_.<>!@$?*":\\] | -[a-zA-Z_0-9] ) /ox + PREFIX_VARIABLE = / #{GLOBAL_VARIABLE} | #{OBJECT_VARIABLE} /ox + VARIABLE = / @?@? #{IDENT} | #{GLOBAL_VARIABLE} /ox + + QUOTE_TO_TYPE = { + '`' => :shell, + '/'=> :regexp, + } + QUOTE_TO_TYPE.default = :string + + REGEXP_MODIFIERS = /[mousenix]*/ + + DECIMAL = /\d+(?:_\d+)*/ + OCTAL = /0_?[0-7]+(?:_[0-7]+)*/ + HEXADECIMAL = /0x[0-9A-Fa-f]+(?:_[0-9A-Fa-f]+)*/ + BINARY = /0b[01]+(?:_[01]+)*/ + + EXPONENT = / [eE] [+-]? #{DECIMAL} /ox + FLOAT_SUFFIX = / #{EXPONENT} | \. #{DECIMAL} #{EXPONENT}? /ox + FLOAT_OR_INT = / #{DECIMAL} (?: #{FLOAT_SUFFIX} () )? /ox + NUMERIC = / (?: (?=0) (?: #{OCTAL} | #{HEXADECIMAL} | #{BINARY} ) | #{FLOAT_OR_INT} ) /ox + + SYMBOL = / + : + (?: + #{METHOD_NAME_EX} + | #{PREFIX_VARIABLE} + | ['"] + ) + /ox + METHOD_NAME_OR_SYMBOL = / #{METHOD_NAME_EX} | #{SYMBOL} /ox + + SIMPLE_ESCAPE = / + [abefnrstv] + | [0-7]{1,3} + | x[0-9A-Fa-f]{1,2} + | . + /mx + + CONTROL_META_ESCAPE = / + (?: M-|C-|c ) + (?: \\ (?: M-|C-|c ) )* + (?: [^\\] | \\ #{SIMPLE_ESCAPE} )? + /mox + + ESCAPE = / + #{CONTROL_META_ESCAPE} | #{SIMPLE_ESCAPE} + /mox + + CHARACTER = / + \? + (?: + [^\s\\] + | \\ #{ESCAPE} + ) + /mox + + # NOTE: This is not completely correct, but + # nobody needs heredoc delimiters ending with \n. + HEREDOC_OPEN = / + << (-)? # $1 = float + (?: + ( [A-Za-z_0-9]+ ) # $2 = delim + | + ( ["'`\/] ) # $3 = quote, type + ( [^\n]*? ) \3 # $4 = delim + ) + /mx + + RUBYDOC = / + =begin (?!\S) + .*? + (?: \Z | ^=end (?!\S) [^\n]* ) + /mx + + DATA = / + __END__$ + .*? + (?: \Z | (?=^\#CODE) ) + /mx + + RUBYDOC_OR_DATA = / #{RUBYDOC} | #{DATA} /xo + + # Checks for a valid value to follow. This enables + # value_expected in method calls without parentheses. + VALUE_FOLLOWS = / + (?>[ \t\f\v]+) + (?: + [%\/][^\s=] + | <<-?\S + | [-+] \d + | #{CHARACTER} + ) + /ox + KEYWORDS_EXPECTING_VALUE = WordList.new.add(%w[ + and end in or unless begin + defined? ensure redo super until + break do next rescue then + when case else for retry + while elsif if not return + yield + ]) + + FANCY_STRING_START = / % ( [iIqQrswWx] | (?![a-zA-Z0-9]) ) ([^a-zA-Z0-9]) /x + FANCY_STRING_KIND = Hash.new(:string).merge({ + 'i' => :symbol, + 'I' => :symbol, + 'r' => :regexp, + 's' => :symbol, + 'x' => :shell, + }) + FANCY_STRING_INTERPRETED = Hash.new(true).merge({ + 'i' => false, + 'q' => false, + 's' => false, + 'w' => false, + }) + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/ruby/string_state.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/ruby/string_state.rb new file mode 100644 index 0000000..28ddd6c --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/ruby/string_state.rb @@ -0,0 +1,71 @@ +# encoding: utf-8 +module CodeRay +module Scanners + + class Ruby + + class StringState < Struct.new :type, :interpreted, :delim, :heredoc, + :opening_paren, :paren_depth, :pattern, :next_state # :nodoc: all + + CLOSING_PAREN = Hash[ *%w[ + ( ) + [ ] + < > + { } + ] ].each { |k,v| k.freeze; v.freeze } # debug, if I try to change it with << + + STRING_PATTERN = Hash.new do |h, k| + delim, interpreted = *k + delim_pattern = Regexp.escape(delim) + if closing_paren = CLOSING_PAREN[delim] + delim_pattern << Regexp.escape(closing_paren) + end + delim_pattern << '\\\\' unless delim == '\\' + + # special_escapes = + # case interpreted + # when :regexp_symbols + # '| [|?*+(){}\[\].^$]' + # end + + if interpreted && delim != '#' + / (?= [#{delim_pattern}] | \# [{$@] ) /mx + else + / (?= [#{delim_pattern}] ) /mx + end.tap do |pattern| + h[k] = pattern if (delim.respond_to?(:ord) ? delim.ord : delim[0]) < 256 + end + end + + def initialize kind, interpreted, delim, heredoc = false + if heredoc + pattern = heredoc_pattern delim, interpreted, heredoc == :indented + delim = nil + else + pattern = STRING_PATTERN[ [delim, interpreted] ] + if closing_paren = CLOSING_PAREN[delim] + opening_paren = delim + delim = closing_paren + paren_depth = 1 + end + end + super kind, interpreted, delim, heredoc, opening_paren, paren_depth, pattern, :initial + end + + def heredoc_pattern delim, interpreted, indented + # delim = delim.dup # workaround for old Ruby + delim_pattern = Regexp.escape(delim) + delim_pattern = / (?:\A|\n) #{ '(?>[ \t]*)' if indented } #{ Regexp.new delim_pattern } $ /x + if interpreted + / (?= #{delim_pattern}() | \\ | \# [{$@] ) /mx # $1 set == end of heredoc + else + / (?= #{delim_pattern}() | \\ ) /mx + end + end + + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/sass.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/sass.rb new file mode 100644 index 0000000..e3296b9 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/sass.rb @@ -0,0 +1,232 @@ +module CodeRay +module Scanners + + # A scanner for Sass. + class Sass < CSS + + register_for :sass + file_extension 'sass' + + protected + + def setup + @state = :initial + end + + def scan_tokens encoder, options + states = Array(options[:state] || @state).dup + + encoder.begin_group :string if states.last == :sqstring || states.last == :dqstring + + until eos? + + if bol? && (match = scan(/(?>( +)?(\/[\*\/])(.+)?)(?=\n)/)) + encoder.text_token self[1], :space if self[1] + encoder.begin_group :comment + encoder.text_token self[2], :delimiter + encoder.text_token self[3], :content if self[3] + if match = scan(/(?:\n+#{self[1]} .*)+/) + encoder.text_token match, :content + end + encoder.end_group :comment + elsif match = scan(/\n|[^\n\S]+\n?/) + encoder.text_token match, :space + if match.index(/\n/) + value_expected = false + states.pop if states.last == :include + end + + elsif states.last == :sass_inline && (match = scan(/\}/)) + encoder.text_token match, :inline_delimiter + encoder.end_group :inline + states.pop + + elsif case states.last + when :initial, :media, :sass_inline + if match = scan(/(?>#{RE::Ident})(?!\()/ox) + encoder.text_token match, value_expected ? :value : (check(/.*:(?![a-z])/) ? :key : :tag) + next + elsif !value_expected && (match = scan(/\*/)) + encoder.text_token match, :tag + next + elsif match = scan(RE::Class) + encoder.text_token match, :class + next + elsif match = scan(RE::Id) + encoder.text_token match, :id + next + elsif match = scan(RE::PseudoClass) + encoder.text_token match, :pseudo_class + next + elsif match = scan(RE::AttributeSelector) + # TODO: Improve highlighting inside of attribute selectors. + encoder.text_token match[0,1], :operator + encoder.text_token match[1..-2], :attribute_name if match.size > 2 + encoder.text_token match[-1,1], :operator if match[-1] == ?] + next + elsif match = scan(/(\=|@mixin +)#{RE::Ident}/o) + encoder.text_token match, :function + next + elsif match = scan(/@import\b/) + encoder.text_token match, :directive + states << :include + next + elsif match = scan(/@media\b/) + encoder.text_token match, :directive + # states.push :media_before_name + next + end + + when :block + if match = scan(/(?>#{RE::Ident})(?!\()/ox) + if value_expected + encoder.text_token match, :value + else + encoder.text_token match, :key + end + next + end + + when :sqstring, :dqstring + if match = scan(states.last == :sqstring ? /(?:[^\n\'\#]+|\\\n|#{RE::Escape}|#(?!\{))+/o : /(?:[^\n\"\#]+|\\\n|#{RE::Escape}|#(?!\{))+/o) + encoder.text_token match, :content + elsif match = scan(/['"]/) + encoder.text_token match, :delimiter + encoder.end_group :string + states.pop + elsif match = scan(/#\{/) + encoder.begin_group :inline + encoder.text_token match, :inline_delimiter + states.push :sass_inline + elsif match = scan(/ \\ | $ /x) + encoder.end_group states.last + encoder.text_token match, :error unless match.empty? + states.pop + else + raise_inspect "else case #{states.last} reached; %p not handled." % peek(1), encoder + end + + when :include + if match = scan(/[^\s'",]+/) + encoder.text_token match, :include + next + end + + else + #:nocov: + raise_inspect 'Unknown state: %p' % [states.last], encoder + #:nocov: + + end + + elsif match = scan(/\$#{RE::Ident}/o) + encoder.text_token match, :variable + next + + elsif match = scan(/&/) + encoder.text_token match, :local_variable + + elsif match = scan(/\+#{RE::Ident}/o) + encoder.text_token match, :include + value_expected = true + + elsif match = scan(/\/\*(?:.*?\*\/|.*)|\/\/.*/) + encoder.text_token match, :comment + + elsif match = scan(/#\{/) + encoder.begin_group :inline + encoder.text_token match, :inline_delimiter + states.push :sass_inline + + elsif match = scan(/\{/) + value_expected = false + encoder.text_token match, :operator + states.push :block + + elsif match = scan(/\}/) + value_expected = false + encoder.text_token match, :operator + if states.last == :block || states.last == :media + states.pop + end + + elsif match = scan(/['"]/) + encoder.begin_group :string + encoder.text_token match, :delimiter + if states.include? :sass_inline + # no nesting, just scan the string until delimiter + content = scan_until(/(?=#{match}|\}|\z)/) + encoder.text_token content, :content unless content.empty? + encoder.text_token match, :delimiter if scan(/#{match}/) + encoder.end_group :string + else + states.push match == "'" ? :sqstring : :dqstring + end + + elsif match = scan(/#{RE::Function}/o) + encoder.begin_group :function + start = match[/^[-\w]+\(/] + encoder.text_token start, :delimiter + if match[-1] == ?) + encoder.text_token match[start.size..-2], :content + encoder.text_token ')', :delimiter + else + encoder.text_token match[start.size..-1], :content if start.size < match.size + end + encoder.end_group :function + + elsif match = scan(/[a-z][-a-z_]*(?=\()/o) + encoder.text_token match, :predefined + + elsif match = scan(/(?: #{RE::Dimension} | #{RE::Percentage} | #{RE::Num} )/ox) + encoder.text_token match, :float + + elsif match = scan(/#{RE::HexColor}/o) + encoder.text_token match, :color + + elsif match = scan(/! *(?:important|optional)/) + encoder.text_token match, :important + + elsif match = scan(/(?:rgb|hsl)a?\([^()\n]*\)?/) + encoder.text_token match, :color + + elsif match = scan(/@else if\b|#{RE::AtKeyword}/o) + encoder.text_token match, :directive + value_expected = true + + elsif match = scan(/ == | != | [-+*\/>~:;,.=()] /x) + if match == ':' + value_expected = true + elsif match == ';' + value_expected = false + end + encoder.text_token match, :operator + + else + encoder.text_token getch, :error + + end + + end + + states.pop if states.last == :include + + if options[:keep_state] + @state = states.dup + end + + while state = states.pop + if state == :sass_inline + encoder.end_group :inline + elsif state == :sqstring || state == :dqstring + encoder.end_group :string + end + end + + encoder + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/sql.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/sql.rb new file mode 100644 index 0000000..93aeaf3 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/sql.rb @@ -0,0 +1,177 @@ +module CodeRay +module Scanners + + # by Josh Goebel + class SQL < Scanner + + register_for :sql + + KEYWORDS = %w( + all and any as before begin between by case check collate + each else end exists + for foreign from full group having if in inner is join + like not of on or order outer over references + then to union using values when where + left right distinct + ) + + OBJECTS = %w( + database databases table tables column columns fields index constraint + constraints transaction function procedure row key view trigger + ) + + COMMANDS = %w( + add alter comment create delete drop grant insert into select update set + show prompt begin commit rollback replace truncate + ) + + PREDEFINED_TYPES = %w( + char varchar varchar2 enum binary text tinytext mediumtext + longtext blob tinyblob mediumblob longblob timestamp + date time datetime year double decimal float int + integer tinyint mediumint bigint smallint unsigned bit + bool boolean hex bin oct + ) + + PREDEFINED_FUNCTIONS = %w( sum cast substring abs pi count min max avg now ) + + DIRECTIVES = %w( + auto_increment unique default charset initially deferred + deferrable cascade immediate read write asc desc after + primary foreign return engine + ) + + PREDEFINED_CONSTANTS = %w( null true false ) + + IDENT_KIND = WordList::CaseIgnoring.new(:ident). + add(KEYWORDS, :keyword). + add(OBJECTS, :type). + add(COMMANDS, :class). + add(PREDEFINED_TYPES, :predefined_type). + add(PREDEFINED_CONSTANTS, :predefined_constant). + add(PREDEFINED_FUNCTIONS, :predefined). + add(DIRECTIVES, :directive) + + ESCAPE = / [rbfntv\n\\\/'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} | . /mx + UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x + + STRING_PREFIXES = /[xnb]|_\w+/i + + def scan_tokens encoder, options + + state = :initial + string_type = nil + string_content = '' + name_expected = false + + until eos? + + if state == :initial + + if match = scan(/ \s+ | \\\n /x) + encoder.text_token match, :space + + elsif match = scan(/(?:--\s?|#).*/) + encoder.text_token match, :comment + + elsif match = scan(%r( /\* (!)? (?: .*? \*/ | .* ) )mx) + encoder.text_token match, self[1] ? :directive : :comment + + elsif match = scan(/ [*\/=<>:;,!&^|()\[\]{}~%] | [-+\.](?!\d) /x) + name_expected = true if match == '.' && check(/[A-Za-z_]/) + encoder.text_token match, :operator + + elsif match = scan(/(#{STRING_PREFIXES})?([`"'])/o) + prefix = self[1] + string_type = self[2] + encoder.begin_group :string + encoder.text_token prefix, :modifier if prefix + match = string_type + state = :string + encoder.text_token match, :delimiter + + elsif match = scan(/ @? [A-Za-z_][A-Za-z_0-9]* /x) + encoder.text_token match, name_expected ? :ident : (match[0] == ?@ ? :variable : IDENT_KIND[match]) + name_expected = false + + elsif match = scan(/0[xX][0-9A-Fa-f]+/) + encoder.text_token match, :hex + + elsif match = scan(/0[0-7]+(?![89.eEfF])/) + encoder.text_token match, :octal + + elsif match = scan(/[-+]?(?>\d+)(?![.eEfF])/) + encoder.text_token match, :integer + + elsif match = scan(/[-+]?(?:\d[fF]|\d*\.\d+(?:[eE][+-]?\d+)?|\d+[eE][+-]?\d+)/) + encoder.text_token match, :float + + elsif match = scan(/\\N/) + encoder.text_token match, :predefined_constant + + else + encoder.text_token getch, :error + + end + + elsif state == :string + if match = scan(/[^\\"'`]+/) + string_content << match + next + elsif match = scan(/["'`]/) + if string_type == match + if peek(1) == string_type # doubling means escape + string_content << string_type << getch + next + end + unless string_content.empty? + encoder.text_token string_content, :content + string_content = '' + end + encoder.text_token match, :delimiter + encoder.end_group :string + state = :initial + string_type = nil + else + string_content << match + end + elsif match = scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox) + unless string_content.empty? + encoder.text_token string_content, :content + string_content = '' + end + encoder.text_token match, :char + elsif match = scan(/ \\ . /mox) + string_content << match + next + elsif match = scan(/ \\ | $ /x) + unless string_content.empty? + encoder.text_token string_content, :content + string_content = '' + end + encoder.text_token match, :error unless match.empty? + encoder.end_group :string + state = :initial + else + raise "else case \" reached; %p not handled." % peek(1), encoder + end + + else + raise 'else-case reached', encoder + + end + + end + + if state == :string + encoder.end_group state + end + + encoder + + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/taskpaper.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/taskpaper.rb new file mode 100644 index 0000000..42670bc --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/taskpaper.rb @@ -0,0 +1,36 @@ +module CodeRay +module Scanners + + class Taskpaper < Scanner + + register_for :taskpaper + file_extension 'taskpaper' + + protected + + def scan_tokens encoder, options + until eos? + if match = scan(/\S.*:.*$/) # project + encoder.text_token(match, :namespace) + elsif match = scan(/-.+@done.*/) # completed task + encoder.text_token(match, :done) + elsif match = scan(/-(?:[^@\n]+|@(?!due))*/) # task + encoder.text_token(match, :plain) + elsif match = scan(/@due.*/) # comment + encoder.text_token(match, :important) + elsif match = scan(/.+/) # comment + encoder.text_token(match, :comment) + elsif match = scan(/\s+/) # space + encoder.text_token(match, :space) + else # other + encoder.text_token getch, :error + end + end + + encoder + end + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/text.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/text.rb new file mode 100644 index 0000000..bde9029 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/text.rb @@ -0,0 +1,26 @@ +module CodeRay + module Scanners + + # Scanner for plain text. + # + # Yields just one token of the kind :plain. + # + # Alias: +plaintext+, +plain+ + class Text < Scanner + + register_for :text + title 'Plain text' + + KINDS_NOT_LOC = [:plain] # :nodoc: + + protected + + def scan_tokens encoder, options + encoder.text_token string, :plain + encoder + end + + end + + end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/xml.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/xml.rb new file mode 100644 index 0000000..947f16e --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/xml.rb @@ -0,0 +1,17 @@ +module CodeRay +module Scanners + + load :html + + # Scanner for XML. + # + # Currently this is the same scanner as Scanners::HTML. + class XML < HTML + + register_for :xml + file_extension 'xml' + + end + +end +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/yaml.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/yaml.rb new file mode 100644 index 0000000..32c8e2c --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/scanners/yaml.rb @@ -0,0 +1,140 @@ +module CodeRay +module Scanners + + # Scanner for YAML. + # + # Based on the YAML scanner from Syntax by Jamis Buck. + class YAML < Scanner + + register_for :yaml + file_extension 'yml' + + KINDS_NOT_LOC = :all + + protected + + def scan_tokens encoder, options + + state = :initial + key_indent = string_indent = 0 + + until eos? + + key_indent = nil if bol? + + if match = scan(/ +[\t ]*/) + encoder.text_token match, :space + + elsif match = scan(/\n+/) + encoder.text_token match, :space + state = :initial if match.index(?\n) + + elsif match = scan(/#.*/) + encoder.text_token match, :comment + + elsif bol? and case + when match = scan(/---|\.\.\./) + encoder.begin_group :head + encoder.text_token match, :head + encoder.end_group :head + next + when match = scan(/%.*/) + encoder.text_token match, :doctype + next + end + + elsif state == :value and case + when !check(/(?:"[^"]*")(?=: |:$)/) && match = scan(/"/) + encoder.begin_group :string + encoder.text_token match, :delimiter + encoder.text_token match, :content if (match = scan(/ [^"\\]* (?: \\. [^"\\]* )* /mx)) && !match.empty? + encoder.text_token match, :delimiter if match = scan(/"/) + encoder.end_group :string + next + when match = scan(/[|>][-+]?/) + encoder.begin_group :string + encoder.text_token match, :delimiter + string_indent = key_indent || column(pos - match.size) - 1 + encoder.text_token matched, :content if scan(/(?:\n+ {#{string_indent + 1}}.*)+/) + encoder.end_group :string + next + when match = scan(/(?![!"*&]).+?(?=$|\s+#)/) + encoder.begin_group :string + encoder.text_token match, :content + string_indent = key_indent || column(pos - match.size) - 1 + encoder.text_token matched, :content if scan(/(?:\n+ {#{string_indent + 1}}.*)+/) + encoder.end_group :string + next + end + + elsif case + when match = scan(/[-:](?= |$)/) + state = :value if state == :colon && (match == ':' || match == '-') + state = :value if state == :initial && match == '-' + encoder.text_token match, :operator + next + when match = scan(/[,{}\[\]]/) + encoder.text_token match, :operator + next + when state == :initial && match = scan(/[-\w.()\/ ]*\S(?= *:(?: |$))/) + encoder.text_token match, :key + key_indent = column(pos - match.size) - 1 + state = :colon + next + when match = scan(/(?:"[^"\n]*"|'[^'\n]*')(?= *:(?: |$))/) + encoder.begin_group :key + encoder.text_token match[0,1], :delimiter + encoder.text_token match[1..-2], :content if match.size > 2 + encoder.text_token match[-1,1], :delimiter + encoder.end_group :key + key_indent = column(pos - match.size) - 1 + state = :colon + next + when match = scan(/(![\w\/]+)(:([\w:]+))?/) + encoder.text_token self[1], :type + if self[2] + encoder.text_token ':', :operator + encoder.text_token self[3], :class + end + next + when match = scan(/&\S+/) + encoder.text_token match, :variable + next + when match = scan(/\*\w+/) + encoder.text_token match, :global_variable + next + when match = scan(/< 'debug', # highlight for debugging (white on blue background) + + :annotation => 'annotation', # Groovy, Java + :attribute_name => 'attribute-name', # HTML, CSS + :attribute_value => 'attribute-value', # HTML + :binary => 'binary', # Python, Ruby + :char => 'char', # most scanners, also inside of strings + :class => 'class', # lots of scanners, for different purposes also in CSS + :class_variable => 'class-variable', # Ruby, YAML + :color => 'color', # CSS + :comment => 'comment', # most scanners + :constant => 'constant', # PHP, Ruby + :content => 'content', # inside of strings, most scanners + :decorator => 'decorator', # Python + :definition => 'definition', # CSS + :delimiter => 'delimiter', # inside strings, comments and other types + :directive => 'directive', # lots of scanners + :doctype => 'doctype', # Goorvy, HTML, Ruby, YAML + :docstring => 'docstring', # Python + :done => 'done', # Taskpaper + :entity => 'entity', # HTML + :error => 'error', # invalid token, most scanners + :escape => 'escape', # Ruby (string inline variables like #$foo, #@bar) + :exception => 'exception', # Java, PHP, Python + :filename => 'filename', # Diff + :float => 'float', # most scanners + :function => 'function', # CSS, JavaScript, PHP + :global_variable => 'global-variable', # Ruby, YAML + :hex => 'hex', # hexadecimal number; lots of scanners + :id => 'id', # CSS + :imaginary => 'imaginary', # Python + :important => 'important', # CSS, Taskpaper + :include => 'include', # C, Groovy, Java, Python, Sass + :inline => 'inline', # nested code, eg. inline string evaluation; lots of scanners + :inline_delimiter => 'inline-delimiter', # used instead of :inline > :delimiter FIXME: Why use inline_delimiter? + :instance_variable => 'instance-variable', # Ruby + :integer => 'integer', # most scanners + :key => 'key', # lots of scanners, used together with :value + :keyword => 'keyword', # reserved word that's actually implemented; most scanners + :label => 'label', # C, PHP + :local_variable => 'local-variable', # local and magic variables; some scanners + :map => 'map', # Lua tables + :modifier => 'modifier', # used inside on strings; lots of scanners + :namespace => 'namespace', # Clojure, Java, Taskpaper + :octal => 'octal', # lots of scanners + :predefined => 'predefined', # predefined function: lots of scanners + :predefined_constant => 'predefined-constant',# lots of scanners + :predefined_type => 'predefined-type', # C, Java, PHP + :preprocessor => 'preprocessor', # C, Delphi, HTML + :pseudo_class => 'pseudo-class', # CSS + :regexp => 'regexp', # Groovy, JavaScript, Ruby + :reserved => 'reserved', # most scanners + :shell => 'shell', # Ruby + :string => 'string', # most scanners + :symbol => 'symbol', # Clojure, Ruby, YAML + :tag => 'tag', # CSS, HTML + :type => 'type', # CSS, Java, SQL, YAML + :value => 'value', # used together with :key; CSS, JSON, YAML + :variable => 'variable', # Sass, SQL, YAML + + :change => 'change', # Diff + :delete => 'delete', # Diff + :head => 'head', # Diff, YAML + :insert => 'insert', # Diff + :eyecatcher => 'eyecatcher', # Diff + + :ident => false, # almost all scanners + :operator => false, # almost all scanners + + :space => false, # almost all scanners + :plain => false # almost all scanners + ) + + TokenKinds[:method] = TokenKinds[:function] + TokenKinds[:unknown] = TokenKinds[:plain] +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/tokens.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/tokens.rb new file mode 100644 index 0000000..e7bffce --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/tokens.rb @@ -0,0 +1,161 @@ +module CodeRay + + # The Tokens class represents a list of tokens returned from + # a Scanner. It's actually just an Array with a few helper methods. + # + # A token itself is not a special object, just two elements in an Array: + # * the _token_ _text_ (the original source of the token in a String) or + # a _token_ _action_ (begin_group, end_group, begin_line, end_line) + # * the _token_ _kind_ (a Symbol representing the type of the token) + # + # It looks like this: + # + # ..., '# It looks like this', :comment, ... + # ..., '3.1415926', :float, ... + # ..., '$^', :error, ... + # + # Some scanners also yield sub-tokens, represented by special + # token actions, for example :begin_group and :end_group. + # + # The Ruby scanner, for example, splits "a string" into: + # + # [ + # :begin_group, :string, + # '"', :delimiter, + # 'a string', :content, + # '"', :delimiter, + # :end_group, :string + # ] + # + # Tokens can be used to save the output of a Scanners in a simple + # Ruby object that can be send to an Encoder later: + # + # tokens = CodeRay.scan('price = 2.59', :ruby).tokens + # tokens.encode(:html) + # tokens.html + # CodeRay.encoder(:html).encode_tokens(tokens) + # + # Tokens gives you the power to handle pre-scanned code very easily: + # You can serialize it to a JSON string and store it in a database, pass it + # around to encode it more than once, send it to other algorithms... + class Tokens < Array + + # The Scanner instance that created the tokens. + attr_accessor :scanner + + # Encode the tokens using encoder. + # + # encoder can be + # * a plugin name like :html oder 'statistic' + # * an Encoder object + # + # options are passed to the encoder. + def encode encoder, options = {} + encoder = Encoders[encoder].new options if encoder.respond_to? :to_sym + encoder.encode_tokens self, options + end + + # Turn tokens into a string by concatenating them. + def to_s + encode CodeRay::Encoders::Encoder.new + end + + # Redirects unknown methods to encoder calls. + # + # For example, if you call +tokens.html+, the HTML encoder + # is used to highlight the tokens. + def method_missing meth, options = {} + encode meth, options + rescue PluginHost::PluginNotFound + super + end + + # Split the tokens into parts of the given +sizes+. + # + # The result will be an Array of Tokens objects. The parts have + # the text size specified by the parameter. In addition, each + # part closes all opened tokens. This is useful to insert tokens + # betweem them. + # + # This method is used by @Scanner#tokenize@ when called with an Array + # of source strings. The Diff encoder uses it for inline highlighting. + def split_into_parts *sizes + return Array.new(sizes.size) { Tokens.new } if size == 2 && first == '' + parts = [] + opened = [] + content = nil + part = Tokens.new + part_size = 0 + size = sizes.first + i = 0 + for item in self + case content + when nil + content = item + when String + if size && part_size + content.size > size # token must be cut + if part_size < size # some part of the token goes into this part + content = content.dup # content may no be safe to change + part << content.slice!(0, size - part_size) << item + end + # close all open groups and lines... + closing = opened.reverse.flatten.map do |content_or_kind| + case content_or_kind + when :begin_group + :end_group + when :begin_line + :end_line + else + content_or_kind + end + end + part.concat closing + begin + parts << part + part = Tokens.new + size = sizes[i += 1] + end until size.nil? || size > 0 + # ...and open them again. + part.concat opened.flatten + part_size = 0 + redo unless content.empty? + else + part << content << item + part_size += content.size + end + content = nil + when Symbol + case content + when :begin_group, :begin_line + opened << [content, item] + when :end_group, :end_line + opened.pop + else + raise ArgumentError, 'Unknown token action: %p, kind = %p' % [content, item] + end + part << content << item + content = nil + else + raise ArgumentError, 'Token input junk: %p, kind = %p' % [content, item] + end + end + parts << part + parts << Tokens.new while parts.size < sizes.size + parts + end + + # Return the actual number of tokens. + def count + size / 2 + end + + alias text_token push + def begin_group kind; push :begin_group, kind end + def end_group kind; push :end_group, kind end + def begin_line kind; push :begin_line, kind end + def end_line kind; push :end_line, kind end + alias tokens concat + + end + +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/tokens_proxy.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/tokens_proxy.rb new file mode 100644 index 0000000..31ff39b --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/tokens_proxy.rb @@ -0,0 +1,55 @@ +module CodeRay + + # The result of a scan operation is a TokensProxy, but should act like Tokens. + # + # This proxy makes it possible to use the classic CodeRay.scan.encode API + # while still providing the benefits of direct streaming. + class TokensProxy + + attr_accessor :input, :lang, :options, :block + + # Create a new TokensProxy with the arguments of CodeRay.scan. + def initialize input, lang, options = {}, block = nil + @input = input + @lang = lang + @options = options + @block = block + end + + # Call CodeRay.encode if +encoder+ is a Symbol; + # otherwise, convert the receiver to tokens and call encoder.encode_tokens. + def encode encoder, options = {} + if encoder.respond_to? :to_sym + CodeRay.encode(input, lang, encoder, options) + else + encoder.encode_tokens tokens, options + end + end + + # Tries to call encode; + # delegates to tokens otherwise. + def method_missing method, *args, &blk + encode method.to_sym, *args + rescue PluginHost::PluginNotFound + tokens.send(method, *args, &blk) + end + + # The (cached) result of the tokenized input; a Tokens instance. + def tokens + @tokens ||= scanner.tokenize(input) + end + + # A (cached) scanner instance to use for the scan task. + def scanner + @scanner ||= CodeRay.scanner(lang, options, &block) + end + + # Overwrite Struct#each. + def each *args, &blk + tokens.each(*args, &blk) + self + end + + end + +end diff --git a/.bundle/gems/coderay-1.1.0/lib/coderay/version.rb b/.bundle/gems/coderay-1.1.0/lib/coderay/version.rb new file mode 100644 index 0000000..4b4f085 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/lib/coderay/version.rb @@ -0,0 +1,3 @@ +module CodeRay + VERSION = '1.1.0' +end diff --git a/.bundle/gems/coderay-1.1.0/test/functional/basic.rb b/.bundle/gems/coderay-1.1.0/test/functional/basic.rb new file mode 100755 index 0000000..752d4ba --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/test/functional/basic.rb @@ -0,0 +1,318 @@ +# encoding: utf-8 +require 'test/unit' +require File.expand_path('../../lib/assert_warning', __FILE__) + +$:.unshift File.expand_path('../../../lib', __FILE__) +require 'coderay' + +class BasicTest < Test::Unit::TestCase + + def test_version + assert_nothing_raised do + assert_match(/\A\d\.\d\.\d?\z/, CodeRay::VERSION) + end + end + + def with_empty_load_path + old_load_path = $:.dup + $:.clear + yield + ensure + $:.replace old_load_path + end + + def test_autoload + with_empty_load_path do + assert_nothing_raised do + CodeRay::Scanners::Java::BuiltinTypes + end + end + end + + RUBY_TEST_CODE = 'puts "Hello, World!"' + + RUBY_TEST_TOKENS = [ + ['puts', :ident], + [' ', :space], + [:begin_group, :string], + ['"', :delimiter], + ['Hello, World!', :content], + ['"', :delimiter], + [:end_group, :string] + ].flatten + def test_simple_scan + assert_nothing_raised do + assert_equal RUBY_TEST_TOKENS, CodeRay.scan(RUBY_TEST_CODE, :ruby).tokens + end + end + + RUBY_TEST_HTML = 'puts "' + + 'Hello, World!"' + def test_simple_highlight + assert_nothing_raised do + assert_equal RUBY_TEST_HTML, CodeRay.scan(RUBY_TEST_CODE, :ruby).html + end + end + + def test_scan_file + CodeRay.scan_file __FILE__ + end + + def test_encode + assert_equal 1, CodeRay.encode('test', :python, :count) + end + + def test_encode_tokens + assert_equal 1, CodeRay.encode_tokens(CodeRay::Tokens['test', :string], :count) + end + + def test_encode_file + assert_equal File.read(__FILE__), CodeRay.encode_file(__FILE__, :text) + end + + def test_highlight + assert_match '
test
', CodeRay.highlight('test', :python) + end + + def test_highlight_file + assert_match "require 'test/unit'\n", CodeRay.highlight_file(__FILE__) + end + + def test_duo + assert_equal(RUBY_TEST_CODE, + CodeRay::Duo[:plain, :text].highlight(RUBY_TEST_CODE)) + assert_equal(RUBY_TEST_CODE, + CodeRay::Duo[:plain => :text].highlight(RUBY_TEST_CODE)) + end + + def test_duo_stream + assert_equal(RUBY_TEST_CODE, + CodeRay::Duo[:plain, :text].highlight(RUBY_TEST_CODE, :stream => true)) + end + + def test_comment_filter + assert_equal <<-EXPECTED, CodeRay.scan(<<-INPUT, :ruby).comment_filter.text +#!/usr/bin/env ruby + +code + +more code + EXPECTED +#!/usr/bin/env ruby +=begin +A multi-line comment. +=end +code +# A single-line comment. +more code # and another comment, in-line. + INPUT + end + + def test_lines_of_code + assert_equal 2, CodeRay.scan(<<-INPUT, :ruby).lines_of_code +#!/usr/bin/env ruby +=begin +A multi-line comment. +=end +code +# A single-line comment. +more code # and another comment, in-line. + INPUT + rHTML = <<-RHTML + + + + + + <%= controller.controller_name.titleize %>: <%= controller.action_name %> + <%= stylesheet_link_tag 'scaffold' %> + + + +

<%= flash[:notice] %>

+ +
+ <%= yield %> +
+ + + + RHTML + assert_equal 0, CodeRay.scan(rHTML, :html).lines_of_code + assert_equal 0, CodeRay.scan(rHTML, :php).lines_of_code + assert_equal 0, CodeRay.scan(rHTML, :yaml).lines_of_code + assert_equal 4, CodeRay.scan(rHTML, :erb).lines_of_code + end + + def test_list_of_encoders + assert_kind_of(Array, CodeRay::Encoders.list) + assert CodeRay::Encoders.list.include?(:count) + end + + def test_list_of_scanners + assert_kind_of(Array, CodeRay::Scanners.list) + assert CodeRay::Scanners.list.include?(:text) + end + + def test_token_kinds + assert_kind_of Hash, CodeRay::TokenKinds + for kind, css_class in CodeRay::TokenKinds + assert_kind_of Symbol, kind + if css_class != false + assert_kind_of String, css_class, "TokenKinds[%p] == %p" % [kind, css_class] + end + end + assert_equal 'reserved', CodeRay::TokenKinds[:reserved] + assert_equal false, CodeRay::TokenKinds[:shibboleet] + end + + class Milk < CodeRay::Encoders::Encoder + FILE_EXTENSION = 'cocoa' + end + + class HoneyBee < CodeRay::Encoders::Encoder + end + + def test_encoder_file_extension + assert_nothing_raised do + assert_equal 'html', CodeRay::Encoders::Page::FILE_EXTENSION + assert_equal 'cocoa', Milk::FILE_EXTENSION + assert_equal 'cocoa', Milk.new.file_extension + assert_equal 'honeybee', HoneyBee::FILE_EXTENSION + assert_equal 'honeybee', HoneyBee.new.file_extension + end + assert_raise NameError do + HoneyBee::MISSING_CONSTANT + end + end + + def test_encoder_tokens + encoder = CodeRay::Encoders::Encoder.new + encoder.send :setup, {} + assert_raise(ArgumentError) { encoder.token :strange, '' } + encoder.token 'test', :debug + end + + def test_encoder_deprecated_interface + encoder = CodeRay::Encoders::Encoder.new + encoder.send :setup, {} + assert_warning 'Using old Tokens#<< interface.' do + encoder << ['test', :content] + end + assert_raise ArgumentError do + encoder << [:strange, :input] + end + assert_raise ArgumentError do + encoder.encode_tokens [['test', :token]] + end + end + + def encoder_token_interface_deprecation_warning_given + CodeRay::Encoders::Encoder.send :class_variable_get, :@@CODERAY_TOKEN_INTERFACE_DEPRECATION_WARNING_GIVEN + end + + def test_scanner_file_extension + assert_equal 'rb', CodeRay::Scanners::Ruby.file_extension + assert_equal 'rb', CodeRay::Scanners::Ruby.new.file_extension + assert_equal 'java', CodeRay::Scanners::Java.file_extension + assert_equal 'java', CodeRay::Scanners::Java.new.file_extension + end + + def test_scanner_lang + assert_equal :ruby, CodeRay::Scanners::Ruby.lang + assert_equal :ruby, CodeRay::Scanners::Ruby.new.lang + assert_equal :java, CodeRay::Scanners::Java.lang + assert_equal :java, CodeRay::Scanners::Java.new.lang + end + + def test_scanner_tokenize + assert_equal ['foo', :plain], CodeRay::Scanners::Plain.new.tokenize('foo') + assert_equal [['foo', :plain], ['bar', :plain]], CodeRay::Scanners::Plain.new.tokenize(['foo', 'bar']) + CodeRay::Scanners::Plain.new.tokenize 42 + end + + def test_scanner_tokens + scanner = CodeRay::Scanners::Plain.new + scanner.tokenize('foo') + assert_equal ['foo', :plain], scanner.tokens + scanner.string = '' + assert_equal ['', :plain], scanner.tokens + end + + def test_scanner_line_and_column + scanner = CodeRay::Scanners::Plain.new "foo\nbär+quux" + assert_equal 0, scanner.pos + assert_equal 1, scanner.line + assert_equal 1, scanner.column + scanner.scan(/foo/) + assert_equal 3, scanner.pos + assert_equal 1, scanner.line + assert_equal 4, scanner.column + scanner.scan(/\n/) + assert_equal 4, scanner.pos + assert_equal 2, scanner.line + assert_equal 1, scanner.column + scanner.scan(/b/) + assert_equal 5, scanner.pos + assert_equal 2, scanner.line + assert_equal 2, scanner.column + scanner.scan(/a/) + assert_equal 5, scanner.pos + assert_equal 2, scanner.line + assert_equal 2, scanner.column + scanner.scan(/ä/) + assert_equal 7, scanner.pos + assert_equal 2, scanner.line + assert_equal 4, scanner.column + scanner.scan(/r/) + assert_equal 8, scanner.pos + assert_equal 2, scanner.line + assert_equal 5, scanner.column + end + + def test_scanner_use_subclasses + assert_raise NotImplementedError do + CodeRay::Scanners::Scanner.new + end + end + + class InvalidScanner < CodeRay::Scanners::Scanner + end + + def test_scanner_scan_tokens + assert_raise NotImplementedError do + InvalidScanner.new.tokenize '' + end + end + + class RaisingScanner < CodeRay::Scanners::Scanner + def scan_tokens encoder, options + raise_inspect 'message', [], :initial + end + end + + def test_scanner_raise_inspect + assert_raise CodeRay::Scanners::Scanner::ScanError do + RaisingScanner.new.tokenize '' + end + end + + def test_scan_a_frozen_string + assert_nothing_raised do + CodeRay.scan RUBY_VERSION, :ruby + CodeRay.scan RUBY_VERSION, :plain + end + end + + def test_scan_a_non_string + assert_nothing_raised do + CodeRay.scan 42, :ruby + CodeRay.scan nil, :ruby + CodeRay.scan self, :ruby + CodeRay.encode ENV.to_hash, :ruby, :page + CodeRay.highlight CodeRay, :plain + end + end + +end diff --git a/.bundle/gems/coderay-1.1.0/test/functional/examples.rb b/.bundle/gems/coderay-1.1.0/test/functional/examples.rb new file mode 100755 index 0000000..985ef87 --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/test/functional/examples.rb @@ -0,0 +1,129 @@ +require 'test/unit' + +$:.unshift File.expand_path('../../../lib', __FILE__) +require 'coderay' + +class ExamplesTest < Test::Unit::TestCase + + def test_examples + # output as HTML div (using inline CSS styles) + div = CodeRay.scan('puts "Hello, world!"', :ruby).div + assert_equal <<-DIV, div +
+
puts "Hello, world!"
+
+ DIV + + # ...with line numbers + div = CodeRay.scan(<<-CODE.chomp, :ruby).div(:line_numbers => :table) +5.times do + puts 'Hello, world!' +end + CODE + assert_equal <<-DIV, div + + + +
1
+2
+3
+
5.times do
+  puts 'Hello, world!'
+end
+ DIV + + # output as standalone HTML page (using CSS classes) + page = CodeRay.scan('puts "Hello, world!"', :ruby).page + assert_match <<-PAGE, page + + + + + +
1
+
puts "Hello, world!"
+ + + PAGE + + # keep scanned tokens for later use + tokens = CodeRay.scan('{ "just": "an", "example": 42 }', :json) + assert_kind_of CodeRay::TokensProxy, tokens + + assert_equal ["{", :operator, " ", :space, :begin_group, :key, + "\"", :delimiter, "just", :content, "\"", :delimiter, + :end_group, :key, ":", :operator, " ", :space, + :begin_group, :string, "\"", :delimiter, "an", :content, + "\"", :delimiter, :end_group, :string, ",", :operator, + " ", :space, :begin_group, :key, "\"", :delimiter, + "example", :content, "\"", :delimiter, :end_group, :key, + ":", :operator, " ", :space, "42", :integer, + " ", :space, "}", :operator], tokens.tokens + + # produce a token statistic + assert_equal <<-STATISTIC, tokens.statistic + +Code Statistics + +Tokens 26 + Non-Whitespace 15 +Bytes Total 31 + +Token Types (7): + type count ratio size (average) +------------------------------------------------------------- + TOTAL 26 100.00 % 1.2 + delimiter 6 23.08 % 1.0 + operator 5 19.23 % 1.0 + space 5 19.23 % 1.0 + key 4 15.38 % 0.0 + :begin_group 3 11.54 % 0.0 + :end_group 3 11.54 % 0.0 + content 3 11.54 % 4.3 + string 2 7.69 % 0.0 + integer 1 3.85 % 2.0 + + STATISTIC + + # count the tokens + assert_equal 26, tokens.count + + # produce a HTML div, but with CSS classes + div = tokens.div(:css => :class) + assert_equal <<-DIV, div +
+
{ "just": "an", "example": 42 }
+
+ DIV + + # highlight a file (HTML div); guess the file type base on the extension + assert_equal :ruby, CodeRay::FileType[__FILE__] + + # get a new scanner for Python + python_scanner = CodeRay.scanner :python + assert_kind_of CodeRay::Scanners::Python, python_scanner + + # get a new encoder for terminal + terminal_encoder = CodeRay.encoder :term + assert_kind_of CodeRay::Encoders::Terminal, terminal_encoder + + # scanning into tokens + tokens = python_scanner.tokenize 'import this; # The Zen of Python' + assert_equal ["import", :keyword, " ", :space, "this", :include, + ";", :operator, " ", :space, "# The Zen of Python", :comment], tokens + + # format the tokens + term = terminal_encoder.encode_tokens(tokens) + assert_equal "\e[32mimport\e[0m \e[31mthis\e[0m; \e[1;30m# The Zen of Python\e[0m", term + + # re-using scanner and encoder + ruby_highlighter = CodeRay::Duo[:ruby, :div] + div = ruby_highlighter.encode('puts "Hello, world!"') + assert_equal <<-DIV, div +
+
puts "Hello, world!"
+
+ DIV + end + +end diff --git a/.bundle/gems/coderay-1.1.0/test/functional/for_redcloth.rb b/.bundle/gems/coderay-1.1.0/test/functional/for_redcloth.rb new file mode 100644 index 0000000..9fd244e --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/test/functional/for_redcloth.rb @@ -0,0 +1,78 @@ +require 'test/unit' + +$:.unshift File.expand_path('../../../lib', __FILE__) +require 'coderay' + +begin + require 'rubygems' unless defined? Gem + gem 'RedCloth', '>= 4.0.3' rescue nil + require 'redcloth' +rescue LoadError + warn 'RedCloth not found - skipping for_redcloth tests.' + undef RedCloth if defined? RedCloth +end + +class BasicTest < Test::Unit::TestCase + + def test_for_redcloth + require 'coderay/for_redcloth' + assert_equal "

puts "Hello, World!"

", + RedCloth.new('@[ruby]puts "Hello, World!"@').to_html + assert_equal <<-BLOCKCODE.chomp, +
+
puts "Hello, World!"
+
+ BLOCKCODE + RedCloth.new('bc[ruby]. puts "Hello, World!"').to_html + end + + def test_for_redcloth_no_lang + require 'coderay/for_redcloth' + assert_equal "

puts \"Hello, World!\"

", + RedCloth.new('@puts "Hello, World!"@').to_html + assert_equal <<-BLOCKCODE.chomp, +
puts \"Hello, World!\"
+ BLOCKCODE + RedCloth.new('bc. puts "Hello, World!"').to_html + end + + def test_for_redcloth_style + require 'coderay/for_redcloth' + assert_equal <<-BLOCKCODE.chomp, +
puts \"Hello, World!\"
+ BLOCKCODE + RedCloth.new('bc{color: red}. puts "Hello, World!"').to_html + end + + def test_for_redcloth_escapes + require 'coderay/for_redcloth' + assert_equal '

>

', + RedCloth.new('@[ruby]>@').to_html + assert_equal <<-BLOCKCODE.chomp, +
+
&
+
+ BLOCKCODE + RedCloth.new('bc[ruby]. &').to_html + end + + def test_for_redcloth_escapes2 + require 'coderay/for_redcloth' + assert_equal "

#include <test.h>

", + RedCloth.new('@[c]#include @').to_html + end + + # See http://jgarber.lighthouseapp.com/projects/13054/tickets/124-code-markup-does-not-allow-brackets. + def test_for_redcloth_false_positive + require 'coderay/for_redcloth' + assert_equal '

[project]_dff.skjd

', + RedCloth.new('@[project]_dff.skjd@').to_html + # false positive, but expected behavior / known issue + assert_equal "

_dff.skjd

", + RedCloth.new('@[ruby]_dff.skjd@').to_html + assert_equal <<-BLOCKCODE.chomp, RedCloth.new('bc. [project]_dff.skjd').to_html +
[project]_dff.skjd
+ BLOCKCODE + end + +end if defined? RedCloth \ No newline at end of file diff --git a/.bundle/gems/coderay-1.1.0/test/functional/suite.rb b/.bundle/gems/coderay-1.1.0/test/functional/suite.rb new file mode 100755 index 0000000..ec23eec --- /dev/null +++ b/.bundle/gems/coderay-1.1.0/test/functional/suite.rb @@ -0,0 +1,15 @@ +require 'test/unit' + +$VERBOSE = $CODERAY_DEBUG = true +$:.unshift File.expand_path('../../../lib', __FILE__) +require 'coderay' + +mydir = File.dirname(__FILE__) +suite = Dir[File.join(mydir, '*.rb')]. + map { |tc| File.basename(tc).sub(/\.rb$/, '') } - %w'suite for_redcloth' + +puts "Running basic CodeRay #{CodeRay::VERSION} tests: #{suite.join(', ')}" + +for test_case in suite + load File.join(mydir, test_case + '.rb') +end diff --git a/.bundle/gems/diff-lcs-1.2.5/.autotest b/.bundle/gems/diff-lcs-1.2.5/.autotest new file mode 100644 index 0000000..1236395 --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/.autotest @@ -0,0 +1,3 @@ +require 'rubygems' + +# vim: syntax=ruby diff --git a/.bundle/gems/diff-lcs-1.2.5/.gemtest b/.bundle/gems/diff-lcs-1.2.5/.gemtest new file mode 100644 index 0000000..e69de29 diff --git a/.bundle/gems/diff-lcs-1.2.5/.hoerc b/.bundle/gems/diff-lcs-1.2.5/.hoerc new file mode 100644 index 0000000..0a13543 --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/.hoerc @@ -0,0 +1,2 @@ +--- +exclude: !ruby/regexp /(tmp|swp)$|CVS|TAGS|\.(svn|git|hg|DS_Store|idea)|Gemfile\.lock|research\/|\.gemspec$/ diff --git a/.bundle/gems/diff-lcs-1.2.5/.rspec b/.bundle/gems/diff-lcs-1.2.5/.rspec new file mode 100644 index 0000000..7438fbe --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/.rspec @@ -0,0 +1,2 @@ +--colour +--format documentation diff --git a/.bundle/gems/diff-lcs-1.2.5/.travis.yml b/.bundle/gems/diff-lcs-1.2.5/.travis.yml new file mode 100644 index 0000000..903cddf --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/.travis.yml @@ -0,0 +1,22 @@ +--- +after_script: +- rake travis:after -t +before_script: +- gem install hoe-travis --no-rdoc --no-ri +- rake travis:before -t +language: ruby +notifications: + email: true +rvm: + - 2.0.0 + - 1.9.3 + - 1.9.2 + - ruby-head + - 1.8.7 + - jruby-19mode + - jruby-head + - jruby-18mode + - rbx-19mode + - rbx-18mode + - ree +script: rake travis diff --git a/.bundle/gems/diff-lcs-1.2.5/Contributing.rdoc b/.bundle/gems/diff-lcs-1.2.5/Contributing.rdoc new file mode 100644 index 0000000..a0f37de --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/Contributing.rdoc @@ -0,0 +1,64 @@ +== Contributing + +I value any contribution to Diff::LCS you can provide: a bug report, a feature +request, or code contributions. + +Code contributions to Diff::LCS are especially welcomeencouraged. +Because Diff::LCS is a complex codebase, there are a few guidelines: + +* Changes will not be accepted without tests. +* The test suite is written with RSpec.‡ +* Match my coding style. +* Use a thoughtfully-named topic branch that contains your change. Rebase your + commits into logical chunks as necessary. +* Use {quality commit messages}[http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html]. +* Do not change the version number; when your patch is accepted and a release + is made, the version will be updated at that point. +* Submit a GitHub pull request with your changes. +* New features require new documentation. + +=== Test Dependencies + +To run the test suite, you will need to install the development dependencies +for Diff::LCS. If you have Bundler, you can accomplish this easily: + + $ bundle install + +Diff::LCS uses Ryan Davis’s excellent {Hoe}[https://github.com/seattlerb/hoe] +to manage the release process, and it adds a number of rake tasks. You will +mostly be interested in: + + $ rake + +which runs the tests the same way that: + + $ rake spec + $ rake test + $ rake travis + +will do. + +=== Workflow + +Here's the most direct way to get your work merged into the project: + +* Fork the project. +* Clone down your fork (+git clone git://github.com//diff-lcs.git+). +* Create a topic branch to contain your change (+git checkout -b my\_awesome\_feature+). +* Hack away, add tests. Not necessarily in that order. +* Make sure everything still passes by running `rake`. +* If necessary, rebase your commits into logical chunks, without errors. +* Push the branch up (+git push origin my\_awesome\_feature+). +* Create a pull request against halostatue/diff-lcs and describe what your + change does and the why you think it should be merged. + +=== Contributors + +* Austin Ziegler created Diff::LCS. + +Thanks to everyone else who has contributed to Diff::LCS: + +* Kenichi Kamiya +* Michael Granger +* Vít Ondruch +* Jon Rowe diff --git a/.bundle/gems/diff-lcs-1.2.5/Gemfile b/.bundle/gems/diff-lcs-1.2.5/Gemfile new file mode 100644 index 0000000..174f15f --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/Gemfile @@ -0,0 +1,20 @@ +# -*- ruby -*- + +# DO NOT EDIT THIS FILE. Instead, edit Rakefile, and run `rake bundler:gemfile`. + +source "https://rubygems.org/" + + +gem "rubyforge", ">=2.0.4", :group => [:development, :test] +gem "rdoc", "~>4.0", :group => [:development, :test] +gem "hoe-bundler", "~>1.2", :group => [:development, :test] +gem "hoe-doofus", "~>1.0", :group => [:development, :test] +gem "hoe-gemspec2", "~>1.1", :group => [:development, :test] +gem "hoe-git", "~>1.5", :group => [:development, :test] +gem "hoe-rubygems", "~>1.0", :group => [:development, :test] +gem "hoe-travis", "~>1.2", :group => [:development, :test] +gem "rake", "~>10.0", :group => [:development, :test] +gem "rspec", "~>2.0", :group => [:development, :test] +gem "hoe", "~>3.7", :group => [:development, :test] + +# vim: syntax=ruby diff --git a/.bundle/gems/diff-lcs-1.2.5/History.rdoc b/.bundle/gems/diff-lcs-1.2.5/History.rdoc new file mode 100644 index 0000000..69e5ddc --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/History.rdoc @@ -0,0 +1,152 @@ +== 1.2.5 / 2013-11-08 + +* Bugs fixed: + * Comparing arrays flattened them too far, especially with Diff::LCS.sdiff. + https://github.com/halostatue/diff-lcs/pull/23 + +== 1.2.4 / 2013-04-20 + +* Bugs fixed: + * A bug was introduced after 1.1.3 when pruning common sequences at the start + of comparison. Paul Kunysch (@pck) fixed this in pull request 18. Thanks! + https://github.com/halostatue/diff-lcs/pull/18 +* The Rubinius (1.9 mode) bug in rubinius/rubinius#2268 has been fixed by the + Rubinius team two days after it was filed. Thanks for fixing this so quickly! + https://github.com/rubinius/rubinius/issues/2268 +* Switching to Raggi's hoe-gemspec2 for gemspec generation. + +== 1.2.3 / 2013-04-11 + +* Bugs Fixed: + * The new encoding detection for diff output generation (added in 1.2.2) + introduced a bug if the left side of the comparison was the empty set. + Originally found in rspec/rspec-expectations#238 and + rspec/rspec-expectations#239. Jon Rowe developed a reasonable heuristic + (left side, right side, empty string literal) to avoid this bug. + https://github.com/rspec/rspec-expectations/pull/238 + https://github.com/rspec/rspec-expectations/pull/239 +* There is a known issue with Rubinius in 1.9 mode reported in + rubinius/rubinius#2268 and demonstrated in the Travis CI builds. For all + other tested platforms, diff-lcs is considered stable. As soon as a suitably + small test-case can be created for the Rubinius team to examine, this will be + added to the Rubinius issue around this. + https://github.com/rubinius/rubinius/issues/2268 + https://travis-ci.org/halostatue/diff-lcs/jobs/6241195 + +== 1.2.2 / 2013-03-30 + +* Bugs Fixed: + * Diff::LCS::Hunk could not properly generate a difference for comparison + sets that are not US-ASCII-compatible because of the use of literal regular + expressions and strings. Jon Rowe (JonRowe) found this in + rspec/rspec-expectations#219 and provided a first pass implementation in + diff-lcs#15. I've reworked it because of test failures in Rubinius when + running in Ruby 1.9 mode. This coerces the added values to the encoding of + the old dataset (as determined by the first piece of the old dataset). + https://github.com/rspec/rspec-expectations/issues/219 + https://github.com/halostatue/diff-lcs/pull/15 +* Adding Travis CI testing for Ruby 2.0. + +== 1.2.1 / 2013-02-09 + +* Bugs Fixed: + * As seen in https://github.com/rspec/rspec-expectations/pull/200, the + release of Diff::LCS 1.2 introduced an unnecessary public API change to + Diff::LCS::Hunk (see the change at + https://github.com/rspec/rspec-expectations/commit/3d6fc82c for details). + The new method name (and behaviour) is more correct, but I should not have + renamed the function or should have at least provided an alias. This + release restores Diff::LCS::Hunk#unshift as an alias to + #merge. Note that the old #unshift behaviour was incorrect and will not be + restored. + +== 1.2.0 / 2013-01-21 +* Minor Enhancements: + * Added special case handling for Diff::LCS.patch so that it handles patches + that are empty or contain no changes. + * Added two new methods (#patch\_me and #unpatch\_me) to the includable + module. +* Bugs Fixed: + * Fixed issue #1 patch direction detection. + https://github.com/halostatue/diff-lcs/issues/1 + * Resolved issue #2 by handling string[string.size, 1] properly (it returns + "" not nil). https://github.com/halostatue/diff-lcs/issues/2 + * Michael Granger (ged) fixed an implementation error in Diff::LCS::Change + and added specs in pull request #8. Thanks! + https://github.com/halostatue/diff-lcs/issues/8 + * Made the code auto-testable. + * Vít Ondruch (voxik) provided the latest version of the GPL2 license file in + pull request #10. Thanks! https://github.com/halostatue/diff-lcs/issues/10 + * Fixed a documentation issue with the includable versions of #patch! and + #unpatch! where they implied that they would replace the original value. + Given that Diff::LCS.patch always returns a copy, the documentation was + incorrect and has been corrected. To provide the behaviour that was + originally documented, two new methods were added to provide this + behaviour. Found by scooter-dangle in issue #12. Thanks! + https://github.com/halostatue/diff-lcs/issues/12 +* Code Style Changes: + * Removed trailing spaces. + * Calling class methods using '.' instead of '::'. + * Vít Ondruch (voxik) removed unnecessary shebangs in pull request #9. + Thanks! https://github.com/halostatue/diff-lcs/issues/9 + * Kenichi Kamiya (kachick) removed some warnings of an unused variable in + lucky pull request #13. https://github.com/halostatue/diff-lcs/issues/13 + Thanks! + * Embarked on a major refactoring to make the files a little more manageable + and understand the code on a deeper level. + * Adding to http://travis-ci.org. + +== 1.1.3 / 2011-08-27 +* Converted to 'hoe' for release. +* Converted tests to RSpec 2. +* Extracted the body of htmldiff into a class available from + diff/lcs/htmldiff. +* Migrated development and issue tracking to GitHub. +* Bugs fixed: + - Eliminated the explicit use of RubyGems in both bin/htmldiff and bin/ldiff. + Resolves issue 4 (https://github.com/halostatue/diff-lcs/issues/4). + - Eliminated Ruby warnings. Resolves issue 3 + (https://github.com/halostatue/diff-lcs/issues/3). + +== 1.1.2 / 2004-10-20 +* Fixed a problem reported by Mauricio Fernandez in htmldiff. + +== 1.1.1 / 2004-09-25 +* Fixed bug #891: + http://rubyforge.org/tracker/?func=detail&atid=407&aid=891&group_id=84 +* Fixed a problem with callback initialisation code (it assumed that all + callbacks passed as classes can be initialised; now, it rescues + NoMethodError in the event of private :new being called). +* Modified the non-initialisable callbacks to have a private #new method. +* Moved ldiff core code to Diff::LCS::Ldiff (diff/lcs/ldiff.rb). + +== 1.1.0 / - +* Eliminated the need for Diff::LCS::Event and removed it. +* Added a contextual diff callback, Diff::LCS::ContextDiffCallback. +* Implemented patching/unpatching for standard Diff callback output formats + with both #diff and #sdiff. +* Extensive documentation changes. + +== 1.0.4 / - +* Fixed a problem with bin/ldiff output, especially for unified format. + Newlines that should have been present weren't. +* Changed the .tar.gz installer to generate Windows batch files if ones do not + exist already. Removed the existing batch files as they didn't work. + +== 1.0.3 / - +* Fixed a problem with #traverse\_sequences where the first difference from the + left sequence might not be appropriately captured. + +== 1.0.2 / - +* Fixed an issue with ldiff not working because actions were changed from + symbols to strings. + +== 1.0.1 / - +* Minor modifications to the gemspec, the README. +* Renamed the diff program to ldiff (as well as the companion batch file) so as + to not collide with the standard diff program. +* Fixed issues with RubyGems. Requires RubyGems > 0.6.1 or >= 0.6.1 with the + latest CVS version. + +== 1.0 / - +* Initial release based mostly on Perl's Algorithm::Diff. diff --git a/.bundle/gems/diff-lcs-1.2.5/License.rdoc b/.bundle/gems/diff-lcs-1.2.5/License.rdoc new file mode 100644 index 0000000..63b763d --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/License.rdoc @@ -0,0 +1,39 @@ +== License + +This software is available under three licenses: the GNU GPL version 2 (or at +your option, a later version), the Perl Artistic license, or the MIT license. +Note that my preference for licensing is the MIT license, but Algorithm::Diff +was dually originally licensed with the Perl Artistic and the GNU GPL ("the +same terms as Perl itself") and given that the Ruby implementation originally +hewed pretty closely to the Perl version, I must maintain the additional +licensing terms. + +* Copyright 2004–2013 Austin Ziegler. +* Adapted from Algorithm::Diff (Perl) by Ned Konz and a Smalltalk version by + Mario I. Wolczko. + +=== MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +=== Perl Artistic License (version 2) +See the file docs/artistic.txt in the main distribution. + +=== GNU GPL version 2 +See the file docs/COPYING.txt in the main distribution. diff --git a/.bundle/gems/diff-lcs-1.2.5/Manifest.txt b/.bundle/gems/diff-lcs-1.2.5/Manifest.txt new file mode 100644 index 0000000..d078734 --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/Manifest.txt @@ -0,0 +1,38 @@ +.autotest +.gemtest +.hoerc +.rspec +.travis.yml +Contributing.rdoc +Gemfile +History.rdoc +License.rdoc +Manifest.txt +README.rdoc +Rakefile +autotest/discover.rb +bin/htmldiff +bin/ldiff +docs/COPYING.txt +docs/artistic.txt +lib/diff-lcs.rb +lib/diff/lcs.rb +lib/diff/lcs/array.rb +lib/diff/lcs/block.rb +lib/diff/lcs/callbacks.rb +lib/diff/lcs/change.rb +lib/diff/lcs/htmldiff.rb +lib/diff/lcs/hunk.rb +lib/diff/lcs/internals.rb +lib/diff/lcs/ldiff.rb +lib/diff/lcs/string.rb +spec/change_spec.rb +spec/diff_spec.rb +spec/hunk_spec.rb +spec/issues_spec.rb +spec/lcs_spec.rb +spec/patch_spec.rb +spec/sdiff_spec.rb +spec/spec_helper.rb +spec/traverse_balanced_spec.rb +spec/traverse_sequences_spec.rb diff --git a/.bundle/gems/diff-lcs-1.2.5/README.rdoc b/.bundle/gems/diff-lcs-1.2.5/README.rdoc new file mode 100644 index 0000000..fd6964e --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/README.rdoc @@ -0,0 +1,85 @@ += Diff::LCS + +home :: http://diff-lcs.rubyforge.org/ +code :: https://github.com/halostatue/diff-lcs +bugs :: https://github.com/halostatue/diff-lcs/issues +rdoc :: http://rubydoc.info/github/halostatue/diff-lcs + +== Description + +Diff::LCS computes the difference between two Enumerable sequences using the +McIlroy-Hunt longest common subsequence (LCS) algorithm. It includes utilities +to create a simple HTML diff output format and a standard diff-like tool. + +This is release 1.2.4, fixing a bug introduced after diff-lcs 1.1.3 that did +not properly prune common sequences at the beginning of a comparison set. +Thanks to Paul Kunysch for fixing this issue. + +Coincident with the release of diff-lcs 1.2.3, we reported an issue with +Rubinius in 1.9 mode +({rubinius/rubinius#2268}[https://github.com/rubinius/rubinius/issues/2268]). +We are happy to report that this issue has been resolved. + +== Synopsis + +Using this module is quite simple. By default, Diff::LCS does not extend +objects with the Diff::LCS interface, but will be called as if it were a +function: + + require 'diff/lcs' + + seq1 = %w(a b c e h j l m n p) + seq2 = %w(b c d e f j k l m r s t) + + lcs = Diff::LCS.LCS(seq1, seq2) + diffs = Diff::LCS.diff(seq1, seq2) + sdiff = Diff::LCS.sdiff(seq1, seq2) + seq = Diff::LCS.traverse_sequences(seq1, seq2, callback_obj) + bal = Diff::LCS.traverse_balanced(seq1, seq2, callback_obj) + seq2 == Diff::LCS.patch!(seq1, diffs) + seq1 == Diff::LCS.unpatch!(seq2, diffs) + seq2 == Diff::LCS.patch!(seq1, sdiff) + seq1 == Diff::LCS.unpatch!(seq2, sdiff) + +Objects can be extended with Diff::LCS: + + seq1.extend(Diff::LCS) + lcs = seq1.lcs(seq2) + diffs = seq1.diff(seq2) + sdiff = seq1.sdiff(seq2) + seq = seq1.traverse_sequences(seq2, callback_obj) + bal = seq1.traverse_balanced(seq2, callback_obj) + seq2 == seq1.patch!(diffs) + seq1 == seq2.unpatch!(diffs) + seq2 == seq1.patch!(sdiff) + seq1 == seq2.unpatch!(sdiff) + +By requiring 'diff/lcs/array' or 'diff/lcs/string', Array or String will be +extended for use this way. + +Note that Diff::LCS requires a sequenced enumerable container, which means that +the order of enumeration is both predictable and consistent for the same set of +data. While it is theoretically possible to generate a diff for an unordered +hash, it will only be meaningful if the enumeration of the hashes is +consistent. In general, this will mean that containers that behave like String +or Array will perform best. + +== History + +Diff::LCS is a port of Perl's Algorithm::Diff that uses the McIlroy-Hunt +longest common subsequence (LCS) algorithm to compute intelligent differences +between two sequenced enumerable containers. The implementation is based on +Mario I. Wolczko's {Smalltalk version 1.2}[ftp://st.cs.uiuc.edu/pub/Smalltalk/MANCHESTER/manchester/4.0/diff.st] +(1993) and Ned Konz's Perl version +{Algorithm::Diff 1.15}[http://search.cpan.org/~nedkonz/Algorithm-Diff-1.15/]. + +This library is called Diff::LCS because of an early version of Algorithm::Diff +which was restrictively licensed. + +== Continuous Integration Status + +{}[https://travis-ci.org/halostatue/diff-lcs] + +:include: Contributing.rdoc + +:include: License.rdoc diff --git a/.bundle/gems/diff-lcs-1.2.5/Rakefile b/.bundle/gems/diff-lcs-1.2.5/Rakefile new file mode 100644 index 0000000..5186800 --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/Rakefile @@ -0,0 +1,41 @@ +# -*- ruby encoding: utf-8 -*- + +require 'rubygems' +require 'rspec' +require 'hoe' + +Hoe.plugin :bundler +Hoe.plugin :doofus +Hoe.plugin :email +Hoe.plugin :gemspec2 +Hoe.plugin :git +Hoe.plugin :rubyforge +Hoe.plugin :travis + +Hoe.spec 'diff-lcs' do + developer('Austin Ziegler', 'austin@rubyforge.org') + + self.remote_rdoc_dir = '.' + self.rsync_args << ' --exclude=statsvn/' + + self.history_file = 'History.rdoc' + self.readme_file = 'README.rdoc' + self.extra_rdoc_files = FileList["*.rdoc"].to_a + + %w(MIT Perl\ Artistic\ v2 GNU\ GPL\ v2).each { |l| self.license l } + + self.extra_dev_deps << ['hoe-bundler', '~> 1.2'] + self.extra_dev_deps << ['hoe-doofus', '~> 1.0'] + self.extra_dev_deps << ['hoe-gemspec2', '~> 1.1'] + self.extra_dev_deps << ['hoe-git', '~> 1.5'] + self.extra_dev_deps << ['hoe-rubygems', '~> 1.0'] + self.extra_dev_deps << ['hoe-travis', '~> 1.2'] + self.extra_dev_deps << ['rake', '~> 10.0'] + self.extra_dev_deps << ['rspec', '~> 2.0'] +end + +unless Rake::Task.task_defined? :test + task :test => :spec +end + +# vim: syntax=ruby diff --git a/.bundle/gems/diff-lcs-1.2.5/autotest/discover.rb b/.bundle/gems/diff-lcs-1.2.5/autotest/discover.rb new file mode 100644 index 0000000..cd6892c --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/autotest/discover.rb @@ -0,0 +1 @@ +Autotest.add_discovery { "rspec2" } diff --git a/.bundle/gems/diff-lcs-1.2.5/bin/htmldiff b/.bundle/gems/diff-lcs-1.2.5/bin/htmldiff new file mode 100755 index 0000000..1e4efe7 --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/bin/htmldiff @@ -0,0 +1,32 @@ +#!ruby -w + +require 'diff/lcs' +require 'diff/lcs/htmldiff' + +begin + require 'text/format' +rescue LoadError + Diff::LCS::HTMLDiff.can_expand_tabs = false +end + +if ARGV.size < 2 or ARGV.size > 3 + $stderr.puts "usage: #{File.basename($0)} old new [output.html]" + $stderr.puts " #{File.basename($0)} old new > output.html" + exit 127 +end + +left = IO.read(ARGV[0]).split($/) +right = IO.read(ARGV[1]).split($/) + +options = { :title => "diff #{ARGV[0]} #{ARGV[1]}" } + +htmldiff = Diff::LCS::HTMLDiff.new(left, right, options) + +if ARGV[2] + File.open(ARGV[2], "w") do |f| + htmldiff.options[:output] = f + htmldiff.run + end +else + htmldiff.run +end diff --git a/.bundle/gems/diff-lcs-1.2.5/bin/ldiff b/.bundle/gems/diff-lcs-1.2.5/bin/ldiff new file mode 100755 index 0000000..a9b876f --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/bin/ldiff @@ -0,0 +1,6 @@ +#!ruby -w + +require 'diff/lcs' +require 'diff/lcs/ldiff' + +exit Diff::LCS::Ldiff.run(ARGV) diff --git a/.bundle/gems/diff-lcs-1.2.5/docs/COPYING.txt b/.bundle/gems/diff-lcs-1.2.5/docs/COPYING.txt new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/docs/COPYING.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/.bundle/gems/diff-lcs-1.2.5/docs/artistic.txt b/.bundle/gems/diff-lcs-1.2.5/docs/artistic.txt new file mode 100644 index 0000000..c04639a --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/docs/artistic.txt @@ -0,0 +1,127 @@ +The "Artistic License" + + Preamble + +The intent of this document is to state the conditions under which a +Package may be copied, such that the Copyright Holder maintains some +semblance of artistic control over the development of the package, +while giving the users of the package the right to use and distribute +the Package in a more-or-less customary fashion, plus the right to make +reasonable modifications. + +Definitions: + + "Package" refers to the collection of files distributed by the + Copyright Holder, and derivatives of that collection of files + created through textual modification. + + "Standard Version" refers to such a Package if it has not been + modified, or has been modified in accordance with the wishes + of the Copyright Holder as specified below. + + "Copyright Holder" is whoever is named in the copyright or + copyrights for the package. + + "You" is you, if you're thinking about copying or distributing + this Package. + + "Reasonable copying fee" is whatever you can justify on the + basis of media cost, duplication charges, time of people involved, + and so on. (You will not be required to justify it to the + Copyright Holder, but only to the computing community at large + as a market that must bear the fee.) + + "Freely Available" means that no fee is charged for the item + itself, though there may be fees involved in handling the item. + It also means that recipients of the item may redistribute it + under the same conditions they received it. + +1. You may make and give away verbatim copies of the source form of the +Standard Version of this Package without restriction, provided that you +duplicate all of the original copyright notices and associated disclaimers. + +2. You may apply bug fixes, portability fixes and other modifications +derived from the Public Domain or from the Copyright Holder. A Package +modified in such a way shall still be considered the Standard Version. + +3. You may otherwise modify your copy of this Package in any way, provided +that you insert a prominent notice in each changed file stating how and +when you changed that file, and provided that you do at least ONE of the +following: + + a) place your modifications in the Public Domain or otherwise make them + Freely Available, such as by posting said modifications to Usenet or + an equivalent medium, or placing the modifications on a major archive + site such as uunet.uu.net, or by allowing the Copyright Holder to include + your modifications in the Standard Version of the Package. + + b) use the modified Package only within your corporation or organization. + + c) rename any non-standard executables so the names do not conflict + with standard executables, which must also be provided, and provide + a separate manual page for each non-standard executable that clearly + documents how it differs from the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +4. You may distribute the programs of this Package in object code or +executable form, provided that you do at least ONE of the following: + + a) distribute a Standard Version of the executables and library files, + together with instructions (in the manual page or equivalent) on where + to get the Standard Version. + + b) accompany the distribution with the machine-readable source of + the Package with your modifications. + + c) give non-standard executables non-standard names, and clearly + document the differences in manual pages (or equivalent), together + with instructions on where to get the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +5. You may charge a reasonable copying fee for any distribution of this +Package. You may charge any fee you choose for support of this +Package. You may not charge a fee for this Package itself. However, +you may distribute this Package in aggregate with other (possibly +commercial) programs as part of a larger (possibly commercial) software +distribution provided that you do not advertise this Package as a +product of your own. You may embed this Package's interpreter within +an executable of yours (by linking); this shall be construed as a mere +form of aggregation, provided that the complete Standard Version of the +interpreter is so embedded. + +6. The scripts and library files supplied as input to or produced as +output from the programs of this Package do not automatically fall +under the copyright of this Package, but belong to whoever generated +them, and may be sold commercially, and may be aggregated with this +Package. If such scripts or library files are aggregated with this +Package via the so-called "undump" or "unexec" methods of producing a +binary executable image, then distribution of such an image shall +neither be construed as a distribution of this Package nor shall it +fall under the restrictions of Paragraphs 3 and 4, provided that you do +not represent such an executable image as a Standard Version of this +Package. + +7. C subroutines (or comparably compiled subroutines in other +languages) supplied by you and linked into this Package in order to +emulate subroutines and variables of the language defined by this +Package shall not be considered part of this Package, but are the +equivalent of input as in Paragraph 6, provided these subroutines do +not change the language in any way that would cause it to fail the +regression tests for the language. + +8. Aggregation of this Package with a commercial distribution is always +permitted provided that the use of this Package is embedded; that is, +when no overt attempt is made to make this Package's interfaces visible +to the end user of the commercial distribution. Such use shall not be +construed as a distribution of this Package. + +9. The name of the Copyright Holder may not be used to endorse or promote +products derived from this software without specific prior written permission. + +10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + The End diff --git a/.bundle/gems/diff-lcs-1.2.5/lib/diff-lcs.rb b/.bundle/gems/diff-lcs-1.2.5/lib/diff-lcs.rb new file mode 100644 index 0000000..10d6e8a --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/lib/diff-lcs.rb @@ -0,0 +1,3 @@ +# -*- ruby encoding: utf-8 -*- + +require 'diff/lcs' diff --git a/.bundle/gems/diff-lcs-1.2.5/lib/diff/lcs.rb b/.bundle/gems/diff-lcs-1.2.5/lib/diff/lcs.rb new file mode 100644 index 0000000..5559615 --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/lib/diff/lcs.rb @@ -0,0 +1,805 @@ +# -*- ruby encoding: utf-8 -*- + +module Diff; end unless defined? Diff +# = Diff::LCS 1.2.5 +# +# Computes "intelligent" differences between two sequenced Enumerables. This +# is an implementation of the McIlroy-Hunt "diff" algorithm for Enumerable +# objects that include Diffable. +# +# Based on Mario I. Wolczko's Smalltalk version (1.2, 1993) and Ned Konz's +# Perl version (Algorithm::Diff 1.15). +# +# == Synopsis +# require 'diff/lcs' +# +# seq1 = %w(a b c e h j l m n p) +# seq2 = %w(b c d e f j k l m r s t) +# +# lcs = Diff::LCS.lcs(seq1, seq2) +# diffs = Diff::LCS.diff(seq1, seq2) +# sdiff = Diff::LCS.sdiff(seq1, seq2) +# seq = Diff::LCS.traverse_sequences(seq1, seq2, callback_obj) +# bal = Diff::LCS.traverse_balanced(seq1, seq2, callback_obj) +# seq2 == Diff::LCS.patch(seq1, diffs) +# seq2 == Diff::LCS.patch!(seq1, diffs) +# seq1 == Diff::LCS.unpatch(seq2, diffs) +# seq1 == Diff::LCS.unpatch!(seq2, diffs) +# seq2 == Diff::LCS.patch(seq1, sdiff) +# seq2 == Diff::LCS.patch!(seq1, sdiff) +# seq1 == Diff::LCS.unpatch(seq2, sdiff) +# seq1 == Diff::LCS.unpatch!(seq2, sdiff) +# +# Alternatively, objects can be extended with Diff::LCS: +# +# seq1.extend(Diff::LCS) +# lcs = seq1.lcs(seq2) +# diffs = seq1.diff(seq2) +# sdiff = seq1.sdiff(seq2) +# seq = seq1.traverse_sequences(seq2, callback_obj) +# bal = seq1.traverse_balanced(seq2, callback_obj) +# seq2 == seq1.patch(diffs) +# seq2 == seq1.patch!(diffs) +# seq1 == seq2.unpatch(diffs) +# seq1 == seq2.unpatch!(diffs) +# seq2 == seq1.patch(sdiff) +# seq2 == seq1.patch!(sdiff) +# seq1 == seq2.unpatch(sdiff) +# seq1 == seq2.unpatch!(sdiff) +# +# Default extensions are provided for Array and String objects through the +# use of 'diff/lcs/array' and 'diff/lcs/string'. +# +# == Introduction (by Mark-Jason Dominus) +# +# The following text is from the Perl documentation. The only changes +# have been to make the text appear better in Rdoc. +# +# I once read an article written by the authors of +diff+; they said that +# they hard worked very hard on the algorithm until they found the right +# one. +# +# I think what they ended up using (and I hope someone will correct me, +# because I am not very confident about this) was the `longest common +# subsequence' method. In the LCS problem, you have two sequences of items: +# +# a b c d f g h j q z +# a b c d e f g i j k r x y z +# +# and you want to find the longest sequence of items that is present in both +# original sequences in the same order. That is, you want to find a new +# sequence *S* which can be obtained from the first sequence by deleting +# some items, and from the second sequence by deleting other items. You also +# want *S* to be as long as possible. In this case *S* is: +# +# a b c d f g j z +# +# From there it's only a small step to get diff-like output: +# +# e h i k q r x y +# + - + + - + + + +# +# This module solves the LCS problem. It also includes a canned function to +# generate +diff+-like output. +# +# It might seem from the example above that the LCS of two sequences is +# always pretty obvious, but that's not always the case, especially when the +# two sequences have many repeated elements. For example, consider +# +# a x b y c z p d q +# a b c a x b y c z +# +# A naive approach might start by matching up the +a+ and +b+ that appear at +# the beginning of each sequence, like this: +# +# a x b y c z p d q +# a b c a b y c z +# +# This finds the common subsequence +a b c z+. But actually, the LCS is +a x +# b y c z+: +# +# a x b y c z p d q +# a b c a x b y c z +# +# == Author +# This version is by Austin Ziegler . +# +# It is based on the Perl Algorithm::Diff (1.15) by Ned Konz , copyright +# © 2000–2002 and the Smalltalk diff version by Mario I. +# Wolczko, copyright © 1993. Documentation includes work by +# Mark-Jason Dominus. +# +# == Licence +# Copyright © 2004–2013 Austin Ziegler +# This program is free software; you can redistribute it and/or modify it +# under the same terms as Ruby, or alternatively under the Perl Artistic +# licence. +# +# == Credits +# Much of the documentation is taken directly from the Perl Algorithm::Diff +# implementation and was written originally by Mark-Jason Dominus and later +# by Ned Konz. The basic Ruby implementation was re-ported from the +# Smalltalk implementation, available at +# ftp://st.cs.uiuc.edu/pub/Smalltalk/MANCHESTER/manchester/4.0/diff.st +# +# #sdiff and #traverse_balanced were written for the Perl version by Mike +# Schilli . +# +# "The algorithm is described in A Fast Algorithm for Computing Longest +# Common Subsequences, CACM, vol.20, no.5, pp.350-353, May +# 1977, with a few minor improvements to improve the speed." +module Diff::LCS + VERSION = '1.2.5' +end + +require 'diff/lcs/callbacks' +require 'diff/lcs/internals' + +module Diff::LCS + # Returns an Array containing the longest common subsequence(s) between + # +self+ and +other+. See Diff::LCS#LCS. + # + # lcs = seq1.lcs(seq2) + def lcs(other, &block) #:yields self[i] if there are matched subsequences: + Diff::LCS.lcs(self, other, &block) + end + + # Returns the difference set between +self+ and +other+. See + # Diff::LCS#diff. + def diff(other, callbacks = nil, &block) + Diff::LCS.diff(self, other, callbacks, &block) + end + + # Returns the balanced ("side-by-side") difference set between +self+ and + # +other+. See Diff::LCS#sdiff. + def sdiff(other, callbacks = nil, &block) + Diff::LCS.sdiff(self, other, callbacks, &block) + end + + # Traverses the discovered longest common subsequences between +self+ and + # +other+. See Diff::LCS#traverse_sequences. + def traverse_sequences(other, callbacks = nil, &block) + traverse_sequences(self, other, callbacks || + Diff::LCS.YieldingCallbacks, &block) + end + + # Traverses the discovered longest common subsequences between +self+ and + # +other+ using the alternate, balanced algorithm. See + # Diff::LCS#traverse_balanced. + def traverse_balanced(other, callbacks = nil, &block) + traverse_balanced(self, other, callbacks || + Diff::LCS.YieldingCallbacks, &block) + end + + # Attempts to patch +self+ with the provided +patchset+. A new sequence + # based on +self+ and the +patchset+ will be created. See Diff::LCS#patch. + # Attempts to autodiscover the direction of the patch. + def patch(patchset) + Diff::LCS.patch(self, patchset) + end + alias_method :unpatch, :patch + + # Attempts to patch +self+ with the provided +patchset+. A new sequence + # based on +self+ and the +patchset+ will be created. See Diff::LCS#patch. + # Does no patch direction autodiscovery. + def patch!(patchset) + Diff::LCS.patch!(self, patchset) + end + + # Attempts to unpatch +self+ with the provided +patchset+. A new sequence + # based on +self+ and the +patchset+ will be created. See Diff::LCS#unpatch. + # Does no patch direction autodiscovery. + def unpatch!(patchset) + Diff::LCS.unpatch!(self, patchset) + end + + # Attempts to patch +self+ with the provided +patchset+, using #patch!. If + # the sequence this is used on supports #replace, the value of +self+ will + # be replaced. See Diff::LCS#patch. Does no patch direction autodiscovery. + def patch_me(patchset) + if respond_to? :replace + replace(patch!(patchset)) + else + patch!(patchset) + end + end + + # Attempts to unpatch +self+ with the provided +patchset+, using + # #unpatch!. If the sequence this is used on supports #replace, the value + # of +self+ will be replaced. See Diff::LCS#unpatch. Does no patch direction + # autodiscovery. + def unpatch_me(patchset) + if respond_to? :replace + replace(unpatch!(patchset)) + else + unpatch!(patchset) + end + end +end + +class << Diff::LCS + def lcs(seq1, seq2, &block) #:yields seq1[i] for each matched: + matches = Diff::LCS::Internals.lcs(seq1, seq2) + ret = [] + string = seq1.kind_of? String + matches.each_with_index do |e, i| + unless matches[i].nil? + v = string ? seq1[i, 1] : seq1[i] + v = block[v] if block + ret << v + end + end + ret + end + alias_method :LCS, :lcs + + # #diff computes the smallest set of additions and deletions necessary to + # turn the first sequence into the second, and returns a description of + # these changes. + # + # See Diff::LCS::DiffCallbacks for the default behaviour. An alternate + # behaviour may be implemented with Diff::LCS::ContextDiffCallbacks. If a + # Class argument is provided for +callbacks+, #diff will attempt to + # initialise it. If the +callbacks+ object (possibly initialised) responds + # to #finish, it will be called. + def diff(seq1, seq2, callbacks = nil, &block) # :yields diff changes: + diff_traversal(:diff, seq1, seq2, callbacks || Diff::LCS::DiffCallbacks, + &block) + end + + # #sdiff computes all necessary components to show two sequences and their + # minimized differences side by side, just like the Unix utility + # sdiff does: + # + # old < - + # same same + # before | after + # - > new + # + # See Diff::LCS::SDiffCallbacks for the default behaviour. An alternate + # behaviour may be implemented with Diff::LCS::ContextDiffCallbacks. If a + # Class argument is provided for +callbacks+, #diff will attempt to + # initialise it. If the +callbacks+ object (possibly initialised) responds + # to #finish, it will be called. + def sdiff(seq1, seq2, callbacks = nil, &block) #:yields diff changes: + diff_traversal(:sdiff, seq1, seq2, callbacks || Diff::LCS::SDiffCallbacks, + &block) + end + + # #traverse_sequences is the most general facility provided by this + # module; #diff and #lcs are implemented as calls to it. + # + # The arguments to #traverse_sequences are the two sequences to traverse, + # and a callback object, like this: + # + # traverse_sequences(seq1, seq2, Diff::LCS::ContextDiffCallbacks.new) + # + # == Callback Methods + # + # Optional callback methods are emphasized. + # + # callbacks#match:: Called when +a+ and +b+ are pointing to + # common elements in +A+ and +B+. + # callbacks#discard_a:: Called when +a+ is pointing to an + # element not in +B+. + # callbacks#discard_b:: Called when +b+ is pointing to an + # element not in +A+. + # callbacks#finished_a:: Called when +a+ has reached the end of + # sequence +A+. + # callbacks#finished_b:: Called when +b+ has reached the end of + # sequence +B+. + # + # == Algorithm + # + # a---+ + # v + # A = a b c e h j l m n p + # B = b c d e f j k l m r s t + # ^ + # b---+ + # + # If there are two arrows (+a+ and +b+) pointing to elements of sequences + # +A+ and +B+, the arrows will initially point to the first elements of + # their respective sequences. #traverse_sequences will advance the arrows + # through the sequences one element at a time, calling a method on the + # user-specified callback object before each advance. It will advance the + # arrows in such a way that if there are elements A[i] and + # B[j] which are both equal and part of the longest common + # subsequence, there will be some moment during the execution of + # #traverse_sequences when arrow +a+ is pointing to A[i] and + # arrow +b+ is pointing to B[j]. When this happens, + # #traverse_sequences will call callbacks#match and then it will + # advance both arrows. + # + # Otherwise, one of the arrows is pointing to an element of its sequence + # that is not part of the longest common subsequence. #traverse_sequences + # will advance that arrow and will call callbacks#discard_a or + # callbacks#discard_b, depending on which arrow it advanced. If + # both arrows point to elements that are not part of the longest common + # subsequence, then #traverse_sequences will advance one of them and call + # the appropriate callback, but it is not specified which it will call. + # + # The methods for callbacks#match, callbacks#discard_a, + # and callbacks#discard_b are invoked with an event comprising + # the action ("=", "+", or "-", respectively), the indicies +i+ and +j+, + # and the elements A[i] and B[j]. Return values are + # discarded by #traverse_sequences. + # + # === End of Sequences + # + # If arrow +a+ reaches the end of its sequence before arrow +b+ does, + # #traverse_sequence will try to call callbacks#finished_a with + # the last index and element of +A+ (A[-1]) and the current index + # and element of +B+ (B[j]). If callbacks#finished_a + # does not exist, then callbacks#discard_b will be called on each + # element of +B+ until the end of the sequence is reached (the call will + # be done with A[-1] and B[j] for each element). + # + # If +b+ reaches the end of +B+ before +a+ reaches the end of +A+, + # callbacks#finished_b will be called with the current index and + # element of +A+ (A[i]) and the last index and element of +B+ + # (A[-1]). Again, if callbacks#finished_b does not exist + # on the callback object, then callbacks#discard_a will be called + # on each element of +A+ until the end of the sequence is reached + # (A[i] and B[-1]). + # + # There is a chance that one additional callbacks#discard_a or + # callbacks#discard_b will be called after the end of the + # sequence is reached, if +a+ has not yet reached the end of +A+ or +b+ + # has not yet reached the end of +B+. + def traverse_sequences(seq1, seq2, callbacks = Diff::LCS::SequenceCallbacks, &block) #:yields change events: + callbacks ||= Diff::LCS::SequenceCallbacks + matches = Diff::LCS::Internals.lcs(seq1, seq2) + + run_finished_a = run_finished_b = false + string = seq1.kind_of?(String) + + a_size = seq1.size + b_size = seq2.size + ai = bj = 0 + + (0..matches.size).each do |i| + b_line = matches[i] + + ax = string ? seq1[i, 1] : seq1[i] + bx = string ? seq2[bj, 1] : seq2[bj] + + if b_line.nil? + unless ax.nil? or (string and ax.empty?) + event = Diff::LCS::ContextChange.new('-', i, ax, bj, bx) + event = yield event if block_given? + callbacks.discard_a(event) + end + else + loop do + break unless bj < b_line + bx = string ? seq2[bj, 1] : seq2[bj] + event = Diff::LCS::ContextChange.new('+', i, ax, bj, bx) + event = yield event if block_given? + callbacks.discard_b(event) + bj += 1 + end + bx = string ? seq2[bj, 1] : seq2[bj] + event = Diff::LCS::ContextChange.new('=', i, ax, bj, bx) + event = yield event if block_given? + callbacks.match(event) + bj += 1 + end + ai = i + end + ai += 1 + + # The last entry (if any) processed was a match. +ai+ and +bj+ point + # just past the last matching lines in their sequences. + while (ai < a_size) or (bj < b_size) + # last A? + if ai == a_size and bj < b_size + if callbacks.respond_to?(:finished_a) and not run_finished_a + ax = string ? seq1[-1, 1] : seq1[-1] + bx = string ? seq2[bj, 1] : seq2[bj] + event = Diff::LCS::ContextChange.new('>', (a_size - 1), ax, bj, bx) + event = yield event if block_given? + callbacks.finished_a(event) + run_finished_a = true + else + ax = string ? seq1[ai, 1] : seq1[ai] + loop do + bx = string ? seq2[bj, 1] : seq2[bj] + event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx) + event = yield event if block_given? + callbacks.discard_b(event) + bj += 1 + break unless bj < b_size + end + end + end + + # last B? + if bj == b_size and ai < a_size + if callbacks.respond_to?(:finished_b) and not run_finished_b + ax = string ? seq1[ai, 1] : seq1[ai] + bx = string ? seq2[-1, 1] : seq2[-1] + event = Diff::LCS::ContextChange.new('<', ai, ax, (b_size - 1), bx) + event = yield event if block_given? + callbacks.finished_b(event) + run_finished_b = true + else + bx = string ? seq2[bj, 1] : seq2[bj] + loop do + ax = string ? seq1[ai, 1] : seq1[ai] + event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx) + event = yield event if block_given? + callbacks.discard_a(event) + ai += 1 + break unless bj < b_size + end + end + end + + if ai < a_size + ax = string ? seq1[ai, 1] : seq1[ai] + bx = string ? seq2[bj, 1] : seq2[bj] + event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx) + event = yield event if block_given? + callbacks.discard_a(event) + ai += 1 + end + + if bj < b_size + ax = string ? seq1[ai, 1] : seq1[ai] + bx = string ? seq2[bj, 1] : seq2[bj] + event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx) + event = yield event if block_given? + callbacks.discard_b(event) + bj += 1 + end + end + end + + # #traverse_balanced is an alternative to #traverse_sequences. It uses a + # different algorithm to iterate through the entries in the computed + # longest common subsequence. Instead of viewing the changes as insertions + # or deletions from one of the sequences, #traverse_balanced will report + # changes between the sequences. + # + # The arguments to #traverse_balanced are the two sequences to traverse + # and a callback object, like this: + # + # traverse_balanced(seq1, seq2, Diff::LCS::ContextDiffCallbacks.new) + # + # #sdiff is implemented with #traverse_balanced. + # + # == Callback Methods + # + # Optional callback methods are emphasized. + # + # callbacks#match:: Called when +a+ and +b+ are pointing to + # common elements in +A+ and +B+. + # callbacks#discard_a:: Called when +a+ is pointing to an + # element not in +B+. + # callbacks#discard_b:: Called when +b+ is pointing to an + # element not in +A+. + # callbacks#change:: Called when +a+ and +b+ are pointing to + # the same relative position, but + # A[a] and B[b] are not + # the same; a change has + # occurred. + # + # #traverse_balanced might be a bit slower than #traverse_sequences, + # noticable only while processing huge amounts of data. + # + # == Algorithm + # + # a---+ + # v + # A = a b c e h j l m n p + # B = b c d e f j k l m r s t + # ^ + # b---+ + # + # === Matches + # + # If there are two arrows (+a+ and +b+) pointing to elements of sequences + # +A+ and +B+, the arrows will initially point to the first elements of + # their respective sequences. #traverse_sequences will advance the arrows + # through the sequences one element at a time, calling a method on the + # user-specified callback object before each advance. It will advance the + # arrows in such a way that if there are elements A[i] and + # B[j] which are both equal and part of the longest common + # subsequence, there will be some moment during the execution of + # #traverse_sequences when arrow +a+ is pointing to A[i] and + # arrow +b+ is pointing to B[j]. When this happens, + # #traverse_sequences will call callbacks#match and then it will + # advance both arrows. + # + # === Discards + # + # Otherwise, one of the arrows is pointing to an element of its sequence + # that is not part of the longest common subsequence. #traverse_sequences + # will advance that arrow and will call callbacks#discard_a or + # callbacks#discard_b, depending on which arrow it advanced. + # + # === Changes + # + # If both +a+ and +b+ point to elements that are not part of the longest + # common subsequence, then #traverse_sequences will try to call + # callbacks#change and advance both arrows. If + # callbacks#change is not implemented, then + # callbacks#discard_a and callbacks#discard_b will be + # called in turn. + # + # The methods for callbacks#match, callbacks#discard_a, + # callbacks#discard_b, and callbacks#change are invoked + # with an event comprising the action ("=", "+", "-", or "!", + # respectively), the indicies +i+ and +j+, and the elements + # A[i] and B[j]. Return values are discarded by + # #traverse_balanced. + # + # === Context + # Note that +i+ and +j+ may not be the same index position, even if +a+ + # and +b+ are considered to be pointing to matching or changed elements. + def traverse_balanced(seq1, seq2, callbacks = Diff::LCS::BalancedCallbacks) + matches = Diff::LCS::Internals.lcs(seq1, seq2) + a_size = seq1.size + b_size = seq2.size + ai = bj = mb = 0 + ma = -1 + string = seq1.kind_of?(String) + + # Process all the lines in the match vector. + loop do + # Find next match indices +ma+ and +mb+ + loop do + ma += 1 + break unless ma < matches.size and matches[ma].nil? + end + + break if ma >= matches.size # end of matches? + mb = matches[ma] + + # Change(seq2) + while (ai < ma) or (bj < mb) + ax = string ? seq1[ai, 1] : seq1[ai] + bx = string ? seq2[bj, 1] : seq2[bj] + + case [(ai < ma), (bj < mb)] + when [true, true] + if callbacks.respond_to?(:change) + event = Diff::LCS::ContextChange.new('!', ai, ax, bj, bx) + event = yield event if block_given? + callbacks.change(event) + ai += 1 + bj += 1 + else + event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx) + event = yield event if block_given? + callbacks.discard_a(event) + ai += 1 + ax = string ? seq1[ai, 1] : seq1[ai] + event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx) + event = yield event if block_given? + callbacks.discard_b(event) + bj += 1 + end + when [true, false] + event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx) + event = yield event if block_given? + callbacks.discard_a(event) + ai += 1 + when [false, true] + event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx) + event = yield event if block_given? + callbacks.discard_b(event) + bj += 1 + end + end + + # Match + ax = string ? seq1[ai, 1] : seq1[ai] + bx = string ? seq2[bj, 1] : seq2[bj] + event = Diff::LCS::ContextChange.new('=', ai, ax, bj, bx) + event = yield event if block_given? + callbacks.match(event) + ai += 1 + bj += 1 + end + + while (ai < a_size) or (bj < b_size) + ax = string ? seq1[ai, 1] : seq1[ai] + bx = string ? seq2[bj, 1] : seq2[bj] + + case [(ai < a_size), (bj < b_size)] + when [true, true] + if callbacks.respond_to?(:change) + event = Diff::LCS::ContextChange.new('!', ai, ax, bj, bx) + event = yield event if block_given? + callbacks.change(event) + ai += 1 + bj += 1 + else + event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx) + event = yield event if block_given? + callbacks.discard_a(event) + ai += 1 + ax = string ? seq1[ai, 1] : seq1[ai] + event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx) + event = yield event if block_given? + callbacks.discard_b(event) + bj += 1 + end + when [true, false] + event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx) + event = yield event if block_given? + callbacks.discard_a(event) + ai += 1 + when [false, true] + event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx) + event = yield event if block_given? + callbacks.discard_b(event) + bj += 1 + end + end + end + + PATCH_MAP = { #:nodoc: + :patch => { '+' => '+', '-' => '-', '!' => '!', '=' => '=' }, + :unpatch => { '+' => '-', '-' => '+', '!' => '!', '=' => '=' } + } + + # Applies a +patchset+ to the sequence +src+ according to the +direction+ + # (:patch or :unpatch), producing a new sequence. + # + # If the +direction+ is not specified, Diff::LCS::patch will attempt to + # discover the direction of the +patchset+. + # + # A +patchset+ can be considered to apply forward (:patch) if the + # following expression is true: + # + # patch(s1, diff(s1, s2)) -> s2 + # + # A +patchset+ can be considered to apply backward (:unpatch) if + # the following expression is true: + # + # patch(s2, diff(s1, s2)) -> s1 + # + # If the +patchset+ contains no changes, the +src+ value will be returned + # as either src.dup or +src+. A +patchset+ can be deemed as + # having no changes if the following predicate returns true: + # + # patchset.empty? or + # patchset.flatten.all? { |change| change.unchanged? } + # + # === Patchsets + # + # A +patchset+ is always an enumerable sequence of changes, hunks of + # changes, or a mix of the two. A hunk of changes is an enumerable + # sequence of changes: + # + # [ # patchset + # # change + # [ # hunk + # # change + # ] + # ] + # + # The +patch+ method accepts patchsets that are enumerable + # sequences containing either Diff::LCS::Change objects (or a subclass) or + # the array representations of those objects. Prior to application, array + # representations of Diff::LCS::Change objects will be reified. + def patch(src, patchset, direction = nil) + # Normalize the patchset. + has_changes, patchset = Diff::LCS::Internals.analyze_patchset(patchset) + + if not has_changes + return src.dup if src.respond_to? :dup + return src + end + + string = src.kind_of?(String) + # Start with a new empty type of the source's class + res = src.class.new + + direction ||= Diff::LCS::Internals.intuit_diff_direction(src, patchset) + + ai = bj = 0 + + patch_map = PATCH_MAP[direction] + + patchset.flatten.each do |change| + # Both Change and ContextChange support #action + action = patch_map[change.action] + + case change + when Diff::LCS::ContextChange + case direction + when :patch + el = change.new_element + op = change.old_position + np = change.new_position + when :unpatch + el = change.old_element + op = change.new_position + np = change.old_position + end + + case action + when '-' # Remove details from the old string + while ai < op + res << (string ? src[ai, 1] : src[ai]) + ai += 1 + bj += 1 + end + ai += 1 + when '+' + while bj < np + res << (string ? src[ai, 1] : src[ai]) + ai += 1 + bj += 1 + end + + res << el + bj += 1 + when '=' + # This only appears in sdiff output with the SDiff callback. + # Therefore, we only need to worry about dealing with a single + # element. + res << el + + ai += 1 + bj += 1 + when '!' + while ai < op + res << (string ? src[ai, 1] : src[ai]) + ai += 1 + bj += 1 + end + + bj += 1 + ai += 1 + + res << el + end + when Diff::LCS::Change + case action + when '-' + while ai < change.position + res << (string ? src[ai, 1] : src[ai]) + ai += 1 + bj += 1 + end + ai += 1 + when '+' + while bj < change.position + res << (string ? src[ai, 1] : src[ai]) + ai += 1 + bj += 1 + end + + bj += 1 + + res << change.element + end + end + end + + while ai < src.size + res << (string ? src[ai, 1] : src[ai]) + ai += 1 + bj += 1 + end + + res + end + + # Given a set of patchset, convert the current version to the prior + # version. Does no auto-discovery. + def unpatch!(src, patchset) + patch(src, patchset, :unpatch) + end + + # Given a set of patchset, convert the current version to the next + # version. Does no auto-discovery. + def patch!(src, patchset) + patch(src, patchset, :patch) + end +end diff --git a/.bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/array.rb b/.bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/array.rb new file mode 100644 index 0000000..1acd8c9 --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/array.rb @@ -0,0 +1,7 @@ +# -*- ruby encoding: utf-8 -*- + +require 'diff/lcs' + +class Array + include Diff::LCS +end diff --git a/.bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/block.rb b/.bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/block.rb new file mode 100644 index 0000000..8518727 --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/block.rb @@ -0,0 +1,37 @@ +# -*- ruby encoding: utf-8 -*- + +# A block is an operation removing, adding, or changing a group of items. +# Basically, this is just a list of changes, where each change adds or +# deletes a single item. Used by bin/ldiff. +class Diff::LCS::Block + attr_reader :changes, :insert, :remove + + def initialize(chunk) + @changes = [] + @insert = [] + @remove = [] + + chunk.each do |item| + @changes << item + @remove << item if item.deleting? + @insert << item if item.adding? + end + end + + def diff_size + @insert.size - @remove.size + end + + def op + case [@remove.empty?, @insert.empty?] + when [false, false] + '!' + when [false, true] + '-' + when [true, false] + '+' + else # [true, true] + '^' + end + end +end diff --git a/.bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/callbacks.rb b/.bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/callbacks.rb new file mode 100644 index 0000000..8eec5fc --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/callbacks.rb @@ -0,0 +1,322 @@ +# -*- ruby encoding: utf-8 -*- + +require 'diff/lcs/change' + +module Diff::LCS + # This callback object implements the default set of callback events, + # which only returns the event itself. Note that #finished_a and + # #finished_b are not implemented -- I haven't yet figured out where they + # would be useful. + # + # Note that this is intended to be called as is, e.g., + # + # Diff::LCS.LCS(seq1, seq2, Diff::LCS::DefaultCallbacks) + class DefaultCallbacks + class << self + # Called when two items match. + def match(event) + event + end + # Called when the old value is discarded in favour of the new value. + def discard_a(event) + event + end + # Called when the new value is discarded in favour of the old value. + def discard_b(event) + event + end + # Called when both the old and new values have changed. + def change(event) + event + end + + private :new + end + end + + # An alias for DefaultCallbacks that is used in + # Diff::LCS#traverse_sequences. + # + # Diff::LCS.LCS(seq1, seq2, Diff::LCS::SequenceCallbacks) + SequenceCallbacks = DefaultCallbacks + + # An alias for DefaultCallbacks that is used in + # Diff::LCS#traverse_balanced. + # + # Diff::LCS.LCS(seq1, seq2, Diff::LCS::BalancedCallbacks) + BalancedCallbacks = DefaultCallbacks + + def self.callbacks_for(callbacks) + callbacks.new rescue callbacks + end +end + +# This will produce a compound array of simple diff change objects. Each +# element in the #diffs array is a +hunk+ or +hunk+ array, where each +# element in each +hunk+ array is a single Change object representing the +# addition or removal of a single element from one of the two tested +# sequences. The +hunk+ provides the full context for the changes. +# +# diffs = Diff::LCS.diff(seq1, seq2) +# # This example shows a simplified array format. +# # [ [ [ '-', 0, 'a' ] ], # 1 +# # [ [ '+', 2, 'd' ] ], # 2 +# # [ [ '-', 4, 'h' ], # 3 +# # [ '+', 4, 'f' ] ], +# # [ [ '+', 6, 'k' ] ], # 4 +# # [ [ '-', 8, 'n' ], # 5 +# # [ '-', 9, 'p' ], +# # [ '+', 9, 'r' ], +# # [ '+', 10, 's' ], +# # [ '+', 11, 't' ] ] ] +# +# There are five hunks here. The first hunk says that the +a+ at position 0 +# of the first sequence should be deleted ('-'). The second hunk +# says that the +d+ at position 2 of the second sequence should be inserted +# ('+'). The third hunk says that the +h+ at position 4 of the +# first sequence should be removed and replaced with the +f+ from position 4 +# of the second sequence. The other two hunks are described similarly. +# +# === Use +# +# This callback object must be initialised and is used by the Diff::LCS#diff +# method. +# +# cbo = Diff::LCS::DiffCallbacks.new +# Diff::LCS.LCS(seq1, seq2, cbo) +# cbo.finish +# +# Note that the call to #finish is absolutely necessary, or the last set of +# changes will not be visible. Alternatively, can be used as: +# +# cbo = Diff::LCS::DiffCallbacks.new { |tcbo| Diff::LCS.LCS(seq1, seq2, tcbo) } +# +# The necessary #finish call will be made. +# +# === Simplified Array Format +# +# The simplified array format used in the example above can be obtained +# with: +# +# require 'pp' +# pp diffs.map { |e| e.map { |f| f.to_a } } +class Diff::LCS::DiffCallbacks + # Returns the difference set collected during the diff process. + attr_reader :diffs + + def initialize # :yields self: + @hunk = [] + @diffs = [] + + if block_given? + begin + yield self + ensure + self.finish + end + end + end + + # Finalizes the diff process. If an unprocessed hunk still exists, then it + # is appended to the diff list. + def finish + finish_hunk + end + + def match(event) + finish_hunk + end + + def discard_a(event) + @hunk << Diff::LCS::Change.new('-', event.old_position, event.old_element) + end + + def discard_b(event) + @hunk << Diff::LCS::Change.new('+', event.new_position, event.new_element) + end + + def finish_hunk + @diffs << @hunk unless @hunk.empty? + @hunk = [] + end + private :finish_hunk +end + +# This will produce a compound array of contextual diff change objects. Each +# element in the #diffs array is a "hunk" array, where each element in each +# "hunk" array is a single change. Each change is a Diff::LCS::ContextChange +# that contains both the old index and new index values for the change. The +# "hunk" provides the full context for the changes. Both old and new objects +# will be presented for changed objects. +nil+ will be substituted for a +# discarded object. +# +# seq1 = %w(a b c e h j l m n p) +# seq2 = %w(b c d e f j k l m r s t) +# +# diffs = Diff::LCS.diff(seq1, seq2, Diff::LCS::ContextDiffCallbacks) +# # This example shows a simplified array format. +# # [ [ [ '-', [ 0, 'a' ], [ 0, nil ] ] ], # 1 +# # [ [ '+', [ 3, nil ], [ 2, 'd' ] ] ], # 2 +# # [ [ '-', [ 4, 'h' ], [ 4, nil ] ], # 3 +# # [ '+', [ 5, nil ], [ 4, 'f' ] ] ], +# # [ [ '+', [ 6, nil ], [ 6, 'k' ] ] ], # 4 +# # [ [ '-', [ 8, 'n' ], [ 9, nil ] ], # 5 +# # [ '+', [ 9, nil ], [ 9, 'r' ] ], +# # [ '-', [ 9, 'p' ], [ 10, nil ] ], +# # [ '+', [ 10, nil ], [ 10, 's' ] ], +# # [ '+', [ 10, nil ], [ 11, 't' ] ] ] ] +# +# The five hunks shown are comprised of individual changes; if there is a +# related set of changes, they are still shown individually. +# +# This callback can also be used with Diff::LCS#sdiff, which will produce +# results like: +# +# diffs = Diff::LCS.sdiff(seq1, seq2, Diff::LCS::ContextCallbacks) +# # This example shows a simplified array format. +# # [ [ [ "-", [ 0, "a" ], [ 0, nil ] ] ], # 1 +# # [ [ "+", [ 3, nil ], [ 2, "d" ] ] ], # 2 +# # [ [ "!", [ 4, "h" ], [ 4, "f" ] ] ], # 3 +# # [ [ "+", [ 6, nil ], [ 6, "k" ] ] ], # 4 +# # [ [ "!", [ 8, "n" ], [ 9, "r" ] ], # 5 +# # [ "!", [ 9, "p" ], [ 10, "s" ] ], +# # [ "+", [ 10, nil ], [ 11, "t" ] ] ] ] +# +# The five hunks are still present, but are significantly shorter in total +# presentation, because changed items are shown as changes ("!") instead of +# potentially "mismatched" pairs of additions and deletions. +# +# The result of this operation is similar to that of +# Diff::LCS::SDiffCallbacks. They may be compared as: +# +# s = Diff::LCS.sdiff(seq1, seq2).reject { |e| e.action == "=" } +# c = Diff::LCS.sdiff(seq1, seq2, Diff::LCS::ContextDiffCallbacks).flatten +# +# s == c # -> true +# +# === Use +# +# This callback object must be initialised and can be used by the +# Diff::LCS#diff or Diff::LCS#sdiff methods. +# +# cbo = Diff::LCS::ContextDiffCallbacks.new +# Diff::LCS.LCS(seq1, seq2, cbo) +# cbo.finish +# +# Note that the call to #finish is absolutely necessary, or the last set of +# changes will not be visible. Alternatively, can be used as: +# +# cbo = Diff::LCS::ContextDiffCallbacks.new { |tcbo| Diff::LCS.LCS(seq1, seq2, tcbo) } +# +# The necessary #finish call will be made. +# +# === Simplified Array Format +# +# The simplified array format used in the example above can be obtained +# with: +# +# require 'pp' +# pp diffs.map { |e| e.map { |f| f.to_a } } +class Diff::LCS::ContextDiffCallbacks < Diff::LCS::DiffCallbacks + def discard_a(event) + @hunk << Diff::LCS::ContextChange.simplify(event) + end + + def discard_b(event) + @hunk << Diff::LCS::ContextChange.simplify(event) + end + + def change(event) + @hunk << Diff::LCS::ContextChange.simplify(event) + end +end + +# This will produce a simple array of diff change objects. Each element in +# the #diffs array is a single ContextChange. In the set of #diffs provided +# by SDiffCallbacks, both old and new objects will be presented for both +# changed and unchanged objects. +nil+ will be substituted +# for a discarded object. +# +# The diffset produced by this callback, when provided to Diff::LCS#sdiff, +# will compute and display the necessary components to show two sequences +# and their minimized differences side by side, just like the Unix utility +# +sdiff+. +# +# same same +# before | after +# old < - +# - > new +# +# seq1 = %w(a b c e h j l m n p) +# seq2 = %w(b c d e f j k l m r s t) +# +# diffs = Diff::LCS.sdiff(seq1, seq2) +# # This example shows a simplified array format. +# # [ [ "-", [ 0, "a"], [ 0, nil ] ], +# # [ "=", [ 1, "b"], [ 0, "b" ] ], +# # [ "=", [ 2, "c"], [ 1, "c" ] ], +# # [ "+", [ 3, nil], [ 2, "d" ] ], +# # [ "=", [ 3, "e"], [ 3, "e" ] ], +# # [ "!", [ 4, "h"], [ 4, "f" ] ], +# # [ "=", [ 5, "j"], [ 5, "j" ] ], +# # [ "+", [ 6, nil], [ 6, "k" ] ], +# # [ "=", [ 6, "l"], [ 7, "l" ] ], +# # [ "=", [ 7, "m"], [ 8, "m" ] ], +# # [ "!", [ 8, "n"], [ 9, "r" ] ], +# # [ "!", [ 9, "p"], [ 10, "s" ] ], +# # [ "+", [ 10, nil], [ 11, "t" ] ] ] +# +# The result of this operation is similar to that of +# Diff::LCS::ContextDiffCallbacks. They may be compared as: +# +# s = Diff::LCS.sdiff(seq1, seq2).reject { |e| e.action == "=" } +# c = Diff::LCS.sdiff(seq1, seq2, Diff::LCS::ContextDiffCallbacks).flatten +# +# s == c # -> true +# +# === Use +# +# This callback object must be initialised and is used by the Diff::LCS#sdiff +# method. +# +# cbo = Diff::LCS::SDiffCallbacks.new +# Diff::LCS.LCS(seq1, seq2, cbo) +# +# As with the other initialisable callback objects, +# Diff::LCS::SDiffCallbacks can be initialised with a block. As there is no +# "fininishing" to be done, this has no effect on the state of the object. +# +# cbo = Diff::LCS::SDiffCallbacks.new { |tcbo| Diff::LCS.LCS(seq1, seq2, tcbo) } +# +# === Simplified Array Format +# +# The simplified array format used in the example above can be obtained +# with: +# +# require 'pp' +# pp diffs.map { |e| e.to_a } +class Diff::LCS::SDiffCallbacks + # Returns the difference set collected during the diff process. + attr_reader :diffs + + def initialize #:yields self: + @diffs = [] + yield self if block_given? + end + + def match(event) + @diffs << Diff::LCS::ContextChange.simplify(event) + end + + def discard_a(event) + @diffs << Diff::LCS::ContextChange.simplify(event) + end + + def discard_b(event) + @diffs << Diff::LCS::ContextChange.simplify(event) + end + + def change(event) + @diffs << Diff::LCS::ContextChange.simplify(event) + end +end diff --git a/.bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/change.rb b/.bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/change.rb new file mode 100644 index 0000000..4077095 --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/change.rb @@ -0,0 +1,177 @@ +# -*- ruby encoding: utf-8 -*- + +# Represents a simplistic (non-contextual) change. Represents the removal or +# addition of an element from either the old or the new sequenced +# enumerable. +class Diff::LCS::Change + # The only actions valid for changes are '+' (add), '-' (delete), '=' + # (no change), '!' (changed), '<' (tail changes from first sequence), or + # '>' (tail changes from second sequence). The last two ('<>') are only + # found with Diff::LCS::diff and Diff::LCS::sdiff. + VALID_ACTIONS = %W(+ - = ! > <) + + def self.valid_action?(action) + VALID_ACTIONS.include? action + end + + # Returns the action this Change represents. + attr_reader :action + + # Returns the position of the Change. + attr_reader :position + # Returns the sequence element of the Change. + attr_reader :element + + def initialize(*args) + @action, @position, @element = *args + + unless Diff::LCS::Change.valid_action?(@action) + raise "Invalid Change Action '#{@action}'" + end + raise "Invalid Position Type" unless @position.kind_of? Fixnum + end + + def inspect + to_a.inspect + end + + def to_a + [ @action, @position, @element ] + end + + def self.from_a(arr) + arr = arr.flatten(1) + case arr.size + when 5 + Diff::LCS::ContextChange.new(*(arr[0...5])) + when 3 + Diff::LCS::Change.new(*(arr[0...3])) + else + raise "Invalid change array format provided." + end + end + + include Comparable + + def ==(other) + (self.action == other.action) and + (self.position == other.position) and + (self.element == other.element) + end + + def <=>(other) + r = self.action <=> other.action + r = self.position <=> other.position if r.zero? + r = self.element <=> other.element if r.zero? + r + end + + def adding? + @action == '+' + end + + def deleting? + @action == '-' + end + + def unchanged? + @action == '=' + end + + def changed? + @action == '!' + end + + def finished_a? + @action == '>' + end + + def finished_b? + @action == '<' + end +end + +# Represents a contextual change. Contains the position and values of the +# elements in the old and the new sequenced enumerables as well as the action +# taken. +class Diff::LCS::ContextChange < Diff::LCS::Change + # We don't need these two values. + undef :position + undef :element + + # Returns the old position being changed. + attr_reader :old_position + # Returns the new position being changed. + attr_reader :new_position + # Returns the old element being changed. + attr_reader :old_element + # Returns the new element being changed. + attr_reader :new_element + + def initialize(*args) + @action, @old_position, @old_element, @new_position, @new_element = *args + + unless Diff::LCS::Change.valid_action?(@action) + raise "Invalid Change Action '#{@action}'" + end + unless @old_position.nil? or @old_position.kind_of? Fixnum + raise "Invalid (Old) Position Type" + end + unless @new_position.nil? or @new_position.kind_of? Fixnum + raise "Invalid (New) Position Type" + end + end + + def to_a + [ @action, + [ @old_position, @old_element ], + [ @new_position, @new_element ] + ] + end + + def inspect(*args) + to_a.inspect + end + + def self.from_a(arr) + Diff::LCS::Change.from_a(arr) + end + + # Simplifies a context change for use in some diff callbacks. '<' actions + # are converted to '-' and '>' actions are converted to '+'. + def self.simplify(event) + ea = event.to_a + + case ea[0] + when '-' + ea[2][1] = nil + when '<' + ea[0] = '-' + ea[2][1] = nil + when '+' + ea[1][1] = nil + when '>' + ea[0] = '+' + ea[1][1] = nil + end + + Diff::LCS::ContextChange.from_a(ea) + end + + def ==(other) + (@action == other.action) and + (@old_position == other.old_position) and + (@new_position == other.new_position) and + (@old_element == other.old_element) and + (@new_element == other.new_element) + end + + def <=>(other) + r = @action <=> other.action + r = @old_position <=> other.old_position if r.zero? + r = @new_position <=> other.new_position if r.zero? + r = @old_element <=> other.old_element if r.zero? + r = @new_element <=> other.new_element if r.zero? + r + end +end diff --git a/.bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/htmldiff.rb b/.bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/htmldiff.rb new file mode 100644 index 0000000..56b972c --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/htmldiff.rb @@ -0,0 +1,149 @@ +# -*- ruby encoding: utf-8 -*- + +require 'cgi' + +class Diff::LCS::HTMLDiff + class << self + attr_accessor :can_expand_tabs #:nodoc: + end + self.can_expand_tabs = true + + class Callbacks + attr_accessor :output + attr_accessor :match_class + attr_accessor :only_a_class + attr_accessor :only_b_class + + def initialize(output, options = {}) + @output = output + options ||= {} + + @match_class = options[:match_class] || "match" + @only_a_class = options[:only_a_class] || "only_a" + @only_b_class = options[:only_b_class] || "only_b" + end + + def htmlize(element, css_class) + element = " " if element.empty? + %Q|
#{element}
\n| + end + private :htmlize + + # This will be called with both lines are the same + def match(event) + @output << htmlize(event.old_element, :match_class) + end + + # This will be called when there is a line in A that isn't in B + def discard_a(event) + @output << htmlize(event.old_element, :only_a_class) + end + + # This will be called when there is a line in B that isn't in A + def discard_b(event) + @output << htmlize(event.new_element, :only_b_class) + end + end + + DEFAULT_OPTIONS = { + :expand_tabs => nil, + :output => nil, + :css => nil, + :title => nil, + } + + DEFAULT_CSS = <<-CSS +body { margin: 0; } +.diff +{ + border: 1px solid black; + margin: 1em 2em; +} +p +{ + margin-left: 2em; +} +pre +{ + padding-left: 1em; + margin: 0; + font-family: Inconsolata, Consolas, Lucida, Courier, monospaced; + white-space: pre; +} +.match { } +.only_a +{ + background-color: #fdd; + color: red; + text-decoration: line-through; +} +.only_b +{ + background-color: #ddf; + color: blue; + border-left: 3px solid blue +} +h1 { margin-left: 2em; } + CSS + + def initialize(left, right, options = nil) + @left = left + @right = right + @options = options + + @options = DEFAULT_OPTIONS.dup if @options.nil? + end + + def verify_options + @options[:expand_tabs] ||= 4 + @options[:expand_tabs] = 4 if @options[:expand_tabs] < 0 + + @options[:output] ||= $stdout + + @options[:css] ||= DEFAULT_CSS.dup + + @options[:title] ||= "diff" + end + private :verify_options + + attr_reader :options + + def run + verify_options + + if @options[:expand_tabs] > 0 && self.class.can_expand_tabs + formatter = Text::Format.new + formatter.tabstop = @options[:expand_tabs] + + @left = left.map { |line| formatter.expand(line.chomp) } + @right = right.map { |line| formatter.expand(line.chomp) } + end + + @left.map! { |line| CGI.escapeHTML(line.chomp) } + @right.map! { |line| CGI.escapeHTML(line.chomp) } + + @options[:output] << <<-OUTPUT + + + #{@options[:title]} + + + +

#{@options[:title]}

+

Legend: Only in Old  + Only in New

+
+ OUTPUT + + callbacks = Callbacks.new(@options[:output]) + Diff::LCS.traverse_sequences(@left, @right, callbacks) + + @options[:output] << <<-OUTPUT +
+ + + OUTPUT + end +end diff --git a/.bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/hunk.rb b/.bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/hunk.rb new file mode 100644 index 0000000..05c3fb6 --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/hunk.rb @@ -0,0 +1,276 @@ +# -*- ruby encoding: utf-8 -*- + +require 'diff/lcs/block' + +# A Hunk is a group of Blocks which overlap because of the context +# surrounding each block. (So if we're not using context, every hunk will +# contain one block.) Used in the diff program (bin/diff). +class Diff::LCS::Hunk + # Create a hunk using references to both the old and new data, as well as + # the piece of data. + def initialize(data_old, data_new, piece, flag_context, file_length_difference) + # At first, a hunk will have just one Block in it + @blocks = [ Diff::LCS::Block.new(piece) ] + if String.method_defined?(:encoding) + @preferred_data_encoding = data_old.fetch(0, data_new.fetch(0,'') ).encoding + end + @data_old = data_old + @data_new = data_new + + before = after = file_length_difference + after += @blocks[0].diff_size + @file_length_difference = after # The caller must get this manually + + # Save the start & end of each array. If the array doesn't exist (e.g., + # we're only adding items in this block), then figure out the line + # number based on the line number of the other file and the current + # difference in file lengths. + if @blocks[0].remove.empty? + a1 = a2 = nil + else + a1 = @blocks[0].remove[0].position + a2 = @blocks[0].remove[-1].position + end + + if @blocks[0].insert.empty? + b1 = b2 = nil + else + b1 = @blocks[0].insert[0].position + b2 = @blocks[0].insert[-1].position + end + + @start_old = a1 || (b1 - before) + @start_new = b1 || (a1 + before) + @end_old = a2 || (b2 - after) + @end_new = b2 || (a2 + after) + + self.flag_context = flag_context + end + + attr_reader :blocks + attr_reader :start_old, :start_new + attr_reader :end_old, :end_new + attr_reader :file_length_difference + + # Change the "start" and "end" fields to note that context should be added + # to this hunk. + attr_accessor :flag_context + undef :flag_context=; + def flag_context=(context) #:nodoc: + return if context.nil? or context.zero? + + add_start = (context > @start_old) ? @start_old : context + @start_old -= add_start + @start_new -= add_start + + if (@end_old + context) > @data_old.size + add_end = @data_old.size - @end_old + else + add_end = context + end + @end_old += add_end + @end_new += add_end + end + + # Merges this hunk and the provided hunk together if they overlap. Returns + # a truthy value so that if there is no overlap, you can know the merge + # was skipped. + def merge(hunk) + if overlaps?(hunk) + @start_old = hunk.start_old + @start_new = hunk.start_new + blocks.unshift(*hunk.blocks) + else + nil + end + end + alias_method :unshift, :merge + + # Determines whether there is an overlap between this hunk and the + # provided hunk. This will be true if the difference between the two hunks + # start or end positions is within one position of each other. + def overlaps?(hunk) + hunk and (((@start_old - hunk.end_old) <= 1) or + ((@start_new - hunk.end_new) <= 1)) + end + + # Returns a diff string based on a format. + def diff(format) + case format + when :old + old_diff + when :unified + unified_diff + when :context + context_diff + when :ed + self + when :reverse_ed, :ed_finish + ed_diff(format) + else + raise "Unknown diff format #{format}." + end + end + + # Note that an old diff can't have any context. Therefore, we know that + # there's only one block in the hunk. + def old_diff + warn "Expecting only one block in an old diff hunk!" if @blocks.size > 1 + op_act = { "+" => 'a', "-" => 'd', "!" => "c" } + + block = @blocks[0] + + # Calculate item number range. Old diff range is just like a context + # diff range, except the ranges are on one line with the action between + # them. + s = encode("#{context_range(:old)}#{op_act[block.op]}#{context_range(:new)}\n") + # If removing anything, just print out all the remove lines in the hunk + # which is just all the remove lines in the block. + @data_old[@start_old .. @end_old].each { |e| s << encode("< ") + e + encode("\n") } unless block.remove.empty? + s << encode("---\n") if block.op == "!" + @data_new[@start_new .. @end_new].each { |e| s << encode("> ") + e + encode("\n") } unless block.insert.empty? + s + end + private :old_diff + + def unified_diff + # Calculate item number range. + s = encode("@@ -#{unified_range(:old)} +#{unified_range(:new)} @@\n") + + # Outlist starts containing the hunk of the old file. Removing an item + # just means putting a '-' in front of it. Inserting an item requires + # getting it from the new file and splicing it in. We splice in + # +num_added+ items. Remove blocks use +num_added+ because splicing + # changed the length of outlist. + # + # We remove +num_removed+ items. Insert blocks use +num_removed+ + # because their item numbers -- corresponding to positions in the NEW + # file -- don't take removed items into account. + lo, hi, num_added, num_removed = @start_old, @end_old, 0, 0 + + outlist = @data_old[lo .. hi].map { |e| e.insert(0, encode(' ')) } + + @blocks.each do |block| + block.remove.each do |item| + op = item.action.to_s # - + offset = item.position - lo + num_added + outlist[offset][0, 1] = encode(op) + num_removed += 1 + end + block.insert.each do |item| + op = item.action.to_s # + + offset = item.position - @start_new + num_removed + outlist[offset, 0] = encode(op) + @data_new[item.position] + num_added += 1 + end + end + + s << outlist.join(encode("\n")) + end + private :unified_diff + + def context_diff + s = encode("***************\n") + s << encode("*** #{context_range(:old)} ****\n") + r = context_range(:new) + + # Print out file 1 part for each block in context diff format if there + # are any blocks that remove items + lo, hi = @start_old, @end_old + removes = @blocks.select { |e| not e.remove.empty? } + if removes + outlist = @data_old[lo .. hi].map { |e| e.insert(0, encode(' ')) } + + removes.each do |block| + block.remove.each do |item| + outlist[item.position - lo][0, 1] = encode(block.op) # - or ! + end + end + s << outlist.join("\n") + end + + s << encode("\n--- #{r} ----\n") + lo, hi = @start_new, @end_new + inserts = @blocks.select { |e| not e.insert.empty? } + if inserts + outlist = @data_new[lo .. hi].collect { |e| e.insert(0, encode(' ')) } + inserts.each do |block| + block.insert.each do |item| + outlist[item.position - lo][0, 1] = encode(block.op) # + or ! + end + end + s << outlist.join("\n") + end + s + end + private :context_diff + + def ed_diff(format) + op_act = { "+" => 'a', "-" => 'd', "!" => "c" } + warn "Expecting only one block in an old diff hunk!" if @blocks.size > 1 + + if format == :reverse_ed + s = encode("#{op_act[@blocks[0].op]}#{context_range(:old)}\n") + else + s = encode("#{context_range(:old, ' ')}#{op_act[@blocks[0].op]}\n") + end + + unless @blocks[0].insert.empty? + @data_new[@start_new .. @end_new].each { |e| s << e + encode("\n") } + s << encode(".\n") + end + s + end + private :ed_diff + + # Generate a range of item numbers to print. Only print 1 number if the + # range has only one item in it. Otherwise, it's 'start,end' + def context_range(mode, op = ',') + case mode + when :old + s, e = (@start_old + 1), (@end_old + 1) + when :new + s, e = (@start_new + 1), (@end_new + 1) + end + + (s < e) ? "#{s}#{op}#{e}" : "#{e}" + end + private :context_range + + # Generate a range of item numbers to print for unified diff. Print number + # where block starts, followed by number of lines in the block + # (don't print number of lines if it's 1) + def unified_range(mode) + case mode + when :old + s, e = (@start_old + 1), (@end_old + 1) + when :new + s, e = (@start_new + 1), (@end_new + 1) + end + + length = e - s + 1 + first = (length < 2) ? e : s # "strange, but correct" + (length == 1) ? "#{first}" : "#{first},#{length}" + end + private :unified_range + + if String.method_defined?(:encoding) + def encode(literal, target_encoding = @preferred_data_encoding) + literal.encode target_encoding + end + + def encode_as(string, *args) + args.map { |arg| arg.encode(string.encoding) } + end + else + def encode(literal, target_encoding = nil) + literal + end + def encode_as(string, *args) + args + end + end + + private :encode + private :encode_as +end diff --git a/.bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/internals.rb b/.bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/internals.rb new file mode 100644 index 0000000..9d9e3f3 --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/internals.rb @@ -0,0 +1,301 @@ +# -*- ruby encoding: utf-8 -*- + +class << Diff::LCS + def diff_traversal(method, seq1, seq2, callbacks, &block) + callbacks = callbacks_for(callbacks) + case method + when :diff + traverse_sequences(seq1, seq2, callbacks) + when :sdiff + traverse_balanced(seq1, seq2, callbacks) + end + callbacks.finish if callbacks.respond_to? :finish + + if block + callbacks.diffs.map do |hunk| + if hunk.kind_of? Array + hunk.map { |hunk_block| block[hunk_block] } + else + block[hunk] + end + end + else + callbacks.diffs + end + end + private :diff_traversal +end + +module Diff::LCS::Internals # :nodoc: +end + +class << Diff::LCS::Internals + # Compute the longest common subsequence between the sequenced + # Enumerables +a+ and +b+. The result is an array whose contents is such + # that + # + # result = Diff::LCS::Internals.lcs(a, b) + # result.each_with_index do |e, i| + # assert_equal(a[i], b[e]) unless e.nil? + # end + def lcs(a, b) + a_start = b_start = 0 + a_finish = a.size - 1 + b_finish = b.size - 1 + vector = [] + + # Prune off any common elements at the beginning... + while ((a_start <= a_finish) and (b_start <= b_finish) and + (a[a_start] == b[b_start])) + vector[a_start] = b_start + a_start += 1 + b_start += 1 + end + b_start = a_start + + # Now the end... + while ((a_start <= a_finish) and (b_start <= b_finish) and + (a[a_finish] == b[b_finish])) + vector[a_finish] = b_finish + a_finish -= 1 + b_finish -= 1 + end + + # Now, compute the equivalence classes of positions of elements. + b_matches = position_hash(b, b_start..b_finish) + + thresh = [] + links = [] + string = a.kind_of?(String) + + (a_start .. a_finish).each do |i| + ai = string ? a[i, 1] : a[i] + bm = b_matches[ai] + k = nil + bm.reverse_each do |j| + if k and (thresh[k] > j) and (thresh[k - 1] < j) + thresh[k] = j + else + k = replace_next_larger(thresh, j, k) + end + links[k] = [ (k > 0) ? links[k - 1] : nil, i, j ] unless k.nil? + end + end + + unless thresh.empty? + link = links[thresh.size - 1] + while not link.nil? + vector[link[1]] = link[2] + link = link[0] + end + end + + vector + end + + # This method will analyze the provided patchset to provide a + # single-pass normalization (conversion of the array form of + # Diff::LCS::Change objects to the object form of same) and detection of + # whether the patchset represents changes to be made. + def analyze_patchset(patchset, depth = 0) + raise "Patchset too complex" if depth > 1 + + has_changes = false + + # Format: + # [ # patchset + # # hunk (change) + # [ # hunk + # # change + # ] + # ] + + patchset = patchset.map do |hunk| + case hunk + when Diff::LCS::Change + has_changes ||= !hunk.unchanged? + hunk + when Array + # Detect if the 'hunk' is actually an array-format + # Change object. + if Diff::LCS::Change.valid_action? hunk[0] + hunk = Diff::LCS::Change.from_a(hunk) + has_changes ||= !hunk.unchanged? + hunk + else + with_changes, hunk = analyze_patchset(hunk, depth + 1) + has_changes ||= with_changes + hunk.flatten + end + else + raise ArgumentError, "Cannot normalise a hunk of class #{hunk.class}." + end + end + + [ has_changes, patchset.flatten(1) ] + end + + # Examine the patchset and the source to see in which direction the + # patch should be applied. + # + # WARNING: By default, this examines the whole patch, so this could take + # some time. This also works better with Diff::LCS::ContextChange or + # Diff::LCS::Change as its source, as an array will cause the creation + # of one of the above. + # + # Note: This will be deprecated as a public function in a future release. + def intuit_diff_direction(src, patchset, limit = nil) + string = src.kind_of?(String) + count = left_match = left_miss = right_match = right_miss = 0 + + patchset.each do |change| + count += 1 + + case change + when Diff::LCS::ContextChange + le = string ? src[change.old_position, 1] : src[change.old_position] + re = string ? src[change.new_position, 1] : src[change.new_position] + + case change.action + when '-' # Remove details from the old string + if le == change.old_element + left_match += 1 + else + left_miss += 1 + end + when '+' + if re == change.new_element + right_match += 1 + else + right_miss += 1 + end + when '=' + left_miss += 1 if le != change.old_element + right_miss += 1 if re != change.new_element + when '!' + if le == change.old_element + left_match += 1 + else + if re == change.new_element + right_match += 1 + else + left_miss += 1 + right_miss += 1 + end + end + end + when Diff::LCS::Change + # With a simplistic change, we can't tell the difference between + # the left and right on '!' actions, so we ignore those. On '=' + # actions, if there's a miss, we miss both left and right. + element = string ? src[change.position, 1] : src[change.position] + + case change.action + when '-' + if element == change.element + left_match += 1 + else + left_miss += 1 + end + when '+' + if element == change.element + right_match += 1 + else + right_miss += 1 + end + when '=' + if element != change.element + left_miss += 1 + right_miss += 1 + end + end + end + + break if (not limit.nil?) && (count > limit) + end + + no_left = (left_match == 0) && (left_miss > 0) + no_right = (right_match == 0) && (right_miss > 0) + + case [no_left, no_right] + when [false, true] + :patch + when [true, false] + :unpatch + else + case left_match <=> right_match + when 1 + :patch + when -1 + :unpatch + else + raise "The provided patchset does not appear to apply to the provided value as either source or destination value." + end + end + end + + # Find the place at which +value+ would normally be inserted into the + # Enumerable. If that place is already occupied by +value+, do nothing + # and return +nil+. If the place does not exist (i.e., it is off the end + # of the Enumerable), add it to the end. Otherwise, replace the element + # at that point with +value+. It is assumed that the Enumerable's values + # are numeric. + # + # This operation preserves the sort order. + def replace_next_larger(enum, value, last_index = nil) + # Off the end? + if enum.empty? or (value > enum[-1]) + enum << value + return enum.size - 1 + end + + # Binary search for the insertion point + last_index ||= enum.size + first_index = 0 + while (first_index <= last_index) + i = (first_index + last_index) >> 1 + + found = enum[i] + + if value == found + return nil + elsif value > found + first_index = i + 1 + else + last_index = i - 1 + end + end + + # The insertion point is in first_index; overwrite the next larger + # value. + enum[first_index] = value + return first_index + end + private :replace_next_larger + + # If +vector+ maps the matching elements of another collection onto this + # Enumerable, compute the inverse of +vector+ that maps this Enumerable + # onto the collection. (Currently unused.) + def inverse_vector(a, vector) + inverse = a.dup + (0...vector.size).each do |i| + inverse[vector[i]] = i unless vector[i].nil? + end + inverse + end + private :inverse_vector + + # Returns a hash mapping each element of an Enumerable to the set of + # positions it occupies in the Enumerable, optionally restricted to the + # elements specified in the range of indexes specified by +interval+. + def position_hash(enum, interval) + string = enum.kind_of?(String) + hash = Hash.new { |h, k| h[k] = [] } + interval.each do |i| + k = string ? enum[i, 1] : enum[i] + hash[k] << i + end + hash + end + private :position_hash +end diff --git a/.bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/ldiff.rb b/.bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/ldiff.rb new file mode 100644 index 0000000..fff325a --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/ldiff.rb @@ -0,0 +1,195 @@ +# -*- ruby encoding: utf-8 -*- + +require 'optparse' +require 'ostruct' +require 'diff/lcs/hunk' + +# == ldiff Usage +# ldiff [options] oldfile newfile +# +# -c:: Displays a context diff with 3 lines of context. +# -C [LINES], --context [LINES]:: Displays a context diff with LINES lines of context. Default 3 lines. +# -u:: Displays a unified diff with 3 lines of context. +# -U [LINES], --unified [LINES]:: Displays a unified diff with LINES lines of context. Default 3 lines. +# -e:: Creates an 'ed' script to change oldfile to newfile. +# -f:: Creates an 'ed' script to change oldfile to newfile in reverse order. +# -a, --text:: Treats the files as text and compares them line-by-line, even if they do not seem to be text. +# --binary:: Treats the files as binary. +# -q, --brief:: Reports only whether or not the files differ, not the details. +# --help:: Shows the command-line help. +# --version:: Shows the version of Diff::LCS. +# +# By default, runs produces an "old-style" diff, with output like UNIX diff. +# +# == Copyright +# Copyright © 2004 Austin Ziegler +# +# Part of Diff::LCS +# Austin Ziegler +# +# This program is free software. It may be redistributed and/or modified under +# the terms of the GPL version 2 (or later), the Perl Artistic licence, or the +# Ruby licence. +module Diff::LCS::Ldiff + BANNER = <<-COPYRIGHT +ldiff #{Diff::LCS::VERSION} + Copyright 2004-2013 Austin Ziegler + + Part of Diff::LCS. + http://rubyforge.org/projects/ruwiki/ + + Austin Ziegler + + This program is free software. It may be redistributed and/or modified under + the terms of the GPL version 2 (or later), the Perl Artistic licence, or the + MIT licence. + COPYRIGHT +end + +class << Diff::LCS::Ldiff + attr_reader :format, :lines #:nodoc: + attr_reader :file_old, :file_new #:nodoc: + attr_reader :data_old, :data_new #:nodoc: + + def run(args, input = $stdin, output = $stdout, error = $stderr) #:nodoc: + @binary = nil + + args.options do |o| + o.banner = "Usage: #{File.basename($0)} [options] oldfile newfile" + o.separator "" + o.on('-c', '-C', '--context [LINES]', Numeric, 'Displays a context diff with LINES lines', 'of context. Default 3 lines.') do |ctx| + @format = :context + @lines = ctx || 3 + end + o.on('-u', '-U', '--unified [LINES]', Numeric, 'Displays a unified diff with LINES lines', 'of context. Default 3 lines.') do |ctx| + @format = :unified + @lines = ctx || 3 + end + o.on('-e', 'Creates an \'ed\' script to change', 'oldfile to newfile.') do |ctx| + @format = :ed + end + o.on('-f', 'Creates an \'ed\' script to change', 'oldfile to newfile in reverse order.') do |ctx| + @format = :reverse_ed + end + o.on('-a', '--text', 'Treat the files as text and compare them', 'line-by-line, even if they do not seem', 'to be text.') do |txt| + @binary = false + end + o.on('--binary', 'Treats the files as binary.') do |bin| + @binary = true + end + o.on('-q', '--brief', 'Report only whether or not the files', 'differ, not the details.') do |ctx| + @format = :report + end + o.on_tail('--help', 'Shows this text.') do + error << o + return 0 + end + o.on_tail('--version', 'Shows the version of Diff::LCS.') do + error << BANNER + return 0 + end + o.on_tail "" + o.on_tail 'By default, runs produces an "old-style" diff, with output like UNIX diff.' + o.parse! + end + + unless args.size == 2 + error << args.options + return 127 + end + + # Defaults are for old-style diff + @format ||= :old + @lines ||= 0 + + file_old, file_new = *ARGV + + case @format + when :context + char_old = '*' * 3 + char_new = '-' * 3 + when :unified + char_old = '-' * 3 + char_new = '+' * 3 + end + + # After we've read up to a certain point in each file, the number of + # items we've read from each file will differ by FLD (could be 0). + file_length_difference = 0 + + if @binary.nil? or @binary + data_old = IO::read(file_old) + data_new = IO::read(file_new) + + # Test binary status + if @binary.nil? + old_txt = data_old[0...4096].scan(/\0/).empty? + new_txt = data_new[0...4096].scan(/\0/).empty? + @binary = (not old_txt) or (not new_txt) + old_txt = new_txt = nil + end + + unless @binary + data_old = data_old.split($/).map { |e| e.chomp } + data_new = data_new.split($/).map { |e| e.chomp } + end + else + data_old = IO::readlines(file_old).map { |e| e.chomp } + data_new = IO::readlines(file_new).map { |e| e.chomp } + end + + # diff yields lots of pieces, each of which is basically a Block object + if @binary + diffs = (data_old == data_new) + else + diffs = Diff::LCS.diff(data_old, data_new) + diffs = nil if diffs.empty? + end + + return 0 unless diffs + + if @format == :report + output << "Files #{file_old} and #{file_new} differ\n" + return 1 + end + + if (@format == :unified) or (@format == :context) + ft = File.stat(file_old).mtime.localtime.strftime('%Y-%m-%d %H:%M:%S.%N %z') + puts "#{char_old} #{file_old}\t#{ft}" + ft = File.stat(file_new).mtime.localtime.strftime('%Y-%m-%d %H:%M:%S.%N %z') + puts "#{char_new} #{file_new}\t#{ft}" + end + + # Loop over hunks. If a hunk overlaps with the last hunk, join them. + # Otherwise, print out the old one. + oldhunk = hunk = nil + + if @format == :ed + real_output = output + output = [] + end + + diffs.each do |piece| + begin + hunk = Diff::LCS::Hunk.new(data_old, data_new, piece, @lines, + file_length_difference) + file_length_difference = hunk.file_length_difference + + next unless oldhunk + next if (@lines > 0) and hunk.merge(oldhunk) + + output << oldhunk.diff(@format) << "\n" + ensure + oldhunk = hunk + end + end + + output << oldhunk.diff(@format) << "\n" + + if @format == :ed + output.reverse_each { |e| real_output << e.diff(:ed_finish) } + end + + return 1 + end +end diff --git a/.bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/string.rb b/.bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/string.rb new file mode 100644 index 0000000..8545bcf --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/lib/diff/lcs/string.rb @@ -0,0 +1,5 @@ +# -*- ruby encoding: utf-8 -*- + +class String + include Diff::LCS +end diff --git a/.bundle/gems/diff-lcs-1.2.5/spec/change_spec.rb b/.bundle/gems/diff-lcs-1.2.5/spec/change_spec.rb new file mode 100644 index 0000000..dfe385f --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/spec/change_spec.rb @@ -0,0 +1,65 @@ +# -*- ruby encoding: utf-8 -*- + +require 'spec_helper' + +describe Diff::LCS::Change do + describe "an add" do + subject { described_class.new('+', 0, 'element') } + it { should_not be_deleting } + it { should be_adding } + it { should_not be_unchanged } + it { should_not be_changed } + it { should_not be_finished_a } + it { should_not be_finished_b } + end + + describe "a delete" do + subject { described_class.new('-', 0, 'element') } + it { should be_deleting } + it { should_not be_adding } + it { should_not be_unchanged } + it { should_not be_changed } + it { should_not be_finished_a } + it { should_not be_finished_b } + end + + describe "an unchanged" do + subject { described_class.new('=', 0, 'element') } + it { should_not be_deleting } + it { should_not be_adding } + it { should be_unchanged } + it { should_not be_changed } + it { should_not be_finished_a } + it { should_not be_finished_b } + end + + describe "a changed" do + subject { described_class.new('!', 0, 'element') } + it { should_not be_deleting } + it { should_not be_adding } + it { should_not be_unchanged } + it { should be_changed } + it { should_not be_finished_a } + it { should_not be_finished_b } + end + + describe "a finished_a" do + subject { described_class.new('>', 0, 'element') } + it { should_not be_deleting } + it { should_not be_adding } + it { should_not be_unchanged } + it { should_not be_changed } + it { should be_finished_a } + it { should_not be_finished_b } + end + + describe "a finished_b" do + subject { described_class.new('<', 0, 'element') } + it { should_not be_deleting } + it { should_not be_adding } + it { should_not be_unchanged } + it { should_not be_changed } + it { should_not be_finished_a } + it { should be_finished_b } + end +end diff --git a/.bundle/gems/diff-lcs-1.2.5/spec/diff_spec.rb b/.bundle/gems/diff-lcs-1.2.5/spec/diff_spec.rb new file mode 100644 index 0000000..95d7b40 --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/spec/diff_spec.rb @@ -0,0 +1,47 @@ +# -*- ruby encoding: utf-8 -*- + +require 'spec_helper' + +describe "Diff::LCS.diff" do + include Diff::LCS::SpecHelper::Matchers + + it "should correctly diff seq1 to seq2" do + diff_s1_s2 = Diff::LCS.diff(seq1, seq2) + change_diff(correct_forward_diff).should == diff_s1_s2 + end + + it "should correctly diff seq2 to seq1" do + diff_s2_s1 = Diff::LCS.diff(seq2, seq1) + change_diff(correct_backward_diff).should == diff_s2_s1 + end + + it "should correctly diff against an empty sequence" do + diff = Diff::LCS.diff(word_sequence, []) + correct_diff = [ + [ [ '-', 0, 'abcd' ], + [ '-', 1, 'efgh' ], + [ '-', 2, 'ijkl' ], + [ '-', 3, 'mnopqrstuvwxyz' ] ] + ] + + change_diff(correct_diff).should == diff + + diff = Diff::LCS.diff([], word_sequence) + correct_diff.each { |hunk| hunk.each { |change| change[0] = '+' } } + change_diff(correct_diff).should == diff + end + + it "should correctly diff 'xx' and 'xaxb'" do + left = 'xx' + right = 'xaxb' + Diff::LCS.patch(left, Diff::LCS.diff(left, right)).should == right + end + + it "should return an empty diff with (hello, hello)" do + Diff::LCS.diff(hello, hello).should == [] + end + + it "should return an empty diff with (hello_ary, hello_ary)" do + Diff::LCS.diff(hello_ary, hello_ary).should == [] + end +end diff --git a/.bundle/gems/diff-lcs-1.2.5/spec/hunk_spec.rb b/.bundle/gems/diff-lcs-1.2.5/spec/hunk_spec.rb new file mode 100644 index 0000000..dc6f532 --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/spec/hunk_spec.rb @@ -0,0 +1,72 @@ +# -*- ruby encoding: utf-8 -*- + +require 'spec_helper' + +def h(v) + v.to_s.bytes.to_a.map { |e| "%02x" % e }.join +end + +describe "Diff::LCS::Hunk" do + if String.method_defined?(:encoding) + + let(:old_data) { ["Tu avec carté {count} itém has".encode('UTF-16LE')] } + let(:new_data) { ["Tu avec carte {count} item has".encode('UTF-16LE')] } + let(:pieces) { Diff::LCS.diff old_data, new_data } + let(:hunk) { Diff::LCS::Hunk.new(old_data, new_data, pieces[0], 3, 0) } + + it 'should be able to produce a unified diff from the two pieces' do + expected = (<<-EOD.gsub(/^\s+/,'').encode('UTF-16LE').chomp) + @@ -1,2 +1,2 @@ + -Tu avec carté {count} itém has + +Tu avec carte {count} item has + EOD + expect(hunk.diff(:unified).to_s == expected).to eql true + end + + it 'should be able to produce a context diff from the two pieces' do + expected = (<<-EOD.gsub(/^\s+/,'').encode('UTF-16LE').chomp) + *************** + *** 1,2 **** + !Tu avec carté {count} itém has + --- 1,2 ---- + !Tu avec carte {count} item has + EOD + + expect(hunk.diff(:context).to_s == expected).to eql true + end + + it 'should be able to produce an old diff from the two pieces' do + expected = (<<-EOD.gsub(/^ +/,'').encode('UTF-16LE').chomp) + 1,2c1,2 + < Tu avec carté {count} itém has + --- + > Tu avec carte {count} item has + + EOD + expect(hunk.diff(:old).to_s == expected).to eql true + end + + it 'should be able to produce a reverse ed diff from the two pieces' do + expected = (<<-EOD.gsub(/^ +/,'').encode('UTF-16LE').chomp) + c1,2 + Tu avec carte {count} item has + . + + EOD + expect(hunk.diff(:reverse_ed).to_s == expected).to eql true + end + + context 'with empty first data set' do + let(:old_data) { [] } + + it 'should be able to produce a unified diff' do + expected = (<<-EOD.gsub(/^\s+/,'').encode('UTF-16LE').chomp) + @@ -1 +1,2 @@ + +Tu avec carte {count} item has + EOD + expect(hunk.diff(:unified).to_s == expected).to eql true + end + end + + end +end diff --git a/.bundle/gems/diff-lcs-1.2.5/spec/issues_spec.rb b/.bundle/gems/diff-lcs-1.2.5/spec/issues_spec.rb new file mode 100644 index 0000000..c3d8f87 --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/spec/issues_spec.rb @@ -0,0 +1,24 @@ +# -*- ruby encoding: utf-8 -*- + +require 'spec_helper' + +describe "Diff::LCS Issues" do + include Diff::LCS::SpecHelper::Matchers + + it "should not fail to provide a simple patchset (issue 1)" do + s1, s2 = *%W(aX bXaX) + correct_forward_diff = [ + [ [ '+', 0, 'b' ], + [ '+', 1, 'X' ] ], + ] + + diff_s1_s2 = Diff::LCS.diff(s1, s2) + change_diff(correct_forward_diff).should == diff_s1_s2 + expect do + Diff::LCS.patch(s1, diff_s1_s2).should == s2 + end.to_not raise_error(RuntimeError, /provided patchset/) + expect do + Diff::LCS.patch(s2, diff_s1_s2).should == s1 + end.to_not raise_error(RuntimeError, /provided patchset/) + end +end diff --git a/.bundle/gems/diff-lcs-1.2.5/spec/lcs_spec.rb b/.bundle/gems/diff-lcs-1.2.5/spec/lcs_spec.rb new file mode 100644 index 0000000..205d563 --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/spec/lcs_spec.rb @@ -0,0 +1,54 @@ +# -*- ruby encoding: utf-8 -*- + +require 'spec_helper' + +describe "Diff::LCS::Internals.lcs" do + include Diff::LCS::SpecHelper::Matchers + + it "should return a meaningful LCS array with (seq1, seq2)" do + res = Diff::LCS::Internals.lcs(seq1, seq2) + # The result of the LCS (less the +nil+ values) must be as long as the + # correct result. + res.compact.size.should == correct_lcs.size + res.should correctly_map_sequence(seq1).to_other_sequence(seq2) + + # Compact these transformations and they should be the correct LCS. + x_seq1 = (0...res.size).map { |ix| res[ix] ? seq1[ix] : nil }.compact + x_seq2 = (0...res.size).map { |ix| res[ix] ? seq2[res[ix]] : nil }.compact + + x_seq1.should == correct_lcs + x_seq2.should == correct_lcs + end + + it "should return all indexes with (hello, hello)" do + Diff::LCS::Internals.lcs(hello, hello).should == (0...hello.size).to_a + end + + it "should return all indexes with (hello_ary, hello_ary)" do + Diff::LCS::Internals.lcs(hello_ary, hello_ary).should == (0...hello_ary.size).to_a + end +end + +describe "Diff::LCS.LCS" do + include Diff::LCS::SpecHelper::Matchers + + it "should return the correct compacted values from Diff::LCS.LCS" do + res = Diff::LCS.LCS(seq1, seq2) + res.should == correct_lcs + res.compact.should == res + end + + it "should be transitive" do + res = Diff::LCS.LCS(seq2, seq1) + res.should == correct_lcs + res.compact.should == res + end + + it "should return %W(h e l l o) with (hello, hello)" do + Diff::LCS.LCS(hello, hello).should == hello.split(//) + end + + it "should return hello_ary with (hello_ary, hello_ary)" do + Diff::LCS.LCS(hello_ary, hello_ary).should == hello_ary + end +end diff --git a/.bundle/gems/diff-lcs-1.2.5/spec/patch_spec.rb b/.bundle/gems/diff-lcs-1.2.5/spec/patch_spec.rb new file mode 100644 index 0000000..0fc9160 --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/spec/patch_spec.rb @@ -0,0 +1,414 @@ +# -*- ruby encoding: utf-8 -*- + +require 'spec_helper' + +describe "Diff::LCS.patch" do + include Diff::LCS::SpecHelper::Matchers + + shared_examples "patch sequences correctly" do + it "should correctly patch left-to-right (patch autodiscovery)" do + Diff::LCS.patch(s1, patch_set).should == s2 + end + + it "should correctly patch left-to-right (explicit patch)" do + Diff::LCS.patch(s1, patch_set, :patch).should == s2 + Diff::LCS.patch!(s1, patch_set).should == s2 + end + + it "should correctly patch right-to-left (unpatch autodiscovery)" do + Diff::LCS.patch(s2, patch_set).should == s1 + end + + it "should correctly patch right-to-left (explicit unpatch)" do + Diff::LCS.patch(s2, patch_set, :unpatch).should == s1 + Diff::LCS.unpatch!(s2, patch_set).should == s1 + end + end + + describe "using a Diff::LCS.diff patchset" do + describe "an empty patchset returns the source" do + it "works on a string (hello)" do + Diff::LCS::patch(hello, Diff::LCS.diff(hello, hello)).should == hello + end + + it "works on an array %W(h e l l o)" do + Diff::LCS::patch(hello_ary, Diff::LCS.diff(hello_ary, hello_ary)).should == hello_ary + end + end + + describe "with default diff callbacks (DiffCallbacks)" do + describe "forward (s1 -> s2)" do + it_has_behavior "patch sequences correctly" do + let(:s1) { seq1 } + let(:s2) { seq2 } + let(:patch_set) { Diff::LCS.diff(seq1, seq2) } + end + end + + describe "reverse (s2 -> s1)" do + it_has_behavior "patch sequences correctly" do + let(:s1) { seq2 } + let(:s2) { seq1 } + let(:patch_set) { Diff::LCS.diff(seq2, seq1) } + end + end + end + + describe "with context diff callbacks (ContextDiffCallbacks)" do + describe "forward (s1 -> s2)" do + it_has_behavior "patch sequences correctly" do + let(:s1) { seq1 } + let(:s2) { seq2 } + let(:patch_set) { + Diff::LCS.diff(seq1, seq2, Diff::LCS::ContextDiffCallbacks) + } + end + end + + describe "reverse (s2 -> s1)" do + it_has_behavior "patch sequences correctly" do + let(:s1) { seq2 } + let(:s2) { seq1 } + let(:patch_set) { + Diff::LCS.diff(seq2, seq1, Diff::LCS::ContextDiffCallbacks) + } + end + end + end + + describe "with sdiff callbacks (SDiffCallbacks)" do + describe "forward (s1 -> s2)" do + it_has_behavior "patch sequences correctly" do + let(:s1) { seq1 } + let(:s2) { seq2 } + let(:patch_set) { + Diff::LCS.diff(seq1, seq2, Diff::LCS::SDiffCallbacks) + } + end + end + + describe "reverse (s2 -> s1)" do + it_has_behavior "patch sequences correctly" do + let(:s1) { seq2 } + let(:s2) { seq1 } + let(:patch_set) { + Diff::LCS.diff(seq2, seq1, Diff::LCS::SDiffCallbacks) + } + end + end + end + end + + describe "using a Diff::LCS.sdiff patchset" do + describe "an empty patchset returns the source" do + it "works on a string (hello)" do + Diff::LCS::patch(hello, Diff::LCS.sdiff(hello, hello)).should == hello + end + + it "works on an array %W(h e l l o)" do + Diff::LCS::patch(hello_ary, Diff::LCS.sdiff(hello_ary, hello_ary)).should == hello_ary + end + end + + describe "with default diff callbacks (DiffCallbacks)" do + describe "forward (s1 -> s2)" do + it_has_behavior "patch sequences correctly" do + let(:s1) { seq1 } + let(:s2) { seq2 } + let(:patch_set) { + Diff::LCS.sdiff(seq1, seq2, Diff::LCS::DiffCallbacks) + } + end + end + + describe "reverse (s2 -> s1)" do + it_has_behavior "patch sequences correctly" do + let(:s1) { seq2 } + let(:s2) { seq1 } + let(:patch_set) { + Diff::LCS.sdiff(seq2, seq1, Diff::LCS::DiffCallbacks) + } + end + end + end + + describe "with context diff callbacks (DiffCallbacks)" do + describe "forward (s1 -> s2)" do + it_has_behavior "patch sequences correctly" do + let(:s1) { seq1 } + let(:s2) { seq2 } + let(:patch_set) { + Diff::LCS.sdiff(seq1, seq2, Diff::LCS::ContextDiffCallbacks) + } + end + end + + describe "reverse (s2 -> s1)" do + it_has_behavior "patch sequences correctly" do + let(:s1) { seq2 } + let(:s2) { seq1 } + let(:patch_set) { + Diff::LCS.sdiff(seq2, seq1, Diff::LCS::ContextDiffCallbacks) + } + end + end + end + + describe "with sdiff callbacks (SDiffCallbacks)" do + describe "forward (s1 -> s2)" do + it_has_behavior "patch sequences correctly" do + let(:s1) { seq1 } + let(:s2) { seq2 } + let(:patch_set) { Diff::LCS.sdiff(seq1, seq2) } + end + end + + describe "reverse (s2 -> s1)" do + it_has_behavior "patch sequences correctly" do + let(:s1) { seq2 } + let(:s2) { seq1 } + let(:patch_set) { Diff::LCS.sdiff(seq2, seq1) } + end + end + end + end + + # Note: because of the error in autodiscovery ("does not autodiscover s1 + # to s2 patches"), this cannot use the "patch sequences correctly" shared + # set. Once the bug in autodiscovery is fixed, this can be converted as + # above. + describe "fix bug 891: patchsets do not contain the last equal part" do + before(:each) do + @s1 = %w(a b c d e f g h i j k) + @s2 = %w(a b c d D e f g h i j k) + end + + describe "using Diff::LCS.diff with default diff callbacks" do + before(:each) do + @patch_set_s1_s2 = Diff::LCS.diff(@s1, @s2) + @patch_set_s2_s1 = Diff::LCS.diff(@s2, @s1) + end + + it "should autodiscover s1 to s2 patches" do + expect do + Diff::LCS.patch(@s1, @patch_set_s1_s2).should == @s2 + end.to_not raise_error(RuntimeError, /provided patchset/) + end + + it "should autodiscover s2 to s1 patches" do + expect do + Diff::LCS.patch(@s1, @patch_set_s2_s1).should == @s2 + end.to_not raise_error(RuntimeError, /provided patchset/) + end + + it "should autodiscover s2 to s1 the left-to-right patches" do + Diff::LCS.patch(@s2, @patch_set_s2_s1).should == @s1 + Diff::LCS.patch(@s2, @patch_set_s1_s2).should == @s1 + end + + it "should correctly patch left-to-right (explicit patch)" do + Diff::LCS.patch(@s1, @patch_set_s1_s2, :patch).should == @s2 + Diff::LCS.patch(@s2, @patch_set_s2_s1, :patch).should == @s1 + Diff::LCS.patch!(@s1, @patch_set_s1_s2).should == @s2 + Diff::LCS.patch!(@s2, @patch_set_s2_s1).should == @s1 + end + + it "should correctly patch right-to-left (explicit unpatch)" do + Diff::LCS.patch(@s2, @patch_set_s1_s2, :unpatch).should == @s1 + Diff::LCS.patch(@s1, @patch_set_s2_s1, :unpatch).should == @s2 + Diff::LCS.unpatch!(@s2, @patch_set_s1_s2).should == @s1 + Diff::LCS.unpatch!(@s1, @patch_set_s2_s1).should == @s2 + end + end + + describe "using Diff::LCS.diff with context diff callbacks" do + before(:each) do + @patch_set_s1_s2 = Diff::LCS.diff(@s1, @s2, Diff::LCS::ContextDiffCallbacks) + @patch_set_s2_s1 = Diff::LCS.diff(@s2, @s1, Diff::LCS::ContextDiffCallbacks) + end + + it "should autodiscover s1 to s2 patches" do + expect do + Diff::LCS.patch(@s1, @patch_set_s1_s2).should == @s2 + end.to_not raise_error(RuntimeError, /provided patchset/) + end + + it "should autodiscover s2 to s1 patches" do + expect do + Diff::LCS.patch(@s1, @patch_set_s2_s1).should == @s2 + end.to_not raise_error(RuntimeError, /provided patchset/) + end + + it "should autodiscover s2 to s1 the left-to-right patches" do + Diff::LCS.patch(@s2, @patch_set_s2_s1).should == @s1 + Diff::LCS.patch(@s2, @patch_set_s1_s2).should == @s1 + end + + it "should correctly patch left-to-right (explicit patch)" do + Diff::LCS.patch(@s1, @patch_set_s1_s2, :patch).should == @s2 + Diff::LCS.patch(@s2, @patch_set_s2_s1, :patch).should == @s1 + Diff::LCS.patch!(@s1, @patch_set_s1_s2).should == @s2 + Diff::LCS.patch!(@s2, @patch_set_s2_s1).should == @s1 + end + + it "should correctly patch right-to-left (explicit unpatch)" do + Diff::LCS.patch(@s2, @patch_set_s1_s2, :unpatch).should == @s1 + Diff::LCS.patch(@s1, @patch_set_s2_s1, :unpatch).should == @s2 + Diff::LCS.unpatch!(@s2, @patch_set_s1_s2).should == @s1 + Diff::LCS.unpatch!(@s1, @patch_set_s2_s1).should == @s2 + end + end + + describe "using Diff::LCS.diff with sdiff callbacks" do + before(:each) do + @patch_set_s1_s2 = Diff::LCS.diff(@s1, @s2, Diff::LCS::SDiffCallbacks) + @patch_set_s2_s1 = Diff::LCS.diff(@s2, @s1, Diff::LCS::SDiffCallbacks) + end + + it "should autodiscover s1 to s2 patches" do + expect do + Diff::LCS.patch(@s1, @patch_set_s1_s2).should == @s2 + end.to_not raise_error(RuntimeError, /provided patchset/) + end + + it "should autodiscover s2 to s1 patches" do + expect do + Diff::LCS.patch(@s1, @patch_set_s2_s1).should == @s2 + end.to_not raise_error(RuntimeError, /provided patchset/) + end + + it "should autodiscover s2 to s1 the left-to-right patches" do + Diff::LCS.patch(@s2, @patch_set_s2_s1).should == @s1 + Diff::LCS.patch(@s2, @patch_set_s1_s2).should == @s1 + end + + it "should correctly patch left-to-right (explicit patch)" do + Diff::LCS.patch(@s1, @patch_set_s1_s2, :patch).should == @s2 + Diff::LCS.patch(@s2, @patch_set_s2_s1, :patch).should == @s1 + Diff::LCS.patch!(@s1, @patch_set_s1_s2).should == @s2 + Diff::LCS.patch!(@s2, @patch_set_s2_s1).should == @s1 + end + + it "should correctly patch right-to-left (explicit unpatch)" do + Diff::LCS.patch(@s2, @patch_set_s1_s2, :unpatch).should == @s1 + Diff::LCS.patch(@s1, @patch_set_s2_s1, :unpatch).should == @s2 + Diff::LCS.unpatch!(@s2, @patch_set_s1_s2).should == @s1 + Diff::LCS.unpatch!(@s1, @patch_set_s2_s1).should == @s2 + end + end + + describe "using Diff::LCS.sdiff with default sdiff callbacks" do + before(:each) do + @patch_set_s1_s2 = Diff::LCS.sdiff(@s1, @s2) + @patch_set_s2_s1 = Diff::LCS.sdiff(@s2, @s1) + end + + it "should autodiscover s1 to s2 patches" do + expect do + Diff::LCS.patch(@s1, @patch_set_s1_s2).should == @s2 + end.to_not raise_error(RuntimeError, /provided patchset/) + end + + it "should autodiscover s2 to s1 patches" do + expect do + Diff::LCS.patch(@s1, @patch_set_s2_s1).should == @s2 + end.to_not raise_error(RuntimeError, /provided patchset/) + end + + it "should autodiscover s2 to s1 the left-to-right patches" do + Diff::LCS.patch(@s2, @patch_set_s2_s1).should == @s1 + Diff::LCS.patch(@s2, @patch_set_s1_s2).should == @s1 + end + + it "should correctly patch left-to-right (explicit patch)", :only => true do + Diff::LCS.patch(@s1, @patch_set_s1_s2, :patch).should == @s2 + Diff::LCS.patch(@s2, @patch_set_s2_s1, :patch).should == @s1 + Diff::LCS.patch!(@s1, @patch_set_s1_s2).should == @s2 + Diff::LCS.patch!(@s2, @patch_set_s2_s1).should == @s1 + end + + it "should correctly patch right-to-left (explicit unpatch)" do + Diff::LCS.patch(@s2, @patch_set_s1_s2, :unpatch).should == @s1 + Diff::LCS.patch(@s1, @patch_set_s2_s1, :unpatch).should == @s2 + Diff::LCS.unpatch!(@s2, @patch_set_s1_s2).should == @s1 + Diff::LCS.unpatch!(@s1, @patch_set_s2_s1).should == @s2 + end + end + + describe "using Diff::LCS.sdiff with context diff callbacks" do + before(:each) do + @patch_set_s1_s2 = Diff::LCS.sdiff(@s1, @s2, Diff::LCS::ContextDiffCallbacks) + @patch_set_s2_s1 = Diff::LCS.sdiff(@s2, @s1, Diff::LCS::ContextDiffCallbacks) + end + + it "should autodiscover s1 to s2 patches" do + expect do + Diff::LCS.patch(@s1, @patch_set_s1_s2).should == @s2 + end.to_not raise_error(RuntimeError, /provided patchset/) + end + + it "should autodiscover s2 to s1 patches" do + expect do + Diff::LCS.patch(@s1, @patch_set_s2_s1).should == @s2 + end.to_not raise_error(RuntimeError, /provided patchset/) + end + + it "should autodiscover s2 to s1 the left-to-right patches" do + Diff::LCS.patch(@s2, @patch_set_s2_s1).should == @s1 + Diff::LCS.patch(@s2, @patch_set_s1_s2).should == @s1 + end + + it "should correctly patch left-to-right (explicit patch)" do + Diff::LCS.patch(@s1, @patch_set_s1_s2, :patch).should == @s2 + Diff::LCS.patch(@s2, @patch_set_s2_s1, :patch).should == @s1 + Diff::LCS.patch!(@s1, @patch_set_s1_s2).should == @s2 + Diff::LCS.patch!(@s2, @patch_set_s2_s1).should == @s1 + end + + it "should correctly patch right-to-left (explicit unpatch)" do + Diff::LCS.patch(@s2, @patch_set_s1_s2, :unpatch).should == @s1 + Diff::LCS.patch(@s1, @patch_set_s2_s1, :unpatch).should == @s2 + Diff::LCS.unpatch!(@s2, @patch_set_s1_s2).should == @s1 + Diff::LCS.unpatch!(@s1, @patch_set_s2_s1).should == @s2 + end + end + + describe "using Diff::LCS.sdiff with default diff callbacks" do + before(:each) do + @patch_set_s1_s2 = Diff::LCS.sdiff(@s1, @s2, Diff::LCS::DiffCallbacks) + @patch_set_s2_s1 = Diff::LCS.sdiff(@s2, @s1, Diff::LCS::DiffCallbacks) + end + + it "should autodiscover s1 to s2 patches" do + expect do + Diff::LCS.patch(@s1, @patch_set_s1_s2).should == @s2 + end.to_not raise_error(RuntimeError, /provided patchset/) + end + + it "should autodiscover s2 to s1 patches" do + expect do + Diff::LCS.patch(@s1, @patch_set_s2_s1).should == @s2 + end.to_not raise_error(RuntimeError, /provided patchset/) + end + + it "should autodiscover s2 to s1 the left-to-right patches" do + Diff::LCS.patch(@s2, @patch_set_s2_s1).should == @s1 + Diff::LCS.patch(@s2, @patch_set_s1_s2).should == @s1 + end + + it "should correctly patch left-to-right (explicit patch)" do + Diff::LCS.patch(@s1, @patch_set_s1_s2, :patch).should == @s2 + Diff::LCS.patch(@s2, @patch_set_s2_s1, :patch).should == @s1 + Diff::LCS.patch!(@s1, @patch_set_s1_s2).should == @s2 + Diff::LCS.patch!(@s2, @patch_set_s2_s1).should == @s1 + end + + it "should correctly patch right-to-left (explicit unpatch)" do + Diff::LCS.patch(@s2, @patch_set_s1_s2, :unpatch).should == @s1 + Diff::LCS.patch(@s1, @patch_set_s2_s1, :unpatch).should == @s2 + Diff::LCS.unpatch!(@s2, @patch_set_s1_s2).should == @s1 + Diff::LCS.unpatch!(@s1, @patch_set_s2_s1).should == @s2 + end + end + end +end diff --git a/.bundle/gems/diff-lcs-1.2.5/spec/sdiff_spec.rb b/.bundle/gems/diff-lcs-1.2.5/spec/sdiff_spec.rb new file mode 100644 index 0000000..7ab3bb6 --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/spec/sdiff_spec.rb @@ -0,0 +1,214 @@ +# -*- ruby encoding: utf-8 -*- + +require 'spec_helper' + +describe "Diff::LCS.sdiff" do + include Diff::LCS::SpecHelper::Matchers + + shared_examples "compare sequences correctly" do + it "should compare s1 -> s2 correctly" do + Diff::LCS.sdiff(s1, s2).should == context_diff(result) + end + + it "should compare s2 -> s1 correctly" do + Diff::LCS.sdiff(s2, s1).should == context_diff(reverse_sdiff(result)) + end + end + + describe "using seq1 & seq2" do + let(:s1) { seq1 } + let(:s2) { seq2 } + let(:result) { correct_forward_sdiff } + + it_has_behavior "compare sequences correctly" + end + + describe "using %w(abc def yyy xxx ghi jkl) & %w(abc dxf xxx ghi jkl)" do + let(:s1) { %w(abc def yyy xxx ghi jkl) } + let(:s2) { %w(abc dxf xxx ghi jkl) } + let(:result) { + [ + [ '=', [ 0, 'abc' ], [ 0, 'abc' ] ], + [ '!', [ 1, 'def' ], [ 1, 'dxf' ] ], + [ '-', [ 2, 'yyy' ], [ 2, nil ] ], + [ '=', [ 3, 'xxx' ], [ 2, 'xxx' ] ], + [ '=', [ 4, 'ghi' ], [ 3, 'ghi' ] ], + [ '=', [ 5, 'jkl' ], [ 4, 'jkl' ] ] + ] + } + + it_has_behavior "compare sequences correctly" + end + + describe "using %w(a b c d e) & %w(a e)" do + let(:s1) { %w(a b c d e) } + let(:s2) { %w(a e) } + let(:result) { + [ + [ '=', [ 0, 'a' ], [ 0, 'a' ] ], + [ '-', [ 1, 'b' ], [ 1, nil ] ], + [ '-', [ 2, 'c' ], [ 1, nil ] ], + [ '-', [ 3, 'd' ], [ 1, nil ] ], + [ '=', [ 4, 'e' ], [ 1, 'e' ] ] + ] + } + + it_has_behavior "compare sequences correctly" + end + + describe "using %w(a e) & %w(a b c d e)" do + let(:s1) { %w(a e) } + let(:s2) { %w(a b c d e) } + let(:result) { + [ + [ '=', [ 0, 'a' ], [ 0, 'a' ] ], + [ '+', [ 1, nil ], [ 1, 'b' ] ], + [ '+', [ 1, nil ], [ 2, 'c' ] ], + [ '+', [ 1, nil ], [ 3, 'd' ] ], + [ '=', [ 1, 'e' ], [ 4, 'e' ] ] + ] + } + + it_has_behavior "compare sequences correctly" + end + + describe "using %w(v x a e) & %w(w y a b c d e)" do + let(:s1) { %w(v x a e) } + let(:s2) { %w(w y a b c d e) } + let(:result) { + [ + [ '!', [ 0, 'v' ], [ 0, 'w' ] ], + [ '!', [ 1, 'x' ], [ 1, 'y' ] ], + [ '=', [ 2, 'a' ], [ 2, 'a' ] ], + [ '+', [ 3, nil ], [ 3, 'b' ] ], + [ '+', [ 3, nil ], [ 4, 'c' ] ], + [ '+', [ 3, nil ], [ 5, 'd' ] ], + [ '=', [ 3, 'e' ], [ 6, 'e' ] ] + ] + } + + it_has_behavior "compare sequences correctly" + end + + describe "using %w(x a e) & %w(a b c d e)" do + let(:s1) { %w(x a e) } + let(:s2) { %w(a b c d e) } + let(:result) { + [ + [ '-', [ 0, 'x' ], [ 0, nil ] ], + [ '=', [ 1, 'a' ], [ 0, 'a' ] ], + [ '+', [ 2, nil ], [ 1, 'b' ] ], + [ '+', [ 2, nil ], [ 2, 'c' ] ], + [ '+', [ 2, nil ], [ 3, 'd' ] ], + [ '=', [ 2, 'e' ], [ 4, 'e' ] ] + ] + } + + it_has_behavior "compare sequences correctly" + end + + describe "using %w(a e) & %w(x a b c d e)" do + let(:s1) { %w(a e) } + let(:s2) { %w(x a b c d e) } + let(:result) { + [ + [ '+', [ 0, nil ], [ 0, 'x' ] ], + [ '=', [ 0, 'a' ], [ 1, 'a' ] ], + [ '+', [ 1, nil ], [ 2, 'b' ] ], + [ '+', [ 1, nil ], [ 3, 'c' ] ], + [ '+', [ 1, nil ], [ 4, 'd' ] ], + [ '=', [ 1, 'e' ], [ 5, 'e' ] ] + ] + } + + it_has_behavior "compare sequences correctly" + end + + describe "using %w(a e v) & %w(x a b c d e w x)" do + let(:s1) { %w(a e v) } + let(:s2) { %w(x a b c d e w x) } + let(:result) { + [ + [ '+', [ 0, nil ], [ 0, 'x' ] ], + [ '=', [ 0, 'a' ], [ 1, 'a' ] ], + [ '+', [ 1, nil ], [ 2, 'b' ] ], + [ '+', [ 1, nil ], [ 3, 'c' ] ], + [ '+', [ 1, nil ], [ 4, 'd' ] ], + [ '=', [ 1, 'e' ], [ 5, 'e' ] ], + [ '!', [ 2, 'v' ], [ 6, 'w' ] ], + [ '+', [ 3, nil ], [ 7, 'x' ] ] + ] + } + + it_has_behavior "compare sequences correctly" + end + + describe "using %w() & %w(a b c)" do + let(:s1) { %w() } + let(:s2) { %w(a b c) } + let(:result) { + [ + [ '+', [ 0, nil ], [ 0, 'a' ] ], + [ '+', [ 0, nil ], [ 1, 'b' ] ], + [ '+', [ 0, nil ], [ 2, 'c' ] ] + ] + } + + it_has_behavior "compare sequences correctly" + end + + describe "using %w(a b c) & %w(1)" do + let(:s1) { %w(a b c) } + let(:s2) { %w(1) } + let(:result) { + [ + [ '!', [ 0, 'a' ], [ 0, '1' ] ], + [ '-', [ 1, 'b' ], [ 1, nil ] ], + [ '-', [ 2, 'c' ], [ 1, nil ] ] + ] + } + + it_has_behavior "compare sequences correctly" + end + + describe "using %w(a b c) & %w(c)" do + let(:s1) { %w(a b c) } + let(:s2) { %w(c) } + let(:result) { + [ + [ '-', [ 0, 'a' ], [ 0, nil ] ], + [ '-', [ 1, 'b' ], [ 0, nil ] ], + [ '=', [ 2, 'c' ], [ 0, 'c' ] ] + ] + } + + it_has_behavior "compare sequences correctly" + end + + describe "using %w(abcd efgh ijkl mnop) & []" do + let(:s1) { %w(abcd efgh ijkl mnop) } + let(:s2) { [] } + let(:result) { + [ + [ '-', [ 0, 'abcd' ], [ 0, nil ] ], + [ '-', [ 1, 'efgh' ], [ 0, nil ] ], + [ '-', [ 2, 'ijkl' ], [ 0, nil ] ], + [ '-', [ 3, 'mnop' ], [ 0, nil ] ] + ] + } + + it_has_behavior "compare sequences correctly" + end + + describe "using [[1,2]] & []" do + let(:s1) { [ [ 1, 2 ] ] } + let(:s2) { [] } + let(:result) { + [ + [ '-', [ 0, [ 1, 2 ] ], [ 0, nil ] ] + ] + } + + it_has_behavior "compare sequences correctly" + end +end diff --git a/.bundle/gems/diff-lcs-1.2.5/spec/spec_helper.rb b/.bundle/gems/diff-lcs-1.2.5/spec/spec_helper.rb new file mode 100644 index 0000000..a5ca00d --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/spec/spec_helper.rb @@ -0,0 +1,290 @@ +# -*- ruby encoding: utf-8 -*- + +require 'rubygems' +require 'pathname' + +file = Pathname.new(__FILE__).expand_path +path = file.parent +parent = path.parent + +$:.unshift parent.join('lib') + +require 'diff-lcs' + +module Diff::LCS::SpecHelper + def hello + "hello" + end + + def hello_ary + %W(h e l l o) + end + + def seq1 + %w(a b c e h j l m n p) + end + + def skipped_seq1 + %w(a h n p) + end + + def seq2 + %w(b c d e f j k l m r s t) + end + + def skipped_seq2 + %w(d f k r s t) + end + + def word_sequence + %w(abcd efgh ijkl mnopqrstuvwxyz) + end + + def correct_lcs + %w(b c e j l m) + end + + def correct_forward_diff + [ + [ [ '-', 0, 'a' ] ], + [ [ '+', 2, 'd' ] ], + [ [ '-', 4, 'h' ], + [ '+', 4, 'f' ] ], + [ [ '+', 6, 'k' ] ], + [ [ '-', 8, 'n' ], + [ '-', 9, 'p' ], + [ '+', 9, 'r' ], + [ '+', 10, 's' ], + [ '+', 11, 't' ] ] + ] + end + + def correct_backward_diff + [ + [ [ '+', 0, 'a' ] ], + [ [ '-', 2, 'd' ] ], + [ [ '-', 4, 'f' ], + [ '+', 4, 'h' ] ], + [ [ '-', 6, 'k' ] ], + [ + [ '-', 9, 'r' ], + [ '-', 10, 's' ], + [ '+', 8, 'n' ], + [ '-', 11, 't' ], + [ '+', 9, 'p' ] ] + ] + end + + def correct_forward_sdiff + [ + [ '-', [ 0, 'a' ], [ 0, nil ] ], + [ '=', [ 1, 'b' ], [ 0, 'b' ] ], + [ '=', [ 2, 'c' ], [ 1, 'c' ] ], + [ '+', [ 3, nil ], [ 2, 'd' ] ], + [ '=', [ 3, 'e' ], [ 3, 'e' ] ], + [ '!', [ 4, 'h' ], [ 4, 'f' ] ], + [ '=', [ 5, 'j' ], [ 5, 'j' ] ], + [ '+', [ 6, nil ], [ 6, 'k' ] ], + [ '=', [ 6, 'l' ], [ 7, 'l' ] ], + [ '=', [ 7, 'm' ], [ 8, 'm' ] ], + [ '!', [ 8, 'n' ], [ 9, 'r' ] ], + [ '!', [ 9, 'p' ], [ 10, 's' ] ], + [ '+', [ 10, nil ], [ 11, 't' ] ] + ] + end + + def reverse_sdiff(forward_sdiff) + forward_sdiff.map { |line| + line[1], line[2] = line[2], line[1] + case line[0] + when '-' then line[0] = '+' + when '+' then line[0] = '-' + end + line + } + end + + def change_diff(diff) + map_diffs(diff, Diff::LCS::Change) + end + + def context_diff(diff) + map_diffs(diff, Diff::LCS::ContextChange) + end + + def format_diffs(diffs) + diffs.map do |e| + if e.kind_of?(Array) + e.map { |f| f.to_a.join }.join(", ") + else + e.to_a.join + end + end.join("\n") + end + + def map_diffs(diffs, klass = Diff::LCS::ContextChange) + diffs.map do |chunks| + if klass == Diff::LCS::ContextChange + klass.from_a(chunks) + else + chunks.map { |changes| klass.from_a(changes) } + end + end + end + + def balanced_traversal(s1, s2, callback_type) + callback = __send__(callback_type) + Diff::LCS.traverse_balanced(s1, s2, callback) + callback + end + + def balanced_reverse(change_result) + new_result = [] + change_result.each { |line| + line = [ line[0], line[2], line[1] ] + case line[0] + when '<' + line[0] = '>' + when '>' + line[0] = '<' + end + new_result << line + } + new_result.sort_by { |line| [ line[1], line[2] ] } + end + + def map_to_no_change(change_result) + new_result = [] + change_result.each { |line| + case line[0] + when '!' + new_result << [ '<', line[1], line[2] ] + new_result << [ '>', line[1] + 1, line[2] ] + else + new_result << line + end + } + new_result + end + + def simple_callback + callbacks = Object.new + class << callbacks + attr_reader :matched_a + attr_reader :matched_b + attr_reader :discards_a + attr_reader :discards_b + attr_reader :done_a + attr_reader :done_b + + def reset + @matched_a = [] + @matched_b = [] + @discards_a = [] + @discards_b = [] + @done_a = [] + @done_b = [] + end + + def match(event) + @matched_a << event.old_element + @matched_b << event.new_element + end + + def discard_b(event) + @discards_b << event.new_element + end + + def discard_a(event) + @discards_a << event.old_element + end + + def finished_a(event) + @done_a << [event.old_element, event.old_position, + event.new_element, event.new_position] + end + + def finished_b(event) + p "called #finished_b" + @done_b << [event.old_element, event.old_position, + event.new_element, event.new_position] + end + end + callbacks.reset + callbacks + end + + def simple_callback_no_finishers + simple = simple_callback + class << simple + undef :finished_a + undef :finished_b + end + simple + end + + def balanced_callback + cb = Object.new + class << cb + attr_reader :result + + def reset + @result = [] + end + + def match(event) + @result << [ "=", event.old_position, event.new_position ] + end + + def discard_a(event) + @result << [ "<", event.old_position, event.new_position ] + end + + def discard_b(event) + @result << [ ">", event.old_position, event.new_position ] + end + + def change(event) + @result << [ "!", event.old_position, event.new_position ] + end + end + cb.reset + cb + end + + def balanced_callback_no_change + balanced = balanced_callback + class << balanced + undef :change + end + balanced + end + + module Matchers + extend RSpec::Matchers::DSL + + matcher :be_nil_or_match_values do |ii, s1, s2| + match do |ee| + ee.should satisfy { |vee| vee.nil? || s1[ii] == s2[ee] } + end + end + + matcher :correctly_map_sequence do |s1| + match do |actual| + actual.each_with_index { |ee, ii| + ee.should be_nil_or_match_values(ii, s1, @s2) + } + end + + chain :to_other_sequence do |s2| + @s2 = s2 + end + end + end +end + +RSpec.configure do |conf| + conf.include Diff::LCS::SpecHelper + conf.alias_it_should_behave_like_to :it_has_behavior, 'has behavior:' + conf.filter_run_excluding :broken => true +end diff --git a/.bundle/gems/diff-lcs-1.2.5/spec/traverse_balanced_spec.rb b/.bundle/gems/diff-lcs-1.2.5/spec/traverse_balanced_spec.rb new file mode 100644 index 0000000..63fe1eb --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/spec/traverse_balanced_spec.rb @@ -0,0 +1,310 @@ +# -*- ruby encoding: utf-8 -*- + +require 'spec_helper' + +describe "Diff::LCS.traverse_balanced" do + include Diff::LCS::SpecHelper::Matchers + + shared_examples "with a #change callback" do |s1, s2, result| + it "should traverse s1 -> s2 correctly" do + traversal = balanced_traversal(s1, s2, :balanced_callback) + traversal.result.should == result + end + + it "should traverse s2 -> s1 correctly" do + traversal = balanced_traversal(s2, s1, :balanced_callback) + traversal.result.should == balanced_reverse(result) + end + end + + shared_examples "without a #change callback" do |s1, s2, result| + it "should traverse s1 -> s2 correctly" do + traversal = balanced_traversal(s1, s2, :balanced_callback_no_change) + traversal.result.should == map_to_no_change(result) + end + + it "should traverse s2 -> s1 correctly" do + traversal = balanced_traversal(s2, s1, :balanced_callback_no_change) + traversal.result.should == map_to_no_change(balanced_reverse(result)) + end + end + + describe "identical string sequences ('abc')" do + s1 = s2 = "abc" + + result = [ + [ '=', 0, 0 ], + [ '=', 1, 1 ], + [ '=', 2, 2 ] + ] + + it_has_behavior "with a #change callback", s1, s2, result + it_has_behavior "without a #change callback", s1, s2, result + end + + describe "identical array sequences %w(a b c)" do + s1 = s2 = %w(a b c) + + result = [ + [ '=', 0, 0 ], + [ '=', 1, 1 ], + [ '=', 2, 2 ] + ] + + it_has_behavior "with a #change callback", s1, s2, result + it_has_behavior "without a #change callback", s1, s2, result + end + + describe "sequences %w(a b c) & %w(a x c)" do + s1 = %w(a b c) + s2 = %w(a x c) + + result = [ + [ '=', 0, 0 ], + [ '!', 1, 1 ], + [ '=', 2, 2 ] + ] + + it_has_behavior "with a #change callback", s1, s2, result + it_has_behavior "without a #change callback", s1, s2, result + end + + describe "sequences %w(a x y c) & %w(a v w c)" do + s1 = %w(a x y c) + s2 = %w(a v w c) + + result = [ + [ '=', 0, 0 ], + [ '!', 1, 1 ], + [ '!', 2, 2 ], + [ '=', 3, 3 ] + ] + + it_has_behavior "with a #change callback", s1, s2, result + it_has_behavior "without a #change callback", s1, s2, result + end + + describe "sequences %w(x y c) & %w(v w c)" do + s1 = %w(x y c) + s2 = %w(v w c) + result = [ + [ '!', 0, 0 ], + [ '!', 1, 1 ], + [ '=', 2, 2 ] + ] + + it_has_behavior "with a #change callback", s1, s2, result + it_has_behavior "without a #change callback", s1, s2, result + end + + describe "sequences %w(a x y z) & %w(b v w)" do + s1 = %w(a x y z) + s2 = %w(b v w) + result = [ + [ '!', 0, 0 ], + [ '!', 1, 1 ], + [ '!', 2, 2 ], + [ '<', 3, 3 ] + ] + + it_has_behavior "with a #change callback", s1, s2, result + it_has_behavior "without a #change callback", s1, s2, result + end + + describe "sequences %w(a z) & %w(a)" do + s1 = %w(a z) + s2 = %w(a) + result = [ + [ '=', 0, 0 ], + [ '<', 1, 1 ] + ] + + it_has_behavior "with a #change callback", s1, s2, result + it_has_behavior "without a #change callback", s1, s2, result + end + + describe "sequences %w(z a) & %w(a)" do + s1 = %w(z a) + s2 = %w(a) + result = [ + [ '<', 0, 0 ], + [ '=', 1, 0 ] + ] + + it_has_behavior "with a #change callback", s1, s2, result + it_has_behavior "without a #change callback", s1, s2, result + end + + describe "sequences %w(a b c) & %w(x y z)" do + s1 = %w(a b c) + s2 = %w(x y z) + result = [ + [ '!', 0, 0 ], + [ '!', 1, 1 ], + [ '!', 2, 2 ] + ] + + it_has_behavior "with a #change callback", s1, s2, result + it_has_behavior "without a #change callback", s1, s2, result + end + + describe "sequences %w(abcd efgh ijkl mnoopqrstuvwxyz) & []" do + s1 = %w(abcd efgh ijkl mnopqrstuvwxyz) + s2 = [] + result = [ + [ '<', 0, 0 ], + [ '<', 1, 0 ], + [ '<', 2, 0 ], + [ '<', 3, 0 ] + ] + + it_has_behavior "with a #change callback", s1, s2, result + it_has_behavior "without a #change callback", s1, s2, result + end + + describe "strings %Q(a b c) & %Q(a x c)" do + s1 = %Q(a b c) + s2 = %Q(a x c) + + result = [ + [ '=', 0, 0 ], + [ '=', 1, 1 ], + [ '!', 2, 2 ], + [ '=', 3, 3 ], + [ '=', 4, 4 ] + ] + + it_has_behavior "with a #change callback", s1, s2, result + it_has_behavior "without a #change callback", s1, s2, result + end + + describe "strings %Q(a x y c) & %Q(a v w c)" do + s1 = %Q(a x y c) + s2 = %Q(a v w c) + + result = [ + [ '=', 0, 0 ], + [ '=', 1, 1 ], + [ '!', 2, 2 ], + [ '=', 3, 3 ], + [ '!', 4, 4 ], + [ '=', 5, 5 ], + [ '=', 6, 6 ] + ] + + it_has_behavior "with a #change callback", s1, s2, result + it_has_behavior "without a #change callback", s1, s2, result + end + + describe "strings %Q(x y c) & %Q(v w c)" do + s1 = %Q(x y c) + s2 = %Q(v w c) + result = [ + [ '!', 0, 0 ], + [ '=', 1, 1 ], + [ '!', 2, 2 ], + [ '=', 3, 3 ], + [ '=', 4, 4 ] + ] + + it_has_behavior "with a #change callback", s1, s2, result + it_has_behavior "without a #change callback", s1, s2, result + end + + describe "strings %Q(a x y z) & %Q(b v w)" do + s1 = %Q(a x y z) + s2 = %Q(b v w) + result = [ + [ '!', 0, 0 ], + [ '=', 1, 1 ], + [ '!', 2, 2 ], + [ '=', 3, 3 ], + [ '!', 4, 4 ], + [ '<', 5, 5 ], + [ '<', 6, 5 ] + ] + + it_has_behavior "with a #change callback", s1, s2, result + it_has_behavior "without a #change callback", s1, s2, result + end + + describe "strings %Q(a z) & %Q(a)" do + s1 = %Q(a z) + s2 = %Q(a) + result = [ + [ '=', 0, 0 ], + [ '<', 1, 1 ], + [ '<', 2, 1 ] + ] + + it_has_behavior "with a #change callback", s1, s2, result + it_has_behavior "without a #change callback", s1, s2, result + end + + describe "strings %Q(z a) & %Q(a)" do + s1 = %Q(z a) + s2 = %Q(a) + result = [ + [ '<', 0, 0 ], + [ '<', 1, 0 ], + [ '=', 2, 0 ] + ] + + it_has_behavior "with a #change callback", s1, s2, result + it_has_behavior "without a #change callback", s1, s2, result + end + + describe "strings %Q(a b c) & %Q(x y z)" do + s1 = %Q(a b c) + s2 = %Q(x y z) + result = [ + [ '!', 0, 0 ], + [ '=', 1, 1 ], + [ '!', 2, 2 ], + [ '=', 3, 3 ], + [ '!', 4, 4 ] + ] + + it_has_behavior "with a #change callback", s1, s2, result + it_has_behavior "without a #change callback", s1, s2, result + end + + describe "strings %Q(abcd efgh ijkl mnopqrstuvwxyz) & %Q()" do + s1 = %Q(abcd efgh ijkl mnopqrstuvwxyz) + s2 = "" + result = [ + [ '<', 0, 0 ], + [ '<', 1, 0 ], + [ '<', 2, 0 ], + [ '<', 3, 0 ], + [ '<', 4, 0 ], + [ '<', 5, 0 ], + [ '<', 6, 0 ], + [ '<', 7, 0 ], + [ '<', 8, 0 ], + [ '<', 9, 0 ], + [ '<', 10, 0 ], + [ '<', 11, 0 ], + [ '<', 12, 0 ], + [ '<', 13, 0 ], + [ '<', 14, 0 ], + [ '<', 15, 0 ], + [ '<', 16, 0 ], + [ '<', 17, 0 ], + [ '<', 18, 0 ], + [ '<', 19, 0 ], + [ '<', 20, 0 ], + [ '<', 21, 0 ], + [ '<', 22, 0 ], + [ '<', 23, 0 ], + [ '<', 24, 0 ], + [ '<', 25, 0 ], + [ '<', 26, 0 ], + [ '<', 27, 0 ], + [ '<', 28, 0 ], + ] + + it_has_behavior "with a #change callback", s1, s2, result + it_has_behavior "without a #change callback", s1, s2, result + end +end diff --git a/.bundle/gems/diff-lcs-1.2.5/spec/traverse_sequences_spec.rb b/.bundle/gems/diff-lcs-1.2.5/spec/traverse_sequences_spec.rb new file mode 100644 index 0000000..f4480df --- /dev/null +++ b/.bundle/gems/diff-lcs-1.2.5/spec/traverse_sequences_spec.rb @@ -0,0 +1,139 @@ +# -*- ruby encoding: utf-8 -*- + +require 'spec_helper' + +describe "Diff::LCS.traverse_sequences" do + describe "callback with no finishers" do + describe "over (seq1, seq2)" do + before(:each) do + @callback_s1_s2 = simple_callback_no_finishers + Diff::LCS.traverse_sequences(seq1, seq2, @callback_s1_s2) + + @callback_s2_s1 = simple_callback_no_finishers + Diff::LCS.traverse_sequences(seq2, seq1, @callback_s2_s1) + end + + it "should have the correct LCS result on left-matches" do + @callback_s1_s2.matched_a.should == correct_lcs + @callback_s2_s1.matched_a.should == correct_lcs + end + + it "should have the correct LCS result on right-matches" do + @callback_s1_s2.matched_b.should == correct_lcs + @callback_s2_s1.matched_b.should == correct_lcs + end + + it "should have the correct skipped sequences with the left sequence" do + @callback_s1_s2.discards_a.should == skipped_seq1 + @callback_s2_s1.discards_a.should == skipped_seq2 + end + + it "should have the correct skipped sequences with the right sequence" do + @callback_s1_s2.discards_b.should == skipped_seq2 + @callback_s2_s1.discards_b.should == skipped_seq1 + end + + it "should not have anything done markers from the left or right sequences" do + @callback_s1_s2.done_a.should be_empty + @callback_s1_s2.done_b.should be_empty + @callback_s2_s1.done_a.should be_empty + @callback_s2_s1.done_b.should be_empty + end + end + + describe "over (hello, hello)" do + before(:each) do + @callback = simple_callback_no_finishers + Diff::LCS.traverse_sequences(hello, hello, @callback) + end + + it "should have the correct LCS result on left-matches" do + @callback.matched_a.should == hello.split(//) + end + + it "should have the correct LCS result on right-matches" do + @callback.matched_b.should == hello.split(//) + end + + it "should have the correct skipped sequences with the left sequence", :only => true do + @callback.discards_a.should be_empty + end + + it "should have the correct skipped sequences with the right sequence" do + @callback.discards_b.should be_empty + end + + it "should not have anything done markers from the left or right sequences" do + @callback.done_a.should be_empty + @callback.done_b.should be_empty + end + end + + describe "over (hello_ary, hello_ary)" do + before(:each) do + @callback = simple_callback_no_finishers + Diff::LCS.traverse_sequences(hello_ary, hello_ary, @callback) + end + + it "should have the correct LCS result on left-matches" do + @callback.matched_a.should == hello_ary + end + + it "should have the correct LCS result on right-matches" do + @callback.matched_b.should == hello_ary + end + + it "should have the correct skipped sequences with the left sequence" do + @callback.discards_a.should be_empty + end + + it "should have the correct skipped sequences with the right sequence" do + @callback.discards_b.should be_empty + end + + it "should not have anything done markers from the left or right sequences" do + @callback.done_a.should be_empty + @callback.done_b.should be_empty + end + end + end + + describe "callback with finisher" do + before(:each) do + @callback_s1_s2 = simple_callback + Diff::LCS.traverse_sequences(seq1, seq2, @callback_s1_s2) + @callback_s2_s1 = simple_callback + Diff::LCS.traverse_sequences(seq2, seq1, @callback_s2_s1) + end + + it "should have the correct LCS result on left-matches" do + @callback_s1_s2.matched_a.should == correct_lcs + @callback_s2_s1.matched_a.should == correct_lcs + end + + it "should have the correct LCS result on right-matches" do + @callback_s1_s2.matched_b.should == correct_lcs + @callback_s2_s1.matched_b.should == correct_lcs + end + + it "should have the correct skipped sequences for the left sequence" do + @callback_s1_s2.discards_a.should == skipped_seq1 + @callback_s2_s1.discards_a.should == skipped_seq2 + end + + it "should have the correct skipped sequences for the right sequence" do + @callback_s1_s2.discards_b.should == skipped_seq2 + @callback_s2_s1.discards_b.should == skipped_seq1 + end + + it "should have done markers differently-sized sequences" do + @callback_s1_s2.done_a.should == [[ "p", 9, "s", 10 ]] + @callback_s1_s2.done_b.should be_empty + + # 20110731 I don't yet understand why this particular behaviour + # isn't transitive. + @callback_s2_s1.done_a.should be_empty + @callback_s2_s1.done_b.should be_empty + end + end +end diff --git a/.bundle/gems/method_source-0.8.2/.gemtest b/.bundle/gems/method_source-0.8.2/.gemtest new file mode 100644 index 0000000..e69de29 diff --git a/.bundle/gems/method_source-0.8.2/.travis.yml b/.bundle/gems/method_source-0.8.2/.travis.yml new file mode 100644 index 0000000..2349f06 --- /dev/null +++ b/.bundle/gems/method_source-0.8.2/.travis.yml @@ -0,0 +1,13 @@ +rvm: + - 1.8.7 + - 1.9.2 + - 1.9.3 + - ree + - rbx-18mode + - rbx-19mode + - jruby + +notifications: + irc: "irc.freenode.org#pry" + recipients: + - jrmair@gmail.com diff --git a/.bundle/gems/method_source-0.8.2/.yardopts b/.bundle/gems/method_source-0.8.2/.yardopts new file mode 100644 index 0000000..a4e7838 --- /dev/null +++ b/.bundle/gems/method_source-0.8.2/.yardopts @@ -0,0 +1 @@ +-m markdown diff --git a/.bundle/gems/method_source-0.8.2/Gemfile b/.bundle/gems/method_source-0.8.2/Gemfile new file mode 100644 index 0000000..e45e65f --- /dev/null +++ b/.bundle/gems/method_source-0.8.2/Gemfile @@ -0,0 +1,2 @@ +source :rubygems +gemspec diff --git a/.bundle/gems/method_source-0.8.2/LICENSE b/.bundle/gems/method_source-0.8.2/LICENSE new file mode 100644 index 0000000..d1a50d6 --- /dev/null +++ b/.bundle/gems/method_source-0.8.2/LICENSE @@ -0,0 +1,25 @@ +License +------- + +(The MIT License) + +Copyright (c) 2011 John Mair (banisterfiend) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/.bundle/gems/method_source-0.8.2/README.markdown b/.bundle/gems/method_source-0.8.2/README.markdown new file mode 100644 index 0000000..d91b810 --- /dev/null +++ b/.bundle/gems/method_source-0.8.2/README.markdown @@ -0,0 +1,91 @@ +method_source +============= + +(C) John Mair (banisterfiend) 2011 + +_retrieve the sourcecode for a method_ + +*NOTE:* This simply utilizes `Method#source_location`; it + does not access the live AST. + +`method_source` is a utility to return a method's sourcecode as a +Ruby string. Also returns `Proc` and `Lambda` sourcecode. + +Method comments can also be extracted using the `comment` method. + +It is written in pure Ruby (no C). + +* Some Ruby 1.8 support now available. +* Support for MRI, RBX, JRuby, REE + +`method_source` provides the `source` and `comment` methods to the `Method` and +`UnboundMethod` and `Proc` classes. + +* Install the [gem](https://rubygems.org/gems/method_source): `gem install method_source` +* Read the [documentation](http://rdoc.info/github/banister/method_source/master/file/README.markdown) +* See the [source code](http://github.com/banister/method_source) + +Example: display method source +------------------------------ + + Set.instance_method(:merge).source.display + # => + def merge(enum) + if enum.instance_of?(self.class) + @hash.update(enum.instance_variable_get(:@hash)) + else + do_with_enum(enum) { |o| add(o) } + end + + self + end + +Example: display method comments +-------------------------------- + + Set.instance_method(:merge).comment.display + # => + # Merges the elements of the given enumerable object to the set and + # returns self. + +Limitations: +------------ + +* Occasional strange behaviour in Ruby 1.8 +* Cannot return source for C methods. +* Cannot return source for dynamically defined methods. + +Special Thanks +-------------- + +[Adam Sanderson](https://github.com/adamsanderson) for `comment` functionality. + +[Dmitry Elastic](https://github.com/dmitryelastic) for the brilliant Ruby 1.8 `source_location` hack. + +[Samuel Kadolph](https://github.com/samuelkadolph) for the JRuby 1.8 `source_location`. + +License +------- + +(The MIT License) + +Copyright (c) 2011 John Mair (banisterfiend) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/.bundle/gems/method_source-0.8.2/Rakefile b/.bundle/gems/method_source-0.8.2/Rakefile new file mode 100644 index 0000000..7dad800 --- /dev/null +++ b/.bundle/gems/method_source-0.8.2/Rakefile @@ -0,0 +1,79 @@ +dlext = RbConfig::CONFIG['DLEXT'] +direc = File.dirname(__FILE__) + +require 'rake/clean' +require 'rubygems/package_task' +require "#{direc}/lib/method_source/version" + +CLOBBER.include("**/*.#{dlext}", "**/*~", "**/*#*", "**/*.log", "**/*.o") +CLEAN.include("ext/**/*.#{dlext}", "ext/**/*.log", "ext/**/*.o", + "ext/**/*~", "ext/**/*#*", "ext/**/*.obj", "**/*.rbc", + "ext/**/*.def", "ext/**/*.pdb", "**/*_flymake*.*", "**/*_flymake") + +def apply_spec_defaults(s) + s.name = "method_source" + s.summary = "retrieve the sourcecode for a method" + s.version = MethodSource::VERSION + s.date = Time.now.strftime '%Y-%m-%d' + s.author = "John Mair (banisterfiend)" + s.email = 'jrmair@gmail.com' + s.description = s.summary + s.require_path = 'lib' + + s.add_development_dependency("bacon","~>1.1.0") + s.add_development_dependency("rake", "~>0.9") + s.homepage = "http://banisterfiend.wordpress.com" + s.has_rdoc = 'yard' + s.files = `git ls-files`.split("\n") + s.test_files = `git ls-files -- test/*`.split("\n") +end + +task :test do + sh "bacon -q #{direc}/test/test.rb #{direc}/test/test_code_helpers.rb" +end + +desc "reinstall gem" +task :reinstall => :gems do + sh "gem uninstall method_source" rescue nil + sh "gem install #{direc}/pkg/method_source-#{MethodSource::VERSION}.gem" +end + +desc "Set up and run tests" +task :default => [:test] + +desc "Build the gemspec file" +task :gemspec => "ruby:gemspec" + +namespace :ruby do + spec = Gem::Specification.new do |s| + apply_spec_defaults(s) + s.platform = Gem::Platform::RUBY + end + + Gem::PackageTask.new(spec) do |pkg| + pkg.need_zip = false + pkg.need_tar = false + end + + desc "Generate gemspec file" + task :gemspec do + File.open("#{spec.name}.gemspec", "w") do |f| + f << spec.to_ruby + end + end +end + +desc "build all platform gems at once" +task :gems => [:rmgems, "ruby:gem"] + +desc "remove all platform gems" +task :rmgems => ["ruby:clobber_package"] + +desc "build and push latest gems" +task :pushgems => :gems do + chdir("#{direc}/pkg") do + Dir["*.gem"].each do |gemfile| + sh "gem push #{gemfile}" + end + end +end diff --git a/.bundle/gems/method_source-0.8.2/lib/method_source.rb b/.bundle/gems/method_source-0.8.2/lib/method_source.rb new file mode 100644 index 0000000..7d16c3b --- /dev/null +++ b/.bundle/gems/method_source-0.8.2/lib/method_source.rb @@ -0,0 +1,141 @@ +# (C) John Mair (banisterfiend) 2011 +# MIT License + +direc = File.dirname(__FILE__) + +require "#{direc}/method_source/version" +require "#{direc}/method_source/source_location" +require "#{direc}/method_source/code_helpers" + +module MethodSource + extend MethodSource::CodeHelpers + + # An Exception to mark errors that were raised trying to find the source from + # a given source_location. + # + class SourceNotFoundError < StandardError; end + + # Helper method responsible for extracting method body. + # Defined here to avoid polluting `Method` class. + # @param [Array] source_location The array returned by Method#source_location + # @param [String] method_name + # @return [String] The method body + def self.source_helper(source_location, name=nil) + raise SourceNotFoundError, "Could not locate source for #{name}!" unless source_location + file, line = *source_location + + expression_at(lines_for(file), line) + rescue SyntaxError => e + raise SourceNotFoundError, "Could not parse source for #{name}: #{e.message}" + end + + # Helper method responsible for opening source file and buffering up + # the comments for a specified method. Defined here to avoid polluting + # `Method` class. + # @param [Array] source_location The array returned by Method#source_location + # @param [String] method_name + # @return [String] The comments up to the point of the method. + def self.comment_helper(source_location, name=nil) + raise SourceNotFoundError, "Could not locate source for #{name}!" unless source_location + file, line = *source_location + + comment_describing(lines_for(file), line) + end + + # Load a memoized copy of the lines in a file. + # + # @param [String] file_name + # @param [String] method_name + # @return [Array] the contents of the file + # @raise [SourceNotFoundError] + def self.lines_for(file_name, name=nil) + @lines_for_file ||= {} + @lines_for_file[file_name] ||= File.readlines(file_name) + rescue Errno::ENOENT => e + raise SourceNotFoundError, "Could not load source for #{name}: #{e.message}" + end + + # @deprecated — use MethodSource::CodeHelpers#complete_expression? + def self.valid_expression?(str) + complete_expression?(str) + rescue SyntaxError + false + end + + # @deprecated — use MethodSource::CodeHelpers#expression_at + def self.extract_code(source_location) + source_helper(source_location) + end + + # This module is to be included by `Method` and `UnboundMethod` and + # provides the `#source` functionality + module MethodExtensions + + # We use the included hook to patch Method#source on rubinius. + # We need to use the included hook as Rubinius defines a `source` + # on Method so including a module will have no effect (as it's + # higher up the MRO). + # @param [Class] klass The class that includes the module. + def self.included(klass) + if klass.method_defined?(:source) && Object.const_defined?(:RUBY_ENGINE) && + RUBY_ENGINE =~ /rbx/ + + klass.class_eval do + orig_source = instance_method(:source) + + define_method(:source) do + begin + super + rescue + orig_source.bind(self).call + end + end + + end + end + end + + # Return the sourcecode for the method as a string + # @return [String] The method sourcecode as a string + # @raise SourceNotFoundException + # + # @example + # Set.instance_method(:clear).source.display + # => + # def clear + # @hash.clear + # self + # end + def source + MethodSource.source_helper(source_location, defined?(name) ? name : inspect) + end + + # Return the comments associated with the method as a string. + # @return [String] The method's comments as a string + # @raise SourceNotFoundException + # + # @example + # Set.instance_method(:clear).comment.display + # => + # # Removes all elements and returns self. + def comment + MethodSource.comment_helper(source_location, defined?(name) ? name : inspect) + end + end +end + +class Method + include MethodSource::SourceLocation::MethodExtensions + include MethodSource::MethodExtensions +end + +class UnboundMethod + include MethodSource::SourceLocation::UnboundMethodExtensions + include MethodSource::MethodExtensions +end + +class Proc + include MethodSource::SourceLocation::ProcExtensions + include MethodSource::MethodExtensions +end + diff --git a/.bundle/gems/method_source-0.8.2/lib/method_source/code_helpers.rb b/.bundle/gems/method_source-0.8.2/lib/method_source/code_helpers.rb new file mode 100644 index 0000000..6c1d53e --- /dev/null +++ b/.bundle/gems/method_source-0.8.2/lib/method_source/code_helpers.rb @@ -0,0 +1,154 @@ +module MethodSource + + module CodeHelpers + # Retrieve the first expression starting on the given line of the given file. + # + # This is useful to get module or method source code. + # + # @param [Array, File, String] file The file to parse, either as a File or as + # @param [Fixnum] line_number The line number at which to look. + # NOTE: The first line in a file is + # line 1! + # @param [Hash] options The optional configuration parameters. + # @option options [Boolean] :strict If set to true, then only completely + # valid expressions are returned. Otherwise heuristics are used to extract + # expressions that may have been valid inside an eval. + # @option options [Fixnum] :consume A number of lines to automatically + # consume (add to the expression buffer) without checking for validity. + # @return [String] The first complete expression + # @raise [SyntaxError] If the first complete expression can't be identified + def expression_at(file, line_number, options={}) + options = { + :strict => false, + :consume => 0 + }.merge!(options) + + lines = file.is_a?(Array) ? file : file.each_line.to_a + + relevant_lines = lines[(line_number - 1)..-1] || [] + + extract_first_expression(relevant_lines, options[:consume]) + rescue SyntaxError => e + raise if options[:strict] + + begin + extract_first_expression(relevant_lines) do |code| + code.gsub(/\#\{.*?\}/, "temp") + end + rescue SyntaxError + raise e + end + end + + # Retrieve the comment describing the expression on the given line of the given file. + # + # This is useful to get module or method documentation. + # + # @param [Array, File, String] file The file to parse, either as a File or as + # a String or an Array of lines. + # @param [Fixnum] line_number The line number at which to look. + # NOTE: The first line in a file is line 1! + # @return [String] The comment + def comment_describing(file, line_number) + lines = file.is_a?(Array) ? file : file.each_line.to_a + + extract_last_comment(lines[0..(line_number - 2)]) + end + + # Determine if a string of code is a complete Ruby expression. + # @param [String] code The code to validate. + # @return [Boolean] Whether or not the code is a complete Ruby expression. + # @raise [SyntaxError] Any SyntaxError that does not represent incompleteness. + # @example + # complete_expression?("class Hello") #=> false + # complete_expression?("class Hello; end") #=> true + # complete_expression?("class 123") #=> SyntaxError: unexpected tINTEGER + def complete_expression?(str) + old_verbose = $VERBOSE + $VERBOSE = nil + + catch(:valid) do + eval("BEGIN{throw :valid}\n#{str}") + end + + # Assert that a line which ends with a , or \ is incomplete. + str !~ /[,\\]\s*\z/ + rescue IncompleteExpression + false + ensure + $VERBOSE = old_verbose + end + + private + + # Get the first expression from the input. + # + # @param [Array] lines + # @param [Fixnum] consume A number of lines to automatically + # consume (add to the expression buffer) without checking for validity. + # @yield a clean-up function to run before checking for complete_expression + # @return [String] a valid ruby expression + # @raise [SyntaxError] + def extract_first_expression(lines, consume=0, &block) + code = consume.zero? ? "" : lines.slice!(0..(consume - 1)).join + + lines.each do |v| + code << v + return code if complete_expression?(block ? block.call(code) : code) + end + raise SyntaxError, "unexpected $end" + end + + # Get the last comment from the input. + # + # @param [Array] lines + # @return [String] + def extract_last_comment(lines) + buffer = "" + + lines.each do |line| + # Add any line that is a valid ruby comment, + # but clear as soon as we hit a non comment line. + if (line =~ /^\s*#/) || (line =~ /^\s*$/) + buffer << line.lstrip + else + buffer.replace("") + end + end + + buffer + end + + # An exception matcher that matches only subsets of SyntaxErrors that can be + # fixed by adding more input to the buffer. + module IncompleteExpression + GENERIC_REGEXPS = [ + /unexpected (\$end|end-of-file|end-of-input|END_OF_FILE)/, # mri, jruby, ruby-2.0, ironruby + /embedded document meets end of file/, # =begin + /unterminated (quoted string|string|regexp) meets end of file/, # "quoted string" is ironruby + /can't find string ".*" anywhere before EOF/, # rbx and jruby + /missing 'end' for/, /expecting kWHEN/ # rbx + ] + + RBX_ONLY_REGEXPS = [ + /expecting '[})\]]'(?:$|:)/, /expecting keyword_end/ + ] + + def self.===(ex) + return false unless SyntaxError === ex + case ex.message + when *GENERIC_REGEXPS + true + when *RBX_ONLY_REGEXPS + rbx? + else + false + end + end + + def self.rbx? + RbConfig::CONFIG['ruby_install_name'] == 'rbx' + end + end + end +end diff --git a/.bundle/gems/method_source-0.8.2/lib/method_source/source_location.rb b/.bundle/gems/method_source-0.8.2/lib/method_source/source_location.rb new file mode 100644 index 0000000..1e2a22a --- /dev/null +++ b/.bundle/gems/method_source-0.8.2/lib/method_source/source_location.rb @@ -0,0 +1,138 @@ +module MethodSource + module ReeSourceLocation + # Ruby enterprise edition provides all the information that's + # needed, in a slightly different way. + def source_location + [__file__, __line__] rescue nil + end + end + + module SourceLocation + module MethodExtensions + if Proc.method_defined? :__file__ + include ReeSourceLocation + + elsif defined?(RUBY_ENGINE) && RUBY_ENGINE =~ /jruby/ + require 'java' + + # JRuby version source_location hack + # @return [Array] A two element array containing the source location of the method + def source_location + to_java.source_location(Thread.current.to_java.getContext()) + end + else + + + def trace_func(event, file, line, id, binding, classname) + return unless event == 'call' + set_trace_func nil + + @file, @line = file, line + raise :found + end + + private :trace_func + + # Return the source location of a method for Ruby 1.8. + # @return [Array] A two element array. First element is the + # file, second element is the line in the file where the + # method definition is found. + def source_location + if @file.nil? + args =[*(1..(arity<-1 ? -arity-1 : arity ))] + + set_trace_func method(:trace_func).to_proc + call(*args) rescue nil + set_trace_func nil + @file = File.expand_path(@file) if @file && File.exist?(File.expand_path(@file)) + end + [@file, @line] if @file + end + end + end + + module ProcExtensions + if Proc.method_defined? :__file__ + include ReeSourceLocation + + elsif defined?(RUBY_ENGINE) && RUBY_ENGINE =~ /rbx/ + + # Return the source location for a Proc (Rubinius only) + # @return [Array] A two element array. First element is the + # file, second element is the line in the file where the + # proc definition is found. + def source_location + [block.file.to_s, block.line] + end + else + + # Return the source location for a Proc (in implementations + # without Proc#source_location) + # @return [Array] A two element array. First element is the + # file, second element is the line in the file where the + # proc definition is found. + def source_location + self.to_s =~ /@(.*):(\d+)/ + [$1, $2.to_i] + end + end + end + + module UnboundMethodExtensions + if Proc.method_defined? :__file__ + include ReeSourceLocation + + elsif defined?(RUBY_ENGINE) && RUBY_ENGINE =~ /jruby/ + require 'java' + + # JRuby version source_location hack + # @return [Array] A two element array containing the source location of the method + def source_location + to_java.source_location(Thread.current.to_java.getContext()) + end + + else + + + # Return the source location of an instance method for Ruby 1.8. + # @return [Array] A two element array. First element is the + # file, second element is the line in the file where the + # method definition is found. + def source_location + klass = case owner + when Class + owner + when Module + method_owner = owner + Class.new { include(method_owner) } + end + + # deal with immediate values + case + when klass == Symbol + return :a.method(name).source_location + when klass == Fixnum + return 0.method(name).source_location + when klass == TrueClass + return true.method(name).source_location + when klass == FalseClass + return false.method(name).source_location + when klass == NilClass + return nil.method(name).source_location + end + + begin + Object.instance_method(:method).bind(klass.allocate).call(name).source_location + rescue TypeError + + # Assume we are dealing with a Singleton Class: + # 1. Get the instance object + # 2. Forward the source_location lookup to the instance + instance ||= ObjectSpace.each_object(owner).first + Object.instance_method(:method).bind(instance).call(name).source_location + end + end + end + end + end +end diff --git a/.bundle/gems/method_source-0.8.2/lib/method_source/version.rb b/.bundle/gems/method_source-0.8.2/lib/method_source/version.rb new file mode 100644 index 0000000..7a91c7d --- /dev/null +++ b/.bundle/gems/method_source-0.8.2/lib/method_source/version.rb @@ -0,0 +1,3 @@ +module MethodSource + VERSION = "0.8.2" +end diff --git a/.bundle/gems/method_source-0.8.2/method_source.gemspec b/.bundle/gems/method_source-0.8.2/method_source.gemspec new file mode 100644 index 0000000..d24b3d9 --- /dev/null +++ b/.bundle/gems/method_source-0.8.2/method_source.gemspec @@ -0,0 +1,33 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = "method_source" + s.version = "0.8.1" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["John Mair (banisterfiend)"] + s.date = "2012-10-17" + s.description = "retrieve the sourcecode for a method" + s.email = "jrmair@gmail.com" + s.files = [".gemtest", ".travis.yml", ".yardopts", "Gemfile", "LICENSE", "README.markdown", "Rakefile", "lib/method_source.rb", "lib/method_source/code_helpers.rb", "lib/method_source/source_location.rb", "lib/method_source/version.rb", "method_source.gemspec", "test/test.rb", "test/test_code_helpers.rb", "test/test_helper.rb"] + s.homepage = "http://banisterfiend.wordpress.com" + s.require_paths = ["lib"] + s.rubygems_version = "1.8.23" + s.summary = "retrieve the sourcecode for a method" + s.test_files = ["test/test.rb", "test/test_code_helpers.rb", "test/test_helper.rb"] + + if s.respond_to? :specification_version then + s.specification_version = 3 + + if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then + s.add_development_dependency(%q, ["~> 1.1.0"]) + s.add_development_dependency(%q, ["~> 0.9"]) + else + s.add_dependency(%q, ["~> 1.1.0"]) + s.add_dependency(%q, ["~> 0.9"]) + end + else + s.add_dependency(%q, ["~> 1.1.0"]) + s.add_dependency(%q, ["~> 0.9"]) + end +end diff --git a/.bundle/gems/method_source-0.8.2/test/test.rb b/.bundle/gems/method_source-0.8.2/test/test.rb new file mode 100644 index 0000000..4743a50 --- /dev/null +++ b/.bundle/gems/method_source-0.8.2/test/test.rb @@ -0,0 +1,138 @@ +direc = File.expand_path(File.dirname(__FILE__)) + +require 'rubygems' +require 'bacon' +require "#{direc}/../lib/method_source" +require "#{direc}/test_helper" + +describe MethodSource do + + describe "source_location (testing 1.8 implementation)" do + it 'should return correct source_location for a method' do + method(:hello).source_location.first.should =~ /test_helper/ + end + + it 'should not raise for immediate instance methods' do + [Symbol, Fixnum, TrueClass, FalseClass, NilClass].each do |immediate_class| + lambda { immediate_class.instance_method(:to_s).source_location }.should.not.raise + end + end + + it 'should not raise for immediate methods' do + [:a, 1, true, false, nil].each do |immediate| + lambda { immediate.method(:to_s).source_location }.should.not.raise + end + end + end + + before do + @hello_module_source = " def hello; :hello_module; end\n" + @hello_singleton_source = "def $o.hello; :hello_singleton; end\n" + @hello_source = "def hello; :hello; end\n" + @hello_comment = "# A comment for hello\n# It spans two lines and is indented by 2 spaces\n" + @lambda_comment = "# This is a comment for MyLambda\n" + @lambda_source = "MyLambda = lambda { :lambda }\n" + @proc_source = "MyProc = Proc.new { :proc }\n" + @hello_instance_evaled_source = " def hello_\#{name}(*args)\n send_mesg(:\#{name}, *args)\n end\n" + @hello_instance_evaled_source_2 = " def \#{name}_two()\n if 44\n 45\n end\n end\n" + @hello_class_evaled_source = " def hello_\#{name}(*args)\n send_mesg(:\#{name}, *args)\n end\n" + @hi_module_evaled_source = " def hi_\#{name}\n @var = \#{name}\n end\n" + end + + it 'should define methods on Method and UnboundMethod and Proc' do + Method.method_defined?(:source).should == true + UnboundMethod.method_defined?(:source).should == true + Proc.method_defined?(:source).should == true + end + + describe "Methods" do + it 'should return source for method' do + method(:hello).source.should == @hello_source + end + + it 'should return source for a method defined in a module' do + M.instance_method(:hello).source.should == @hello_module_source + end + + it 'should return source for a singleton method as an instance method' do + class << $o; self; end.instance_method(:hello).source.should == @hello_singleton_source + end + + it 'should return source for a singleton method' do + $o.method(:hello).source.should == @hello_singleton_source + end + + it 'should return a comment for method' do + method(:hello).comment.should == @hello_comment + end + + # These tests fail because of http://jira.codehaus.org/browse/JRUBY-4576 + unless defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby" + it 'should return source for an *_evaled method' do + M.method(:hello_name).source.should == @hello_instance_evaled_source + M.method(:name_two).source.should == @hello_instance_evaled_source_2 + M.instance_method(:hello_name).source.should == @hello_class_evaled_source + M.instance_method(:hi_name).source.should == @hi_module_evaled_source + end + end + + it "should raise error for evaled methods that do not pass __FILE__ and __LINE__ + 1 as its arguments" do + lambda { M.instance_method(:name_three).source }.should.raise MethodSource::SourceNotFoundError + end + + if !is_rbx? + it 'should raise for C methods' do + lambda { method(:puts).source }.should.raise MethodSource::SourceNotFoundError + end + end + end + + # if RUBY_VERSION =~ /1.9/ || is_rbx? + describe "Lambdas and Procs" do + it 'should return source for proc' do + MyProc.source.should == @proc_source + end + + it 'should return an empty string if there is no comment' do + MyProc.comment.should == '' + end + + it 'should return source for lambda' do + MyLambda.source.should == @lambda_source + end + + it 'should return comment for lambda' do + MyLambda.comment.should == @lambda_comment + end + end + # end + describe "Comment tests" do + before do + @comment1 = "# a\n# b\n" + @comment2 = "# a\n# b\n" + @comment3 = "# a\n#\n# b\n" + @comment4 = "# a\n# b\n" + @comment5 = "# a\n# b\n# c\n# d\n" + end + + it "should correctly extract multi-line comments" do + method(:comment_test1).comment.should == @comment1 + end + + it "should correctly strip leading whitespace before comments" do + method(:comment_test2).comment.should == @comment2 + end + + it "should keep empty comment lines" do + method(:comment_test3).comment.should == @comment3 + end + + it "should ignore blank lines between comments" do + method(:comment_test4).comment.should == @comment4 + end + + it "should align all comments to same indent level" do + method(:comment_test5).comment.should == @comment5 + end + end +end diff --git a/.bundle/gems/method_source-0.8.2/test/test_code_helpers.rb b/.bundle/gems/method_source-0.8.2/test/test_code_helpers.rb new file mode 100644 index 0000000..ba83a63 --- /dev/null +++ b/.bundle/gems/method_source-0.8.2/test/test_code_helpers.rb @@ -0,0 +1,41 @@ +describe MethodSource::CodeHelpers do + before do + @tester = Object.new.extend(MethodSource::CodeHelpers) + end + + [ + ["p = '", "'"], + ["def", "a", "(); end"], + ["p = < 1.1.0` +* Remove deprecated hooks API ([#1209](https://github.com/pry/pry/pull/1209)) +* Add 64-bit windows support. + +#### Bug fixes, etc. +* The `gem-install` command can require gems like `net-ssh` thanks to better + logic for guessing what path to require. (#1188) +* `toggle-color` command toggles the local `_pry_.color` setting instead of the + global `Pry.color`. +* Update `Pry::CLIPPED_PRINT` to include a hex representation of object ID when + printing a return value. (#1162) +* Wrap exceptions in a proxy instead of adding singleton methods. (#1145) + * `Pry#last_exception=` now supports exception objects that have been frozen. +* `binding.pry` inside `.pryrc` file now works, with some limitations (@richo / #1118) +* Add support for BasicObjects to `ls` (#984) +* Allow `ls -c ` (#891) +* Fix indentation not working if the `mathn` stdlib was loaded (#872) +* Fix `hist`'s `--exclude-pry` switch (#874) +* Fix `gem-install` on JRuby (#870) +* Fix source lookup for instrumented classes (#923) +* Improved thread safety when multiple instances are running (#944) +* Make `edit` ignore `-n`/`--no-reload` flag and `disable_auto_reload` config + in cases where the user was editing a tempfile +* Make `gem-cd` use the most recent gem, not the oldest +* Make `install-command` honor `.gemrc` switches (#666) +* Make `hist` with no parameters show just the current session's history (#205) + * `hist --all` shows older history +* Make `-s`/`--super` flag of `show-source`/`show-doc` work when method name is + being inferred from context (#877) +* Rename `--installed-plugins` flag to `--plugins` +* Strip ANSI codes from prompt before measuring length for indentation (#493) +* Fix bug in `edit` regarding recognition of file names without suffix. +* Reduced download size by removing tests etc. from distributed gem. + +#### Dev-facing changes +* `CommandSet#commands`, sometimes referenced through `Pry.commands.commands`, + renamed to `CommandSet#to_hash`. It returns a duplicate of the internal hash + a CommandSet uses. +* `CommandSet#keys` is now an alias of `CommandSet#list_commands`. +* All commands should now reference configuration values via `_pry_.config` + (local) and not `Pry.config` (global). (#1096) + * This change improves support for concurrent environments and + context-specific Pry sessions. `_pry_.config` inherits default values from + `Pry.config` but can override them locally. +* `rake pry` now accepts switches prefixed with `_` (e.g., `rake pry _v`) +* Pagers now act like `IO`s and accept streaming output + * See `_pry_.pager.page` and `_pry_.pager.open`. +* The `Pry` class has been broken up into two smaller classes. + * `Pry` represents non-UI-specific session state, including the eval string + * `Pry::REPL` controls the user-facing interface + * This should make it easier to drive Pry from alternative interfaces + * `Pry.start` now has a `:driver` option that defaults to `Pry::REPL` + * This involved a lot of refactoring and may break plugins that depend on + the old layout +* Add `ColorPrinter` subclass of `PP` for colorized object inspection +* Add `[]` and `[]=` methods to `CommandSet`, which find and replace commands + * Example: `Pry.commands["help"] = MyHelpCommand` +* The completion API has been refactored (see fdb703a8de4ef3) +* `Pry.config.input_stack` (and the input stack concept in general) no longer + exists +* There's a new `Pry::Terminal` class that implements a number of different + methods of determining the terminal's dimensions +* Add `ReplTester` class for high-level simulation of Pry sessions in tests +* Add `Pry.main`. Returns the special instance of Object referenced by self of + `TOPLEVEL_BINDING`: "main". +* Changed second argument of `Pry.view_clip()` from Fixnum to Hash to support + returning a string with or without a hex representation of object ID. (#1162) +* The `output` and `pager` objects will now strip color-codes, so commands should + always print in color. +* Commands now have a `state` hash that is persistent across invocations of the command + in the same pry session. + +### 0.9.12.6 (2014/01/28) +* Don't fail if Bond is not installed (#1106) + +### 0.9.12.5 (2014/01/27) +* Fix early readline errors by deferring require of readline (#1081, #1095) + +### 0.9.12.4 (2013/11/23) +* Fix issue with Coderay colors being black, even when on a black background (#1016) + +### 0.9.12.3 (2013/09/11) +* Bump Coderay dependency (#987) +* Fix consecutive newlines in heredocs being collapsed (#962) +* Fix pager not working in JRuby > 1.7.5 (#992) + +### 0.9.12.2 (2013/05/10) +* Make `reload-code` with no args reload "current" file (#920) + +### 0.9.12.1 (2013/04/21) +* Add workaround for JRuby crashing bug (#890) + * Related to http://jira.codehaus.org/browse/JRUBY-7114 + +### 0.9.12 (2013/02/12) +#### Features +* `pry --gem` (see 19bfc13aa) +* `show-source` now works on commands created with `create_command` +* `whereami` now has `-m` (method), `-c` (class), and `-f` (file) options +* `show-source` now falls back to superclass (and displays warning) if it + can't find class code +* `show-source`/`show-doc` now indicate when `-a` option is available + +#### Bug fixes, etc. +* Fix commands breaking due to Slop looking at `ARGV` instead of command + parameters (#828) +* Fix pager breaking in some situations (#845) +* Fix broken rendering of some docs (#795) +* Silence warnings during failed tab-completion attempts +* Fix broken prompt when prompt is colored (#822 / #823) +* Added `reload-method` as alias for `reload-code` (for backwards + compatibility) +* Reopen `Readline.output` if it is not a tty (see 1538bc0990) + +### 0.9.11.4 (2013/01/20) +* Fix pager not rendering color codes in some circumstances +* Add `Pry.last_internal_error`, useful for devs debugging commands + +### 0.9.11.3 (2013/01/17) +* Fix `Pry.run_command` +* Improve `ls` output +* Add `:requires_gem => "jist"` to `gist` command (so dependencies can be + installed via `install-command`) +* Improve help for `edit` command + +### 0.9.11.2 (2013/01/16) +* Fix minor bug in `gist` on Windows: rescue `Jist::ClipboardError` rather + than letting the scary error spill out to users and potentially having them + think the gist didn't post. + +### 0.9.11.1 (2013/01/16) +* Fix minor bug in `gist` command where I neglected to remove + a call to a non-existent method (`no_arg`) which was called when + `gist` is invoked with no parameters + +### 0.9.11 (2013/01/16) +#### Dependency changes +* Upgrade `slop` to `~> 3.4` +* New optional dependency: `bond` + * You'll need to perform `gem install bond` + * It improves autocompletion if you use Readline + * Does not work for libedit + (More info: https://github.com/pry/pry/wiki/FAQ#wiki-readline) + * Big thanks to cldwalker + +#### Features +* Basic Ruby 2.0 support (#738) +* JRuby 1.7.0+ support (#732) +* New `reload-code` command + * Reload code for methods, classes, commands, objects and so on + * Examples: `reload-code MyClass`, `reload-code my_method`, + `reload-code my_obj` +* Bond tab completion (see "Dependency changes") +* Consolidate "show" commands into `show-source` + * `show-source` can now extract source for: + * Classes + * Methods + * Procs + * Pry commands + * Arbitrary objects (it shows the source for the class of the object) + * As a result, `show-command` is now removed +* `gist`, `play`, and `save-file` now infer object type without requiring flags + * Examples: `play MyClass`, `play my_file.rb`, `play my_method` +* Consolidate editing commands into `edit` + * `edit` can now edit: + * Files + * Methods + * Classes + * Pry commands + * As a result, `edit-method` is now removed + * Examples: `edit MyClass`, `edit my_file.rb`, `edit my_method` +* `amend-line` and `play` now properly indent code added to input buffer +* Support for multiple require switches (`pry -rubygems -r./a.rb`) (#674) +* Support for multiple exec switches (`pry -e ':one' -e ':two'`) +* Ability to customize the name displayed in the prompt (#695) +* `--patch` switch for `edit --ex` command (#716) +* Respect the `$PAGER` environment variable (#736) +* `disable-pry` command (#497) +* Two new hooks, `before_eval` and `after_eval` +* Tab completion for `Array#` in `show-source` and `show-doc` +* `gem-install` immediately requires gems +* `-l` switch for `ls` command (displays local variables) +* `gem-open` command +* `fix-indent` command +* Subcommands API +* Public test API for plugin writers (see d1489a) +* Tabular `ls` output +* `--no-line-numbers` switch for `whereami` command +* `--lines` switch for `play` command + +#### Bug fixes, etc. +* Use single escape instead of double in `find-method` (#652) +* Fix blank string delimiters (#657) +* Fix unwanted `binding_impl_method` local in scratch bindings (#622) +* Fix `edit-method -p` changing constant lookup (#645) +* Fix `.pryrc` loading twice when invoked from `$HOME` directory (#682) +* Fix Pry not remembering initial `pwd` (#675) +* Fix multiline object coloring (#717) +* Fix `show-method` not supporting `String::new` notation (#719) +* Fix `whereami` command not showing correct line numbers (#754) +* Fix buggy Cucumber AST output (#751) +* Fix `while/until do` loops indentation (#787) +* Fix `--no-plugins` switch (#526) +* Ensure all errors go to the error handler (#774) +* Fix `.pryrc` loading with wrong `__FILE__` +* Fix pager not working if `less` is not available +* Fix `^D` in nested REPL +* Many small improvements to error message clarity and documentation formatting + +### 0.9.10 (2012/07/04) +#### Dependency changes +* Upgrade `slop` to version 3 (#561) +* Switch from `gist` gem to `jist` (#590) +* Upgrade `method_source` to 0.8 + +#### Features +* Add `--hist`, `-o` and `-k` flags to `gist` command (#572) +* Support `show-source`/`show-doc` on methods defined in `class_eval` (#584) +* Support `show-source`/`show-doc` on gem methods defined in C (#585) +* Add `--disable-plugin` and `--select-plugin` options (#596) +* Allow `cd -` to switch between bindings (#597) +* Add `Pry.config.should_load_local_rc` to turn off `./.pryrc` (#612) +* Allow running a file of Pry input with `pry ` +* Support colours in `ri` command +* Add `before_eval` hook +* The prompt proc now gets a lot more data when its arity is 1 + +#### Bug fixes, etc. +* Removed the `req` command (#554) +* Fix rendering bugs when starting Pry (#567) +* Fix `Array#pretty_print` on Jruby (#568) +* Fix `edit` on Windows (#575) +* Fix `find-method` in the presence of badly behaved objects (#576) +* Fix `whereami` in ERb files on Rails (#580) +* Raise fewer exceptions while tab completing (#632) +* Don't immediately quit Pry when an error happens in Readline (#605) +* Support for `ansicon` to give JRuby Windows users colour (#606) +* Massive speed improvements to `show-source` for modules (#613) +* Improve `whereami` command when not in a `binding.pry` (#620) +* Support embedded documents (`=begin` ... `=end`) (#622) +* Support editing files with spaces in the name (#627) +* Renamed `__binding_impl__` to `__pry__` +* Support for absolute paths in `$EDITOR` +* Fix `cat` command on files with unknown extensions +* Many, many internal refactorings and tidyings + +### 0.9.9.6 (2012/05/09) +* Fix `ZeroDivisionError` in `correct_indentation` (#558) + +### 0.9.9.5 (2012/05/09) +* Fix `ZeroDivisionError` in `correct_indentation` (#558) +* Fix double highlighting in RDoc (#562) +* Automatically create configuration for plugins (#548) + +### 0.9.9.4 (2012/04/26) +* Fix `NoMethodError: undefined method `winsize' for #>` (#549) +* Fixes for JRuby +* Fix syntax error on `exit` (550) +* Heredoc content no longer auto-indented + +### 0.9.9.3 (2012/04/19) +* Fix `show-doc` failing on some core classes, like `Bignum` + +### 0.9.9.2 (2012/04/18) +* Make `correct_indentation`'s auto-colorization respect `Pry.color` + +### 0.9.9.1 (2012/04/18) +* Clear up confusion in `show-source`/`show-doc` docs + * `-a` switch applies to classes as well as modules + +### 0.9.9 (2012/04/18) +#### New features +* Lines of input are syntax highlighted upon Enter keypress +* `show-source` command can now show class/module source code + * Use `-a` to see all monkeypatches + * Hard dependency on `ruby18_source_location` gem in MRI 1.8 +* `show-doc` command can now show class/module docs + * Use `-a` to see docs for all monkeypatches + * Hard dependency on `ruby18_source_location` gem in MRI 1.8 +* New `find-method` command + * Performs a recursive search in a namespace for the existence of methods + * Can find methods whose names match a regex or methods which contain + provided code + * This command is like a ruby-aware `grep`, very cool (thanks swarley) +* [`pry-coolline`](https://github.com/pry/pry-coolline) now works properly +* `alias_command` method now much more powerful + * Example: `alias_command "lM", "ls -M"` +* `whereami` is now more intelligent + * Automatically shows entire source code of current method if current + context is a method (thanks robgleeson) +* New `raise-up` command + * Allows you to raise an exception that will bubble out of pry (ending the + session) and escape into enclosing program + +#### Bug fixes, etc. +* Fixed crash when paging under Windows +* Lines ending with `\` are incomplete (kudos to fowl) +* `edit-method -n` no longer blocks (thanks misfo) +* Show instance methods of modules by default in `ls` +* Docs for REPL-defined methods can now be displayed using `show-doc` +* Autoload `ruby18_source_location` on MRI 1.8, when available + * See https://github.com/conradirwin/ruby18_source_location +* Tab completion should work on first line now (historic bug fixed) +* `:quiet => true` option added to `Pry.start`, turns off `whereami` +* Another easter egg added +* Show unloaded constants in yellow for `ls` +* Improved documentation for `Pry.config` options +* Improved auto-indentation +* JRuby: heuristics used to clean up `ls` output + * Fewer internal methods polluting output + +### 0.9.8.4 (2012/6/3) +* ~/.pry_history wasnt being created (if it did not exist)! FIXED +* `hist --save` saved colors! FIXED +* added Pry#add_sticky_local API for adding sticky locals to individual pry instances + +### 0.9.8.3 (2012/3/2) +* various tweaks to improve rbx support +* commands now support optional block arguments +* much improved help command +* updated method_source dependencya +* added wtf command +* jruby should now work in windows (though without color) + +### 0.9.8.2 (2012/2/9) +* fixed bugs related to --super +* upgraded slop dependency +* added edit -c (edit current line) +* edit now respects Pry.config.disable_autoreload option + +### 0.9.8.1 (2012/1/30) +* fixed broken --no-plugins option +* Ensure ARGV is not mutated during option parsing. +* Use a more rbx-friendly test for unicodeness +* Use rbx-{18,19}mode as indicated http://about.travis-ci.org/docs/user/languages/ruby/ +* Don't explode in gem-list [Fixes #453, #454] +* Check for command-name collision on assignment [Fixes #450] + +### 0.9.8 (2012/1/25) + +MAJOR NEW FEATURES +- upgraded command api, https://github.com/pry/pry/wiki/Custom-commands +- added a system of hooks for customizing pry behaviour +- changed syntax checking to use eval() for improved accuracy +- added save-file command +- added gist command (removed gist-method, new gist command is more general) + +complete CHANGELOG: +* CommandError's no longer cause the current input to be disgarded +* Better syntax highlighting for rbx code code +* added cat --in to show pry input history +* prefixed temporary file names with 'pry' +* show-doc now supports -l and -b options (line numbers) +* play now supports -i and -d options +* moved UserCommandAPI command-set to pry-developer_tools plugin +* added :when_started event for hooks, called in Pry.start +* added a man page +* added rename method to Pry::CommandSet (commands can be renamed) +* added CommandSet#{before_command,after_command} for enhancing builtin commands +* added checking for namespace collisions with pry commands, set Pry.config.collision_warning +* work around namespace collisions by ensuring lines starting with a space are executed as +* ruby.work around namespace collisions by prensuring lines starting with a space are executed as ruby +* added handlers for Ctrl+C (SIGINT) on jruby, these are now caught as in other ruby versions +* removed dependency on ruby_parser +* prevented colours leaking across the pry prompt +* fixed edge cases in Pry::Method, for methods with crazy names and methods that have been 'undef'd +* refactored history handling code for clarity and correctness +* added Pry::WrappedModule as a counterpart to Pry::Method +* made a trailing , cause pry to wait for further input +* removed gist-method command, added gist command +* added pry-backtrace command to show history of current session +* fixed whereami within 'super' methods +* replaced inline version guards by Pry::Helpers::BaseHelpers.{rbx?,jruby?,windows?} etc. +* removed the CommandProcessor, its functionality is part of the new Command class +* changed cd .. at the top level so it doesn't quit pry. +* changed edit-command to no-longer need a command set argument +* fixed empty lines so that they don't replace _ by nil +* fixed SyntaxErrors at the REPL level so they don't replace _ex_. + +### 0.9.7.4 (2011/11/5) +* ls -M now works in modules (bugfix) +* added exception msg for bad cd object/path +* no longer die when encounter exceptions in .pryrc +* baked in CoolLine support +* Pry.config.input in .pryrc now respected + +### 0.9.7.3 (2011/10/28) +* really fixed indentation for 'super if' and friends +* Fixed indentation for tmux +* added Pry.config.correct_indent option (to toggle whether indentation +* corrected optional param behaviour for method signatures: e.g Signature meth(param1=?, param2=?) + +### 0.9.7.2 (2011/10/27) +* fixed indentation for 'super if' and 'ensure', 'next if', etc +* refactored Pry#run_command so it can accept an eval_string parameter (so amend-line and so on can work with it) +* changed ^D so it no longer resets indent level automatically + +### 0.9.7.1 (2011/10/26) +* fixed gem dependecy issues + +### 0.9.7 (2011/10/25) + +MAJOR NEW FEATURES: +- upgraded ls command to have a more intuitive interface +- added automatic indentation (thanks YorickPeterse!) +- added Pry::Method wrapper class to encapsulate method-related functionality + +complete CHANGELOG: +* fixed syntax highlighting for object literals +* fixed ActiveSupport method-naming conflict with "in?" +* added --super option to edit-method, show-method, and friends - making it easier to operate on superclass methods +* officially added edit --in to open previous expressions in an editor +* whereami now works for REPL-defined code +* started using JRuby parser for input validation in JRuby (thanks pangloss!) +* fixed bug where ~/.pryrc could be loaded more than once (thanks kelseyjudson!) +* added parse_options! helper to pull option parsing out of commands +* Pry now respects the terminal's input encoding +* moved some requires out of the startup process for improved speed +* added input_array info to DEFAULT_PROMPT, e.g [1] pry(main)> +* added --no-history option to pry binary (prevent history being LOADED, history will still be saved) + +### 0.9.6.2 (2011/9/27) +* downgrading to CodeRay 0.9.8 due to problems with 1.0 and rails (autoloading problem) see #280 on pry and #6 on CodeRay +* also added (as a minor feature) cirwin's implementation of edit --in +* added early break/exit for objectpath errors (the 'cd 34/@hello/bad_path/23') + +### 0.9.6 (2011/9/19) +* restored previous behavior of command-line switches (allowing "-rfilename") +* removed -p option (--play) from edit command +* `edit` with no arguments now edits the current or most recent expression +* `edit` auto-reloads .rb files (need to specify -n to suppress) +* added -p option (--patch) to edit-method command, which allows + monkeypatching methods without touching the original file +* edit-method can now edit REPL-defined methods +* cat --ex now works on exceptions in REPL-defined code +* play -m now uses eval_string.replace() +* play -m --open uses show-input to show play'd code +* added "unindent" helper to make adding help to commands easier +* local ./.pryrc now loaded after ~/.pryrc if it exists +* cat --ex N and edit --ex N now can navigate through backtrace, where cat --ex (with no args) moves throuh successive levels of the backtrace automatically with state stored on the exceptino object itself +* new option Pry.config.exception_window_size determines window size for cat --ex +* input_stack now implemented - pushing objects onto a pry instance's input_stack causes the instance to read from those objects in turn as it encounters EOF on the previous object. On finishing the input_stack the input object for the pry instance is set back to Pry.config.input, if this fails, pry breaks out of the REPL (throw(:breakout)) with an error message +* Pry.config.system() defines how pry runs system commands +* now injecting target_self method into command scope +* play now performs 'show-input' always unless eval_string contains a valid expression (i.e it's about to be eval'd) +* play and hist --replay now push the current input object onto the input_stack before redirecting input to a StringIO (works much better with pry-remote now) + +### 0.9.5 (2011/9/8) + +MAJOR NEW FEATURES: +- JRuby support, including show-method/edit-method and editor integration on both 1.8 and 1.9 versions +- extended cd syntax: cd ../@x/y +- play command now works much better with _in_ array (this is a very powerful feature, esp with Pry::NAV_PROMPT) +- history saving/loading is now lightning fast +- 'edit' (entered by itself) now opens current lines in input buffer in an editor, and evals on exit +- 'edit' command is also, in general more intelligent +- ls output no longer in array format, and colors can be configured, e.g: Pry.config.ls.ivar_color = :bright_blue +- new switch-to command for moving around the binding stack without exiting out of sessions +- more sophisticated prompts, Pry::NAV_PROMPT to ease deep spelunking of code +- major bug fix for windows systems +- much better support for huge objects, should no longer hang pry (see #245) +- cat --ex and edit --ex now work better + +complete CHANGELOG: +* tempfile should end in .rb (for edit -t) +* ls output should not be in array format +* fix history saving (should not save all of Readline::HISTORY, but only what changed) +* prevent blank lines going to Readline::HISTORY (thanks cirwin!) +* ensure that cat --ex emulates the `whereami` format - includes line numbers and formatted the same, etc +* fixed bug #200 ( https://github.com/pry/pry/issues/200 )- string interpolation bug (thanks to ryanf) +* show-doc and stat now display method visibility (update WIKI) +* got rid of warnings caused by stricter ruby 1.9.3 rules +* remove interpolation of command names and fix interpolation error messag (update WIKI) (thanks ryanf!) +* 'nested sessions' now use binding stacks (so each instance manages its own collection of bindings without spawning other instances) +* 'cd ..' just pops a binding off the binding_stack with special behaviour when only one binding in stack - it breaks out of the repl loop +* added switch-to command (like jump-to but doesnt unwind the stack) +* show-method and show-doc now accept multiple method names +* control_d hook added (Pry.config.control_d_handler) +* behaviour of ^d is now to break out of current expr if in multi-line expr, or break out of current context if nested, or break out of pry repl loop if at top-level +* can no longer interpolate command name itself e.g #{x}-#{y} where x = "show" and y = "doc" +* ^C no longer captured +* got rid of Pry.active_instance, Pry.last_exception and friends. +* also special locals now shared among bindings in a pry instance (i.e _ex_ (and friends) re-injected into new binding entered with 'cd') +* renamed inp and out to _in_ and _out_ (to avoid collisions with actual locals in debugging scope) +* added third parameter to prompts, the pry instance itself (_pry) see https://github.com/pry/pry/issues/233 for why it's important +* cd behaviour when no args performs the same as `cd /` +* commands with keep_retval can now return nil (to suppress output now return 'void' instead) +* Pry::CommandProcessor::Result introduced +* Pry.view_clip() modified to be more robust and properly display Class#name +* edit command when invoked with no args now works like edit -t +* when edit is invoked (with no args or with -t) inside a multi-line expression input buffer, it dumps that buffer into a temp file and takes you to it +* got rid of Pry#null_input? since all that was needed was eval_string.empty? +* cd command now supports complex syntax: cd ../@y/y/../z +* JRuby is no longer a 2nd class citizen, almost full JRuby support, passing 100% tests +* added Pry::NAV_PROMPT (great new navigation prompt, per robgleeson) and Pry::SIMPLE_PRINT for simple (IRB-style) print output (just using inspect) +* _pry_ now passed as 3rd parameter to :before_session hook +* ls colors now configurable via Pry.config.ls.local_var_color = :bright_red etc +* ls separator configurable via, e.g Pry.config.ls.separator = " " +* Pry.view_clip() now only calls inspect on a few immediates, otherwise uses the #<> syntax, which has been truncated further to exclude teh mem address, again related to #245 + +### 0.9.3 (2011/7/27) +* cat --ex (cats 5 lines above and below line in file where exception was raised) +* edit --ex (edits line in file where exception was raised) +* edit -t (opens a temporary file and evals it in current context when closed) +* `pry -r` requires now happen after plugin loading (so as not to interfere with +* new Pry.config.disable_auto_reload option, for turning off auto reloading by edit-method and related (thanks ryanf) +* add better error messages for `cd` command +* fixed exotic object regression - BasicObject.new etc now return "=> unknown" +* added reload-method command (reloads the associated file of a method) +* converted: import => import-set, version => pry-version, install => install-command +* Pry.config.command_prefix support (thanks ryanf!) +* fixed indentation for simple-prompt +* hist command now excludes last line of input (the command invocation itself) +* hist now has `history` alias +* missing plugins no longer raise exception, just print a warning to $stderr +* fixed jedit editor support + +### 0.9.2 (2011/6/21) +* fixed string interpolation bug (caused valid ruby code not to execute, sorry!) +* fixed `ls` command, so it can properly display members of Object and classes, and BasicObject, etc +* added a few git related commands to experimental command set, blame and diff + +### 0.9.0 (2011/6/17) +* plugin system +* regex commands +* show-method works on methods defined in REPL +* new command system/API +* rubinius core support +* more backports to ruby 1.8 +* inp/out special locals +* _ex_ backtrace navigation object (_ex_.line, _ex_.file) +* readline history saving/loading +* prompt stack +* more hooks +* amend-line +* play +* show-input +* edit +* much more comprehensive test suite +* support for new and old rubygems API +* changed -s behaviour of ls (now excludes Object methods) +* removed eval-file, lls, lcd, and a few other commands + + +### 0.7.6.1 (2011/3/26) +* added slightly better support for YARD +* now @param and @return tags are colored green and markdown `code` is syntax highlighted using coderay + +### 0.7.6 (2011/3/26) +* `whereami` command now accepts parameter AROUND, to display AROUND lines on eitherside of invocation line. +* made it so `whereami` is invoked even if no method exists in current context (i.e in rspec tests) +* added rubinius support for `whereami` invocation in HOOKS by checking for __unknown__.rb rather than just
+ +### 0.7.0 (2011/3/15) +* add pry-doc support with syntax highlighting for docs +* add 'mj' option to ls (restrict to singleton methods) +* add _ex_ local to hold last exception raised in an exception + +### 0.6.8 (2011/3/6) +* add whereami command, a la the `ir_b` gem +* make whereami run at the start of every session +* make .pryrc be loaded by run-time pry sessions + +### 0.6.7 (2011/3/4) +* color support +* --simple-prompt for pry commandline +* -I mode for pry commandline +* --color mode for pry commandline +* clean up requires (put them all in one place) +* simple-prompt command and toggle-color commandd. + +### 0.6.3 (2011/2/28) +* Using MethodSource 0.3.4 so 1.8 show-method support provided +* `Set` class added to list of classes that are inspected + +### 0.6.1 (2011/2/26) +* !@ command alias for exit_all +* `cd /` for breaking out to pry top level (jump-to 0) +* made `-e` option work in a more effective way for `pry` command line invocation +* exit and exit-all commands now accept a parameter, this parameter becomes the return value of repl() +* `command` method from CommandBase now accepts a :keep_retval arg that determines if command value is returned to pry session or just `nil` (`nil` was old behaviour) +* tests for new :keep_retval and exit-all/exit behaviour; :keep_retval will remain undocumented. + +### 0.5.8 (2011/2/22) +* Added -c (context) option to show-doc, show-methods and eval-file +* Fixed up ordering issue of -c and -r parameters to command line pry + +### 0.5.7 (2011/2/21) +* Added pry executable, auto-loads .pryrc in user's home directory, if it + exists. + +### 0.5.5 (2011/2/19) +* Added Pry.run_command +* More useful error messages +* Easter eggs (game and cohen-poem) + +### 0.5.0 (2011/2/17) +* Use clipped version of Pry.view() for large objects +* Exit Pry session on ^d +* Use Shellwords for breaking up parameters to pry commands +* Use OptionParser to parse options for default pry commands +* Add version command +* Refactor 'status' command: add current method info +* Add meth_name_from_binding utility lambda to commands.rb +* Add -M, -m, -v(erbose), -a(ll), -s(uper), -l(ocals), -i(ivars), -k(klass + vars), etc options to ls +* add -M(instance method) options to show-method and show-doc +* add --help option to most commands +* Get rid of ls_method and ls_imethods (subsumed by more powerful ls) +* Get rid of show_idoc and show_imethod +* Add special eval-file command that evals target file in current context + +### 0.4.5 (2011/1/27) +* fixed show_method (though fragile as it references __binding_impl__ + directly, making a name change to that method difficult + +### 0.4.4 (2011/1/27) +* oops, added examples/ directory + +### 0.4.3 (2011/1/26) +* added alias_command and desc methods to Pry::CommandBase +* changed behaviour of ls_methods and ls_imethods to return sorted lists + of methods + +### 0.4.1 (2011/1/23) +* made it so a 'def meth;end' in an object Pry session defines singleton + methods, not methods on the class (except in the case of + immediates) +* reorganized documentation, moving customization to a separate wiki file +* storing wiki in a nested git repo, as github wiki pages have their own + repo +* added more tests for new method definition behaviour + +### 0.4.0 (2011/1/21) +* added command API +* added many new commands, i.e ls_methods and friends +* modified other commands +* now accepts greater customization, can modify: input, output, hooks, + prompt, print object +* added tab completion (even completes commands) +* added extensive tests +* added examples +* many more changes + +### 0.1.3 (2010/12/9) +* Got rid of rubygems dependency, refactored some code. + +### 0.1.2 (2010/12/8) +* now rescuing SyntaxError as well as Racc::Parser error in valid_expression? + +### 0.1.0 (2010/12/8) +* release! diff --git a/.bundle/gems/pry-0.10.2/LICENSE b/.bundle/gems/pry-0.10.2/LICENSE new file mode 100644 index 0000000..1258004 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/LICENSE @@ -0,0 +1,25 @@ +License +------- + +(The MIT License) + +Copyright (c) 2013 John Mair (banisterfiend) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/.bundle/gems/pry-0.10.2/README.md b/.bundle/gems/pry-0.10.2/README.md new file mode 100644 index 0000000..b42c87a --- /dev/null +++ b/.bundle/gems/pry-0.10.2/README.md @@ -0,0 +1,406 @@ +[![Build Status](https://img.shields.io/travis/pry/pry.svg)](https://travis-ci.org/pry/pry) +[![Code Climate](https://img.shields.io/codeclimate/github/pry/pry.svg)](https://codeclimate.com/github/pry/pry) +[![Inline docs](http://inch-ci.org/github/pry/pry.svg)](http://inch-ci.org/github/pry/pry) + +
+![The Pry Logo](https://dl.dropbox.com/u/26521875/pry%20stuff/logo/pry_logo_350.png) + +© John Mair ([banisterfiend](https://twitter.com/banisterfiend)) 2013
+ +**Please** [DONATE](http://www.pledgie.com/campaigns/15899) to the Pry project - Pry was a **huge** amount of work and every donation received is encouraging and supports Pry's continued development! + +**Sponsors** + +[Tealeaf Academy](http://www.gotealeaf.com)
+[Atomic Object](http://www.atomicobject.com/)
+[Hashrocket](http://hashrocket.com/)
+[Intridea](http://intridea.com/)
+[Gaslight](http://gaslight.co/home)
+ +**Other Resources** + +[Skip to the website (recommended)](http://pry.github.com)
+[Skip to the wiki](https://github.com/pry/pry/wiki) +
+ +Pry is a powerful alternative to the standard IRB shell for Ruby. It is +written from scratch to provide a number of advanced features, +including: + +* Source code browsing (including core C source with the pry-doc gem) +* Documentation browsing +* Live help system +* Open methods in editors (`edit Class#method`) +* Syntax highlighting +* Command shell integration (start editors, run git, and rake from within Pry) +* Gist integration +* Navigation around state (`cd`, `ls` and friends) +* Runtime invocation (use Pry as a developer console or debugger) +* Exotic object support (BasicObject instances, IClasses, ...) +* A Powerful and flexible command system +* Ability to view and replay history +* Many convenience commands inspired by IPython, Smalltalk and other advanced REPLs +* A wide-range number of [plugins](https://github.com/pry/pry/wiki/Available-plugins) that provide remote sessions, full debugging functionality, and more. + +Pry also aims to be more than an IRB replacement; it is an +attempt to bring REPL driven programming to the Ruby language. It is +currently not as powerful as tools like [SLIME](http://en.wikipedia.org/wiki/SLIME) for lisp, but that is the +general direction Pry is heading. + +Pry is also fairly flexible and allows significant user +[customization](https://github.com/pry/pry/wiki/Customization-and-configuration) +is trivial to set it to read from any object that has a `readline` method and write to any object that has a +`puts` method - many other aspects of Pry are also configurable making +it a good choice for implementing custom shells. + +Pry comes with an executable so it can be invoked at the command line. +Just enter `pry` to start. A `.pryrc` file in the user's home directory will +be loaded if it exists. Type `pry --help` at the command line for more +information. + +Try `gem install pry-doc` for additional documentation on Ruby Core +methods. The additional docs are accessed through the `show-doc` and +`show-method` commands. + +* Install the [gem](https://rubygems.org/gems/pry): `gem install pry` +* Browse the comprehensive [documentation at the official Pry wiki](https://github.com/pry/pry/wiki) +* Read the [YARD API documentation](http://rdoc.info/github/pry/pry/master/file/README.markdown) +* See the [source code](http://github.com/pry/pry) + +### Commands + +Nearly every piece of functionality in a Pry session is implemented as +a command. Commands are not methods and must start at the beginning of a line, with no +whitespace in between. Commands support a flexible syntax and allow +'options' in the same way as shell commands, for example the following +Pry command will show a list of all private instance methods (in +scope) that begin with 'pa' + + pry(YARD::Parser::SourceParser):5> ls -Mp --grep ^pa + YARD::Parser::SourceParser#methods: parse parser_class parser_type parser_type= parser_type_for_filename + +### Navigating around state + +Pry allows us to pop in and out of different scopes (objects) using +the `cd` command. This enables us to explore the run-time view of a +program or library. To view which variables and methods are available +within a particular scope we use the versatile [ls command.](https://gist.github.com/c0fc686ef923c8b87715) + +Here we will begin Pry at top-level, then Pry on a class and then on +an instance variable inside that class: + + pry(main)> class Hello + pry(main)* @x = 20 + pry(main)* end + => 20 + pry(main)> cd Hello + pry(Hello):1> ls -i + instance variables: @x + pry(Hello):1> cd @x + pry(20):2> self + 10 + => 30 + pry(20):2> cd .. + pry(Hello):1> cd .. + pry(main)> cd .. + +The number after the `:` in the pry prompt indicates the nesting +level. To display more information about nesting, use the `nesting` +command. E.g + + pry("friend"):3> nesting + Nesting status: + 0. main (Pry top level) + 1. Hello + 2. 100 + 3. "friend" + => nil + +We can then jump back to any of the previous nesting levels by using +the `jump-to` command: + + pry("friend"):3> jump-to 1 + => 100 + pry(Hello):1> + +### Runtime invocation + +Pry can be invoked in the middle of a running program. It opens a Pry +session at the point it's called and makes all program state at that +point available. It can be invoked on any object using the +`my_object.pry` syntax or on the current binding (or any binding) +using `binding.pry`. The Pry session will then begin within the scope +of the object (or binding). When the session ends the program continues with any +modifications you made to it. + +This functionality can be used for such things as: debugging, +implementing developer consoles and applying hot patches. + +code: + + # test.rb + require 'pry' + + class A + def hello() puts "hello world!" end + end + + a = A.new + + # start a REPL session + binding.pry + + # program resumes here (after pry session) + puts "program resumes here." + +Pry session: + + pry(main)> a.hello + hello world! + => nil + pry(main)> def a.goodbye + pry(main)* puts "goodbye cruel world!" + pry(main)* end + => nil + pry(main)> a.goodbye + goodbye cruel world! + => nil + pry(main)> exit + + program resumes here. + +### Command Shell Integration + +A line of input that begins with a '.' will be forwarded to the +command shell. This enables us to navigate the file system, spawn +editors, and run git and rake directly from within Pry. + +Further, we can use the `shell-mode` command to incorporate the +present working directory into the Pry prompt and bring in (limited at this stage, sorry) file name completion. +We can also interpolate Ruby code directly into the shell by +using the normal `#{}` string interpolation syntax. + +In the code below we're going to switch to `shell-mode` and edit the +`.pryrc` file in the home directory. We'll then cat its contents and +reload the file. + + pry(main)> shell-mode + pry main:/home/john/ruby/projects/pry $ .cd ~ + pry main:/home/john $ .emacsclient .pryrc + pry main:/home/john $ .cat .pryrc + def hello_world + puts "hello world!" + end + pry main:/home/john $ load ".pryrc" + => true + pry main:/home/john $ hello_world + hello world! + +We can also interpolate Ruby code into the shell. In the +example below we use the shell command `cat` on a random file from the +current directory and count the number of lines in that file with +`wc`: + + pry main:/home/john $ .cat #{Dir['*.*'].sample} | wc -l + 44 + +### Code Browsing + +You can browse method source code with the `show-method` command. Nearly all Ruby methods (and some C methods, with the pry-doc +gem) can have their source viewed. Code that is longer than a page is +sent through a pager (such as less), and all code is properly syntax +highlighted (even C code). + +The `show-method` command accepts two syntaxes, the typical ri +`Class#method` syntax and also simply the name of a method that's in +scope. You can optionally pass the `-l` option to show-method to +include line numbers in the output. + +In the following example we will enter the `Pry` class, list the +instance methods beginning with 're' and display the source code for the `rep` method: + + pry(main)> cd Pry + pry(Pry):1> ls -M --grep re + Pry#methods: re readline refresh rep repl repl_epilogue repl_prologue retrieve_line + pry(Pry):1> show-method rep -l + + From: /home/john/ruby/projects/pry/lib/pry/pry_instance.rb @ line 143: + Number of lines: 6 + + 143: def rep(target=TOPLEVEL_BINDING) + 144: target = Pry.binding_for(target) + 145: result = re(target) + 146: + 147: show_result(result) if should_print? + 148: end + +Note that we can also view C methods (from Ruby Core) using the +`pry-doc` plugin; we also show off the alternate syntax for +`show-method`: + + pry(main)> show-method Array#select + + From: array.c in Ruby Core (C Method): + Number of lines: 15 + + static VALUE + rb_ary_select(VALUE ary) + { + VALUE result; + long i; + + RETURN_ENUMERATOR(ary, 0, 0); + result = rb_ary_new2(RARRAY_LEN(ary)); + for (i = 0; i < RARRAY_LEN(ary); i++) { + if (RTEST(rb_yield(RARRAY_PTR(ary)[i]))) { + rb_ary_push(result, rb_ary_elt(ary, i)); + } + } + return result; + } + +### Documentation Browsing + +One use-case for Pry is to explore a program at run-time by `cd`-ing +in and out of objects and viewing and invoking methods. In the course +of exploring it may be useful to read the documentation for a +specific method that you come across. Like `show-method` the `show-doc` command supports +two syntaxes - the normal `ri` syntax as well as accepting the name of +any method that is currently in scope. + +The Pry documentation system does not rely on pre-generated `rdoc` or +`ri`, instead it grabs the comments directly above the method on +demand. This results in speedier documentation retrieval and allows +the Pry system to retrieve documentation for methods that would not be +picked up by `rdoc`. Pry also has a basic understanding of both the +rdoc and yard formats and will attempt to syntax highlight the +documentation appropriately. + +Nonetheless, the `ri` functionality is very good and +has an advantage over Pry's system in that it allows documentation +lookup for classes as well as methods. Pry therefore has good +integration with `ri` through the `ri` command. The syntax +for the command is exactly as it would be in command-line - +so it is not necessary to quote strings. + +In our example we will enter the `Gem` class and view the +documentation for the `try_activate` method: + + pry(main)> cd Gem + pry(Gem):1> show-doc try_activate + + From: /Users/john/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/site_ruby/1.9.1/rubygems.rb @ line 201: + Number of lines: 3 + + Try to activate a gem containing path. Returns true if + activation succeeded or wasn't needed because it was already + activated. Returns false if it can't find the path in a gem. + pry(Gem):1> + +We can also use `ri` in the normal way: + + pry(main) ri Array#each + ----------------------------------------------------------- Array#each + array.each {|item| block } -> array + ------------------------------------------------------------------------ + Calls _block_ once for each element in _self_, passing that element + as a parameter. + + a = [ "a", "b", "c" ] + a.each {|x| print x, " -- " } + + produces: + + a -- b -- c -- + +### Gist integration + +If the `gist` gem is installed then method source or documentation can be gisted to github with the +`gist` command. The `gist` command is capable of gisting [almost any REPL content](https://gist.github.com/cae143e4533416529726), including methods, documentation, +input expressions, command source, and so on. In the example below we will gist the C source +code for the `Symbol#to_proc` method to github: + + pry(main)> gist -m Symbol#to_proc + Gist created at https://gist.github.com/5332c38afc46d902ce46 and added to clipboard. + pry(main)> + +You can see the actual gist generated here: [https://gist.github.com/5332c38afc46d902ce46](https://gist.github.com/5332c38afc46d902ce46) + +### Edit methods + +You can use `edit Class#method` or `edit my_method` +(if the method is in scope) to open a method for editing directly in +your favorite editor. Pry has knowledge of a few different editors and +will attempt to open the file at the line the method is defined. + +You can set the editor to use by assigning to the `Pry.editor` +accessor. `Pry.editor` will default to `$EDITOR` or failing that will +use `nano` as the backup default. The file that is edited will be +automatically reloaded after exiting the editor - reloading can be +suppressed by passing the `--no-reload` option to `edit` + +In the example below we will set our default editor to "emacsclient" +and open the `Pry#repl` method for editing: + + pry(main)> Pry.editor = "emacsclient" + pry(main)> edit Pry#repl + +### Live Help System + +Many other commands are available in Pry; to see the full list type +`help` at the prompt. A short description of each command is provided +with basic instructions for use; some commands have a more extensive +help that can be accessed via typing `command_name --help`. A command +will typically say in its description if the `--help` option is +avaiable. + +### Use Pry as your Rails Console + +The recommended way to use Pry as your Rails console is to add +[the `pry-rails` gem](https://github.com/rweng/pry-rails) to +your Gemfile. This replaces the default console with Pry, in +addition to loading the Rails console helpers and adding some +useful Rails-specific commands. + +If you don't want to change your Gemfile, you can still run a Pry +console in your app's environment using Pry's `-r` flag: + + pry -r ./config/environment + +Also check out the [wiki](https://github.com/pry/pry/wiki/Setting-up-Rails-or-Heroku-to-use-Pry) +for more information about integrating Pry with Rails. + +### Limitations: + +* Tab completion is currently a bit broken/limited this will have a + major overhaul in a future version. + +### Syntax Highlighting + +Syntax highlighting is on by default in Pry. If you want to change +the colors, check out the [pry-theme](https://github.com/kyrylo/pry-theme) +gem. + +You can toggle the syntax highlighting on and off in a session by +using the `toggle-color` command. Alternatively, you can turn it off +permanently by putting the line `Pry.color = false` in your `~/.pryrc` +file. + +### Future Directions + +Many new features are planned such as: + +* Increase modularity (rely more on plugin system) +* Much improved documentation system, better support for YARD +* Better support for code and method reloading and saving code +* Extended and more sophisticated command system, allowing piping +between commands and running commands in background + +### Contact + +Problems or questions? file an issue at [github](https://github.com/pry/pry/issues) + +### Contributors + +Pry is primarily the work of [John Mair (banisterfiend)](http://github.com/banister), for full list +of contributors see the +[CONTRIBUTORS](https://github.com/pry/pry/blob/master/CONTRIBUTORS) file. diff --git a/.bundle/gems/pry-0.10.2/bin/pry b/.bundle/gems/pry-0.10.2/bin/pry new file mode 100755 index 0000000..3904fe9 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/bin/pry @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby + +# (C) John Mair (banisterfiend) +# MIT license + +$0 = 'pry' + +begin + require 'pry' +rescue LoadError + require 'rubygems' + require 'pry' +end + +# Process command line options and run Pry +Pry::CLI.parse_options diff --git a/.bundle/gems/pry-0.10.2/lib/pry.rb b/.bundle/gems/pry-0.10.2/lib/pry.rb new file mode 100644 index 0000000..a8e81c0 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry.rb @@ -0,0 +1,161 @@ +# (C) John Mair (banisterfiend) 2013 +# MIT License +# +require 'pp' + +require 'pry/input_lock' +require 'pry/exceptions' +require 'pry/helpers/base_helpers' +require 'pry/hooks' +require 'forwardable' + +class Pry + # The default hooks - display messages when beginning and ending Pry sessions. + DEFAULT_HOOKS = Pry::Hooks.new.add_hook(:before_session, :default) do |out, target, _pry_| + next if _pry_.quiet? + _pry_.run_command("whereami --quiet") + end + + # The default print + DEFAULT_PRINT = proc do |output, value, _pry_| + _pry_.pager.open do |pager| + pager.print _pry_.config.output_prefix + Pry::ColorPrinter.pp(value, pager, Pry::Terminal.width! - 1) + end + end + + # may be convenient when working with enormous objects and + # pretty_print is too slow + SIMPLE_PRINT = proc do |output, value| + begin + output.puts value.inspect + rescue RescuableException + output.puts "unknown" + end + end + + # useful when playing with truly enormous objects + CLIPPED_PRINT = proc do |output, value| + output.puts Pry.view_clip(value, id: true) + end + + # Will only show the first line of the backtrace + DEFAULT_EXCEPTION_HANDLER = proc do |output, exception, _| + if UserError === exception && SyntaxError === exception + output.puts "SyntaxError: #{exception.message.sub(/.*syntax error, */m, '')}" + else + output.puts "#{exception.class}: #{exception.message}" + output.puts "from #{exception.backtrace.first}" + end + end + + DEFAULT_PROMPT_NAME = 'pry' + + # The default prompt; includes the target and nesting level + DEFAULT_PROMPT = [ + proc { |target_self, nest_level, pry| + "[#{pry.input_array.size}] #{pry.config.prompt_name}(#{Pry.view_clip(target_self)})#{":#{nest_level}" unless nest_level.zero?}> " + }, + + proc { |target_self, nest_level, pry| + "[#{pry.input_array.size}] #{pry.config.prompt_name}(#{Pry.view_clip(target_self)})#{":#{nest_level}" unless nest_level.zero?}* " + } + ] + + DEFAULT_PROMPT_SAFE_OBJECTS = [String, Numeric, Symbol, nil, true, false] + + # A simple prompt - doesn't display target or nesting level + SIMPLE_PROMPT = [proc { ">> " }, proc { " | " }] + + NO_PROMPT = [proc { '' }, proc { '' }] + + SHELL_PROMPT = [ + proc { |target_self, _, _pry_| "#{_pry_.config.prompt_name} #{Pry.view_clip(target_self)}:#{Dir.pwd} $ " }, + proc { |target_self, _, _pry_| "#{_pry_.config.prompt_name} #{Pry.view_clip(target_self)}:#{Dir.pwd} * " } + ] + + # A prompt that includes the full object path as well as + # input/output (_in_ and _out_) information. Good for navigation. + NAV_PROMPT = [ + proc do |_, _, _pry_| + tree = _pry_.binding_stack.map { |b| Pry.view_clip(b.eval("self")) }.join " / " + "[#{_pry_.input_array.count}] (#{_pry_.config.prompt_name}) #{tree}: #{_pry_.binding_stack.size - 1}> " + end, + proc do |_, _, _pry_| + tree = _pry_.binding_stack.map { |b| Pry.view_clip(b.eval("self")) }.join " / " + "[#{_pry_.input_array.count}] (#{ _pry_.config.prompt_name}) #{tree}: #{_pry_.binding_stack.size - 1}* " + end, + ] + + # Deal with the ^D key being pressed. Different behaviour in different cases: + # 1. In an expression behave like `!` command. + # 2. At top-level session behave like `exit` command. + # 3. In a nested session behave like `cd ..`. + DEFAULT_CONTROL_D_HANDLER = proc do |eval_string, _pry_| + if !eval_string.empty? + eval_string.replace('') # Clear input buffer. + elsif _pry_.binding_stack.one? + _pry_.binding_stack.clear + throw(:breakout) + else + # Otherwise, saves current binding stack as old stack and pops last + # binding out of binding stack (the old stack still has that binding). + _pry_.command_state["cd"] ||= Pry::Config.from_hash({}) # FIXME + _pry_.command_state['cd'].old_stack = _pry_.binding_stack.dup + _pry_.binding_stack.pop + end + end + + DEFAULT_SYSTEM = proc do |output, cmd, _| + if !system(cmd) + output.puts "Error: there was a problem executing system command: #{cmd}" + end + end + + # Store the current working directory. This allows show-source etc. to work if + # your process has changed directory since boot. [Issue #675] + INITIAL_PWD = Dir.pwd + + # This is to keep from breaking under Rails 3.2 for people who are doing that + # IRB = Pry thing. + module ExtendCommandBundle; end +end + +require 'method_source' +require 'shellwords' +require 'stringio' +require 'coderay' +require 'slop' +require 'rbconfig' +require 'tempfile' +require 'pathname' + +require 'pry/version' +require 'pry/repl' +require 'pry/rbx_path' +require 'pry/code' +require 'pry/history_array' +require 'pry/helpers' +require 'pry/code_object' +require 'pry/method' +require 'pry/wrapped_module' +require 'pry/history' +require 'pry/command' +require 'pry/command_set' +require 'pry/commands' +require 'pry/plugins' +require 'pry/core_extensions' +require 'pry/pry_class' +require 'pry/pry_instance' +require 'pry/cli' +require 'pry/color_printer' +require 'pry/pager' +require 'pry/terminal' +require 'pry/editor' +require 'pry/rubygem' +require "pry/indent" +require "pry/last_exception" +require "pry/prompt" +require "pry/inspector" +require 'pry/object_path' +require 'pry/output' diff --git a/.bundle/gems/pry-0.10.2/lib/pry/cli.rb b/.bundle/gems/pry-0.10.2/lib/pry/cli.rb new file mode 100644 index 0000000..ef73869 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/cli.rb @@ -0,0 +1,220 @@ +class Pry + + # Manage the processing of command line options + class CLI + + NoOptionsError = Class.new(StandardError) + + class << self + + # @return [Proc] The Proc defining the valid command line options. + attr_accessor :options + + # @return [Array] The Procs that process the parsed options. Plugins can + # utilize this facility in order to add and process their own Pry + # options. + attr_accessor :option_processors + + # @return [Array] The input array of strings to process + # as CLI options. + attr_accessor :input_args + + # Add another set of CLI options (a Slop block) + def add_options(&block) + if options + old_options = options + self.options = proc do + instance_exec(&old_options) + instance_exec(&block) + end + else + self.options = block + end + + self + end + + # Bring in options defined in plugins + def add_plugin_options + Pry.plugins.values.each do |plugin| + plugin.load_cli_options + end + + self + end + + # Add a block responsible for processing parsed options. + def add_option_processor(&block) + self.option_processors ||= [] + option_processors << block + + self + end + + # Clear `options` and `option_processors` + def reset + self.options = nil + self.option_processors = nil + end + + def parse_options(args=ARGV) + unless options + raise NoOptionsError, "No command line options defined! Use Pry::CLI.add_options to add command line options." + end + + self.input_args = args + + begin + opts = Slop.parse!( + args, + :help => true, + :multiple_switches => false, + :strict => true, + &options + ) + rescue Slop::InvalidOptionError + # Display help message on unknown switches and exit. + puts Slop.new(&options) + exit + end + + # Option processors are optional. + if option_processors + option_processors.each { |processor| processor.call(opts) } + end + + self + end + + end + + reset + end +end + + +# String that is built to be executed on start (created by -e and -exec switches) +exec_string = "" + +# Bring in options defined by plugins +Slop.new do + on "no-plugins" do + Pry.config.should_load_plugins = false + end +end.parse(ARGV.dup) + +if Pry.config.should_load_plugins + Pry::CLI.add_plugin_options +end + +# The default Pry command line options (before plugin options are included) +Pry::CLI.add_options do + banner %{Usage: pry [OPTIONS] +Start a Pry session. +See http://pryrepl.org/ for more information. +Copyright (c) 2013 John Mair (banisterfiend) +-- +} + on :e, :exec=, "A line of code to execute in context before the session starts" do |input| + exec_string << input << "\n" + end + + on "no-pager", "Disable pager for long output" do + Pry.config.pager = false + end + + on "no-history", "Disable history loading" do + Pry.config.history.should_load = false + end + + on "no-color", "Disable syntax highlighting for session" do + Pry.config.color = false + end + + on :f, "Suppress loading of ~/.pryrc and ./.pryrc" do + Pry.config.should_load_rc = false + Pry.config.should_load_local_rc = false + end + + on :s, "select-plugin=", "Only load specified plugin (and no others)." do |plugin_name| + Pry.config.should_load_plugins = false + Pry.plugins[plugin_name].activate! + end + + on :d, "disable-plugin=", "Disable a specific plugin." do |plugin_name| + Pry.plugins[plugin_name].disable! + end + + on "no-plugins", "Suppress loading of plugins." do + Pry.config.should_load_plugins = false + end + + on "plugins", "List installed plugins." do + puts "Installed Plugins:" + puts "--" + Pry.locate_plugins.each do |plugin| + puts "#{plugin.name}".ljust(18) << plugin.spec.summary + end + exit + end + + on "simple-prompt", "Enable simple prompt mode" do + Pry.config.prompt = Pry::SIMPLE_PROMPT + end + + on "noprompt", "No prompt mode" do + Pry.config.prompt = Pry::NO_PROMPT + end + + on :r, :require=, "`require` a Ruby script at startup" do |file| + Pry.config.requires << file + end + + on :I=, "Add a path to the $LOAD_PATH", :as => Array, :delimiter => ":" do |load_path| + load_path.map! do |path| + /\A\.\// =~ path ? path : File.expand_path(path) + end + + $LOAD_PATH.unshift(*load_path) + end + + on "gem", "Shorthand for -I./lib -rgemname" do |load_path| + $LOAD_PATH.unshift("./lib") + Dir["./lib/*.rb"].each do |file| + Pry.config.requires << file + end + end + + on :v, :version, "Display the Pry version" do + puts "Pry version #{Pry::VERSION} on Ruby #{RUBY_VERSION}" + exit + end + + on(:c, :context=, + "Start the session in the specified context. Equivalent to `context.pry` in a session.", + :default => "Pry.toplevel_binding" + ) +end.add_option_processor do |opts| + + exit if opts.help? + + # invoked via cli + Pry.cli = true + + # create the actual context + if opts[:context] + Pry.initial_session_setup + context = Pry.binding_for(eval(opts[:context])) + else + context = Pry.toplevel_binding + end + + if Pry::CLI.input_args.any? && Pry::CLI.input_args != ["pry"] + full_name = File.expand_path(Pry::CLI.input_args.first) + Pry.load_file_through_repl(full_name) + exit + end + + # Start the session (running any code passed with -e, if there is any) + Pry.start(context, :input => StringIO.new(exec_string)) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/code.rb b/.bundle/gems/pry-0.10.2/lib/pry/code.rb new file mode 100644 index 0000000..f58189e --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/code.rb @@ -0,0 +1,346 @@ +require 'pry/code/loc' +require 'pry/code/code_range' +require 'pry/code/code_file' + +class Pry + class << self + # Convert the given object into an instance of `Pry::Code`, if it isn't + # already one. + # + # @param [Code, Method, UnboundMethod, Proc, Pry::Method, String, Array, + # IO] obj + def Code(obj) + case obj + when Code + obj + when ::Method, UnboundMethod, Proc, Pry::Method + Code.from_method(obj) + else + Code.new(obj) + end + end + end + + # `Pry::Code` is a class that encapsulates lines of source code and their + # line numbers and formats them for terminal output. It can read from a file + # or method definition or be instantiated with a `String` or an `Array`. + # + # In general, the formatting methods in `Code` return a new `Code` object + # which will format the text as specified when `#to_s` is called. This allows + # arbitrary chaining of formatting methods without mutating the original + # object. + class Code + class << self + include MethodSource::CodeHelpers + + # Instantiate a `Code` object containing code loaded from a file or + # Pry's line buffer. + # + # @param [String] filename The name of a file, or "(pry)". + # @param [Symbol] code_type The type of code the file contains. + # @return [Code] + def from_file(filename, code_type = nil) + code_file = CodeFile.new(filename, code_type) + new(code_file.code, 1, code_file.code_type) + end + + # Instantiate a `Code` object containing code extracted from a + # `::Method`, `UnboundMethod`, `Proc`, or `Pry::Method` object. + # + # @param [::Method, UnboundMethod, Proc, Pry::Method] meth The method + # object. + # @param [Integer, nil] start_line The line number to start on, or nil to + # use the method's original line numbers. + # @return [Code] + def from_method(meth, start_line = nil) + meth = Pry::Method(meth) + start_line ||= meth.source_line || 1 + new(meth.source, start_line, meth.source_type) + end + + # Attempt to extract the source code for module (or class) `mod`. + # + # @param [Module, Class] mod The module (or class) of interest. + # @param [Integer] candidate_rank The module candidate (by rank) + # to use (see `Pry::WrappedModule::Candidate` for more information). + # @param [Integer, nil] start_line The line number to start on, or nil to + # use the method's original line numbers. + # @return [Code] + def from_module(mod, candidate_rank = 0, start_line=nil) + candidate = Pry::WrappedModule(mod).candidate(candidate_rank) + start_line ||= candidate.line + new(candidate.source, start_line, :ruby) + end + end + + # @return [Symbol] The type of code stored in this wrapper. + attr_accessor :code_type + + # Instantiate a `Code` object containing code from the given `Array`, + # `String`, or `IO`. The first line will be line 1 unless specified + # otherwise. If you need non-contiguous line numbers, you can create an + # empty `Code` object and then use `#push` to insert the lines. + # + # @param [Array, String, IO] lines + # @param [Integer?] start_line + # @param [Symbol?] code_type + def initialize(lines = [], start_line = 1, code_type = :ruby) + if lines.is_a? String + lines = lines.lines + end + @lines = lines.each_with_index.map { |line, lineno| + LOC.new(line, lineno + start_line.to_i) } + @code_type = code_type + end + + # Append the given line. +lineno+ is one more than the last existing + # line, unless specified otherwise. + # + # @param [String] line + # @param [Integer?] lineno + # @return [String] The inserted line. + def push(line, lineno = nil) + if lineno.nil? + lineno = @lines.last.lineno + 1 + end + @lines.push(LOC.new(line, lineno)) + line + end + alias << push + + # Filter the lines using the given block. + # + # @yield [LOC] + # @return [Code] + def select(&block) + alter do + @lines = @lines.select(&block) + end + end + + # Remove all lines that aren't in the given range, expressed either as a + # `Range` object or a first and last line number (inclusive). Negative + # indices count from the end of the array of lines. + # + # @param [Range, Integer] start_line + # @param [Integer?] end_line + # @return [Code] + def between(start_line, end_line = nil) + return self unless start_line + + code_range = CodeRange.new(start_line, end_line) + + alter do + @lines = @lines[code_range.indices_range(@lines)] || [] + end + end + + # Take `num_lines` from `start_line`, forward or backwards. + # + # @param [Integer] start_line + # @param [Integer] num_lines + # @return [Code] + def take_lines(start_line, num_lines) + start_idx = + if start_line >= 0 + @lines.index { |loc| loc.lineno >= start_line } || @lines.length + else + [@lines.length + start_line, 0].max + end + + alter do + @lines = @lines.slice(start_idx, num_lines) + end + end + + # Remove all lines except for the +lines+ up to and excluding +lineno+. + # + # @param [Integer] lineno + # @param [Integer] lines + # @return [Code] + def before(lineno, lines = 1) + return self unless lineno + + select do |loc| + loc.lineno >= lineno - lines && loc.lineno < lineno + end + end + + # Remove all lines except for the +lines+ on either side of and including + # +lineno+. + # + # @param [Integer] lineno + # @param [Integer] lines + # @return [Code] + def around(lineno, lines = 1) + return self unless lineno + + select do |loc| + loc.lineno >= lineno - lines && loc.lineno <= lineno + lines + end + end + + # Remove all lines except for the +lines+ after and excluding +lineno+. + # + # @param [Integer] lineno + # @param [Integer] lines + # @return [Code] + def after(lineno, lines = 1) + return self unless lineno + + select do |loc| + loc.lineno > lineno && loc.lineno <= lineno + lines + end + end + + # Remove all lines that don't match the given `pattern`. + # + # @param [Regexp] pattern + # @return [Code] + def grep(pattern) + return self unless pattern + pattern = Regexp.new(pattern) + + select do |loc| + loc.line =~ pattern + end + end + + # Format output with line numbers next to it, unless `y_n` is falsy. + # + # @param [Boolean?] y_n + # @return [Code] + def with_line_numbers(y_n = true) + alter do + @with_line_numbers = y_n + end + end + + # Format output with a marker next to the given +lineno+, unless +lineno+ is + # falsy. + # + # @param [Integer?] lineno + # @return [Code] + def with_marker(lineno = 1) + alter do + @with_marker = !!lineno + @marker_lineno = lineno + end + end + + # Format output with the specified number of spaces in front of every line, + # unless `spaces` is falsy. + # + # @param [Integer?] spaces + # @return [Code] + def with_indentation(spaces = 0) + alter do + @with_indentation = !!spaces + @indentation_num = spaces + end + end + + # @return [String] + def inspect + Object.instance_method(:to_s).bind(self).call + end + + # @return [Integer] the number of digits in the last line. + def max_lineno_width + @lines.length > 0 ? @lines.last.lineno.to_s.length : 0 + end + + # @return [String] a formatted representation (based on the configuration of + # the object). + def to_s + print_to_output("", false) + end + + # @return [String] a (possibly highlighted) copy of the source code. + def highlighted + print_to_output("", true) + end + + # Writes a formatted representation (based on the configuration of the + # object) to the given output, which must respond to `#<<`. + def print_to_output(output, color=false) + @lines.each do |loc| + loc = loc.dup + loc.colorize(@code_type) if color + loc.add_line_number(max_lineno_width, color) if @with_line_numbers + loc.add_marker(@marker_lineno) if @with_marker + loc.indent(@indentation_num) if @with_indentation + output << loc.line + output << "\n" + end + output + end + + # Get the comment that describes the expression on the given line number. + # + # @param [Integer] line_number (1-based) + # @return [String] the code. + def comment_describing(line_number) + self.class.comment_describing(raw, line_number) + end + + # Get the multiline expression that starts on the given line number. + # + # @param [Integer] line_number (1-based) + # @return [String] the code. + def expression_at(line_number, consume = 0) + self.class.expression_at(raw, line_number, :consume => consume) + end + + # Get the (approximate) Module.nesting at the give line number. + # + # @param [Integer] line_number line number starting from 1 + # @param [Module] top_module the module in which this code exists + # @return [Array] a list of open modules. + def nesting_at(line_number, top_module = Object) + Pry::Indent.nesting_at(raw, line_number) + end + + # Return an unformatted String of the code. + # + # @return [String] + def raw + @lines.map(&:line).join("\n") << "\n" + end + + # Return the number of lines stored. + # + # @return [Integer] + def length + @lines ? @lines.length : 0 + end + + # Two `Code` objects are equal if they contain the same lines with the same + # numbers. Otherwise, call `to_s` and `chomp` and compare as Strings. + # + # @param [Code, Object] other + # @return [Boolean] + def ==(other) + if other.is_a?(Code) + other_lines = other.instance_variable_get(:@lines) + @lines.each_with_index.all? { |loc, i| loc == other_lines[i] } + else + to_s.chomp == other.to_s.chomp + end + end + + # Forward any missing methods to the output of `#to_s`. + def method_missing(name, *args, &block) + to_s.send(name, *args, &block) + end + undef =~ + + protected + + # An abstraction of the `dup.instance_eval` pattern used throughout this + # class. + def alter(&block) + dup.tap { |o| o.instance_eval(&block) } + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/code/code_file.rb b/.bundle/gems/pry-0.10.2/lib/pry/code/code_file.rb new file mode 100644 index 0000000..9ccb23b --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/code/code_file.rb @@ -0,0 +1,103 @@ +class Pry + class CodeFile + DEFAULT_EXT = '.rb' + + # List of all supported languages. + # @return [Hash] + EXTENSIONS = { + %w(.py) => :python, + %w(.js) => :javascript, + %w(.css) => :css, + %w(.xml) => :xml, + %w(.php) => :php, + %w(.html) => :html, + %w(.diff) => :diff, + %w(.java) => :java, + %w(.json) => :json, + %w(.c .h) => :c, + %w(.rhtml) => :rhtml, + %w(.yaml .yml) => :yaml, + %w(.cpp .hpp .cc .h cxx) => :cpp, + %w(.rb .ru .irbrc .gemspec .pryrc) => :ruby, + } + + # @return [Symbol] The type of code stored in this wrapper. + attr_reader :code_type + + # @param [String] filename The name of a file with code to be detected + # @param [Symbol] code_type The type of code the `filename` contains + def initialize(filename, code_type = type_from_filename(filename)) + @filename = filename + @code_type = code_type + end + + # @return [String] The code contained in the current `@filename`. + def code + if @filename == Pry.eval_path + Pry.line_buffer.drop(1) + elsif Pry::Method::Patcher.code_for(@filename) + Pry::Method::Patcher.code_for(@filename) + elsif RbxPath.is_core_path?(@filename) + File.read(RbxPath.convert_path_to_full(@filename)) + else + path = abs_path + @code_type = type_from_filename(path) + File.read(path) + end + end + + private + + # @raise [MethodSource::SourceNotFoundError] if the `filename` is not + # readable for some reason. + # @return [String] absolute path for the given `filename`. + def abs_path + code_path.detect { |path| readable?(path) } or + raise MethodSource::SourceNotFoundError, + "Cannot open #{ @filename.inspect } for reading." + end + + # @param [String] path + # @return [Boolean] if the path, with or without the default ext, + # is a readable file then `true`, otherwise `false`. + def readable?(path) + File.readable?(path) && !File.directory?(path) or + File.readable?(path << DEFAULT_EXT) + end + + # @return [Array] All the paths that contain code that Pry can use for its + # API's. Skips directories. + def code_path + [from_pwd, from_pry_init_pwd, *from_load_path] + end + + # @param [String] filename + # @param [Symbol] default (:unknown) the file type to assume if none could be + # detected. + # @return [Symbol, nil] The CodeRay type of a file from its extension, or + # `nil` if `:unknown`. + def type_from_filename(filename, default = :unknown) + _, @code_type = EXTENSIONS.find do |k, _| + k.any? { |ext| ext == File.extname(filename) } + end + + code_type || default + end + + # @return [String] + def from_pwd + File.expand_path(@filename, Dir.pwd) + end + + # @return [String] + def from_pry_init_pwd + File.expand_path(@filename, Pry::INITIAL_PWD) + end + + # @return [String] + def from_load_path + $LOAD_PATH.map { |path| File.expand_path(@filename, path) } + end + + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/code/code_range.rb b/.bundle/gems/pry-0.10.2/lib/pry/code/code_range.rb new file mode 100644 index 0000000..043be02 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/code/code_range.rb @@ -0,0 +1,71 @@ +class Pry + class Code + + # Represents a range of lines in a code listing. + # + # @api private + class CodeRange + + # @param [Integer] start_line + # @param [Integer?] end_line + def initialize(start_line, end_line = nil) + @start_line = start_line + @end_line = end_line + force_set_end_line + end + + # @param [Array] lines + # @return [Range] + def indices_range(lines) + Range.new(*indices(lines)) + end + + private + + def start_line; @start_line; end + def end_line; @end_line; end + + # If `end_line` is equal to `nil`, then calculate it from the first + # parameter, `start_line`. Otherwise, leave it as it is. + # @return [void] + def force_set_end_line + if start_line.is_a?(Range) + set_end_line_from_range + else + @end_line ||= start_line + end + end + + # Finds indices of `start_line` and `end_line` in the given Array of + # +lines+. + # + # @param [Array] lines + # @return [Array] + def indices(lines) + [find_start_index(lines), find_end_index(lines)] + end + + # @return [Integer] + def find_start_index(lines) + return start_line if start_line < 0 + lines.index { |loc| loc.lineno >= start_line } || lines.length + end + + # @return [Integer] + def find_end_index(lines) + return end_line if end_line < 0 + (lines.index { |loc| loc.lineno > end_line } || 0) - 1 + end + + # For example, if the range is 4..10, then `start_line` would be equal to + # 4 and `end_line` to 10. + # @return [void] + def set_end_line_from_range + @end_line = start_line.last + @end_line -= 1 if start_line.exclude_end? + @start_line = start_line.first + end + end + + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/code/loc.rb b/.bundle/gems/pry-0.10.2/lib/pry/code/loc.rb new file mode 100644 index 0000000..905c704 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/code/loc.rb @@ -0,0 +1,92 @@ +class Pry + class Code + + # Represents a line of code. A line of code is a tuple, which consists of a + # line and a line number. A `LOC` object's state (namely, the line + # parameter) can be changed via instance methods. `Pry::Code` heavily uses + # this class. + # + # @api private + # @example + # loc = LOC.new("def example\n :example\nend", 1) + # puts loc.line + # def example + # :example + # end + # #=> nil + # + # loc.indent(3) + # loc.line #=> " def example\n :example\nend" + class LOC + + # @return [Array] + attr_reader :tuple + + # @param [String] line The line of code. + # @param [Integer] lineno The position of the +line+. + def initialize(line, lineno) + @tuple = [line.chomp, lineno.to_i] + end + + # @return [Boolean] + def ==(other) + other.tuple == tuple + end + + def dup + self.class.new(line, lineno) + end + + # @return [String] + def line + tuple.first + end + + # @return [Integer] + def lineno + tuple.last + end + + # Paints the `line` of code. + # + # @param [Symbol] code_type + # @return [void] + def colorize(code_type) + tuple[0] = CodeRay.scan(line, code_type).term + end + + # Prepends the line number `lineno` to the `line`. + # + # @param [Integer] max_width + # @return [void] + def add_line_number(max_width = 0, color = false) + padded = lineno.to_s.rjust(max_width) + colorized_lineno = color ? Pry::Helpers::BaseHelpers.colorize_code(padded) : padded + tuple[0] = "#{ colorized_lineno }: #{ line }" + end + + # Prepends a marker "=>" or an empty marker to the +line+. + # + # @param [Integer] marker_lineno If it is equal to the `lineno`, then + # prepend a hashrocket. Otherwise, an empty marker. + # @return [void] + def add_marker(marker_lineno) + tuple[0] = + if lineno == marker_lineno + " => #{ line }" + else + " #{ line }" + end + end + + # Indents the `line` with +distance+ spaces. + # + # @param [Integer] distance + # @return [void] + def indent(distance) + tuple[0] = "#{ ' ' * distance }#{ line }" + end + end + + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/code_object.rb b/.bundle/gems/pry-0.10.2/lib/pry/code_object.rb new file mode 100644 index 0000000..11a3aa6 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/code_object.rb @@ -0,0 +1,172 @@ +class Pry + + # This class is responsible for taking a string (identifying a + # command/class/method/etc) and returning the relevant type of object. + # For example, if the user looks up "show-source" then a + # `Pry::Command` will be returned. Alternatively, if the user passes in "Pry#repl" then + # a `Pry::Method` object will be returned. + # + # The `CodeObject.lookup` method is responsible for 1. figuring out what kind of + # object the user wants (applying precedence rules in doing so -- i.e methods + # get precedence over commands with the same name) and 2. Returning + # the appropriate object. If the user fails to provide a string + # identifer for the object (i.e they pass in `nil` or "") then the + # object looked up will be the 'current method' or 'current class' + # associated with the Binding. + # + # TODO: This class is a clusterfuck. We need a much more robust + # concept of what a "Code Object" really is. Currently + # commands/classes/candidates/methods and so on just share a very + # ill-defined interface. + class CodeObject + module Helpers + # we need this helper as some Pry::Method objects can wrap Procs + # @return [Boolean] + def real_method_object? + is_a?(::Method) || is_a?(::UnboundMethod) + end + + def c_method? + real_method_object? && source_type == :c + end + + def module_with_yard_docs? + is_a?(WrappedModule) && yard_docs? + end + + def command? + is_a?(Module) && self <= Pry::Command + end + end + + include Pry::Helpers::CommandHelpers + + class << self + def lookup(str, _pry_, options={}) + co = new(str, _pry_, options) + + co.default_lookup || co.method_or_class_lookup || + co.command_lookup || co.empty_lookup + end + end + + attr_accessor :str + attr_accessor :target + attr_accessor :_pry_ + attr_accessor :super_level + + def initialize(str, _pry_, options={}) + options = { + :super => 0, + }.merge!(options) + + @str = str + @_pry_ = _pry_ + @target = _pry_.current_context + @super_level = options[:super] + end + + def command_lookup + # TODO: just make it so find_command_by_match_or_listing doesn't + # raise? + _pry_.commands.find_command_by_match_or_listing(str) rescue nil + end + + # when no paramter is given (i.e CodeObject.lookup(nil)), then we + # lookup the 'current object' from the binding. + def empty_lookup + return nil if str && !str.empty? + + obj = if internal_binding?(target) + mod = target_self.is_a?(Module) ? target_self : target_self.class + Pry::WrappedModule(mod) + else + Pry::Method.from_binding(target) + end + + # respect the super level (i.e user might have specified a + # --super flag to show-source) + lookup_super(obj, super_level) + end + + # lookup variables and constants and `self` that are not modules + def default_lookup + + # we skip instance methods as we want those to fall through to method_or_class_lookup() + if safe_to_evaluate?(str) && !looks_like_an_instance_method?(str) + obj = target.eval(str) + + # restrict to only objects we KNOW for sure support the full API + # Do NOT support just any object that responds to source_location + if sourcable_object?(obj) + Pry::Method(obj) + elsif !obj.is_a?(Module) + Pry::WrappedModule(obj.class) + else + nil + end + end + + rescue Pry::RescuableException + nil + end + + def method_or_class_lookup + obj = case str + when /\S+\(\)\z/ + Pry::Method.from_str(str.sub(/\(\)\z/, ''),target) || Pry::WrappedModule.from_str(str, target) + else + Pry::WrappedModule.from_str(str,target) || Pry::Method.from_str(str, target) + end + + lookup_super(obj, super_level) + end + + private + + def sourcable_object?(obj) + [::Proc, ::Method, ::UnboundMethod].any? { |o| obj.is_a?(o) } + end + + # Returns true if `str` looks like a method, i.e Klass#method + # We need to consider this case because method lookups should fall + # through to the `method_or_class_lookup()` method but a + # defined?() on a "Klass#method` string will see the `#` as a + # comment and only evaluate the `Klass` part. + # @param [String] str + # @return [Boolean] Whether the string looks like an instance method. + def looks_like_an_instance_method?(str) + str =~ /\S#\S/ + end + + # We use this method to decide whether code is safe to eval. Method's are + # generally not, but everything else is. + # TODO: is just checking != "method" enough?? + # TODO: see duplication of this method in Pry::WrappedModule + # @param [String] str The string to lookup + # @return [Boolean] + def safe_to_evaluate?(str) + return true if str.strip == "self" + kind = target.eval("defined?(#{str})") + kind =~ /variable|constant/ + end + + def target_self + target.eval('self') + end + + # grab the nth (`super_level`) super of `obj + # @param [Object] obj + # @param [Fixnum] super_level How far up the super chain to ascend. + def lookup_super(obj, super_level) + return nil if !obj + + sup = obj.super(super_level) + if !sup + raise Pry::CommandError, "No superclass found for #{obj.wrapped}" + else + sup + end + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/color_printer.rb b/.bundle/gems/pry-0.10.2/lib/pry/color_printer.rb new file mode 100644 index 0000000..218a821 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/color_printer.rb @@ -0,0 +1,55 @@ +# PP subclass for streaming inspect output in color. +class Pry + class ColorPrinter < ::PP + OBJ_COLOR = begin + code = CodeRay::Encoders::Terminal::TOKEN_COLORS[:keyword] + if code.start_with? "\e" + code + else + "\e[0m\e[0;#{code}m" + end + end + + CodeRay::Encoders::Terminal::TOKEN_COLORS[:comment][:self] = "\e[1;34m" + + def self.pp(obj, out = $>, width = 79) + q = ColorPrinter.new(out, width) + q.guard_inspect_key { q.pp obj } + q.flush + out << "\n" + end + + def text(str, width = str.length) + # Don't recolorize output with color [Issue #751] + if str.include?("\e[") + super "#{str}\e[0m", width + elsif str.start_with?('#<') || str == '=' || str == '>' + super highlight_object_literal(str), width + else + super CodeRay.scan(str, :ruby).term, width + end + end + + def pp(obj) + super + rescue => e + raise if e.is_a? Pry::Pager::StopPaging + + # Read the class name off of the singleton class to provide a default + # inspect. + singleton = class << obj; self; end + ancestors = Pry::Method.safe_send(singleton, :ancestors) + klass = ancestors.reject { |k| k == singleton }.first + obj_id = obj.__id__.to_s(16) rescue 0 + str = "#<#{klass}:0x#{obj_id}>" + + text highlight_object_literal(str) + end + + private + + def highlight_object_literal(object_literal) + "#{OBJ_COLOR}#{object_literal}\e[0m" + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/command.rb b/.bundle/gems/pry-0.10.2/lib/pry/command.rb new file mode 100644 index 0000000..0cf334f --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/command.rb @@ -0,0 +1,692 @@ +require 'delegate' +require 'pry/helpers/documentation_helpers' + +class Pry + + # The super-class of all commands, new commands should be created by calling + # {Pry::CommandSet#command} which creates a BlockCommand or {Pry::CommandSet#create_command} + # which creates a ClassCommand. Please don't use this class directly. + class Command + extend Helpers::DocumentationHelpers + extend CodeObject::Helpers + + # represents a void return value for a command + VOID_VALUE = Object.new + + # give it a nice inspect + def VOID_VALUE.inspect() "void" end + + # Properties of the command itself (as passed as arguments to + # {CommandSet#command} or {CommandSet#create_command}). + class << self + attr_writer :block + attr_writer :description + attr_writer :command_options + attr_writer :match + + def match(arg=nil) + if arg + @command_options ||= default_options(arg) + @command_options[:listing] = arg.is_a?(String) ? arg : arg.inspect + @match = arg + end + @match ||= nil + end + + # Define or get the command's description + def description(arg=nil) + @description = arg if arg + @description ||= nil + end + + # Define or get the command's options + def command_options(arg=nil) + @command_options ||= default_options(match) + @command_options.merge!(arg) if arg + @command_options + end + # backward compatibility + alias_method :options, :command_options + alias_method :options=, :command_options= + + # Define or get the command's banner + def banner(arg=nil) + @banner = arg if arg + @banner || description + end + + def block + @block || instance_method(:process) + end + + def source + file, line = block.source_location + strip_leading_whitespace(Pry::Code.from_file(file).expression_at(line)) + end + + def doc + new.help + end + + def source_location + block.source_location + end + + def source_file + Array(block.source_location).first + end + alias_method :file, :source_file + + def source_line + Array(block.source_location).last + end + alias_method :line, :source_line + + def default_options(match) + { + :requires_gem => [], + :keep_retval => false, + :argument_required => false, + :interpolate => true, + :shellwords => true, + :listing => (String === match ? match : match.inspect), + :use_prefix => true, + :takes_block => false + } + end + end + + # Make those properties accessible to instances + def name; self.class.name; end + def match; self.class.match; end + def description; self.class.description; end + def block; self.class.block; end + def command_options; self.class.options; end + def command_name; self.class.command_name; end + def source; self.class.source; end + def source_location; self.class.source_location; end + + class << self + def name + super.to_s == "" ? "#" : super + end + + def inspect + name + end + + def command_name + self.options[:listing] + end + + # Create a new command with the given properties. + # @param [String, Regex] match The thing that triggers this command + # @param [String] description The description to appear in `help` + # @param [Hash] options Behavioral options (see {Pry::CommandSet#command}) + # @param [Module] helpers A module of helper functions to be included. + # @yield optional, used for BlockCommands + # @return [Class] (a subclass of {Pry::Command}) + def subclass(match, description, options, helpers, &block) + klass = Class.new(self) + klass.send(:include, helpers) + klass.match = match + klass.description = description + klass.command_options = options + klass.block = block + klass + end + + # Should this command be called for the given line? + # @param [String] val A line input at the REPL + # @return [Boolean] + def matches?(val) + command_regex =~ val + end + + # How well does this command match the given line? + # + # Higher scores are better because they imply that this command matches + # the line more closely. + # + # The score is calculated by taking the number of characters at the start + # of the string that are used only to identify the command, not as part of + # the arguments. + # + # @example + # /\.(.*)/.match_score(".foo") #=> 1 + # /\.*(.*)/.match_score("...foo") #=> 3 + # 'hi'.match_score("hi there") #=> 2 + # + # @param [String] val A line input at the REPL + # @return [Fixnum] + def match_score(val) + if command_regex =~ val + Regexp.last_match.size > 1 ? Regexp.last_match.begin(1) : Regexp.last_match.end(0) + else + -1 + end + end + + # Store hooks to be run before or after the command body. + # @see {Pry::CommandSet#before_command} + # @see {Pry::CommandSet#after_command} + def hooks + @hooks ||= {:before => [], :after => []} + end + + def command_regex + pr = Pry.respond_to?(:config) ? Pry.config.command_prefix : "" + prefix = convert_to_regex(pr) + prefix = "(?:#{prefix})?" unless options[:use_prefix] + + /^#{prefix}#{convert_to_regex(match)}(?!\S)/ + end + + def convert_to_regex(obj) + case obj + when String + Regexp.escape(obj) + else + obj + end + end + + # The group in which the command should be displayed in "help" output. + # This is usually auto-generated from directory naming, but it can be + # manually overridden if necessary. + # Group should not be changed once it is initialized. + def group(name=nil) + @group ||= if name + name + else + case Pry::Method(block).source_file + when %r{/pry/.*_commands/(.*).rb} + $1.capitalize.gsub(/_/, " ") + when %r{(pry-\w+)-([\d\.]+([\w\.]+)?)} + name, version = $1, $2 + "#{name.to_s} (v#{version.to_s})" + when /pryrc/ + "~/.pryrc" + else + "(other)" + end + end + end + end + + # Properties of one execution of a command (passed by {Pry#run_command} as a hash of + # context and expanded in `#initialize` + attr_accessor :output + attr_accessor :target + attr_accessor :captures + attr_accessor :eval_string + attr_accessor :arg_string + attr_accessor :context + attr_accessor :command_set + attr_accessor :_pry_ + + # The block we pass *into* a command so long as `:takes_block` is + # not equal to `false` + # @example + # my-command | do + # puts "block content" + # end + attr_accessor :command_block + + # Run a command from another command. + # @param [String] command_string The string that invokes the command + # @param [Array] args Further arguments to pass to the command + # @example + # run "show-input" + # @example + # run ".ls" + # @example + # run "amend-line", "5", 'puts "hello world"' + def run(command_string, *args) + command_string = _pry_.config.command_prefix.to_s + command_string + complete_string = "#{command_string} #{args.join(" ")}".rstrip + command_set.process_line(complete_string, context) + end + + def commands + command_set.to_hash + end + + def text + Pry::Helpers::Text + end + + def void + VOID_VALUE + end + + include Pry::Helpers::BaseHelpers + include Pry::Helpers::CommandHelpers + + # Instantiate a command, in preparation for calling it. + # @param [Hash] context The runtime context to use with this command. + def initialize(context={}) + self.context = context + self.target = context[:target] + self.output = context[:output] + self.eval_string = context[:eval_string] + self.command_set = context[:command_set] + self._pry_ = context[:pry_instance] + end + + # @return [Object] The value of `self` inside the `target` binding. + def target_self; target.eval('self'); end + + # @return [Hash] Pry commands can store arbitrary state + # here. This state persists between subsequent command invocations. + # All state saved here is unique to the command, it does not + # need to be namespaced. + # @example + # state.my_state = "my state" # this will not conflict with any + # # `state.my_state` used in another command. + def state + _pry_.command_state[match] ||= Pry::Config.from_hash({}) + end + + # Revaluate the string (str) and perform interpolation. + # @param [String] str The string to reevaluate with interpolation. + # + # @return [String] The reevaluated string with interpolations + # applied (if any). + def interpolate_string(str) + dumped_str = str.dump + if dumped_str.gsub!(/\\\#\{/, '#{') + target.eval(dumped_str) + else + str + end + end + + # Display a warning if a command collides with a local/method in + # the current scope. + def check_for_command_collision(command_match, arg_string) + collision_type = target.eval("defined?(#{command_match})") + collision_type ||= 'local-variable' if arg_string.match(%r{\A\s*[-+*/%&|^]*=}) + + if collision_type + output.puts "#{text.bold('WARNING:')} Calling Pry command '#{command_match}', which conflicts with a #{collision_type}.\n\n" + end + rescue Pry::RescuableException + end + + # Extract necessary information from a line that Command.matches? this + # command. + # + # Returns an array of four elements: + # + # ``` + # [String] the portion of the line that matched with the Command match + # [String] a string of all the arguments (i.e. everything but the match) + # [Array] the captures caught by the command_regex + # [Array] the arguments obtained by splitting the arg_string + # ``` + # + # @param [String] val The line of input + # @return [Array] + def tokenize(val) + val.replace(interpolate_string(val)) if command_options[:interpolate] + + self.class.command_regex =~ val + + # please call Command.matches? before Command#call_safely + raise CommandError, "fatal: called a command which didn't match?!" unless Regexp.last_match + captures = Regexp.last_match.captures + pos = Regexp.last_match.end(0) + + arg_string = val[pos..-1] + + # remove the one leading space if it exists + arg_string.slice!(0) if arg_string.start_with?(" ") + + # process and pass a block if one is found + pass_block(arg_string) if command_options[:takes_block] + + if arg_string + args = command_options[:shellwords] ? Shellwords.shellwords(arg_string) : arg_string.split(" ") + else + args = [] + end + + [val[0..pos].rstrip, arg_string, captures, args] + end + + # Process a line that Command.matches? this command. + # @param [String] line The line to process + # @return [Object, Command::VOID_VALUE] + def process_line(line) + command_match, arg_string, captures, args = tokenize(line) + + check_for_command_collision(command_match, arg_string) if Pry.config.collision_warning + + self.arg_string = arg_string + self.captures = captures + + call_safely(*(captures + args)) + end + + # Pass a block argument to a command. + # @param [String] arg_string The arguments (as a string) passed to the command. + # We inspect these for a '| do' or a '| {' and if we find it we use it + # to start a block input sequence. Once we have a complete + # block, we save it to an accessor that can be retrieved from the command context. + # Note that if we find the '| do' or '| {' we delete this and the + # elements following it from `arg_string`. + def pass_block(arg_string) + # Workaround for weird JRuby bug where rindex in this case can return nil + # even when there's a match. + arg_string.scan(/\| *(?:do|\{)/) + block_index = $~ && $~.offset(0)[0] + + return if !block_index + + block_init_string = arg_string.slice!(block_index..-1)[1..-1] + prime_string = "proc #{block_init_string}\n" + + if !Pry::Code.complete_expression?(prime_string) + block_string = _pry_.r(target, prime_string) + else + block_string = prime_string + end + + begin + self.command_block = target.eval(block_string) + rescue Pry::RescuableException + raise CommandError, "Incomplete block definition." + end + end + + private :pass_block + + # Run the command with the given `args`. + # + # This is a public wrapper around `#call` which ensures all preconditions + # are met. + # + # @param [Array] args The arguments to pass to this command. + # @return [Object] The return value of the `#call` method, or + # {Command::VOID_VALUE}. + def call_safely(*args) + unless dependencies_met? + gems_needed = Array(command_options[:requires_gem]) + gems_not_installed = gems_needed.select { |g| !Rubygem.installed?(g) } + output.puts "\nThe command '#{command_name}' is #{text.bold("unavailable")} because it requires the following gems to be installed: #{(gems_not_installed.join(", "))}" + output.puts "-" + output.puts "Type `install-command #{command_name}` to install the required gems and activate this command." + return void + end + + if command_options[:argument_required] && args.empty? + raise CommandError, "The command '#{command_name}' requires an argument." + end + + ret = call_with_hooks(*args) + command_options[:keep_retval] ? ret : void + end + + # Are all the gems required to use this command installed? + # + # @return Boolean + def dependencies_met? + @dependencies_met ||= command_dependencies_met?(command_options) + end + + # Generate completions for this command + # + # @param [String] search The line typed so far + # @return [Array] Completion words + def complete(search) + [] + end + + private + + # Run the `#call` method and all the registered hooks. + # @param [Array] args The arguments to `#call` + # @return [Object] The return value from `#call` + def call_with_hooks(*args) + self.class.hooks[:before].each do |block| + instance_exec(*args, &block) + end + + ret = call(*args) + + self.class.hooks[:after].each do |block| + ret = instance_exec(*args, &block) + end + + ret + end + + # Fix the number of arguments we pass to a block to avoid arity warnings. + # @param [Fixnum] arity The arity of the block + # @param [Array] args The arguments to pass + # @return [Array] A (possibly shorter) array of the arguments to pass + def correct_arg_arity(arity, args) + case + when arity < 0 + args + when arity == 0 + [] + when arity > 0 + args.values_at(*(0..(arity - 1)).to_a) + end + end + end + + # A super-class for Commands that are created with a single block. + # + # This class ensures that the block is called with the correct number of arguments + # and the right context. + # + # Create subclasses using {Pry::CommandSet#command}. + class BlockCommand < Command + # backwards compatibility + alias_method :opts, :context + + # Call the block that was registered with this command. + # @param [Array] args The arguments passed + # @return [Object] The return value of the block + def call(*args) + instance_exec(*correct_arg_arity(block.arity, args), &block) + end + + def help + "#{command_options[:listing].to_s.ljust(18)} #{description}" + end + end + + # A super-class of Commands with structure. + # + # This class implements the bare-minimum functionality that a command should + # have, namely a --help switch, and then delegates actual processing to its + # subclasses. + # + # Create subclasses using {Pry::CommandSet#create_command}, and override the + # `options(opt)` method to set up an instance of Slop, and the `process` + # method to actually run the command. If necessary, you can also override + # `setup` which will be called before `options`, for example to require any + # gems your command needs to run, or to set up state. + class ClassCommand < Command + class << self + + # Ensure that subclasses inherit the options, description and + # match from a ClassCommand super class. + def inherited(klass) + klass.match match + klass.description description + klass.command_options options + end + + def source + source_object.source + end + + def doc + new.help + end + + def source_location + source_object.source_location + end + + def source_file + source_object.source_file + end + alias_method :file, :source_file + + def source_line + source_object.source_line + end + alias_method :line, :source_line + + private + + # The object used to extract the source for the command. + # + # This should be a `Pry::Method(block)` for a command made with `create_command` + # and a `Pry::WrappedModule(self)` for a command that's a standard class. + # @return [Pry::WrappedModule, Pry::Method] + def source_object + @source_object ||= if name =~ /^[A-Z]/ + Pry::WrappedModule(self) + else + Pry::Method(block) + end + end + end + + attr_accessor :opts + attr_accessor :args + + # Set up `opts` and `args`, and then call `process`. + # + # This method will display help if necessary. + # + # @param [Array] args The arguments passed + # @return [Object] The return value of `process` or VOID_VALUE + def call(*args) + setup + + self.opts = slop + self.args = self.opts.parse!(args) + + if opts.present?(:help) + output.puts slop.help + void + else + process(*correct_arg_arity(method(:process).arity, args)) + end + end + + # Return the help generated by Slop for this command. + def help + slop.help + end + + # Return an instance of Slop that can parse either subcommands or the + # options that this command accepts. + def slop + Slop.new do |opt| + opt.banner(unindent(self.class.banner)) + subcommands(opt) + options(opt) + opt.on :h, :help, 'Show this message.' + end + end + + # Generate shell completions + # @param [String] search The line typed so far + # @return [Array] the words to complete + def complete(search) + slop.map do |opt| + [opt.long && "--#{opt.long} " || opt.short && "-#{opt.short}"] + end.flatten(1).compact + super + end + + # A method called just before `options(opt)` as part of `call`. + # + # This method can be used to set up any context your command needs to run, + # for example requiring gems, or setting default values for options. + # + # @example + # def setup + # require 'gist' + # @action = :method + # end + def setup; end + + # A method to setup Slop commands so it can parse the subcommands your + # command expects. If you need to set up default values, use `setup` + # instead. + # + # @example A minimal example + # def subcommands(cmd) + # cmd.command :download do |opt| + # description 'Downloads a content from a server' + # + # opt.on :verbose, 'Use verbose output' + # + # run do |options, arguments| + # ContentDownloader.download(options, arguments) + # end + # end + # end + # + # @example Define the invokation block anywhere you want + # def subcommands(cmd) + # cmd.command :download do |opt| + # description 'Downloads a content from a server' + # + # opt.on :verbose, 'Use verbose output' + # end + # end + # + # def process + # # Perform calculations... + # opts.fetch_command(:download).run do |options, arguments| + # ContentDownloader.download(options, arguments) + # end + # # More calculations... + # end + def subcommands(cmd); end + + # A method to setup Slop so it can parse the options your command expects. + # + # @note Please don't do anything side-effecty in the main part of this + # method, as it may be called by Pry at any time for introspection reasons. + # If you need to set up default values, use `setup` instead. + # + # @example + # def options(opt) + # opt.banner "Gists methods or classes" + # opt.on(:c, :class, "gist a class") do + # @action = :class + # end + # end + def options(opt); end + + # The actual body of your command should go here. + # + # The `opts` mehod can be called to get the options that Slop has passed, + # and `args` gives the remaining, unparsed arguments. + # + # The return value of this method is discarded unless the command was + # created with `:keep_retval => true`, in which case it is returned to the + # repl. + # + # @example + # def process + # if opts.present?(:class) + # gist_class + # else + # gist_method + # end + # end + def process; raise CommandError, "command '#{command_name}' not implemented" end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/command_set.rb b/.bundle/gems/pry-0.10.2/lib/pry/command_set.rb new file mode 100644 index 0000000..9483ab0 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/command_set.rb @@ -0,0 +1,443 @@ +class Pry + class NoCommandError < StandardError + def initialize(match, owner) + super "Command '#{match}' not found in command set #{owner}" + end + end + + # This class is used to create sets of commands. Commands can be imported from + # different sets, aliased, removed, etc. + class CommandSet + include Enumerable + include Pry::Helpers::BaseHelpers + attr_reader :helper_module + + # @param [Array] imported_sets + # Sets which will be imported automatically + # @yield Optional block run to define commands + def initialize(*imported_sets, &block) + @commands = {} + @helper_module = Module.new + import(*imported_sets) + instance_eval(&block) if block + end + + # Defines a new Pry command. + # @param [String, Regexp] match The start of invocations of this command. + # @param [String] description A description of the command. + # @param [Hash] options The optional configuration parameters. + # @option options [Boolean] :keep_retval Whether or not to use return value + # of the block for return of `command` or just to return `nil` + # (the default). + # @option options [Array] :requires_gem Whether the command has + # any gem dependencies, if it does and dependencies not met then + # command is disabled and a stub proc giving instructions to + # install command is provided. + # @option options [Boolean] :interpolate Whether string #{} based + # interpolation is applied to the command arguments before + # executing the command. Defaults to true. + # @option options [String] :listing The listing name of the + # command. That is the name by which the command is looked up by + # help and by show-command. Necessary for commands with regex matches. + # @option options [Boolean] :use_prefix Whether the command uses + # `Pry.config.command_prefix` prefix (if one is defined). Defaults + # to true. + # @option options [Boolean] :shellwords Whether the command's arguments + # should be split using Shellwords instead of just split on spaces. + # Defaults to true. + # @yield The action to perform. The parameters in the block + # determines the parameters the command will receive. All + # parameters passed into the block will be strings. Successive + # command parameters are separated by whitespace at the Pry prompt. + # @example + # MyCommands = Pry::CommandSet.new do + # command "greet", "Greet somebody" do |name| + # puts "Good afternoon #{name.capitalize}!" + # end + # end + # + # # From pry: + # # pry(main)> _pry_.commands = MyCommands + # # pry(main)> greet john + # # Good afternoon John! + # # pry(main)> help greet + # # Greet somebody + # @example Regexp command + # MyCommands = Pry::CommandSet.new do + # command /number-(\d+)/, "number-N regex command", :listing => "number" do |num, name| + # puts "hello #{name}, nice number: #{num}" + # end + # end + # + # # From pry: + # # pry(main)> _pry_.commands = MyCommands + # # pry(main)> number-10 john + # # hello john, nice number: 10 + # # pry(main)> help number + # # number-N regex command + def block_command(match, description="No description.", options={}, &block) + description, options = ["No description.", description] if description.is_a?(Hash) + options = Pry::Command.default_options(match).merge!(options) + + @commands[match] = Pry::BlockCommand.subclass(match, description, options, helper_module, &block) + end + alias_method :command, :block_command + + # Defines a new Pry command class. + # + # @param [String, Regexp] match The start of invocations of this command. + # @param [String] description A description of the command. + # @param [Hash] options The optional configuration parameters, see {#command} + # @yield The class body's definition. + # + # @example + # Pry::Commands.create_command "echo", "echo's the input", :shellwords => false do + # def options(opt) + # opt.banner "Usage: echo [-u | -d] " + # opt.on :u, :upcase, "ensure the output is all upper-case" + # opt.on :d, :downcase, "ensure the output is all lower-case" + # end + # + # def process + # raise Pry::CommandError, "-u and -d makes no sense" if opts.present?(:u) && opts.present?(:d) + # result = args.join(" ") + # result.downcase! if opts.present?(:downcase) + # result.upcase! if opts.present?(:upcase) + # output.puts result + # end + # end + # + def create_command(match, description="No description.", options={}, &block) + description, options = ["No description.", description] if description.is_a?(Hash) + options = Pry::Command.default_options(match).merge!(options) + + @commands[match] = Pry::ClassCommand.subclass(match, description, options, helper_module, &block) + @commands[match].class_eval(&block) + @commands[match] + end + + # Execute a block of code before a command is invoked. The block also + # gets access to parameters that will be passed to the command and + # is evaluated in the same context. + # @param [String, Regexp] search The match or listing of the command. + # @yield The block to be run before the command. + # @example Display parameter before invoking command + # Pry.config.commands.before_command("whereami") do |n| + # output.puts "parameter passed was #{n}" + # end + def before_command(search, &block) + cmd = find_command_by_match_or_listing(search) + cmd.hooks[:before].unshift block + end + + # Execute a block of code after a command is invoked. The block also + # gets access to parameters that will be passed to the command and + # is evaluated in the same context. + # @param [String, Regexp] search The match or listing of the command. + # @yield The block to be run after the command. + # @example Display text 'command complete' after invoking command + # Pry.config.commands.after_command("whereami") do |n| + # output.puts "command complete!" + # end + def after_command(search, &block) + cmd = find_command_by_match_or_listing(search) + cmd.hooks[:after] << block + end + + def each(&block) + @commands.each(&block) + end + + # Removes some commands from the set + # @param [Array] searches the matches or listings of the commands to remove + def delete(*searches) + searches.each do |search| + cmd = find_command_by_match_or_listing(search) + @commands.delete cmd.match + end + end + + # Imports all the commands from one or more sets. + # @param [Array] sets Command sets, all of the commands of which + # will be imported. + # @return [Pry::CommandSet] Returns the reciever (a command set). + def import(*sets) + sets.each do |set| + @commands.merge! set.to_hash + helper_module.send :include, set.helper_module + end + self + end + + # Imports some commands from a set + # @param [CommandSet] set Set to import commands from + # @param [Array] matches Commands to import + # @return [Pry::CommandSet] Returns the reciever (a command set). + def import_from(set, *matches) + helper_module.send :include, set.helper_module + matches.each do |match| + cmd = set.find_command_by_match_or_listing(match) + @commands[cmd.match] = cmd + end + self + end + + # @param [String, Regexp] match_or_listing The match or listing of a command. + # of the command to retrieve. + # @return [Command] The command object matched. + def find_command_by_match_or_listing(match_or_listing) + cmd = (@commands[match_or_listing] || + Pry::Helpers::BaseHelpers.find_command(match_or_listing, @commands)) + cmd or raise ArgumentError, "Cannot find a command: '#{match_or_listing}'!" + end + + # Aliases a command + # @param [String, Regex] match The match of the alias (can be a regex). + # @param [String] action The action to be performed (typically + # another command). + # @param [Hash] options The optional configuration parameters, + # accepts the same as the `command` method, but also allows the + # command description to be passed this way too as `:desc` + # @example Creating an alias for `ls -M` + # Pry.config.commands.alias_command "lM", "ls -M" + # @example Pass explicit description (overriding default). + # Pry.config.commands.alias_command "lM", "ls -M", :desc => "cutiepie" + def alias_command(match, action, options={}) + cmd = find_command(action) or fail "Command: `#{action}` not found" + original_options = cmd.options.dup + + options = original_options.merge!({ + :desc => "Alias for `#{action}`", + :listing => match + }).merge!(options) + + # ensure default description is used if desc is nil + desc = options.delete(:desc).to_s + + c = block_command match, desc, options do |*args| + run action, *args + end + + c.class_eval do + define_method(:complete) do |input| + cmd.new(context).complete(input) + end + end + + c.group "Aliases" + + c + end + + # Rename a command. Accepts either match or listing for the search. + # + # @param [String, Regexp] new_match The new match for the command. + # @param [String, Regexp] search The command's current match or listing. + # @param [Hash] options The optional configuration parameters, + # accepts the same as the `command` method, but also allows the + # command description to be passed this way too. + # @example Renaming the `ls` command and changing its description. + # Pry.config.commands.rename "dir", "ls", :description => "DOS friendly ls" + def rename_command(new_match, search, options={}) + cmd = find_command_by_match_or_listing(search) + + options = { + :listing => new_match, + :description => cmd.description + }.merge!(options) + + @commands[new_match] = cmd.dup + @commands[new_match].match = new_match + @commands[new_match].description = options.delete(:description) + @commands[new_match].options.merge!(options) + @commands.delete(cmd.match) + end + + def disabled_command(name_of_disabled_command, message, matcher=name_of_disabled_command) + create_command name_of_disabled_command do + match matcher + description "" + + define_method(:process) do + output.puts "DISABLED: #{message}" + end + end + end + + # Sets or gets the description for a command (replacing the old + # description). Returns current description if no description + # parameter provided. + # @param [String, Regexp] search The command match. + # @param [String?] description (nil) The command description. + # @example Setting + # MyCommands = Pry::CommandSet.new do + # desc "help", "help description" + # end + # @example Getting + # Pry.config.commands.desc "amend-line" + def desc(search, description=nil) + cmd = find_command_by_match_or_listing(search) + return cmd.description if !description + + cmd.description = description + end + + # Defines helpers methods for this command sets. + # Those helpers are only defined in this command set. + # + # @yield A block defining helper methods + # @example + # helpers do + # def hello + # puts "Hello!" + # end + # + # include OtherModule + # end + def helpers(&block) + helper_module.class_eval(&block) + end + + + # @return [Array] + # The list of commands provided by the command set. + def list_commands + @commands.keys + end + alias_method :keys, :list_commands + + def to_hash + @commands.dup + end + alias_method :to_h, :to_hash + + # Find a command that matches the given line + # @param [String] pattern The line that might be a command invocation + # @return [Pry::Command, nil] + def [](pattern) + @commands.values.select do |command| + command.matches?(pattern) + end.sort_by do |command| + command.match_score(pattern) + end.last + end + alias_method :find_command, :[] + + # + # Re-assign the command found at _pattern_ with _command_. + # + # @param [Regexp, String] pattern + # The command to add or replace(found at _pattern_). + # + # @param [Pry::Command] command + # The command to add. + # + # @return [Pry::Command] + # Returns the new command (matched with "pattern".) + # + # @example + # Pry.config.commands["help"] = MyHelpCommand + # + def []=(pattern, command) + if command.equal?(nil) + return @commands.delete(pattern) + end + unless Class === command && command < Pry::Command + raise TypeError, "command is not a subclass of Pry::Command" + end + bind_command_to_pattern = pattern != command.match + if bind_command_to_pattern + command_copy = command.dup + command_copy.match = pattern + @commands[pattern] = command_copy + else + @commands[pattern] = command + end + end + + # + # Add a command to set. + # + # @param [Command] command + # a subclass of Pry::Command. + # + def add_command(command) + self[command.match] = command + end + + # Find the command that the user might be trying to refer to. + # @param [String] search The user's search. + # @return [Pry::Command?] + def find_command_for_help(search) + find_command(search) || (begin + find_command_by_match_or_listing(search) + rescue ArgumentError + nil + end) + end + + # Is the given line a command invocation? + # @param [String] val + # @return [Boolean] + def valid_command?(val) + !!find_command(val) + end + + # Process the given line to see whether it needs executing as a command. + # @param [String] val The line to execute + # @param [Hash] context The context to execute the commands with + # @return [CommandSet::Result] + def process_line(val, context={}) + if command = find_command(val) + context = context.merge(:command_set => self) + retval = command.new(context).process_line(val) + Result.new(true, retval) + else + Result.new(false) + end + end + + # @private (used for testing) + def run_command(context, match, *args) + command = @commands[match] or raise NoCommandError.new(match, self) + command.new(context).call_safely(*args) + end + + # Generate completions for the user's search. + # @param [String] search The line to search for + # @param [Hash] context The context to create the command with + # @return [Array] + def complete(search, context={}) + if command = find_command(search) + command.new(context).complete(search) + else + @commands.keys.select do |key| + String === key && key.start_with?(search) + end.map{ |key| key + " " } + end + end + end + + # Wraps the return result of process_commands, indicates if the + # result IS a command and what kind of command (e.g void) + class Result + attr_reader :retval + + def initialize(is_command, retval = nil) + @is_command, @retval = is_command, retval + end + + # Is the result a command? + # @return [Boolean] + def command? + @is_command + end + + # Is the result a command and if it is, is it a void command? + # (one that does not return a value) + # @return [Boolean] + def void_command? + retval == Command::VOID_VALUE + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands.rb new file mode 100644 index 0000000..4b85ada --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands.rb @@ -0,0 +1,6 @@ +# Default commands used by Pry. +Pry::Commands = Pry::CommandSet.new + +Dir[File.expand_path('../commands', __FILE__) << '/*.rb'].each do |file| + require file +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/amend_line.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/amend_line.rb new file mode 100644 index 0000000..d30c9a0 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/amend_line.rb @@ -0,0 +1,99 @@ +class Pry + class Command::AmendLine < Pry::ClassCommand + match(/amend-line(?: (-?\d+)(?:\.\.(-?\d+))?)?/) + group 'Editing' + description 'Amend a line of input in multi-line mode.' + command_options :interpolate => false, :listing => 'amend-line' + + banner <<-'BANNER' + Amend a line of input in multi-line mode. `amend-line N`, where the N represents + line to replace. Can also specify a range of lines using `amend-line N..M` + syntax. Passing "!" as replacement content deletes the line(s) instead. + + amend-line 1 puts 'new' # replace line 1 + amend-line 1..4 ! # delete lines 1..4 + amend-line 3 >puts 'bye' # insert before line 3 + amend-line puts 'appended' # no line number modifies immediately preceding line + BANNER + + def process + raise CommandError, "No input to amend." if eval_string.empty? + + eval_string.replace amended_input(eval_string) + run "fix-indent" + run "show-input" + end + + private + + # @param [String] string The string to amend. + # @return [String] A new string with the amendments applied to it. + def amended_input(string) + input_array = eval_string.each_line.to_a + + if arg_string == "!" + delete_from_array(input_array, line_range) + elsif arg_string.start_with?(">") + insert_into_array(input_array, line_range) + else + replace_in_array(input_array, line_range) + end + + input_array.join + end + + def delete_from_array(array, range) + array.slice!(range) + end + + def insert_into_array(array, range) + insert_slot = Array(range).first + array.insert(insert_slot, arg_string[1..-1] << "\n") + end + + def replace_in_array(array, range) + array[range] = arg_string + "\n" + end + + # @return [Fixnum] The number of lines currently in `eval_string` (the input buffer). + def line_count + eval_string.lines.count + end + + # Returns the (one-indexed) start and end lines given by the user. + # The lines in this range will be affected by the `amend-line`. + # Returns `nil` if no lines were specified by the user. + # @return [Array, nil] + def start_and_end_line_number + start_line_number, end_line_number = args + end_line_number ||= start_line_number.to_i + + [start_line_number.to_i, end_line_number.to_i] if start_line_number + end + + # Takes two numbers that are 1-indexed, and returns a range (or + # number) that is 0-indexed. 1-indexed means the first element is + # indentified by 1 rather than by 0 (as is the case for Ruby arrays). + # @param [Fixnum] start_line_number One-indexed number. + # @param [Fixnum] end_line_number One-indexed number. + # @return [Range] The zero-indexed range. + def zero_indexed_range_from_one_indexed_numbers(start_line_number, end_line_number) + # FIXME: one_index_number is a horrible name for this method + one_index_number(start_line_number)..one_index_number(end_line_number) + end + + # The lines (or line) that will be modified by the `amend-line`. + # @return [Range, Fixnum] The lines or line. + def line_range + start_line_number, end_line_number = start_and_end_line_number + if start_line_number + zero_indexed_range_from_one_indexed_numbers(start_line_number, + end_line_number) + else + line_count - 1 + end + end + end + + Pry::Commands.add_command(Pry::Command::AmendLine) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/bang.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/bang.rb new file mode 100644 index 0000000..8843458 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/bang.rb @@ -0,0 +1,20 @@ +class Pry + class Command::Bang < Pry::ClassCommand + match(/^\s*!\s*$/) + group 'Editing' + description 'Clear the input buffer.' + command_options :use_prefix => false + + banner <<-'BANNER' + Clear the input buffer. Useful if the parsing process goes wrong and you get + stuck in the read loop. + BANNER + + def process + output.puts 'Input buffer cleared!' + eval_string.replace('') + end + end + + Pry::Commands.add_command(Pry::Command::Bang) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/bang_pry.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/bang_pry.rb new file mode 100644 index 0000000..71f81ef --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/bang_pry.rb @@ -0,0 +1,17 @@ +class Pry + class Command::BangPry < Pry::ClassCommand + match '!pry' + group 'Navigating Pry' + description 'Start a Pry session on current self.' + + banner <<-'BANNER' + Start a Pry session on current self. Also works mid multi-line expression. + BANNER + + def process + target.pry + end + end + + Pry::Commands.add_command(Pry::Command::BangPry) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/cat.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/cat.rb new file mode 100644 index 0000000..8ca537f --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/cat.rb @@ -0,0 +1,62 @@ +class Pry + class Command::Cat < Pry::ClassCommand + require 'pry/commands/cat/abstract_formatter.rb' + require 'pry/commands/cat/input_expression_formatter.rb' + require 'pry/commands/cat/exception_formatter.rb' + require 'pry/commands/cat/file_formatter.rb' + + match 'cat' + group 'Input and Output' + description "Show code from a file, Pry's input buffer, or the last exception." + + banner <<-'BANNER' + Usage: cat FILE + cat --ex [STACK_INDEX] + cat --in [INPUT_INDEX_OR_RANGE] + + `cat` is capable of showing part or all of a source file, the context of the + last exception, or an expression from Pry's input history. + + `cat --ex` defaults to showing the lines surrounding the location of the last + exception. Invoking it more than once travels up the exception's backtrace, and + providing a number shows the context of the given index of the backtrace. + BANNER + + def options(opt) + opt.on :ex, "Show the context of the last exception", :optional_argument => true, :as => Integer + opt.on :i, :in, "Show one or more entries from Pry's expression history", :optional_argument => true, :as => Range, :default => -5..-1 + opt.on :s, :start, "Starting line (defaults to the first line)", :optional_argument => true, :as => Integer + opt.on :e, :end, "Ending line (defaults to the last line)", :optional_argument => true, :as => Integer + opt.on :l, :'line-numbers', "Show line numbers" + opt.on :t, :type, "The file type for syntax highlighting (e.g., 'ruby' or 'python')", :argument => true, :as => Symbol + end + + def process + output = case + when opts.present?(:ex) + ExceptionFormatter.new(_pry_.last_exception, _pry_, opts).format + when opts.present?(:in) + InputExpressionFormatter.new(_pry_.input_array, opts).format + else + FileFormatter.new(args.first, _pry_, opts).format + end + + _pry_.pager.page output + end + + def complete(search) + super | load_path_completions + end + + def load_path_completions + $LOAD_PATH.flat_map do |path| + Dir[path + '/**/*'].map { |f| + next if File.directory?(f) + f.sub!(path + '/', '') + } + end + end + end + + Pry::Commands.add_command(Pry::Command::Cat) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/cat/abstract_formatter.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/cat/abstract_formatter.rb new file mode 100644 index 0000000..c554647 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/cat/abstract_formatter.rb @@ -0,0 +1,27 @@ +class Pry + class Command::Cat + class AbstractFormatter + include Pry::Helpers::CommandHelpers + include Pry::Helpers::BaseHelpers + + private + def decorate(content) + content.code_type = code_type + content.between(*between_lines). + with_line_numbers(use_line_numbers?).highlighted + end + + def code_type + opts[:type] || :ruby + end + + def use_line_numbers? + opts.present?(:'line-numbers') || opts.present?(:ex) + end + + def between_lines + [opts[:start] || 1, opts[:end] || -1] + end + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/cat/exception_formatter.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/cat/exception_formatter.rb new file mode 100644 index 0000000..af10e9d --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/cat/exception_formatter.rb @@ -0,0 +1,77 @@ +class Pry + class Command::Cat + class ExceptionFormatter < AbstractFormatter + attr_reader :ex + attr_reader :opts + attr_reader :_pry_ + + def initialize(exception, _pry_, opts) + @ex = exception + @opts = opts + @_pry_ = _pry_ + end + + def format + check_for_errors + set_file_and_dir_locals(backtrace_file, _pry_, _pry_.current_context) + code = decorate(Pry::Code.from_file(backtrace_file). + between(*start_and_end_line_for_code_window). + with_marker(backtrace_line)) + "#{header}#{code}" + end + + private + + def code_window_size + _pry_.config.default_window_size || 5 + end + + def backtrace_level + return @backtrace_level if @backtrace_level + + bl = if opts[:ex].nil? + ex.bt_index + else + ex.bt_index = absolute_index_number(opts[:ex], ex.backtrace.size) + end + + increment_backtrace_level + @backtrace_level = bl + end + + def increment_backtrace_level + ex.inc_bt_index + end + + def backtrace_file + Array(ex.bt_source_location_for(backtrace_level)).first + end + + def backtrace_line + Array(ex.bt_source_location_for(backtrace_level)).last + end + + def check_for_errors + raise CommandError, "No exception found." unless ex + raise CommandError, "The given backtrace level is out of bounds." unless backtrace_file + end + + def start_and_end_line_for_code_window + start_line = backtrace_line - code_window_size + start_line = 1 if start_line < 1 + + [start_line, backtrace_line + code_window_size] + end + + def header + unindent %{ + #{Helpers::Text.bold 'Exception:'} #{ex.class}: #{ex.message} + -- + #{Helpers::Text.bold('From:')} #{backtrace_file} @ line #{backtrace_line} @ #{Helpers::Text.bold("level: #{backtrace_level}")} of backtrace (of #{ex.backtrace.size - 1}). + + } + end + + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/cat/file_formatter.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/cat/file_formatter.rb new file mode 100644 index 0000000..a7a8679 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/cat/file_formatter.rb @@ -0,0 +1,67 @@ +class Pry + class Command::Cat + class FileFormatter < AbstractFormatter + attr_reader :file_with_embedded_line + attr_reader :opts + attr_reader :_pry_ + + def initialize(file_with_embedded_line, _pry_, opts) + @file_with_embedded_line = file_with_embedded_line + @opts = opts + @_pry_ = _pry_ + @code_from_file = Pry::Code.from_file(file_name) + end + + def format + raise CommandError, "Must provide a filename, --in, or --ex." if !file_with_embedded_line + + set_file_and_dir_locals(file_name, _pry_, _pry_.current_context) + decorate(@code_from_file) + end + + def file_and_line + file_name, line_num = file_with_embedded_line.split(/:(?!\/|\\)/) + + [file_name, line_num ? line_num.to_i : nil] + end + + private + + def file_name + file_and_line.first + end + + def line_number + file_and_line.last + end + + def code_window_size + _pry_.config.default_window_size || 7 + end + + def decorate(content) + line_number ? super.around(line_number, code_window_size) : super + end + + def code_type + opts[:type] || detect_code_type_from_file(file_name) + end + + def detect_code_type_from_file(file_name) + code_type = @code_from_file.code_type + + if code_type == :unknown + name = File.basename(file_name).split('.', 2).first + case name + when "Rakefile", "Gemfile" + :ruby + else + :text + end + else + code_type + end + end + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/cat/input_expression_formatter.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/cat/input_expression_formatter.rb new file mode 100644 index 0000000..8791ac3 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/cat/input_expression_formatter.rb @@ -0,0 +1,43 @@ +class Pry + class Command::Cat + class InputExpressionFormatter < AbstractFormatter + attr_accessor :input_expressions + attr_accessor :opts + + def initialize(input_expressions, opts) + @input_expressions = input_expressions + @opts = opts + end + + def format + raise CommandError, "No input expressions!" if numbered_input_items.length < 1 + + if numbered_input_items.length > 1 + content = "" + numbered_input_items.each do |i, s| + content << "#{Helpers::Text.bold(i.to_s)}:\n" << decorate(Pry::Code(s).with_indentation(2)).to_s + end + + content + else + decorate(Pry::Code(selected_input_items.first)) + end + end + + private + + def selected_input_items + input_expressions[normalized_expression_range] || [] + end + + def numbered_input_items + @numbered_input_items ||= normalized_expression_range.zip(selected_input_items). + reject { |_, s| s.nil? || s == "" } + end + + def normalized_expression_range + absolute_index_range(opts[:i], input_expressions.length) + end + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/cd.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/cd.rb new file mode 100644 index 0000000..667453a --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/cd.rb @@ -0,0 +1,41 @@ +class Pry + class Command::Cd < Pry::ClassCommand + match 'cd' + group 'Context' + description 'Move into a new context (object or scope).' + + banner <<-'BANNER' + Usage: cd [OPTIONS] [--help] + + Move into new context (object or scope). As in UNIX shells use `cd ..` to go + back, `cd /` to return to Pry top-level and `cd -` to toggle between last two + scopes. Complex syntax (e.g `cd ../@x/@y`) also supported. + + cd @x + cd .. + cd / + cd - + + https://github.com/pry/pry/wiki/State-navigation#wiki-Changing_scope + BANNER + + def process + state.old_stack ||= [] + + if arg_string.strip == "-" + unless state.old_stack.empty? + _pry_.binding_stack, state.old_stack = state.old_stack, _pry_.binding_stack + end + else + stack = ObjectPath.new(arg_string, _pry_.binding_stack).resolve + + if stack && stack != _pry_.binding_stack + state.old_stack = _pry_.binding_stack + _pry_.binding_stack = stack + end + end + end + end + + Pry::Commands.add_command(Pry::Command::Cd) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/change_inspector.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/change_inspector.rb new file mode 100644 index 0000000..183dec4 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/change_inspector.rb @@ -0,0 +1,27 @@ +class Pry::Command::ChangeInspector < Pry::ClassCommand + match 'change-inspector' + group 'Input and Output' + description 'Change the current inspector proc.' + command_options argument_required: true + banner <<-BANNER + Usage: change-inspector NAME + + Change the proc used to print return values. See list-inspectors for a list + of available procs and a short description of what each one does. + BANNER + + def process(inspector) + if inspector_map.key?(inspector) + _pry_.print = inspector_map[inspector][:value] + output.puts "Switched to the '#{inspector}' inspector!" + else + raise Pry::CommandError, "'#{inspector}' isn't a known inspector!" + end + end + +private + def inspector_map + Pry::Inspector::MAP + end + Pry::Commands.add_command(self) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/change_prompt.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/change_prompt.rb new file mode 100644 index 0000000..13d36cb --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/change_prompt.rb @@ -0,0 +1,26 @@ +class Pry::Command::ChangePrompt < Pry::ClassCommand + match 'change-prompt' + group 'Input and Output' + description 'Change the current prompt.' + command_options argument_required: true + banner <<-BANNER + Usage: change-prompt NAME + + Change the current prompt. See list-prompts for a list of available + prompts. + BANNER + + def process(prompt) + if prompt_map.key?(prompt) + _pry_.prompt = prompt_map[prompt][:value] + else + raise Pry::CommandError, "'#{prompt}' isn't a known prompt!" + end + end + +private + def prompt_map + Pry::Prompt::MAP + end + Pry::Commands.add_command(self) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/code_collector.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/code_collector.rb new file mode 100644 index 0000000..72e8181 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/code_collector.rb @@ -0,0 +1,165 @@ +class Pry + class Command::CodeCollector + include Helpers::CommandHelpers + + attr_reader :args + attr_reader :opts + attr_reader :_pry_ + + # The name of the explicitly given file (if any). + attr_accessor :file + + class << self + attr_accessor :input_expression_ranges + attr_accessor :output_result_ranges + end + + @input_expression_ranges = [] + @output_result_ranges = [] + + def initialize(args, opts, _pry_) + @args = args + @opts = opts + @_pry_ = _pry_ + end + + # Add the `--lines`, `-o`, `-i`, `-s`, `-d` options. + def self.inject_options(opt) + @input_expression_ranges = [] + @output_result_ranges = [] + + opt.on :l, :lines, "Restrict to a subset of lines. Takes a line number or range", + :optional_argument => true, :as => Range, :default => 1..-1 + opt.on :o, :out, "Select lines from Pry's output result history. Takes an index or range", + :optional_argument => true, :as => Range, :default => -5..-1 do |r| + output_result_ranges << (r || (-5..-1)) + end + opt.on :i, :in, "Select lines from Pry's input expression history. Takes an index or range", + :optional_argument => true, :as => Range, :default => -5..-1 do |r| + input_expression_ranges << (r || (-5..-1)) + end + opt.on :s, :super, "Select the 'super' method. Can be repeated to traverse the ancestors", + :as => :count + opt.on :d, :doc, "Select lines from the code object's documentation" + end + + # The content (i.e code/docs) for the selected object. + # If the user provided a bare code object, it returns the source. + # If the user provided the `-i` or `-o` switches, it returns the + # selected input/output lines joined as a string. If the user used + # `-d CODE_OBJECT` it returns the docs for that code object. + # + # @return [String] + def content + return @content if @content + raise CommandError, "Only one of --out, --in, --doc and CODE_OBJECT may be specified." if bad_option_combination? + + content = case + when opts.present?(:o) + pry_output_content + when opts.present?(:i) + pry_input_content + when opts.present?(:d) + code_object_doc + else + code_object_source_or_file + end + + @content ||= restrict_to_lines(content, line_range) + end + + # The code object + # + # @return [Pry::WrappedModule, Pry::Method, Pry::Command] + def code_object + Pry::CodeObject.lookup(obj_name, _pry_, :super => opts[:super]) + end + + # Given a string and a range, return the `range` lines of that + # string. + # + # @param [String] content + # @param [Range, Fixnum] range + # @return [String] The string restricted to the given range + def restrict_to_lines(content, range) + Array(content.lines.to_a[range]).join + end + + # The selected `_pry_.output_array` as a string, as specified by + # the `-o` switch. + # + # @return [String] + def pry_output_content + pry_array_content_as_string(_pry_.output_array, self.class.output_result_ranges) do |v| + _pry_.config.gist.inspecter.call(v) + end + end + + # The selected `_pry_.input_array` as a string, as specified by + # the `-i` switch. + # + # @return [String] + def pry_input_content + pry_array_content_as_string(_pry_.input_array, self.class.input_expression_ranges) { |v| v } + end + + # The line range passed to `--lines`, converted to a 0-indexed range. + def line_range + opts.present?(:lines) ? one_index_range_or_number(opts[:lines]) : 0..-1 + end + + # Name of the object argument + def obj_name + @obj_name ||= args.empty? ? "" : args.join(" ") + end + + private + + def bad_option_combination? + [opts.present?(:in), opts.present?(:out), + !args.empty?].count(true) > 1 + end + + def pry_array_content_as_string(array, ranges, &block) + all = '' + ranges.each do |range| + raise CommandError, "Minimum value for range is 1, not 0." if convert_to_range(range).first == 0 + + ranged_array = Array(array[range]) || [] + ranged_array.compact.each { |v| all << block.call(v) } + end + + all + end + + def code_object_doc + (code_object && code_object.doc) or could_not_locate(obj_name) + end + + def code_object_source_or_file + (code_object && code_object.source) || file_content + end + + def file_content + if File.exists?(obj_name) + # Set the file accessor. + self.file = obj_name + File.read(obj_name) + else + could_not_locate(obj_name) + end + end + + def could_not_locate(name) + raise CommandError, "Cannot locate: #{name}!" + end + + def convert_to_range(n) + if !n.is_a?(Range) + (n..n) + else + n + end + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/disable_pry.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/disable_pry.rb new file mode 100644 index 0000000..69bfc4e --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/disable_pry.rb @@ -0,0 +1,27 @@ +class Pry + class Command::DisablePry < Pry::ClassCommand + match 'disable-pry' + group 'Navigating Pry' + description 'Stops all future calls to pry and exits the current session.' + + banner <<-'BANNER' + Usage: disable-pry + + After this command is run any further calls to pry will immediately return `nil` + without interrupting the flow of your program. This is particularly useful when + you've debugged the problem you were having, and now wish the program to run to + the end. + + As alternatives, consider using `exit!` to force the current Ruby process + to quit immediately; or using `edit-method -p` to remove the `binding.pry` + from the code. + BANNER + + def process + ENV['DISABLE_PRY'] = 'true' + _pry_.run_command "exit" + end + end + + Pry::Commands.add_command(Pry::Command::DisablePry) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/disabled_commands.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/disabled_commands.rb new file mode 100644 index 0000000..9866f90 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/disabled_commands.rb @@ -0,0 +1,2 @@ +Pry::Commands.disabled_command("edit-method", "Use `edit` instead.") +Pry::Commands.disabled_command("show-command", "Use show-source [command_name] instead.") diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/easter_eggs.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/easter_eggs.rb new file mode 100644 index 0000000..84a97df --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/easter_eggs.rb @@ -0,0 +1,112 @@ +class Pry + Pry::Commands.instance_eval do + command "nyan-cat", "", :requires_gem => ["nyancat"] do + run ".nyancat" + end + + command(/!s\/(.*?)\/(.*?)/, "") do |source, dest| + eval_string.gsub!(/#{source}/) { dest } + run "show-input" + end + + command "get-naked", "" do + text = %{ + -- + We dont have to take our clothes off to have a good time. + We could dance & party all night And drink some cherry wine. + -- Jermaine Stewart } + output.puts text + text + end + + command "east-coker", "" do + text = %{ + -- + Now the light falls + Across the open field, leaving the deep lane + Shuttered with branches, dark in the afternoon, + Where you lean against a bank while a van passes, + And the deep lane insists on the direction + Into the village, in the electric heat + Hypnotised. In a warm haze the sultry light + Is absorbed, not refracted, by grey stone. + The dahlias sleep in the empty silence. + Wait for the early owl. + -- T.S Eliot + } + output.puts text + text + end + + command "cohen-poem", "" do + text = %{ + -- + When this American woman, + whose thighs are bound in casual red cloth, + comes thundering past my sitting place + like a forest-burning Mongol tribe, + the city is ravished + and brittle buildings of a hundred years + splash into the street; + and my eyes are burnt + for the embroidered Chinese girls, + already old, + and so small between the thin pines + on these enormous landscapes, + that if you turn your head + they are lost for hours. + -- Leonard Cohen + } + output.puts text + text + end + + command "pessoa-poem", "" do + output.puts <<-TEXT + -- + I've gone to bed with every feeling, + I've been the pimp of every emotion, + All felt sensations have bought me drinks, + I've traded glances with every motive for every act, + I've held hands with every urge to depart, + .. + Rage, foam, the vastness that doesn't fit in my handkerchief, + The dog in heat howling in the night, + The pond from the farm going in circles around my insomnia, + The woods as they were, on our late-afternoon walks, the rose, + The indifferent tuft of hair, the moss, the pines, + The rage of not containing all this, not retaining all this, + O abstract hunger for things, impotent libido for moments, + Intellectual orgy of feeling life! + -- Fernando Pessoa +TEXT + end + + command "test-ansi", "" do + prev_color = _pry_.config.color + _pry_.config.color = true + + picture = unindent <<-'EOS'.gsub(/[[:alpha:]!]/) { |s| text.red(s) } + ____ _______________________ + / \ | A W G | + / O O \ | N I O N ! | + | | | S S R I ! | + \ \__/ / __| I K ! | + \____/ \________________________| + EOS + + if windows_ansi? + move_up = proc { |n| "\e[#{n}F" } + else + move_up = proc { |n| "\e[#{n}A\e[0G" } + end + + output.puts "\n" * 6 + output.puts picture.lines.map(&:chomp).reverse.join(move_up[1]) + output.puts "\n" * 6 + output.puts "** ENV['TERM'] is #{ENV['TERM']} **\n\n" + + _pry_.config.color = prev_color + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/edit.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/edit.rb new file mode 100644 index 0000000..cf2cc1c --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/edit.rb @@ -0,0 +1,195 @@ +class Pry + class Command::Edit < Pry::ClassCommand + require 'pry/commands/edit/exception_patcher' + require 'pry/commands/edit/file_and_line_locator' + + match 'edit' + group 'Editing' + description 'Invoke the default editor on a file.' + + banner <<-'BANNER' + Usage: edit [--no-reload|--reload|--patch] [--line LINE] [--temp|--ex|FILE[:LINE]|OBJECT|--in N] + + Open a text editor. When no FILE is given, edits the pry input buffer. + When a method/module/command is given, the code is opened in an editor. + Ensure `Pry.config.editor` or `_pry_.config.editor` is set to your editor of choice. + + edit sample.rb edit -p MyClass#my_method + edit sample.rb --line 105 edit MyClass + edit MyClass#my_method edit --ex + edit --method edit --ex -p + + https://github.com/pry/pry/wiki/Editor-integration#wiki-Edit_command + BANNER + + def options(opt) + opt.on :e, :ex, "Open the file that raised the most recent exception (_ex_.file)", + :optional_argument => true, :as => Integer + opt.on :i, :in, "Open a temporary file containing the Nth input expression. N may be a range", + :optional_argument => true, :as => Range, :default => -1..-1 + opt.on :t, :temp, "Open an empty temporary file" + opt.on :l, :line, "Jump to this line in the opened file", + :argument => true, :as => Integer + opt.on :n, :"no-reload", "Don't automatically reload the edited file" + opt.on :c, :current, "Open the current __FILE__ and at __LINE__ (as returned by `whereami`)" + opt.on :r, :reload, "Reload the edited code immediately (default for ruby files)" + opt.on :p, :patch, "Instead of editing the object's file, try to edit in a tempfile and apply as a monkey patch" + opt.on :m, :method, "Explicitly edit the _current_ method (when inside a method context)." + end + + def process + if bad_option_combination? + raise CommandError, "Only one of --ex, --temp, --in, --method and FILE may be specified." + end + + if repl_edit? + # code defined in pry, eval'd within pry. + repl_edit + elsif runtime_patch? + # patch code without persisting changes + apply_runtime_patch + else + # code stored in actual files, eval'd at top-level + file_edit + end + end + + def repl_edit? + !opts.present?(:ex) && !opts.present?(:current) && !opts.present?(:method) && + filename_argument.empty? + end + + def repl_edit + content = Pry::Editor.new(_pry_).edit_tempfile_with_content(initial_temp_file_content, + initial_temp_file_content.lines.count) + silence_warnings do + eval_string.replace content + end + end + + def file_based_exception? + opts.present?(:ex) && !opts.present?(:patch) + end + + def runtime_patch? + !file_based_exception? && (opts.present?(:patch) || pry_method?(code_object)) + end + + def apply_runtime_patch + if patch_exception? + ExceptionPatcher.new(_pry_, state, file_and_line_for_current_exception).perform_patch + else + if code_object.is_a?(Pry::Method) + code_object.redefine Pry::Editor.new(_pry_).edit_tempfile_with_content(code_object.source) + else + raise NotImplementedError, "Cannot yet patch #{code_object} objects!" + end + end + end + + def ensure_file_name_is_valid(file_name) + raise CommandError, "Cannot find a valid file for #{filename_argument}" if !file_name + raise CommandError, "#{file_name} is not a valid file name, cannot edit!" if not_a_real_file?(file_name) + end + + def file_and_line_for_current_exception + FileAndLineLocator.from_exception(_pry_.last_exception, opts[:ex].to_i) + end + + def file_and_line + file_name, line = if opts.present?(:current) + FileAndLineLocator.from_binding(target) + elsif opts.present?(:ex) + file_and_line_for_current_exception + elsif code_object + FileAndLineLocator.from_code_object(code_object, filename_argument) + else + # when file and line are passed as a single arg, e.g my_file.rb:30 + FileAndLineLocator.from_filename_argument(filename_argument) + end + + [file_name, opts.present?(:line) ? opts[:l].to_i : line] + end + + def file_edit + file_name, line = file_and_line + + ensure_file_name_is_valid(file_name) + + Pry::Editor.new(_pry_).invoke_editor(file_name, line, reload?(file_name)) + set_file_and_dir_locals(file_name) + + if reload?(file_name) + silence_warnings do + load file_name + end + end + end + + def filename_argument + args.join(' ') + end + + def code_object + @code_object ||= !probably_a_file?(filename_argument) && + Pry::CodeObject.lookup(filename_argument, _pry_) + end + + def pry_method?(code_object) + code_object.is_a?(Pry::Method) && + code_object.pry_method? + end + + def patch_exception? + opts.present?(:ex) && opts.present?(:patch) + end + + def bad_option_combination? + [opts.present?(:ex), opts.present?(:temp), + opts.present?(:in), opts.present?(:method), !filename_argument.empty?].count(true) > 1 + end + + def input_expression + case opts[:i] + when Range + (_pry_.input_array[opts[:i]] || []).join + when Fixnum + _pry_.input_array[opts[:i]] || "" + else + raise Pry::CommandError, "Not a valid range: #{opts[:i]}" + end + end + + def reloadable? + opts.present?(:reload) || opts.present?(:ex) + end + + def never_reload? + opts.present?(:'no-reload') || _pry_.config.disable_auto_reload + end + + def reload?(file_name="") + (reloadable? || file_name.end_with?(".rb")) && !never_reload? + end + + def initial_temp_file_content + case + when opts.present?(:temp) + "" + when opts.present?(:in) + input_expression + when eval_string.strip != "" + eval_string + else + _pry_.input_array.reverse_each.find { |x| x && x.strip != "" } || "" + end + end + + def probably_a_file?(str) + [".rb", ".c", ".py", ".yml", ".gemspec"].include?(File.extname(str)) || + str =~ /\/|\\/ + end + end + + Pry::Commands.add_command(Pry::Command::Edit) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/edit/exception_patcher.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/edit/exception_patcher.rb new file mode 100644 index 0000000..07e13bc --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/edit/exception_patcher.rb @@ -0,0 +1,25 @@ +class Pry + class Command::Edit + class ExceptionPatcher + attr_accessor :_pry_ + attr_accessor :state + attr_accessor :file_and_line + + def initialize(_pry_, state, exception_file_and_line) + @_pry_ = _pry_ + @state = state + @file_and_line = exception_file_and_line + end + + # perform the patch + def perform_patch + file_name, _ = file_and_line + lines = state.dynamical_ex_file || File.read(file_name) + + source = Pry::Editor.new(_pry_).edit_tempfile_with_content(lines) + _pry_.evaluate_ruby source + state.dynamical_ex_file = source.split("\n") + end + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/edit/file_and_line_locator.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/edit/file_and_line_locator.rb new file mode 100644 index 0000000..5f712f3 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/edit/file_and_line_locator.rb @@ -0,0 +1,36 @@ +class Pry + class Command::Edit + module FileAndLineLocator + class << self + def from_binding(target) + [target.eval("__FILE__"), target.eval("__LINE__")] + end + + def from_code_object(code_object, filename_argument) + if File.exists?(code_object.source_file.to_s) + [code_object.source_file, code_object.source_line] + else + raise CommandError, "Cannot find a file for #{filename_argument}!" + end + end + + def from_exception(exception, backtrace_level) + raise CommandError, "No exception found." if exception.nil? + + file_name, line = exception.bt_source_location_for(backtrace_level) + raise CommandError, "Exception has no associated file." if file_name.nil? + raise CommandError, "Cannot edit exceptions raised in REPL." if Pry.eval_path == file_name + + [file_name, line] + end + + # when file and line are passed as a single arg, e.g my_file.rb:30 + def from_filename_argument(filename_argument) + f = File.expand_path(filename_argument) + l = f.sub!(/:(\d+)$/, "") ? $1.to_i : 1 + [f, l] + end + end + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/exit.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/exit.rb new file mode 100644 index 0000000..32c0c2e --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/exit.rb @@ -0,0 +1,42 @@ +class Pry + class Command::Exit < Pry::ClassCommand + match 'exit' + group 'Navigating Pry' + description 'Pop the previous binding.' + command_options :keep_retval => true + + banner <<-'BANNER' + Usage: exit [OPTIONS] [--help] + Aliases: quit + + Pop the previous binding (does NOT exit program). It can be useful to exit a + context with a user-provided value. For instance an exit value can be used to + determine program flow. + + exit "pry this" + exit + + https://github.com/pry/pry/wiki/State-navigation#wiki-Exit_with_value + BANNER + + def process + if _pry_.binding_stack.one? + _pry_.run_command "exit-all #{arg_string}" + else + # otherwise just pop a binding and return user supplied value + process_pop_and_return + end + end + + def process_pop_and_return + popped_object = _pry_.binding_stack.pop.eval('self') + + # return a user-specified value if given otherwise return the object + return target.eval(arg_string) unless arg_string.empty? + popped_object + end + end + + Pry::Commands.add_command(Pry::Command::Exit) + Pry::Commands.alias_command 'quit', 'exit' +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/exit_all.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/exit_all.rb new file mode 100644 index 0000000..1136de3 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/exit_all.rb @@ -0,0 +1,29 @@ +class Pry + class Command::ExitAll < Pry::ClassCommand + match 'exit-all' + group 'Navigating Pry' + description 'End the current Pry session.' + + banner <<-'BANNER' + Usage: exit-all [--help] + Aliases: !!@ + + End the current Pry session (popping all bindings and returning to caller). + Accepts optional return value. + BANNER + + def process + # calculate user-given value + exit_value = target.eval(arg_string) + + # clear the binding stack + _pry_.binding_stack.clear + + # break out of the repl loop + throw(:breakout, exit_value) + end + end + + Pry::Commands.add_command(Pry::Command::ExitAll) + Pry::Commands.alias_command '!!@', 'exit-all' +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/exit_program.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/exit_program.rb new file mode 100644 index 0000000..a4d9168 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/exit_program.rb @@ -0,0 +1,23 @@ +class Pry + class Command::ExitProgram < Pry::ClassCommand + match 'exit-program' + group 'Navigating Pry' + description 'End the current program.' + + banner <<-'BANNER' + Usage: exit-program [--help] + Aliases: quit-program + !!! + + End the current program. + BANNER + + def process + Kernel.exit target.eval(arg_string).to_i + end + end + + Pry::Commands.add_command(Pry::Command::ExitProgram) + Pry::Commands.alias_command 'quit-program', 'exit-program' + Pry::Commands.alias_command '!!!', 'exit-program' +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/find_method.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/find_method.rb new file mode 100644 index 0000000..c1ee2c5 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/find_method.rb @@ -0,0 +1,193 @@ +class Pry + class Command::FindMethod < Pry::ClassCommand + extend Pry::Helpers::BaseHelpers + + match 'find-method' + group 'Context' + description 'Recursively search for a method within a Class/Module or the current namespace.' + command_options :shellwords => false + + banner <<-'BANNER' + Usage: find-method [-n|-c] METHOD [NAMESPACE] + + Recursively search for a method within a Class/Module or the current namespace. + Use the `-n` switch (the default) to search for methods whose name matches the + given regex. Use the `-c` switch to search for methods that contain the given + code. + + # Find all methods whose name match /re/ inside + # the Pry namespace. Matches Pry#repl, etc. + find-method re Pry + + # Find all methods that contain the code: + # output.puts inside the Pry namepsace. + find-method -c 'output.puts' Pry + BANNER + + def options(opt) + opt.on :n, :name, "Search for a method by name" + opt.on :c, :content, "Search for a method based on content in Regex form" + end + + def process + return if args.size < 1 + klass = search_class + + matches = if opts.content? + content_search(klass) + else + name_search(klass) + end + + show_search_results(matches) + end + + private + + # @return [Regexp] The pattern to search for. + def pattern + @pattern ||= ::Regexp.new args[0] + end + + # Output the result of the search. + # + # @param [Array] matches + def show_search_results(matches) + if matches.empty? + output.puts text.bold("No Methods Matched") + else + print_matches(matches) + end + end + + # The class to search for methods. + # We only search classes, so if the search object is an + # instance, return its class. If no search object is given + # search `target_self`. + def search_class + klass = if args[1] + target.eval(args[1]) + else + target_self + end + + klass.is_a?(Module) ? klass : klass.class + end + + # pretty-print a list of matching methods. + # + # @param [Array] matches + def print_matches(matches) + grouped = matches.group_by(&:owner) + order = grouped.keys.sort_by{ |x| x.name || x.to_s } + + order.each do |klass| + print_matches_for_class(klass, grouped) + end + end + + # Print matched methods for a class + def print_matches_for_class(klass, grouped) + output.puts text.bold(klass.name) + grouped[klass].each do |method| + header = method.name_with_owner + output.puts header + additional_info(header, method) + end + end + + # Return the matched lines of method source if `-c` is given or "" + # if `-c` was not given + def additional_info(header, method) + if opts.content? + ": " << colorize_code(matched_method_lines(header, method)) + else + "" + end + end + + def matched_method_lines(header, method) + method.source.split(/\n/).select {|x| x =~ pattern }.join("\n#{' ' * header.length}") + end + + # Run the given block against every constant in the provided namespace. + # + # @param [Module] klass The namespace in which to start the search. + # @param [Hash] done The namespaces we've already visited (private) + # @yieldparam klass Each class/module in the namespace. + # + def recurse_namespace(klass, done={}, &block) + return if !(Module === klass) || done[klass] + + done[klass] = true + + yield klass + + klass.constants.each do |name| + next if klass.autoload?(name) + begin + const = klass.const_get(name) + rescue RescuableException + # constant loading is an inexact science at the best of times, + # this often happens when a constant was .autoload? but someone + # tried to load it. It's now not .autoload? but will still raise + # a NameError when you access it. + else + recurse_namespace(const, done, &block) + end + end + end + + # Gather all the methods in a namespace that pass the given block. + # + # @param [Module] namespace The namespace in which to search. + # @yieldparam [Method] method The method to test + # @yieldreturn [Boolean] + # @return [Array] + # + def search_all_methods(namespace) + done = Hash.new{ |h,k| h[k] = {} } + matches = [] + + recurse_namespace(namespace) do |klass| + (Pry::Method.all_from_class(klass) + Pry::Method.all_from_obj(klass)).each do |method| + next if done[method.owner][method.name] + done[method.owner][method.name] = true + + matches << method if yield method + end + end + + matches + end + + # Search for all methods with a name that matches the given regex + # within a namespace. + # + # @param [Module] namespace The namespace to search + # @return [Array] + # + def name_search(namespace) + search_all_methods(namespace) do |meth| + meth.name =~ pattern + end + end + + # Search for all methods who's implementation matches the given regex + # within a namespace. + # + # @param [Module] namespace The namespace to search + # @return [Array] + # + def content_search(namespace) + search_all_methods(namespace) do |meth| + begin + meth.source =~ pattern + rescue RescuableException + false + end + end + end + end + + Pry::Commands.add_command(Pry::Command::FindMethod) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/fix_indent.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/fix_indent.rb new file mode 100644 index 0000000..75c48c7 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/fix_indent.rb @@ -0,0 +1,19 @@ +class Pry + class Command::FixIndent < Pry::ClassCommand + match 'fix-indent' + group 'Input and Output' + + description "Correct the indentation for contents of the input buffer" + + banner <<-USAGE + Usage: fix-indent + USAGE + + def process + indented_str = Pry::Indent.indent(eval_string) + eval_string.replace indented_str + end + end + + Pry::Commands.add_command(Pry::Command::FixIndent) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/gem_cd.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/gem_cd.rb new file mode 100644 index 0000000..da1907a --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/gem_cd.rb @@ -0,0 +1,26 @@ +class Pry + class Command::GemCd < Pry::ClassCommand + match 'gem-cd' + group 'Gems' + description "Change working directory to specified gem's directory." + command_options :argument_required => true + + banner <<-'BANNER' + Usage: gem-cd GEM_NAME + + Change the current working directory to that in which the given gem is + installed. + BANNER + + def process(gem) + Dir.chdir(Rubygem.spec(gem).full_gem_path) + output.puts(Dir.pwd) + end + + def complete(str) + Rubygem.complete(str) + end + end + + Pry::Commands.add_command(Pry::Command::GemCd) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/gem_install.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/gem_install.rb new file mode 100644 index 0000000..873e106 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/gem_install.rb @@ -0,0 +1,32 @@ +class Pry + class Command::GemInstall < Pry::ClassCommand + match 'gem-install' + group 'Gems' + description 'Install a gem and refresh the gem cache.' + command_options :argument_required => true + + banner <<-'BANNER' + Usage: gem-install GEM_NAME + + Installs the given gem, refreshes the gem cache, and requires the gem for you + based on a best guess from the gem name. + + gem-install pry-stack_explorer + BANNER + + def setup + require 'rubygems/dependency_installer' unless defined? Gem::DependencyInstaller + end + + def process(gem) + Rubygem.install(gem) + output.puts "Gem `#{ text.green(gem) }` installed." + require gem + rescue LoadError + require_path = gem.split('-').join('/') + require require_path + end + end + + Pry::Commands.add_command(Pry::Command::GemInstall) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/gem_list.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/gem_list.rb new file mode 100644 index 0000000..e4a5d00 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/gem_list.rb @@ -0,0 +1,33 @@ +class Pry + class Command::GemList < Pry::ClassCommand + match 'gem-list' + group 'Gems' + description 'List and search installed gems.' + + banner <<-'BANNER' + Usage: gem-list [REGEX] + + List all installed gems, when a regex is provided, limit the output to those + that match the regex. + BANNER + + def process(pattern = nil) + pattern = Regexp.compile(pattern || '') + gems = Rubygem.list(pattern).group_by(&:name) + + gems.each do |gem, specs| + specs.sort! do |a,b| + Gem::Version.new(b.version) <=> Gem::Version.new(a.version) + end + + versions = specs.each_with_index.map do |spec, index| + index == 0 ? text.bright_green(spec.version.to_s) : text.green(spec.version.to_s) + end + + output.puts "#{text.default gem} (#{versions.join ', '})" + end + end + end + + Pry::Commands.add_command(Pry::Command::GemList) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/gem_open.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/gem_open.rb new file mode 100644 index 0000000..e21723a --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/gem_open.rb @@ -0,0 +1,29 @@ +class Pry + class Command::GemOpen < Pry::ClassCommand + match 'gem-open' + group 'Gems' + description 'Opens the working directory of the gem in your editor.' + command_options :argument_required => true + + banner <<-'BANNER' + Usage: gem-open GEM_NAME + + Change the current working directory to that in which the given gem is + installed, and then opens your text editor. + + gem-open pry-exception_explorer + BANNER + + def process(gem) + Dir.chdir(Rubygem.spec(gem).full_gem_path) do + Pry::Editor.invoke_editor(".", 0, false) + end + end + + def complete(str) + Rubygem.complete(str) + end + end + + Pry::Commands.add_command(Pry::Command::GemOpen) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/gist.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/gist.rb new file mode 100644 index 0000000..83cdf2b --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/gist.rb @@ -0,0 +1,101 @@ +class Pry + class Command::Gist < Pry::ClassCommand + match 'gist' + group 'Misc' + description 'Upload code, docs, history to https://gist.github.com/.' + command_options :requires_gem => "gist" + + banner <<-'BANNER' + Usage: gist [OPTIONS] [--help] + + The gist command enables you to gist code from files and methods to github. + + gist -i 20 --lines 1..3 + gist Pry#repl --lines 1..-1 + gist Rakefile --lines 5 + BANNER + + def setup + require 'gist' + end + + def options(opt) + CodeCollector.inject_options(opt) + opt.on :login, "Authenticate the gist gem with GitHub" + opt.on :p, :public, "Create a public gist (default: false)", :default => false + opt.on :clip, "Copy the selected content to clipboard instead, do NOT gist it", :default => false + end + + def process + return ::Gist.login! if opts.present?(:login) + cc = CodeCollector.new(args, opts, _pry_) + + if cc.content =~ /\A\s*\z/ + raise CommandError, "Found no code to gist." + end + + if opts.present?(:clip) + clipboard_content(cc.content) + else + # we're overriding the default behavior of the 'in' option (as + # defined on CodeCollector) with our local behaviour. + content = opts.present?(:in) ? input_content : cc.content + gist_content content, cc.file + end + end + + def clipboard_content(content) + ::Gist.copy(content) + output.puts "Copied content to clipboard!" + end + + def input_content + content = "" + CodeCollector.input_expression_ranges.each do |range| + input_expressions = _pry_.input_array[range] || [] + Array(input_expressions).each_with_index do |code, index| + corrected_index = index + range.first + if code && code != "" + content << code + if code !~ /;\Z/ + content << "#{comment_expression_result_for_gist(_pry_.config.gist.inspecter.call(_pry_.output_array[corrected_index]))}" + end + end + end + end + + content + end + + def comment_expression_result_for_gist(result) + content = "" + result.lines.each_with_index do |line, index| + if index == 0 + content << "# => #{line}" + else + content << "# #{line}" + end + end + + content + end + + def gist_content(content, filename) + response = ::Gist.gist(content, :filename => filename || "pry_gist.rb", :public => !!opts[:p]) + if response + url = response['html_url'] + message = "Gist created at URL #{url}" + begin + ::Gist.copy(url) + message << ", which is now in the clipboard." + rescue ::Gist::ClipboardError + end + + output.puts message + end + end + end + + Pry::Commands.add_command(Pry::Command::Gist) + Pry::Commands.alias_command 'clipit', 'gist --clip' +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/help.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/help.rb new file mode 100644 index 0000000..3f29c2c --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/help.rb @@ -0,0 +1,164 @@ +class Pry + class Command::Help < Pry::ClassCommand + match 'help' + group 'Help' + description 'Show a list of commands or information about a specific command.' + + banner <<-'BANNER' + Usage: help [COMMAND] + + With no arguments, help lists all the available commands along with their + descriptions. When given a command name as an argument, shows the help + for that command. + BANNER + + # We only want to show commands that have descriptions, so that the + # easter eggs don't show up. + def visible_commands + visible = {} + commands.each do |key, command| + visible[key] = command if command.description && !command.description.empty? + end + visible + end + + # Get a hash of available commands grouped by the "group" name. + def command_groups + visible_commands.values.group_by(&:group) + end + + def process + if args.empty? + display_index(command_groups) + else + display_search(args.first) + end + end + + # Display the index view, with headings and short descriptions per command. + # + # @param [Hash>] groups + def display_index(groups) + help_text = [] + + sorted_group_names(groups).each do |group_name| + commands = sorted_commands(groups[group_name]) + + if commands.any? + help_text << help_text_for_commands(group_name, commands) + end + end + + _pry_.pager.page help_text.join("\n\n") + end + + # Given a group name and an array of commands, + # return the help string for those commands. + # + # @param [String] name The group name. + # @param [Array] commands + # @return [String] The generated help string. + def help_text_for_commands(name, commands) + "#{text.bold(name.capitalize)}\n" << commands.map do |command| + " #{command.options[:listing].to_s.ljust(18)} #{command.description.capitalize}" + end.join("\n") + end + + # @param [Hash] groups + # @return [Array] An array of sorted group names. + def sorted_group_names(groups) + groups.keys.sort_by(&method(:group_sort_key)) + end + + # Sort an array of commands by their `listing` name. + # + # @param [Array] commands The commands to sort + # @return [Array] commands sorted by listing name. + def sorted_commands(commands) + commands.sort_by{ |command| command.options[:listing].to_s } + end + + # Display help for an individual command or group. + # + # @param [String] search The string to search for. + def display_search(search) + if command = command_set.find_command_for_help(search) + display_command(command) + else + display_filtered_search_results(search) + end + end + + # Display help for a searched item, filtered first by group + # and if that fails, filtered by command name. + # + # @param [String] search The string to search for. + def display_filtered_search_results(search) + groups = search_hash(search, command_groups) + + if groups.size > 0 + display_index(groups) + else + display_filtered_commands(search) + end + end + + # Display help for a searched item, filtered by group + # + # @param [String] search The string to search for. + def display_filtered_commands(search) + filtered = search_hash(search, visible_commands) + raise CommandError, "No help found for '#{args.first}'" if filtered.empty? + + if filtered.size == 1 + display_command(filtered.values.first) + else + display_index({"'#{search}' commands" => filtered.values}) + end + end + + # Display help for an individual command. + # + # @param [Pry::Command] command + def display_command(command) + _pry_.pager.page command.new.help + end + + # Find a subset of a hash that matches the user's search term. + # + # If there's an exact match a Hash of one element will be returned, + # otherwise a sub-Hash with every key that matches the search will + # be returned. + # + # @param [String] search the search term + # @param [Hash] hash the hash to search + def search_hash(search, hash) + matching = {} + + hash.each_pair do |key, value| + next unless key.is_a?(String) + if normalize(key) == normalize(search) + return {key => value} + elsif normalize(key).start_with?(normalize(search)) + matching[key] = value + end + end + + matching + end + + # Clean search terms to make it easier to search group names + # + # @param [String] key + # @return [String] + def normalize(key) + key.downcase.gsub(/pry\W+/, '') + end + + def group_sort_key(group_name) + [%w(Help Context Editing Introspection Input_and_output Navigating_pry Gems Basic Commands).index(group_name.gsub(' ', '_')) || 99, group_name] + end + end + + Pry::Commands.add_command(Pry::Command::Help) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/hist.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/hist.rb new file mode 100644 index 0000000..083d3f5 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/hist.rb @@ -0,0 +1,180 @@ +class Pry + class Command::Hist < Pry::ClassCommand + match 'hist' + group 'Editing' + description 'Show and replay Readline history.' + + banner <<-'BANNER' + Usage: hist [--head|--tail] + hist --all + hist --head N + hist --tail N + hist --show START..END + hist --grep PATTERN + hist --clear + hist --replay START..END + hist --save [START..END] FILE + Aliases: history + + Show and replay Readline history. + BANNER + + def options(opt) + opt.on :a, :all, "Display all history" + opt.on :H, :head, "Display the first N items", :optional_argument => true, :as => Integer + opt.on :T, :tail, "Display the last N items", :optional_argument => true, :as => Integer + opt.on :s, :show, "Show the given range of lines", :optional_argument => true, :as => Range + opt.on :G, :grep, "Show lines matching the given pattern", :argument => true, :as => String + opt.on :c, :clear , "Clear the current session's history" + opt.on :r, :replay, "Replay a line or range of lines", :argument => true, :as => Range + opt.on :save, "Save history to a file", :argument => true, :as => Range + opt.on :e, :'exclude-pry', "Exclude Pry commands from the history" + opt.on :n, :'no-numbers', "Omit line numbers" + end + + def process + @history = find_history + + if opts.present?(:show) + @history = @history.between(opts[:show]) + end + + if opts.present?(:grep) + @history = @history.grep(opts[:grep]) + end + + @history = case + when opts.present?(:head) + @history.take_lines(1, opts[:head] || 10) + when opts.present?(:tail) + @history.take_lines(-(opts[:tail] || 10), opts[:tail] || 10) + when opts.present?(:show) + @history.between(opts[:show]) + else + @history + end + + if opts.present?(:'exclude-pry') + @history = @history.select do |loc| + !command_set.valid_command?(loc.line) + end + end + + if opts.present?(:save) + process_save + elsif opts.present?(:clear) + process_clear + elsif opts.present?(:replay) + process_replay + else + process_display + end + end + + private + + def process_display + unless opts.present?(:'no-numbers') + @history = @history.with_line_numbers + end + + _pry_.pager.open do |pager| + @history.print_to_output(pager, true) + end + end + + def process_save + case opts[:save] + when Range + @history = @history.between(opts[:save]) + + unless args.first + raise CommandError, "Must provide a file name." + end + + file_name = File.expand_path(args.first) + when String + file_name = File.expand_path(opts[:save]) + end + + output.puts "Saving history in #{file_name}..." + + File.open(file_name, 'w') { |f| f.write(@history.raw) } + + output.puts "History saved." + end + + def process_clear + Pry.history.clear + output.puts "History cleared." + end + + def process_replay + @history = @history.between(opts[:r]) + replay_sequence = @history.raw + + # If we met follow-up "hist" call, check for the "--replay" option + # presence. If "hist" command is called with other options, proceed + # further. + check_for_juxtaposed_replay(replay_sequence) + + replay_sequence.lines.each do |line| + _pry_.eval line, :generated => true + end + end + + # Checks +replay_sequence+ for the presence of neighboring replay calls. + # @example + # [1] pry(main)> hist --show 46894 + # 46894: hist --replay 46675..46677 + # [2] pry(main)> hist --show 46675..46677 + # 46675: 1+1 + # 46676: a = 100 + # 46677: hist --tail + # [3] pry(main)> hist --replay 46894 + # Error: Replay index 46894 points out to another replay call: `hist -r 46675..46677` + # [4] pry(main)> + # + # @raise [Pry::CommandError] If +replay_sequence+ contains another + # "hist --replay" call + # @param [String] replay_sequence The sequence of commands to be replayed + # (per saltum) + # @return [Boolean] `false` if +replay_sequence+ does not contain another + # "hist --replay" call + def check_for_juxtaposed_replay(replay_sequence) + if replay_sequence =~ /\Ahist(?:ory)?\b/ + # Create *fresh* instance of Options for parsing of "hist" command. + _slop = self.slop + _slop.parse replay_sequence.split(' ')[1..-1] + + if _slop.present?(:r) + replay_sequence = replay_sequence.split("\n").join('; ') + index = opts[:r] + index = index.min if index.min == index.max || index.max.nil? + + raise CommandError, "Replay index #{ index } points out to another replay call: `#{ replay_sequence }`" + end + else + false + end + end + + # Finds history depending on the given switch. + # + # @return [Pry::Code] if it finds `--all` (or `-a`) switch, returns all + # entries in history. Without the switch returns only the entries from the + # current Pry session. + def find_history + h = if opts.present?(:all) + Pry.history.to_a + else + Pry.history.to_a.last(Pry.history.session_line_count) + end + # The last value in history will be the 'hist' command itself. + Pry::Code(h[0..-2]) + end + end + + Pry::Commands.add_command(Pry::Command::Hist) + Pry::Commands.alias_command 'history', 'hist' +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/import_set.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/import_set.rb new file mode 100644 index 0000000..5689883 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/import_set.rb @@ -0,0 +1,22 @@ +class Pry + class Command::ImportSet < Pry::ClassCommand + match 'import-set' + group 'Commands' + # TODO: Provide a better description with examples and a general conception + # of this command. + description 'Import a Pry command set.' + + banner <<-'BANNER' + Import a Pry command set. + BANNER + + def process(command_set_name) + raise CommandError, "Provide a command set name" if command_set.nil? + + set = target.eval(arg_string) + _pry_.commands.import set + end + end + + Pry::Commands.add_command(Pry::Command::ImportSet) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/install_command.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/install_command.rb new file mode 100644 index 0000000..acafe7b --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/install_command.rb @@ -0,0 +1,53 @@ +class Pry + class Command::InstallCommand < Pry::ClassCommand + match 'install-command' + group 'Commands' + description 'Install a disabled command.' + + banner <<-'BANNER' + Usage: install-command COMMAND + + Installs the gems necessary to run the given COMMAND. You will generally not + need to run this unless told to by an error message. + BANNER + + def process(name) + require 'rubygems/dependency_installer' unless defined? Gem::DependencyInstaller + command = find_command(name) + + unless command + output.puts "Command #{ text.green(name) } is not found" + return + end + + if command_dependencies_met?(command.options) + output.puts "Dependencies for #{ text.green(name) } are met. Nothing to do" + return + end + + output.puts "Attempting to install #{ text.green(name) } command..." + gems_to_install = Array(command.options[:requires_gem]) + + gems_to_install.each do |g| + next if Rubygem.installed?(g) + output.puts "Installing #{ text.green(g) } gem..." + Rubygem.install(g) + end + + gems_to_install.each do |g| + begin + require g + rescue LoadError + fail_msg = "Required gem #{ text.green(g) } installed but not found." + fail_msg += " Aborting command installation\n" + fail_msg += 'Tips: 1. Check your PATH; 2. Run `bundle update`' + raise CommandError, fail_msg + end + end + + output.puts "Installation of #{ text.green(name) } successful! Type `help #{name}` for information" + end + end + + Pry::Commands.add_command(Pry::Command::InstallCommand) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/jump_to.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/jump_to.rb new file mode 100644 index 0000000..4179fc7 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/jump_to.rb @@ -0,0 +1,29 @@ +class Pry + class Command::JumpTo < Pry::ClassCommand + match 'jump-to' + group 'Navigating Pry' + description 'Jump to a binding further up the stack.' + + banner <<-'BANNER' + Jump to a binding further up the stack, popping all bindings below. + BANNER + + def process(break_level) + break_level = break_level.to_i + nesting_level = _pry_.binding_stack.size - 1 + + case break_level + when nesting_level + output.puts "Already at nesting level #{nesting_level}" + when (0...nesting_level) + _pry_.binding_stack.slice!(break_level + 1, _pry_.binding_stack.size) + + else + max_nest_level = nesting_level - 1 + output.puts "Invalid nest level. Must be between 0 and #{max_nest_level}. Got #{break_level}." + end + end + end + + Pry::Commands.add_command(Pry::Command::JumpTo) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/list_inspectors.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/list_inspectors.rb new file mode 100644 index 0000000..c96c395 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/list_inspectors.rb @@ -0,0 +1,35 @@ +class Pry::Command::ListInspectors < Pry::ClassCommand + match 'list-inspectors' + group 'Input and Output' + description 'List the inspector procs available for use.' + banner <<-BANNER + Usage: list-inspectors + + List the inspector procs available to print return values. You can use + change-inspector to switch between them. + BANNER + + def process + output.puts heading("Available inspectors") + "\n" + inspector_map.each do |name, inspector| + output.write "Name: #{text.bold(name)}" + output.puts selected_inspector?(inspector) ? selected_text : "" + output.puts inspector[:description] + output.puts + end + end + +private + def inspector_map + Pry::Inspector::MAP + end + + def selected_text + text.red " (selected) " + end + + def selected_inspector?(inspector) + _pry_.print == inspector[:value] + end + Pry::Commands.add_command(self) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/list_prompts.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/list_prompts.rb new file mode 100644 index 0000000..436f719 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/list_prompts.rb @@ -0,0 +1,35 @@ +class Pry::Command::ListPrompts < Pry::ClassCommand + match 'list-prompts' + group 'Input and Output' + description 'List the prompts available for use.' + banner <<-BANNER + Usage: list-prompts + + List the available prompts. You can use change-prompt to switch between + them. + BANNER + + def process + output.puts heading("Available prompts") + "\n" + prompt_map.each do |name, prompt| + output.write "Name: #{text.bold(name)}" + output.puts selected_prompt?(prompt) ? selected_text : "" + output.puts prompt[:description] + output.puts + end + end + +private + def prompt_map + Pry::Prompt::MAP + end + + def selected_text + text.red " (selected) " + end + + def selected_prompt?(prompt) + _pry_.prompt == prompt[:value] + end + Pry::Commands.add_command(self) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/ls.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/ls.rb new file mode 100644 index 0000000..9f0e68f --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/ls.rb @@ -0,0 +1,114 @@ +require 'pry/commands/ls/ls_entity' +class Pry + class Command::Ls < Pry::ClassCommand + DEFAULT_OPTIONS = { + :heading_color => :bright_blue, + :public_method_color => :default, + :private_method_color => :blue, + :protected_method_color => :blue, + :method_missing_color => :bright_red, + :local_var_color => :yellow, + :pry_var_color => :default, # e.g. _, _pry_, _file_ + :instance_var_color => :blue, # e.g. @foo + :class_var_color => :bright_blue, # e.g. @@foo + :global_var_color => :default, # e.g. $CODERAY_DEBUG, $eventmachine_library + :builtin_global_color => :cyan, # e.g. $stdin, $-w, $PID + :pseudo_global_color => :cyan, # e.g. $~, $1..$9, $LAST_MATCH_INFO + :constant_color => :default, # e.g. VERSION, ARGF + :class_constant_color => :blue, # e.g. Object, Kernel + :exception_constant_color => :magenta, # e.g. Exception, RuntimeError + :unloaded_constant_color => :yellow, # Any constant that is still in .autoload? state + :separator => " ", + :ceiling => [Object, Module, Class] + } + + + match 'ls' + group 'Context' + description 'Show the list of vars and methods in the current scope.' + command_options :shellwords => false, :interpolate => false + + banner <<-'BANNER' + Usage: ls [-m|-M|-p|-pM] [-q|-v] [-c|-i] [Object] + ls [-g] [-l] + + ls shows you which methods, constants and variables are accessible to Pry. By + default it shows you the local variables defined in the current shell, and any + public methods or instance variables defined on the current object. + + The colours used are configurable using Pry.config.ls.*_color, and the separator + is Pry.config.ls.separator. + + Pry.config.ls.ceiling is used to hide methods defined higher up in the + inheritance chain, this is by default set to [Object, Module, Class] so that + methods defined on all Objects are omitted. The -v flag can be used to ignore + this setting and show all methods, while the -q can be used to set the ceiling + much lower and show only methods defined on the object or its direct class. + + Also check out `find-method` command (run `help find-method`). + BANNER + + + def options(opt) + opt.on :m, :methods, "Show public methods defined on the Object" + opt.on :M, "instance-methods", "Show public methods defined in a Module or Class" + opt.on :p, :ppp, "Show public, protected (in yellow) and private (in green) methods" + opt.on :q, :quiet, "Show only methods defined on object.singleton_class and object.class" + opt.on :v, :verbose, "Show methods and constants on all super-classes (ignores Pry.config.ls.ceiling)" + opt.on :g, :globals, "Show global variables, including those builtin to Ruby (in cyan)" + opt.on :l, :locals, "Show hash of local vars, sorted by descending size" + opt.on :c, :constants, "Show constants, highlighting classes (in blue), and exceptions (in purple).\n" << + " " * 32 << "Constants that are pending autoload? are also shown (in yellow)" + opt.on :i, :ivars, "Show instance variables (in blue) and class variables (in bright blue)" + opt.on :G, :grep, "Filter output by regular expression", :argument => true + + if jruby? + opt.on :J, "all-java", "Show all the aliases for methods from java (default is to show only prettiest)" + end + end + + # Exclude -q, -v and --grep because they, + # don't specify what the user wants to see. + def no_user_opts? + !(opts[:methods] || opts['instance-methods'] || opts[:ppp] || + opts[:globals] || opts[:locals] || opts[:constants] || opts[:ivars]) + end + + def process + @interrogatee = args.empty? ? target_self : target.eval(args.join(' ')) + raise_errors_if_arguments_are_weird + ls_entity = LsEntity.new({ + :interrogatee => @interrogatee, + :no_user_opts => no_user_opts?, + :opts => opts, + :args => args, + :_pry_ => _pry_ + }) + + _pry_.pager.page ls_entity.entities_table + end + + private + + def error_list + any_args = args.any? + non_mod_interrogatee = !(Module === @interrogatee) + [ + ['-l does not make sense with a specified Object', :locals, any_args], + ['-g does not make sense with a specified Object', :globals, any_args], + ['-q does not make sense with -v', :quiet, opts.present?(:verbose)], + ['-M only makes sense with a Module or a Class', 'instance-methods', non_mod_interrogatee], + ['-c only makes sense with a Module or a Class', :constants, any_args && non_mod_interrogatee] + ] + end + + def raise_errors_if_arguments_are_weird + error_list.each do |message, option, invalid_expr| + raise Pry::CommandError, message if opts.present?(option) && invalid_expr + end + end + + end + + Pry::Commands.add_command(Pry::Command::Ls) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/constants.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/constants.rb new file mode 100644 index 0000000..3db8162 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/constants.rb @@ -0,0 +1,47 @@ +require 'pry/commands/ls/interrogatable' + +class Pry + class Command::Ls < Pry::ClassCommand + class Constants < Pry::Command::Ls::Formatter + include Pry::Command::Ls::Interrogatable + + + def initialize(interrogatee, no_user_opts, opts, _pry_) + super(_pry_) + @interrogatee = interrogatee + @no_user_opts = no_user_opts + @default_switch = opts[:constants] + @verbose_switch = opts[:verbose] + end + + def correct_opts? + super || (@no_user_opts && interrogating_a_module?) + end + + def output_self + mod = interrogatee_mod + constants = WrappedModule.new(mod).constants(@verbose_switch) + output_section('constants', grep.regexp[format(mod, constants)]) + end + + private + + def format(mod, constants) + constants.sort_by(&:downcase).map do |name| + if const = (!mod.autoload?(name) && (mod.const_get(name) || true) rescue nil) + if (const < Exception rescue false) + color(:exception_constant, name) + elsif (Module === mod.const_get(name) rescue false) + color(:class_constant, name) + else + color(:constant, name) + end + else + color(:unloaded_constant, name) + end + end + end + + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/formatter.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/formatter.rb new file mode 100644 index 0000000..9ad117a --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/formatter.rb @@ -0,0 +1,49 @@ +class Pry + class Command::Ls < Pry::ClassCommand + class Formatter + attr_writer :grep + attr_reader :_pry_ + + def initialize(_pry_) + @_pry_ = _pry_ + @target = _pry_.current_context + end + + def write_out + return false unless correct_opts? + output_self + end + + private + + def color(type, str) + Pry::Helpers::Text.send _pry_.config.ls["#{type}_color"], str + end + + # Add a new section to the output. + # Outputs nothing if the section would be empty. + def output_section(heading, body) + return '' if body.compact.empty? + fancy_heading = Pry::Helpers::Text.bold(color(:heading, heading)) + Pry::Helpers.tablify_or_one_line(fancy_heading, body) + end + + def format_value(value) + Pry::ColorPrinter.pp(value, '') + end + + def correct_opts? + @default_switch + end + + def output_self + raise NotImplementedError + end + + def grep + @grep || proc { |x| x } + end + + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/globals.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/globals.rb new file mode 100644 index 0000000..2b3d0fd --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/globals.rb @@ -0,0 +1,48 @@ +class Pry + class Command::Ls < Pry::ClassCommand + class Globals < Pry::Command::Ls::Formatter + + # Taken from "puts global_variables.inspect". + BUILTIN_GLOBALS = + %w($" $$ $* $, $-0 $-F $-I $-K $-W $-a $-d $-i $-l $-p $-v $-w $. $/ $\\ + $: $; $< $= $> $0 $ARGV $CONSOLE $DEBUG $DEFAULT_INPUT $DEFAULT_OUTPUT + $FIELD_SEPARATOR $FILENAME $FS $IGNORECASE $INPUT_LINE_NUMBER + $INPUT_RECORD_SEPARATOR $KCODE $LOADED_FEATURES $LOAD_PATH $NR $OFS + $ORS $OUTPUT_FIELD_SEPARATOR $OUTPUT_RECORD_SEPARATOR $PID $PROCESS_ID + $PROGRAM_NAME $RS $VERBOSE $deferr $defout $stderr $stdin $stdout) + + # `$SAFE` and `$?` are thread-local, the exception stuff only works in a + # rescue clause, everything else is basically a local variable with a `$` + # in its name. + PSEUDO_GLOBALS = + %w($! $' $& $` $@ $? $+ $_ $~ $1 $2 $3 $4 $5 $6 $7 $8 $9 + $CHILD_STATUS $SAFE $ERROR_INFO $ERROR_POSITION $LAST_MATCH_INFO + $LAST_PAREN_MATCH $LAST_READ_LINE $MATCH $POSTMATCH $PREMATCH) + + def initialize(opts, _pry_) + super(_pry_) + @default_switch = opts[:globals] + end + + def output_self + variables = format(@target.eval('global_variables')) + output_section('global variables', grep.regexp[variables]) + end + + private + + def format(globals) + globals.map(&:to_s).sort_by(&:downcase).map do |name| + if PSEUDO_GLOBALS.include?(name) + color(:pseudo_global, name) + elsif BUILTIN_GLOBALS.include?(name) + color(:builtin_global, name) + else + color(:global_var, name) + end + end + end + + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/grep.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/grep.rb new file mode 100644 index 0000000..14e6b00 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/grep.rb @@ -0,0 +1,21 @@ +class Pry + class Command::Ls < Pry::ClassCommand + class Grep + + def initialize(grep_regexp) + @grep_regexp = grep_regexp + end + + def regexp + proc { |x| + if x.instance_of?(Array) + x.grep(@grep_regexp) + else + x =~ @grep_regexp + end + } + end + + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/instance_vars.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/instance_vars.rb new file mode 100644 index 0000000..2f33677 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/instance_vars.rb @@ -0,0 +1,39 @@ +require 'pry/commands/ls/interrogatable' + +class Pry + class Command::Ls < Pry::ClassCommand + class InstanceVars < Pry::Command::Ls::Formatter + include Pry::Command::Ls::Interrogatable + + def initialize(interrogatee, no_user_opts, opts, _pry_) + super(_pry_) + @interrogatee = interrogatee + @no_user_opts = no_user_opts + @default_switch = opts[:ivars] + end + + def correct_opts? + super || @no_user_opts + end + + def output_self + ivars = if Object === @interrogatee + Pry::Method.safe_send(@interrogatee, :instance_variables) + else + [] #TODO: BasicObject support + end + kvars = Pry::Method.safe_send(interrogatee_mod, :class_variables) + ivars_out = output_section('instance variables', format(:instance_var, ivars)) + kvars_out = output_section('class variables', format(:class_var, kvars)) + ivars_out + kvars_out + end + + private + + def format(type, vars) + vars.sort_by { |var| var.to_s.downcase }.map { |var| color(type, var) } + end + + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/interrogatable.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/interrogatable.rb new file mode 100644 index 0000000..5904d1b --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/interrogatable.rb @@ -0,0 +1,18 @@ +module Pry::Command::Ls::Interrogatable + + private + + def interrogating_a_module? + Module === @interrogatee + end + + def interrogatee_mod + if interrogating_a_module? + @interrogatee + else + singleton = Pry::Method.singleton_class_of(@interrogatee) + singleton.ancestors.grep(::Class).reject { |c| c == singleton }.first + end + end + +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/jruby_hacks.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/jruby_hacks.rb new file mode 100644 index 0000000..0f73e08 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/jruby_hacks.rb @@ -0,0 +1,49 @@ +module Pry::Command::Ls::JRubyHacks + + private + + # JRuby creates lots of aliases for methods imported from java in an attempt + # to make life easier for ruby programmers. (e.g. getFooBar becomes + # get_foo_bar and foo_bar, and maybe foo_bar? if it returns a Boolean). The + # full transformations are in the assignAliases method of: + # https://github.com/jruby/jruby/blob/master/src/org/jruby/javasupport/JavaClass.java + # + # This has the unfortunate side-effect of making the output of ls even more + # incredibly verbose than it normally would be for these objects; and so we + # filter out all but the nicest of these aliases here. + # + # TODO: This is a little bit vague, better heuristics could be used. + # JRuby also has a lot of scala-specific logic, which we don't copy. + def trim_jruby_aliases(methods) + grouped = methods.group_by do |m| + m.name.sub(/\A(is|get|set)(?=[A-Z_])/, '').gsub(/[_?=]/, '').downcase + end + + grouped.map do |key, values| + values = values.sort_by do |m| + rubbishness(m.name) + end + + found = [] + values.select do |x| + (!found.any? { |y| x == y }) && found << x + end + end.flatten(1) + end + + # When removing jruby aliases, we want to keep the alias that is + # "least rubbish" according to this metric. + def rubbishness(name) + name.each_char.map { |x| + case x + when /[A-Z]/ + 1 + when '?', '=', '!' + -2 + else + 0 + end + }.inject(&:+) + (name.size / 100.0) + end + +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/local_names.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/local_names.rb new file mode 100644 index 0000000..9d6350b --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/local_names.rb @@ -0,0 +1,35 @@ +class Pry + class Command::Ls < Pry::ClassCommand + class LocalNames < Pry::Command::Ls::Formatter + + def initialize(no_user_opts, args, _pry_) + super(_pry_) + @no_user_opts = no_user_opts + @args = args + @sticky_locals = _pry_.sticky_locals + end + + def correct_opts? + super || (@no_user_opts && @args.empty?) + end + + def output_self + local_vars = grep.regexp[@target.eval('local_variables')] + output_section('locals', format(local_vars)) + end + + private + + def format(locals) + locals.sort_by(&:downcase).map do |name| + if @sticky_locals.include?(name.to_sym) + color(:pry_var, name) + else + color(:local_var, name) + end + end + end + + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/local_vars.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/local_vars.rb new file mode 100644 index 0000000..d48ddae --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/local_vars.rb @@ -0,0 +1,39 @@ +class Pry + class Command::Ls < Pry::ClassCommand + class LocalVars < Pry::Command::Ls::Formatter + + def initialize(opts, _pry_) + super(_pry_) + @default_switch = opts[:locals] + @sticky_locals = _pry_.sticky_locals + end + + def output_self + name_value_pairs = @target.eval('local_variables').reject { |e| + @sticky_locals.keys.include?(e.to_sym) + }.map { |name| + [name, (@target.eval(name.to_s))] + } + format(name_value_pairs).join('') + end + + private + + def format(name_value_pairs) + name_value_pairs.sort_by { |name, value| + value.to_s.size + }.reverse.map { |name, value| + colorized_assignment_style(name, format_value(value)) + } + end + + def colorized_assignment_style(lhs, rhs, desired_width = 7) + colorized_lhs = color(:local_var, lhs) + color_escape_padding = colorized_lhs.size - lhs.size + pad = desired_width + color_escape_padding + "%-#{pad}s = %s" % [color(:local_var, colorized_lhs), rhs] + end + + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/ls_entity.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/ls_entity.rb new file mode 100644 index 0000000..3d69bcd --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/ls_entity.rb @@ -0,0 +1,70 @@ +require 'pry/commands/ls/grep' +require 'pry/commands/ls/formatter' +require 'pry/commands/ls/globals' +require 'pry/commands/ls/constants' +require 'pry/commands/ls/methods' +require 'pry/commands/ls/self_methods' +require 'pry/commands/ls/instance_vars' +require 'pry/commands/ls/local_names' +require 'pry/commands/ls/local_vars' + +class Pry + class Command::Ls < Pry::ClassCommand + + class LsEntity + attr_reader :_pry_ + + def initialize(opts) + @interrogatee = opts[:interrogatee] + @no_user_opts = opts[:no_user_opts] + @opts = opts[:opts] + @args = opts[:args] + @grep = Grep.new(Regexp.new(opts[:opts][:G] || '.')) + @_pry_ = opts.delete(:_pry_) + end + + def entities_table + entities.map(&:write_out).reject { |o| !o }.join('') + end + + private + + def grep(entity) + entity.tap { |o| o.grep = @grep } + end + + def globals + grep Globals.new(@opts, _pry_) + end + + def constants + grep Constants.new(@interrogatee, @no_user_opts, @opts, _pry_) + end + + def methods + grep(Methods.new(@interrogatee, @no_user_opts, @opts, _pry_)) + end + + def self_methods + grep SelfMethods.new(@interrogatee, @no_user_opts, @opts, _pry_) + end + + def instance_vars + grep InstanceVars.new(@interrogatee, @no_user_opts, @opts, _pry_) + end + + def local_names + grep LocalNames.new(@no_user_opts, @args, _pry_) + end + + def local_vars + LocalVars.new(@opts, _pry_) + end + + def entities + [globals, constants, methods, self_methods, instance_vars, local_names, + local_vars] + end + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/methods.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/methods.rb new file mode 100644 index 0000000..c085f42 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/methods.rb @@ -0,0 +1,57 @@ +require 'pry/commands/ls/methods_helper' +require 'pry/commands/ls/interrogatable' + +class Pry + class Command::Ls < Pry::ClassCommand + class Methods < Pry::Command::Ls::Formatter + + include Pry::Command::Ls::Interrogatable + include Pry::Command::Ls::MethodsHelper + + def initialize(interrogatee, no_user_opts, opts, _pry_) + super(_pry_) + @interrogatee = interrogatee + @no_user_opts = no_user_opts + @default_switch = opts[:methods] + @instance_methods_switch = opts['instance-methods'] + @ppp_switch = opts[:ppp] + @jruby_switch = opts['all-java'] + @quiet_switch = opts[:quiet] + @verbose_switch = opts[:verbose] + end + + def output_self + methods = all_methods.group_by(&:owner) + # Reverse the resolution order so that the most useful information + # appears right by the prompt. + resolution_order.take_while(&below_ceiling).reverse.map do |klass| + methods_here = (methods[klass] || []).select { |m| grep.regexp[m.name] } + heading = "#{ Pry::WrappedModule.new(klass).method_prefix }methods" + output_section(heading, format(methods_here)) + end.join('') + end + + private + + def correct_opts? + super || @instance_methods_switch || @ppp_switch || @no_user_opts + end + + + # Get a lambda that can be used with `take_while` to prevent over-eager + # traversal of the Object's ancestry graph. + def below_ceiling + ceiling = if @quiet_switch + [Pry::Method.safe_send(interrogatee_mod, :ancestors)[1]] + + _pry_.config.ls.ceiling + elsif @verbose_switch + [] + else + _pry_.config.ls.ceiling.dup + end + lambda { |klass| !ceiling.include?(klass) } + end + + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/methods_helper.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/methods_helper.rb new file mode 100644 index 0000000..f0b4414 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/methods_helper.rb @@ -0,0 +1,46 @@ +require 'pry/commands/ls/jruby_hacks' + +module Pry::Command::Ls::MethodsHelper + + include Pry::Command::Ls::JRubyHacks + + private + + # Get all the methods that we'll want to output. + def all_methods(instance_methods = false) + methods = if instance_methods || @instance_methods_switch + Pry::Method.all_from_class(@interrogatee) + else + Pry::Method.all_from_obj(@interrogatee) + end + + if Pry::Helpers::BaseHelpers.jruby? && !@jruby_switch + methods = trim_jruby_aliases(methods) + end + + methods.select { |method| @ppp_switch || method.visibility == :public } + end + + def resolution_order + if @instance_methods_switch + Pry::Method.instance_resolution_order(@interrogatee) + else + Pry::Method.resolution_order(@interrogatee) + end + end + + def format(methods) + methods.sort_by(&:name).map do |method| + if method.name == 'method_missing' + color(:method_missing, 'method_missing') + elsif method.visibility == :private + color(:private_method, method.name) + elsif method.visibility == :protected + color(:protected_method, method.name) + else + color(:public_method, method.name) + end + end + end + +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/self_methods.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/self_methods.rb new file mode 100644 index 0000000..91f3490 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/ls/self_methods.rb @@ -0,0 +1,32 @@ +require 'pry/commands/ls/interrogatable' +require 'pry/commands/ls/methods_helper' + +class Pry + class Command::Ls < Pry::ClassCommand + class SelfMethods < Pry::Command::Ls::Formatter + include Pry::Command::Ls::Interrogatable + include Pry::Command::Ls::MethodsHelper + + def initialize(interrogatee, no_user_opts, opts, _pry_) + super(_pry_) + @interrogatee = interrogatee + @no_user_opts = no_user_opts + end + + def output_self + methods = all_methods(true).select do |m| + m.owner == @interrogatee && grep.regexp[m.name] + end + heading = "#{ Pry::WrappedModule.new(@interrogatee).method_prefix }methods" + output_section(heading, format(methods)) + end + + private + + def correct_opts? + @no_user_opts && interrogating_a_module? + end + + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/nesting.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/nesting.rb new file mode 100644 index 0000000..f9c0297 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/nesting.rb @@ -0,0 +1,25 @@ +class Pry + class Command::Nesting < Pry::ClassCommand + match 'nesting' + group 'Navigating Pry' + description 'Show nesting information.' + + banner <<-'BANNER' + Show nesting information. + BANNER + + def process + output.puts 'Nesting status:' + output.puts '--' + _pry_.binding_stack.each_with_index do |obj, level| + if level == 0 + output.puts "#{level}. #{Pry.view_clip(obj.eval('self'))} (Pry top level)" + else + output.puts "#{level}. #{Pry.view_clip(obj.eval('self'))}" + end + end + end + end + + Pry::Commands.add_command(Pry::Command::Nesting) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/play.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/play.rb new file mode 100644 index 0000000..5498d38 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/play.rb @@ -0,0 +1,103 @@ +class Pry + class Command::Play < Pry::ClassCommand + match 'play' + group 'Editing' + description 'Playback a string variable, method, line, or file as input.' + + banner <<-'BANNER' + Usage: play [OPTIONS] [--help] + + The play command enables you to replay code from files and methods as if they + were entered directly in the Pry REPL. + + play --lines 149..153 # assumes current context + play -i 20 --lines 1..3 # assumes lines of the input expression at 20 + play -o 4 # the output of of an expression at 4 + play Pry#repl -l 1..-1 # play the contents of Pry#repl method + play -e 2 # play from specified line until end of valid expression + play hello.rb # play a file + play Rakefile -l 5 # play line 5 of a file + play -d hi # play documentation of hi method + play hi --open # play hi method and leave it open + + https://github.com/pry/pry/wiki/User-Input#wiki-Play + BANNER + + def options(opt) + CodeCollector.inject_options(opt) + + opt.on :open, 'Plays the selected content except the last line. Useful' \ + ' for replaying methods and leaving the method definition' \ + ' "open". `amend-line` can then be used to' \ + ' modify the method.' + + opt.on :e, :expression=, 'Executes until end of valid expression', :as => Integer + opt.on :p, :print, 'Prints executed code' + end + + def process + @cc = CodeCollector.new(args, opts, _pry_) + + perform_play + show_input + end + + def perform_play + eval_string << content_after_options + run "fix-indent" + end + + def show_input + if opts.present?(:print) or !Pry::Code.complete_expression?(eval_string) + run "show-input" + end + end + + + def content_after_options + if opts.present?(:open) + restrict_to_lines(content, (0..-2)) + elsif opts.present?(:expression) + content_at_expression + else + content + end + end + + def content_at_expression + code_object.expression_at(opts[:expression]) + end + + def code_object + Pry::Code.new(content) + end + + def should_use_default_file? + !args.first && !opts.present?(:in) && !opts.present?(:out) + end + + def content + if should_use_default_file? + file_content + else + @cc.content + end + end + + # The file to play from when no code object is specified. + # e.g `play --lines 4..10` + def default_file + target.eval("__FILE__") && File.expand_path(target.eval("__FILE__")) + end + + def file_content + if default_file && File.exists?(default_file) + @cc.restrict_to_lines(File.read(default_file), @cc.line_range) + else + raise CommandError, "File does not exist! File was: #{default_file.inspect}" + end + end + end + + Pry::Commands.add_command(Pry::Command::Play) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/pry_backtrace.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/pry_backtrace.rb new file mode 100644 index 0000000..6795aa3 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/pry_backtrace.rb @@ -0,0 +1,25 @@ +class Pry + class Command::PryBacktrace < Pry::ClassCommand + match 'pry-backtrace' + group 'Context' + description 'Show the backtrace for the Pry session.' + + banner <<-BANNER + Usage: pry-backtrace [OPTIONS] [--help] + + Show the backtrace for the position in the code where Pry was started. This can + be used to infer the behavior of the program immediately before it entered Pry, + just like the backtrace property of an exception. + + NOTE: if you are looking for the backtrace of the most recent exception raised, + just type: `_ex_.backtrace` instead. + See: https://github.com/pry/pry/wiki/Special-Locals + BANNER + + def process + _pry_.pager.page text.bold('Backtrace:') << "\n--\n" << _pry_.backtrace.join("\n") + end + end + + Pry::Commands.add_command(Pry::Command::PryBacktrace) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/pry_version.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/pry_version.rb new file mode 100644 index 0000000..8cb8fd8 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/pry_version.rb @@ -0,0 +1,17 @@ +class Pry + class Command::Version < Pry::ClassCommand + match 'pry-version' + group 'Misc' + description 'Show Pry version.' + + banner <<-'BANNER' + Show Pry version. + BANNER + + def process + output.puts "Pry version: #{Pry::VERSION} on Ruby #{RUBY_VERSION}." + end + end + + Pry::Commands.add_command(Pry::Command::Version) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/raise_up.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/raise_up.rb new file mode 100644 index 0000000..70ad087 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/raise_up.rb @@ -0,0 +1,32 @@ +class Pry + # N.B. using a regular expresion here so that "raise-up 'foo'" does the right thing. + class Command::RaiseUp < Pry::ClassCommand + match(/raise-up(!?\b.*)/) + group 'Context' + description 'Raise an exception out of the current pry instance.' + command_options :listing => 'raise-up' + + banner <<-BANNER + Raise up, like exit, allows you to quit pry. Instead of returning a value + however, it raises an exception. If you don't provide the exception to be + raised, it will use the most recent exception (in pry `_ex_`). + + When called as raise-up! (with an exclamation mark), this command raises the + exception through any nested prys you have created by "cd"ing into objects. + + raise-up "get-me-out-of-here" + + # This is equivalent to the command above. + raise "get-me-out-of-here" + raise-up + BANNER + + def process + return _pry.pager.page help if captures[0] =~ /(-h|--help)\b/ + # Handle 'raise-up', 'raise-up "foo"', 'raise-up RuntimeError, 'farble' in a rubyesque manner + target.eval("_pry_.raise_up#{captures[0]}") + end + end + + Pry::Commands.add_command(Pry::Command::RaiseUp) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/reload_code.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/reload_code.rb new file mode 100644 index 0000000..7041338 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/reload_code.rb @@ -0,0 +1,62 @@ +class Pry + class Command::ReloadCode < Pry::ClassCommand + match 'reload-code' + group 'Misc' + description 'Reload the source file that contains the specified code object.' + + banner <<-'BANNER' + Reload the source file that contains the specified code object. + + e.g reload-code MyClass#my_method #=> reload a method + reload-code MyClass #=> reload a class + reload-code my-command #=> reload a pry command + reload-code self #=> reload the current object + reload-code #=> reload the current file or object + BANNER + + def process + if !args.empty? + reload_object(args.join(" ")) + elsif internal_binding?(target) + reload_object("self") + else + reload_current_file + end + end + + private + + def current_file + File.expand_path target.eval("__FILE__") + end + + def reload_current_file + if !File.exists?(current_file) + raise CommandError, "Current file: #{current_file} cannot be found on disk!" + end + + load current_file + output.puts "The current file: #{current_file} was reloaded!" + end + + def reload_object(identifier) + code_object = Pry::CodeObject.lookup(identifier, _pry_) + check_for_reloadability(code_object, identifier) + load code_object.source_file + output.puts "#{identifier} was reloaded!" + end + + def check_for_reloadability(code_object, identifier) + if !code_object || !code_object.source_file + raise CommandError, "Cannot locate #{identifier}!" + elsif !File.exists?(code_object.source_file) + raise CommandError, + "Cannot reload #{identifier} as it has no associated file on disk. " \ + "File found was: #{code_object.source_file}" + end + end + end + + Pry::Commands.add_command(Pry::Command::ReloadCode) + Pry::Commands.alias_command 'reload-method', 'reload-code' +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/reset.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/reset.rb new file mode 100644 index 0000000..4414cbb --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/reset.rb @@ -0,0 +1,18 @@ +class Pry + class Command::Reset < Pry::ClassCommand + match 'reset' + group 'Context' + description 'Reset the REPL to a clean state.' + + banner <<-'BANNER' + Reset the REPL to a clean state. + BANNER + + def process + output.puts 'Pry reset.' + exec 'pry' + end + end + + Pry::Commands.add_command(Pry::Command::Reset) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/ri.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/ri.rb new file mode 100644 index 0000000..d29c426 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/ri.rb @@ -0,0 +1,60 @@ +class Pry + class Command::Ri < Pry::ClassCommand + match 'ri' + group 'Introspection' + description 'View ri documentation.' + + banner <<-'BANNER' + Usage: ri [spec] + + View ri documentation. Relies on the "rdoc" gem being installed. + See also "show-doc" command. + + ri Array#each + BANNER + + def process(spec) + # Lazily load RI + require 'rdoc/ri/driver' + + unless defined? RDoc::RI::PryDriver + + # Subclass RI so that it formats its output nicely, and uses `lesspipe`. + subclass = Class.new(RDoc::RI::Driver) # the hard way. + + subclass.class_eval do + def initialize(pager, opts) + @pager = pager + super opts + end + def page + paging_text = StringIO.new + yield paging_text + @pager.page(paging_text.string) + end + + def formatter(io) + if @formatter_klass + @formatter_klass.new + else + RDoc::Markup::ToAnsi.new + end + end + end + + RDoc::RI.const_set :PryDriver, subclass # hook it up! + end + + # Spin-up an RI insance. + ri = RDoc::RI::PryDriver.new _pry_.pager, :use_stdout => true, :interactive => false + + begin + ri.display_names [spec] # Get the documentation (finally!) + rescue RDoc::RI::Driver::NotFoundError => e + output.puts "error: '#{e.name}' not found" + end + end + end + + Pry::Commands.add_command(Pry::Command::Ri) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/save_file.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/save_file.rb new file mode 100644 index 0000000..d22a692 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/save_file.rb @@ -0,0 +1,61 @@ +require 'pry/commands/code_collector' + +class Pry + class Command::SaveFile < Pry::ClassCommand + match 'save-file' + group 'Input and Output' + description 'Export to a file using content from the REPL.' + + banner <<-'BANNER' + Usage: save-file [OPTIONS] --to [FILE] + + Export to a file using content from the REPL. + + save-file my_method --to hello.rb + save-file -i 1..10 --to hello.rb --append + save-file show-method --to my_command.rb + save-file sample_file.rb --lines 2..10 --to output_file.rb + BANNER + + def options(opt) + CodeCollector.inject_options(opt) + + opt.on :to=, "Specify the output file path" + opt.on :a, :append, "Append output to file" + end + + def process + @cc = CodeCollector.new(args, opts, _pry_) + raise CommandError, "Found no code to save." if @cc.content.empty? + + if !file_name + display_content + else + save_file + end + end + + def file_name + opts[:to] || nil + end + + def save_file + File.open(file_name, mode) do |f| + f.puts @cc.content + end + output.puts "#{file_name} successfully saved" + end + + def display_content + output.puts @cc.content + output.puts "\n\n--\nPlease use `--to FILE` to export to a file." + output.puts "No file saved!\n--" + end + + def mode + opts.present?(:append) ? "a" : "w" + end + end + + Pry::Commands.add_command(Pry::Command::SaveFile) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/shell_command.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/shell_command.rb new file mode 100644 index 0000000..78fccd5 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/shell_command.rb @@ -0,0 +1,48 @@ +class Pry + class Command::ShellCommand < Pry::ClassCommand + match(/\.(.*)/) + group 'Input and Output' + description "All text following a '.' is forwarded to the shell." + command_options :listing => '.', :use_prefix => false, + :takes_block => true + + banner <<-'BANNER' + Usage: .COMMAND_NAME + + All text following a "." is forwarded to the shell. + + .ls -aF + .uname + BANNER + + def process(cmd) + if cmd =~ /^cd\s*(.*)/i + process_cd parse_destination($1) + else + pass_block(cmd) + if command_block + command_block.call `#{cmd}` + else + _pry_.config.system.call(output, cmd, _pry_) + end + end + end + + private + + def parse_destination(dest) + return "~" if dest.empty? + return dest unless dest == "-" + state.old_pwd || raise(CommandError, "No prior directory available") + end + + def process_cd(dest) + state.old_pwd = Dir.pwd + Dir.chdir File.expand_path(dest) + rescue Errno::ENOENT + raise CommandError, "No such directory: #{dest}" + end + end + + Pry::Commands.add_command(Pry::Command::ShellCommand) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/shell_mode.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/shell_mode.rb new file mode 100644 index 0000000..ee521d3 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/shell_mode.rb @@ -0,0 +1,25 @@ +class Pry + class Command::ShellMode < Pry::ClassCommand + match 'shell-mode' + group 'Input and Output' + description 'Toggle shell mode. Bring in pwd prompt and file completion.' + + banner <<-'BANNER' + Toggle shell mode. Bring in pwd prompt and file completion. + BANNER + + def process + case _pry_.prompt + when Pry::SHELL_PROMPT + _pry_.pop_prompt + _pry_.custom_completions = _pry_.config.file_completions + else + _pry_.push_prompt Pry::SHELL_PROMPT + _pry_.custom_completions = _pry_.config.command_completions + end + end + end + + Pry::Commands.add_command(Pry::Command::ShellMode) + Pry::Commands.alias_command 'file-mode', 'shell-mode' +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/show_doc.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/show_doc.rb new file mode 100644 index 0000000..4969bcd --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/show_doc.rb @@ -0,0 +1,83 @@ +require 'pry/commands/show_info' + +class Pry + class Command::ShowDoc < Command::ShowInfo + include Pry::Helpers::DocumentationHelpers + + match 'show-doc' + group 'Introspection' + description 'Show the documentation for a method or class.' + + banner <<-BANNER + Usage: show-doc [OPTIONS] [METH] + Aliases: ? + + Show the documentation for a method or class. Tries instance methods first and + then methods by default. + + show-doc hi_method # docs for hi_method + show-doc Pry # for Pry class + show-doc Pry -a # for all definitions of Pry class (all monkey patches) + BANNER + + # The docs for code_object prepared for display. + def content_for(code_object) + Code.new(render_doc_markup_for(code_object), + start_line_for(code_object), :text). + with_line_numbers(use_line_numbers?).to_s + end + + # process the markup (if necessary) and apply colors + def render_doc_markup_for(code_object) + docs = docs_for(code_object) + + if code_object.command? + # command '--help' shouldn't use markup highlighting + docs + else + if docs.empty? + raise CommandError, "No docs found for: #{ + obj_name ? obj_name : 'current context' + }" + end + process_comment_markup(docs) + end + end + + # Return docs for the code_object, adjusting for whether the code_object + # has yard docs available, in which case it returns those. + # (note we only have to check yard docs for modules since they can + # have multiple docs, but methods can only be doc'd once so we + # dont need to check them) + def docs_for(code_object) + if code_object.module_with_yard_docs? + # yard docs + code_object.yard_doc + else + # normal docs (i.e comments above method/module/command) + code_object.doc + end + end + + # Which sections to include in the 'header', can toggle: :owner, + # :signature and visibility. + def header_options + super.merge :signature => true + end + + # figure out start line of docs by back-calculating based on + # number of lines in the comment and the start line of the code_object + # @return [Fixnum] start line of docs + def start_line_for(code_object) + if code_object.command? || opts.present?(:'base-one') + 1 + else + code_object.source_line.nil? ? 1 : + (code_object.source_line - code_object.doc.lines.count) + end + end + end + + Pry::Commands.add_command(Pry::Command::ShowDoc) + Pry::Commands.alias_command '?', 'show-doc' +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/show_info.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/show_info.rb new file mode 100644 index 0000000..92958cb --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/show_info.rb @@ -0,0 +1,195 @@ +class Pry + class Command::ShowInfo < Pry::ClassCommand + extend Pry::Helpers::BaseHelpers + + command_options :shellwords => false, :interpolate => false + + def options(opt) + opt.on :s, :super, "Select the 'super' method. Can be repeated to traverse the ancestors", :as => :count + opt.on :l, "line-numbers", "Show line numbers" + opt.on :b, "base-one", "Show line numbers but start numbering at 1 (useful for `amend-line` and `play` commands)" + opt.on :a, :all, "Show all definitions and monkeypatches of the module/class" + end + + def process + code_object = Pry::CodeObject.lookup(obj_name, _pry_, :super => opts[:super]) + raise CommandError, no_definition_message if !code_object + @original_code_object = code_object + + if show_all_modules?(code_object) + # show all monkey patches for a module + + result = content_and_headers_for_all_module_candidates(code_object) + else + # show a specific code object + co = code_object_with_accessible_source(code_object) + result = content_and_header_for_code_object(co) + end + + set_file_and_dir_locals(code_object.source_file) + _pry_.pager.page result + end + + # This method checks whether the `code_object` is a WrappedModule, + # if it is, then it returns the first candidate (monkeypatch) with + # accessible source (or docs). If `code_object` is not a WrappedModule (i.e a + # method or a command) then the `code_object` itself is just + # returned. + # + # @return [Pry::WrappedModule, Pry::Method, Pry::Command] + def code_object_with_accessible_source(code_object) + if code_object.is_a?(WrappedModule) + candidate = code_object.candidates.find(&:source) + if candidate + return candidate + else + raise CommandError, no_definition_message if !valid_superclass?(code_object) + + @used_super = true + code_object_with_accessible_source(code_object.super) + end + else + code_object + end + end + + def valid_superclass?(code_object) + code_object.super && code_object.super.wrapped != Object + end + + def content_and_header_for_code_object(code_object) + header(code_object) << content_for(code_object) + end + + def content_and_headers_for_all_module_candidates(mod) + result = "Found #{mod.number_of_candidates} candidates for `#{mod.name}` definition:\n" + mod.number_of_candidates.times do |v| + candidate = mod.candidate(v) + begin + result << "\nCandidate #{v+1}/#{mod.number_of_candidates}: #{candidate.source_file} @ line #{candidate.source_line}:\n" + content = content_for(candidate) + + result << "Number of lines: #{content.lines.count}\n\n" << content + rescue Pry::RescuableException + result << "\nNo content found.\n" + next + end + end + result + end + + def no_definition_message + "Couldn't locate a definition for #{obj_name}!" + end + + # Generate a header (meta-data information) for all the code + # object types: methods, modules, commands, procs... + def header(code_object) + file_name, line_num = file_and_line_for(code_object) + h = "\n#{Pry::Helpers::Text.bold('From:')} #{file_name} " + h << code_object_header(code_object, line_num) + h << "\n#{Pry::Helpers::Text.bold('Number of lines:')} " << + "#{content_for(code_object).lines.count}\n\n" + h << Helpers::Text.bold('** Warning:') << " Cannot find code for #{@original_code_object.nonblank_name}. Showing superclass #{code_object.nonblank_name} instead. **\n\n" if @used_super + h + end + + def code_object_header(code_object, line_num) + if code_object.real_method_object? + method_header(code_object, line_num) + + # It sucks we have to test for both Pry::WrappedModule and WrappedModule::Candidate, + # probably indicates a deep refactor needs to happen in those classes. + elsif code_object.is_a?(Pry::WrappedModule) || code_object.is_a?(Pry::WrappedModule::Candidate) + module_header(code_object, line_num) + else + "" + end + end + + def method_header(code_object, line_num) + h = "" + h << (code_object.c_method? ? "(C Method):" : "@ line #{line_num}:") + h << method_sections(code_object)[:owner] + h << method_sections(code_object)[:visibility] + h << method_sections(code_object)[:signature] + h + end + + def module_header(code_object, line_num) + h = "" + h << "@ line #{line_num}:\n" + h << text.bold(code_object.module? ? "Module" : "Class") + h << " #{text.bold('name:')} #{code_object.nonblank_name}" + + if code_object.number_of_candidates > 1 + h << (text.bold("\nNumber of monkeypatches: ") << code_object.number_of_candidates.to_s) + h << ". Use the `-a` option to display all available monkeypatches" + end + h + end + + def method_sections(code_object) + { + :owner => "\n#{text.bold("Owner:")} #{code_object.owner || "N/A"}\n", + :visibility => "#{text.bold("Visibility:")} #{code_object.visibility}", + :signature => "\n#{text.bold("Signature:")} #{code_object.signature}" + }.merge(header_options) { |key, old, new| (new && old).to_s } + end + + def header_options + { + :owner => true, + :visibility => true, + :signature => nil + } + end + + def show_all_modules?(code_object) + code_object.is_a?(Pry::WrappedModule) && opts.present?(:all) + end + + def obj_name + @obj_name ||= args.empty? ? nil : args.join(' ') + end + + def use_line_numbers? + opts.present?(:b) || opts.present?(:l) + end + + def start_line_for(code_object) + if opts.present?(:'base-one') + 1 + else + code_object.source_line || 1 + end + end + + # takes into account possible yard docs, and returns yard_file / yard_line + # Also adjusts for start line of comments (using start_line_for), which it has to infer + # by subtracting number of lines of comment from start line of code_object + def file_and_line_for(code_object) + if code_object.module_with_yard_docs? + [code_object.yard_file, code_object.yard_line] + else + [code_object.source_file, start_line_for(code_object)] + end + end + + def complete(input) + if input =~ /([^ ]*)#([a-z0-9_]*)\z/ + prefix, search = [$1, $2] + methods = begin + Pry::Method.all_from_class(binding.eval(prefix)) + rescue RescuableException + return super + end + methods.map do |method| + [prefix, method.name].join('#') if method.name.start_with?(search) + end.compact + else + super + end + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/show_input.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/show_input.rb new file mode 100644 index 0000000..8b72787 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/show_input.rb @@ -0,0 +1,17 @@ +class Pry + class Command::ShowInput < Pry::ClassCommand + match 'show-input' + group 'Editing' + description 'Show the contents of the input buffer for the current multi-line expression.' + + banner <<-'BANNER' + Show the contents of the input buffer for the current multi-line expression. + BANNER + + def process + output.puts Code.new(eval_string).with_line_numbers + end + end + + Pry::Commands.add_command(Pry::Command::ShowInput) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/show_source.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/show_source.rb new file mode 100644 index 0000000..f8e3a5b --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/show_source.rb @@ -0,0 +1,50 @@ +require 'pry/commands/show_info' + +class Pry + class Command::ShowSource < Command::ShowInfo + match 'show-source' + group 'Introspection' + description 'Show the source for a method or class.' + + banner <<-'BANNER' + Usage: show-source [OPTIONS] [METH|CLASS] + Aliases: $, show-method + + Show the source for a method or class. Tries instance methods first and then + methods by default. + + show-source hi_method + show-source hi_method + show-source Pry#rep # source for Pry#rep method + show-source Pry # for Pry class + show-source Pry -a # for all Pry class definitions (all monkey patches) + show-source Pry.foo -e # for class of the return value of expression `Pry.foo` + show-source Pry --super # for superclass of Pry (Object class) + + https://github.com/pry/pry/wiki/Source-browsing#wiki-Show_method + BANNER + + def options(opt) + opt.on :e, :eval, "evaluate the command's argument as a ruby expression and show the class its return value" + super(opt) + end + + def process + if opts.present?(:e) + obj = target.eval(args.first) + self.args = Array.new(1) { Module === obj ? obj.name : obj.class.name } + end + super + end + + # The source for code_object prepared for display. + def content_for(code_object) + Code.new(code_object.source, start_line_for(code_object)). + with_line_numbers(use_line_numbers?).highlighted + end + end + + Pry::Commands.add_command(Pry::Command::ShowSource) + Pry::Commands.alias_command 'show-method', 'show-source' + Pry::Commands.alias_command '$', 'show-source' +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/simple_prompt.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/simple_prompt.rb new file mode 100644 index 0000000..4d1e6ec --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/simple_prompt.rb @@ -0,0 +1,22 @@ +class Pry + class Command::SimplePrompt < Pry::ClassCommand + match 'simple-prompt' + group 'prompts' + description 'Toggle the simple prompt.' + + banner <<-'BANNER' + Toggle the simple prompt. + BANNER + + def process + case _pry_.prompt + when Pry::SIMPLE_PROMPT + _pry_.pop_prompt + else + _pry_.push_prompt Pry::SIMPLE_PROMPT + end + end + end + + Pry::Commands.add_command(Pry::Command::SimplePrompt) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/stat.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/stat.rb new file mode 100644 index 0000000..06a191b --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/stat.rb @@ -0,0 +1,40 @@ +class Pry + class Command::Stat < Pry::ClassCommand + match 'stat' + group 'Introspection' + description 'View method information and set _file_ and _dir_ locals.' + command_options :shellwords => false + + banner <<-'BANNER' + Usage: stat [OPTIONS] [METH] + + Show method information for method METH and set _file_ and _dir_ locals. + + stat hello_method + BANNER + + def options(opt) + method_options(opt) + end + + def process + meth = method_object + aliases = meth.aliases + + output.puts unindent <<-EOS + Method Information: + -- + Name: #{meth.name} + Alias#{ "es" if aliases.length > 1 }: #{ aliases.any? ? aliases.join(", ") : "None." } + Owner: #{meth.owner ? meth.owner : "Unknown"} + Visibility: #{meth.visibility} + Type: #{meth.is_a?(::Method) ? "Bound" : "Unbound"} + Arity: #{meth.arity} + Method Signature: #{meth.signature} + Source Location: #{meth.source_location ? meth.source_location.join(":") : "Not found."} + EOS + end + end + + Pry::Commands.add_command(Pry::Command::Stat) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/switch_to.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/switch_to.rb new file mode 100644 index 0000000..ad3e71c --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/switch_to.rb @@ -0,0 +1,23 @@ +class Pry + class Command::SwitchTo < Pry::ClassCommand + match 'switch-to' + group 'Navigating Pry' + description 'Start a new subsession on a binding in the current stack.' + + banner <<-'BANNER' + Start a new subsession on a binding in the current stack (numbered by nesting). + BANNER + + def process(selection) + selection = selection.to_i + + if selection < 0 || selection > _pry_.binding_stack.size - 1 + raise CommandError, "Invalid binding index #{selection} - use `nesting` command to view valid indices." + else + Pry.start(_pry_.binding_stack[selection]) + end + end + end + + Pry::Commands.add_command(Pry::Command::SwitchTo) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/toggle_color.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/toggle_color.rb new file mode 100644 index 0000000..602c293 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/toggle_color.rb @@ -0,0 +1,24 @@ +class Pry + class Command::ToggleColor < Pry::ClassCommand + match 'toggle-color' + group 'Misc' + description 'Toggle syntax highlighting.' + + banner <<-'BANNER' + Usage: toggle-color + + Toggle syntax highlighting. + BANNER + + def process + _pry_.color = color_toggle + output.puts "Syntax highlighting #{_pry_.color ? "on" : "off"}" + end + + def color_toggle + !_pry_.color + end + + Pry::Commands.add_command(self) + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/watch_expression.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/watch_expression.rb new file mode 100644 index 0000000..d93b7c7 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/watch_expression.rb @@ -0,0 +1,105 @@ +class Pry + class Command::WatchExpression < Pry::ClassCommand + require 'pry/commands/watch_expression/expression.rb' + + match 'watch' + group 'Context' + description 'Watch the value of an expression and print a notification whenever it changes.' + command_options :use_prefix => false + + banner <<-'BANNER' + Usage: watch [EXPRESSION] + watch + watch --delete [INDEX] + + watch [EXPRESSION] adds an expression to the list of those being watched. + It will be re-evaluated every time you hit enter in pry. If its value has + changed, the new value will be printed to the console. + + This is useful if you are step-through debugging and want to see how + something changes over time. It's also useful if you're trying to write + a method inside pry and want to check that it gives the right answers + every time you redefine it. + + watch on its own displays all the currently watched expressions and their + values, and watch --delete [INDEX] allows you to delete expressions from + the list being watched. + BANNER + + def options(opt) + opt.on :d, :delete, + "Delete the watch expression with the given index. If no index is given; clear all watch expressions.", + :optional_argument => true, :as => Integer + opt.on :l, :list, + "Show all current watch expressions and their values. Calling watch with no expressions or options will also show the watch expressions." + end + + def process + case + when opts.present?(:delete) + delete opts[:delete] + when opts.present?(:list) || args.empty? + list + else + add_hook + add_expression(args) + end + end + + private + + def expressions + _pry_.config.watch_expressions ||= [] + end + + def delete(index) + if index + output.puts "Deleting watch expression ##{index}: #{expressions[index-1]}" + expressions.delete_at(index-1) + else + output.puts "Deleting all watched expressions" + expressions.clear + end + end + + def list + if expressions.empty? + output.puts "No watched expressions" + else + _pry_.pager.open do |pager| + pager.puts "Listing all watched expressions:" + pager.puts "" + expressions.each_with_index do |expr, index| + pager.print text.with_line_numbers(expr.to_s, index+1) + end + pager.puts "" + end + end + end + + def eval_and_print_changed(output) + expressions.each do |expr| + expr.eval! + if expr.changed? + output.puts "#{text.blue "watch"}: #{expr.to_s}" + end + end + end + + def add_expression(arguments) + expressions << Expression.new(_pry_, target, arg_string) + output.puts "Watching #{Code.new(arg_string).highlighted}" + end + + def add_hook + hook = [:after_eval, :watch_expression] + unless _pry_.hooks.hook_exists?(*hook) + _pry_.hooks.add_hook(*hook) do |_, _pry_| + eval_and_print_changed _pry_.output + end + end + end + end + + Pry::Commands.add_command(Pry::Command::WatchExpression) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/watch_expression/expression.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/watch_expression/expression.rb new file mode 100644 index 0000000..514b95d --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/watch_expression/expression.rb @@ -0,0 +1,38 @@ +class Pry + class Command::WatchExpression + class Expression + attr_reader :target, :source, :value, :previous_value, :_pry_ + + def initialize(_pry_, target, source) + @_pry_ = _pry_ + @target = target + @source = Code.new(source).strip + end + + def eval! + @previous_value = @value + @value = Pry::ColorPrinter.pp(target_eval(target, source), "") + end + + def to_s + "#{Code.new(source).highlighted.strip} => #{value}" + end + + # Has the value of the expression changed? + # + # We use the pretty-printed string represenation to detect differences + # as this avoids problems with dup (causes too many differences) and == (causes too few) + def changed? + (value != previous_value) + end + + private + + def target_eval(target, source) + target.eval(source) + rescue => e + e + end + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/whereami.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/whereami.rb new file mode 100644 index 0000000..ac70164 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/whereami.rb @@ -0,0 +1,190 @@ +class Pry + class Command::Whereami < Pry::ClassCommand + + class << self + attr_accessor :method_size_cutoff + end + + @method_size_cutoff = 30 + + match 'whereami' + description 'Show code surrounding the current context.' + group 'Context' + + banner <<-'BANNER' + Usage: whereami [-qn] [LINES] + + Describe the current location. If you use `binding.pry` inside a method then + whereami will print out the source for that method. + + If a number is passed, then LINES lines before and after the current line will be + shown instead of the method itself. + + The `-q` flag can be used to suppress error messages in the case that there's + no code to show. This is used by pry in the default before_session hook to show + you when you arrive at a `binding.pry`. + + The `-n` flag can be used to hide line numbers so that code can be copy/pasted + effectively. + + When pry was started on an Object and there is no associated method, whereami + will instead output a brief description of the current object. + BANNER + + def setup + @file = expand_path(target.eval('__FILE__')) + @line = target.eval('__LINE__') + @method = Pry::Method.from_binding(target) + end + + def options(opt) + opt.on :q, :quiet, "Don't display anything in case of an error" + opt.on :n, :"no-line-numbers", "Do not display line numbers" + opt.on :m, :"method", "Show the complete source for the current method." + opt.on :c, :"class", "Show the complete source for the current class or module." + opt.on :f, :"file", "Show the complete source for the current file." + end + + def code + @code ||= if opts.present?(:m) + method_code or raise CommandError, "Cannot find method code." + elsif opts.present?(:c) + class_code or raise CommandError, "Cannot find class code." + elsif opts.present?(:f) + Pry::Code.from_file(@file) + elsif args.any? + code_window + else + default_code + end + end + + def code? + !!code + rescue MethodSource::SourceNotFoundError + false + end + + def bad_option_combination? + [opts.present?(:m), opts.present?(:f), + opts.present?(:c), args.any?].count(true) > 1 + end + + def location + "#{@file} @ line #{@line} #{@method && @method.name_with_owner}" + end + + def process + if bad_option_combination? + raise CommandError, "Only one of -m, -c, -f, and LINES may be specified." + end + + if nothing_to_do? + return + elsif internal_binding?(target) + handle_internal_binding + return + end + + set_file_and_dir_locals(@file) + + out = "\n#{text.bold('From:')} #{location}:\n\n" << + code.with_line_numbers(use_line_numbers?).with_marker(marker).highlighted << "\n" + + _pry_.pager.page out + end + + private + + def nothing_to_do? + opts.quiet? && (internal_binding?(target) || !code?) + end + + def use_line_numbers? + !opts.present?(:n) + end + + def marker + !opts.present?(:n) && @line + end + + def top_level? + target_self == Pry.main + end + + def handle_internal_binding + if top_level? + output.puts "At the top level." + else + output.puts "Inside #{Pry.view_clip(target_self)}." + end + end + + def small_method? + @method.source_range.count < self.class.method_size_cutoff + end + + def default_code + if method_code && small_method? + method_code + else + code_window + end + end + + def code_window + Pry::Code.from_file(@file).around(@line, window_size) + end + + def method_code + return @method_code if @method_code + + if valid_method? + @method_code = Pry::Code.from_method(@method) + end + end + + # This either returns the `target_self` + # or it returns the class of `target_self` if `target_self` is not a class. + # @return [Pry::WrappedModule] + def target_class + target_self.is_a?(Module) ? Pry::WrappedModule(target_self) : + Pry::WrappedModule(target_self.class) + end + + def class_code + return @class_code if @class_code + + mod = @method ? Pry::WrappedModule(@method.owner) : target_class + + idx = mod.candidates.find_index { |v| expand_path(v.source_file) == @file } + @class_code = idx && Pry::Code.from_module(mod, idx) + end + + def valid_method? + @method && @method.source? && expand_path(@method.source_file) == @file && + @method.source_range.include?(@line) + end + + def expand_path(f) + return if !f + + if Pry.eval_path == f + f + else + File.expand_path(f) + end + end + + def window_size + if args.empty? + _pry_.config.default_window_size + else + args.first.to_i + end + end + end + + Pry::Commands.add_command(Pry::Command::Whereami) + Pry::Commands.alias_command '@', 'whereami' +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/commands/wtf.rb b/.bundle/gems/pry-0.10.2/lib/pry/commands/wtf.rb new file mode 100644 index 0000000..2d47dfa --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/commands/wtf.rb @@ -0,0 +1,57 @@ +class Pry + class Command::Wtf < Pry::ClassCommand + match(/wtf([?!]*)/) + group 'Context' + description 'Show the backtrace of the most recent exception.' + options :listing => 'wtf?' + + banner <<-'BANNER' + Usage: wtf[?|!] + + Show's a few lines of the backtrace of the most recent exception (also available + as `_ex_.backtrace`). If you want to see more lines, add more question marks or + exclamation marks. + + wtf? + wtf?!???!?!? + + # To see the entire backtrace, pass the `-v` or `--verbose` flag. + wtf -v + BANNER + + def options(opt) + opt.on :v, :verbose, "Show the full backtrace" + end + + def process + raise Pry::CommandError, "No most-recent exception" unless exception + + output.puts "#{text.bold('Exception:')} #{exception.class}: #{exception}\n--" + if opts.verbose? + output.puts with_line_numbers(backtrace) + else + output.puts with_line_numbers(backtrace.first(size_of_backtrace)) + end + end + + private + + def exception + _pry_.last_exception + end + + def with_line_numbers(bt) + Pry::Code.new(bt, 0, :text).with_line_numbers.to_s + end + + def backtrace + exception.backtrace + end + + def size_of_backtrace + [captures[0].size, 0.5].max * 10 + end + end + + Pry::Commands.add_command(Pry::Command::Wtf) +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/config.rb b/.bundle/gems/pry-0.10.2/lib/pry/config.rb new file mode 100644 index 0000000..73b7742 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/config.rb @@ -0,0 +1,24 @@ +class Pry::Config + require_relative 'config/behavior' + require_relative 'config/default' + require_relative 'config/convenience' + include Pry::Config::Behavior + + def self.shortcuts + Convenience::SHORTCUTS + end + + # + # FIXME + # @param [Pry::Hooks] hooks + # + def hooks=(hooks) + if hooks.is_a?(Hash) + warn "Hash-based hooks are now deprecated! Use a `Pry::Hooks` object " \ + "instead! http://rubydoc.info/github/pry/pry/master/Pry/Hooks" + self["hooks"] = Pry::Hooks.from_hash(hooks) + else + self["hooks"] = hooks + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/config/behavior.rb b/.bundle/gems/pry-0.10.2/lib/pry/config/behavior.rb new file mode 100644 index 0000000..d2669dd --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/config/behavior.rb @@ -0,0 +1,139 @@ +module Pry::Config::Behavior + ASSIGNMENT = "=".freeze + NODUP = [TrueClass, FalseClass, NilClass, Symbol, Numeric, Module, Proc].freeze + INSPECT_REGEXP = /#{Regexp.escape "default=#<"}/ + + module Builder + def from_hash(hash, default = nil) + new(default).tap do |config| + config.merge!(hash) + end + end + end + + def self.included(klass) + unless defined?(RESERVED_KEYS) + const_set :RESERVED_KEYS, instance_methods(false).map(&:to_s).freeze + end + klass.extend(Builder) + end + + def initialize(default = Pry.config) + @default = default + @lookup = {} + end + + # + # @return [Pry::Config::Behavior] + # returns the default used if a matching value for a key isn't found in self + # + def default + @default + end + + def [](key) + @lookup[key.to_s] + end + + def []=(key, value) + key = key.to_s + if RESERVED_KEYS.include?(key) + raise ArgumentError, "few things are reserved by pry, but using '#{key}' as a configuration key is." + end + @lookup[key] = value + end + + def method_missing(name, *args, &block) + key = name.to_s + if key[-1] == ASSIGNMENT + short_key = key[0..-2] + self[short_key] = args[0] + elsif key?(key) + self[key] + elsif @default.respond_to?(name) + value = @default.public_send(name, *args, &block) + # FIXME: refactor Pry::Hook so that it stores config on the config object, + # so that we can use the normal strategy. + self[key] = value = value.dup if key == 'hooks' + value + else + nil + end + end + + def merge!(other) + other = try_convert_to_hash(other) + raise TypeError, "unable to convert argument into a Hash" unless other + other.each do |key, value| + self[key] = value + end + end + + def ==(other) + @lookup == try_convert_to_hash(other) + end + alias_method :eql?, :== + + def respond_to_missing?(key, include_private=false) + key?(key) or @default.respond_to?(key) or super(key, include_private) + end + + def key?(key) + key = key.to_s + @lookup.key?(key) + end + + def clear + @lookup.clear + true + end + alias_method :refresh, :clear + + def forget(key) + @lookup.delete(key.to_s) + end + + def keys + @lookup.keys + end + + def to_hash + @lookup.dup + end + alias_method :to_h, :to_hash + + + def inspect + key_str = keys.map { |key| "'#{key}'" }.join(",") + "#<#{_clip_inspect(self)} local_keys=[#{key_str}] default=#{@default.inspect}>" + end + + def pretty_print(q) + q.text inspect[1..-1].gsub(INSPECT_REGEXP, "default=<") + end + +private + def _clip_inspect(obj) + "#{obj.class}:0x%x" % obj.object_id << 1 + end + + def _dup(value) + if NODUP.any? { |klass| klass === value } + value + else + value.dup + end + end + + def try_convert_to_hash(obj) + if Hash === obj + obj + elsif obj.respond_to?(:to_h) + obj.to_h + elsif obj.respond_to?(:to_hash) + obj.to_hash + else + nil + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/config/convenience.rb b/.bundle/gems/pry-0.10.2/lib/pry/config/convenience.rb new file mode 100644 index 0000000..ddd39f4 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/config/convenience.rb @@ -0,0 +1,25 @@ +module Pry::Config::Convenience + SHORTCUTS = [ + :input, + :output, + :commands, + :print, + :exception_handler, + :hooks, + :color, + :pager, + :editor, + :memory_size, + :extra_sticky_locals + ] + + + def config_shortcut(*names) + names.each do |name| + reader = name + setter = "#{name}=" + define_method(reader) { config.public_send(name) } + define_method(setter) { |value| config.public_send(setter, value) } + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/config/default.rb b/.bundle/gems/pry-0.10.2/lib/pry/config/default.rb new file mode 100644 index 0000000..db4d8aa --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/config/default.rb @@ -0,0 +1,161 @@ +class Pry::Config::Default + include Pry::Config::Behavior + + default = { + input: proc { + lazy_readline + }, + output: proc { + $stdout + }, + commands: proc { + Pry::Commands + }, + prompt_name: proc { + Pry::DEFAULT_PROMPT_NAME + }, + prompt: proc { + Pry::DEFAULT_PROMPT + }, + prompt_safe_objects: proc { + Pry::DEFAULT_PROMPT_SAFE_OBJECTS + }, + print: proc { + Pry::DEFAULT_PRINT + }, + quiet: proc { + false + }, + exception_handler: proc { + Pry::DEFAULT_EXCEPTION_HANDLER + }, + exception_whitelist: proc { + Pry::DEFAULT_EXCEPTION_WHITELIST + }, + hooks: proc { + Pry::DEFAULT_HOOKS + }, + pager: proc { + true + }, + system: proc { + Pry::DEFAULT_SYSTEM + }, + color: proc { + Pry::Helpers::BaseHelpers.use_ansi_codes? + }, + default_window_size: proc { + 5 + }, + editor: proc { + Pry.default_editor_for_platform + }, # TODO: Pry::Platform.editor + should_load_rc: proc { + true + }, + should_load_local_rc: proc { + true + }, + should_trap_interrupts: proc { + Pry::Helpers::BaseHelpers.jruby? + }, # TODO: Pry::Platform.jruby? + disable_auto_reload: proc { + false + }, + command_prefix: proc { + "" + }, + auto_indent: proc { + Pry::Helpers::BaseHelpers.use_ansi_codes? + }, + correct_indent: proc { + true + }, + collision_warning: proc { + false + }, + output_prefix: proc { + "=> " + }, + requires: proc { + [] + }, + should_load_requires: proc { + true + }, + should_load_plugins: proc { + true + }, + windows_console_warning: proc { + true + }, + control_d_handler: proc { + Pry::DEFAULT_CONTROL_D_HANDLER + }, + memory_size: proc { + 100 + }, + extra_sticky_locals: proc { + {} + }, + command_completions: proc { + proc { commands.keys } + }, + file_completions: proc { + proc { Dir["."] } + }, + ls: proc { + Pry::Config.from_hash(Pry::Command::Ls::DEFAULT_OPTIONS) + }, + completer: proc { + require "pry/input_completer" + Pry::InputCompleter + } + } + + def initialize + super(nil) + configure_gist + configure_history + end + + default.each do |key, value| + define_method(key) do + if default[key].equal?(value) + default[key] = instance_eval(&value) + end + default[key] + end + end + +private + # TODO: + # all of this configure_* stuff is a relic of old code. + # we should try move this code to being command-local. + def configure_gist + self["gist"] = Pry::Config.from_hash(inspecter: proc(&:pretty_inspect)) + end + + def configure_history + self["history"] = Pry::Config.from_hash "should_save" => true, + "should_load" => true + history.file = File.expand_path("~/.pry_history") rescue nil + if history.file.nil? + self.should_load_rc = false + history.should_save = false + history.should_load = false + end + end + + def lazy_readline + require 'readline' + Readline + rescue LoadError + warn "Sorry, you can't use Pry without Readline or a compatible library." + warn "Possible solutions:" + warn " * Rebuild Ruby with Readline support using `--with-readline`" + warn " * Use the rb-readline gem, which is a pure-Ruby port of Readline" + warn " * Use the pry-coolline gem, a pure-ruby alternative to Readline" + raise + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/core_extensions.rb b/.bundle/gems/pry-0.10.2/lib/pry/core_extensions.rb new file mode 100644 index 0000000..a418daf --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/core_extensions.rb @@ -0,0 +1,131 @@ +class Pry + # @return [Array] Code of the method used when implementing Pry's + # __binding__, along with line indication to be used with instance_eval (and + # friends). + # + # @see Object#__binding__ + BINDING_METHOD_IMPL = [<<-METHOD, __FILE__, __LINE__ + 1] + # Get a binding with 'self' set to self, and no locals. + # + # The default definee is determined by the context in which the + # definition is eval'd. + # + # Please don't call this method directly, see {__binding__}. + # + # @return [Binding] + def __pry__ + binding + end + METHOD +end + +class Object + # Start a Pry REPL on self. + # + # If `self` is a Binding then that will be used to evaluate expressions; + # otherwise a new binding will be created. + # + # @param [Object] object the object or binding to pry + # (__deprecated__, use `object.pry`) + # @param [Hash] hash the options hash + # @example With a binding + # binding.pry + # @example On any object + # "dummy".pry + # @example With options + # def my_method + # binding.pry :quiet => true + # end + # my_method() + # @see Pry.start + def pry(object=nil, hash={}) + if object.nil? || Hash === object + Pry.start(self, object || {}) + else + Pry.start(object, hash) + end + end + + # Return a binding object for the receiver. + # + # The `self` of the binding is set to the current object, and it contains no + # local variables. + # + # The default definee (http://yugui.jp/articles/846) is set such that: + # + # * If `self` is a class or module, then new methods created in the binding + # will be defined in that class or module (as in `class Foo; end`). + # * If `self` is a normal object, then new methods created in the binding will + # be defined on its singleton class (as in `class << self; end`). + # * If `self` doesn't have a real singleton class (i.e. it is a Fixnum, Float, + # Symbol, nil, true, or false), then new methods will be created on the + # object's class (as in `self.class.class_eval{ }`) + # + # Newly created constants, including classes and modules, will also be added + # to the default definee. + # + # @return [Binding] + def __binding__ + # If you ever feel like changing this method, be careful about variables + # that you use. They shouldn't be inserted into the binding that will + # eventually be returning. + + # When you're cd'd into a class, methods you define should be added to it. + if is_a?(Module) + # class_eval sets both self and the default definee to this class. + return class_eval "binding" + end + + unless respond_to?(:__pry__) + # The easiest way to check whether an object has a working singleton class + # is to try and define a method on it. (just checking for the presence of + # the singleton class gives false positives for `true` and `false`). + # __pry__ is just the closest method we have to hand, and using + # it has the nice property that we can memoize this check. + begin + # instance_eval sets the default definee to the object's singleton class + instance_eval(*Pry::BINDING_METHOD_IMPL) + + # If we can't define methods on the Object's singleton_class. Then we fall + # back to setting the default definee to be the Object's class. That seems + # nicer than having a REPL in which you can't define methods. + rescue TypeError, Pry::FrozenObjectException + # class_eval sets the default definee to self.class + self.class.class_eval(*Pry::BINDING_METHOD_IMPL) + end + end + + __pry__ + end +end + +class BasicObject + # Return a binding object for the receiver. + # + # The `self` of the binding is set to the current object, and it contains no + # local variables. + # + # The default definee (http://yugui.jp/articles/846) is set such that new + # methods defined will be added to the singleton class of the BasicObject. + # + # @return [Binding] + def __binding__ + # BasicObjects don't have respond_to?, so we just define the method + # every time. As they also don't have `.freeze`, this call won't + # fail as it can for normal Objects. + (class << self; self; end).class_eval <<-EOF, __FILE__, __LINE__ + 1 + # Get a binding with 'self' set to self, and no locals. + # + # The default definee is determined by the context in which the + # definition is eval'd. + # + # Please don't call this method directly, see {__binding__}. + # + # @return [Binding] + def __pry__ + ::Kernel.binding + end + EOF + self.__pry__ + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/editor.rb b/.bundle/gems/pry-0.10.2/lib/pry/editor.rb new file mode 100644 index 0000000..43e649f --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/editor.rb @@ -0,0 +1,135 @@ +class Pry + class Editor + include Pry::Helpers::BaseHelpers + include Pry::Helpers::CommandHelpers + + attr_reader :_pry_ + + def initialize(_pry_) + @_pry_ = _pry_ + end + + def edit_tempfile_with_content(initial_content, line=1) + temp_file do |f| + f.puts(initial_content) + f.flush + f.close(false) + invoke_editor(f.path, line, true) + File.read(f.path) + end + end + + def invoke_editor(file, line, blocking=true) + raise CommandError, "Please set Pry.config.editor or export $VISUAL or $EDITOR" unless _pry_.config.editor + + editor_invocation = build_editor_invocation_string(file, line, blocking) + return nil unless editor_invocation + + if jruby? + open_editor_on_jruby(editor_invocation) + else + open_editor(editor_invocation) + end + end + + private + + # Generate the string that's used to start the editor. This includes + # all the flags we want as well as the file and line number we + # want to open at. + def build_editor_invocation_string(file, line, blocking) + + if _pry_.config.editor.respond_to?(:call) + args = [file, line, blocking][0...(_pry_.config.editor.arity)] + _pry_.config.editor.call(*args) + else + sanitized_file = if windows? + file.gsub(/\//, '\\') + else + Shellwords.escape(file) + end + + "#{_pry_.config.editor} #{blocking_flag_for_editor(blocking)} #{start_line_syntax_for_editor(sanitized_file, line)}" + end + end + + # Start the editor running, using the calculated invocation string + def open_editor(editor_invocation) + # Note we dont want to use Pry.config.system here as that + # may be invoked non-interactively (i.e via Open4), whereas we want to + # ensure the editor is always interactive + system(*Shellwords.split(editor_invocation)) or raise CommandError, "`#{editor_invocation}` gave exit status: #{$?.exitstatus}" + end + + # We need JRuby specific code here cos just shelling out using + # system() appears to be pretty broken :/ + def open_editor_on_jruby(editor_invocation) + begin + require 'spoon' + pid = Spoon.spawnp(*Shellwords.split(editor_invocation)) + Process.waitpid(pid) + rescue FFI::NotFoundError + system(editor_invocation) + end + end + + # Some editors that run outside the terminal allow you to control whether or + # not to block the process from which they were launched (in this case, Pry). + # For those editors, return the flag that produces the desired behavior. + def blocking_flag_for_editor(blocking) + case editor_name + when /^emacsclient/ + '--no-wait' unless blocking + when /^[gm]vim/ + '--nofork' if blocking + when /^jedit/ + '-wait' if blocking + when /^mate/, /^subl/, /^redcar/ + '-w' if blocking + end + end + + # Return the syntax for a given editor for starting the editor + # and moving to a particular line within that file + def start_line_syntax_for_editor(file_name, line_number) + # special case for 1st line + return file_name if line_number <= 1 + + case editor_name + when /^[gm]?vi/, /^emacs/, /^nano/, /^pico/, /^gedit/, /^kate/ + "+#{line_number} #{file_name}" + when /^mate/, /^geany/ + "-l #{line_number} #{file_name}" + when /^subl/ + "#{file_name}:#{line_number}" + when /^uedit32/ + "#{file_name}/#{line_number}" + when /^jedit/ + "#{file_name} +line:#{line_number}" + when /^redcar/ + "-l#{line_number} #{file_name}" + else + if windows? + "#{file_name}" + else + "+#{line_number} #{file_name}" + end + end + end + + # Get the name of the binary that Pry.config.editor points to. + # + # This is useful for deciding which flags we pass to the editor as + # we can just use the program's name and ignore any absolute paths. + # + # @example + # Pry.config.editor="/home/conrad/bin/textmate -w" + # editor_name + # # => textmate + # + def editor_name + File.basename(_pry_.config.editor).split(" ").first + end + + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/exceptions.rb b/.bundle/gems/pry-0.10.2/lib/pry/exceptions.rb new file mode 100644 index 0000000..57bbfc5 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/exceptions.rb @@ -0,0 +1,78 @@ +class Pry + + # As a REPL, we often want to catch any unexpected exceptions that may have + # been raised; however we don't want to go overboard and prevent the user + # from exiting Pry when they want to. + module RescuableException + def self.===(exception) + case exception + # Catch when the user hits ^C (Interrupt < SignalException), and assume + # that they just wanted to stop the in-progress command (just like bash + # etc.) + when Interrupt + true + # Don't catch signals (particularly not SIGTERM) as these are unlikely + # to be intended for pry itself. We should also make sure that + # Kernel#exit works. + when *Pry.config.exception_whitelist + false + # All other exceptions will be caught. + else + true + end + end + end + + # Catches SecurityErrors if $SAFE is set + module Pry::TooSafeException + def self.===(exception) + $SAFE > 0 && SecurityError === exception + end + end + + # An Exception Tag (cf. Exceptional Ruby) that instructs Pry to show the error + # in a more user-friendly manner. This should be used when the exception + # happens within Pry itself as a direct consequence of the user typing + # something wrong. + # + # This allows us to distinguish between the user typing: + # + # pry(main)> def ) + # SyntaxError: unexpected ) + # + # pry(main)> method_that_evals("def )") + # SyntaxError: (eval):1: syntax error, unexpected ')' + # from ./a.rb:2 in `eval' + module UserError; end + + # When we try to get a binding for an object, we try to define a method on + # that Object's singleton class. This doesn't work for "frozen" Object's, and + # the exception is just a vanilla RuntimeError. + module FrozenObjectException + def self.===(exception) + ["can't modify frozen class/module", + "can't modify frozen Class", + "can't modify frozen object" + ].include?(exception.message) + end + end + + # Don't catch these exceptions + DEFAULT_EXCEPTION_WHITELIST = [SystemExit, + SignalException, + Pry::TooSafeException] + + # CommandErrors are caught by the REPL loop and displayed to the user. They + # indicate an exceptional condition that's fatal to the current command. + class CommandError < StandardError; end + class MethodNotFound < CommandError; end + + # indicates obsolete API + class ObsoleteError < StandardError; end + + # This is to keep from breaking under Rails 3.2 for people who are doing that + # IRB = Pry thing. + module ExtendCommandBundle + end + +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/helpers.rb b/.bundle/gems/pry-0.10.2/lib/pry/helpers.rb new file mode 100644 index 0000000..f59c308 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/helpers.rb @@ -0,0 +1,5 @@ +require "pry/helpers/base_helpers" +require "pry/helpers/options_helpers" +require "pry/helpers/command_helpers" +require "pry/helpers/text" +require "pry/helpers/table" diff --git a/.bundle/gems/pry-0.10.2/lib/pry/helpers/base_helpers.rb b/.bundle/gems/pry-0.10.2/lib/pry/helpers/base_helpers.rb new file mode 100644 index 0000000..5dade46 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/helpers/base_helpers.rb @@ -0,0 +1,113 @@ +class Pry + module Helpers + + module BaseHelpers + + module_function + + def silence_warnings + old_verbose = $VERBOSE + $VERBOSE = nil + begin + yield + ensure + $VERBOSE = old_verbose + end + end + + # Acts like send but ignores any methods defined below Object or Class in the + # inheritance hierarchy. + # This is required to introspect methods on objects like Net::HTTP::Get that + # have overridden the `method` method. + def safe_send(obj, method, *args, &block) + (Module === obj ? Module : Object).instance_method(method).bind(obj).call(*args, &block) + end + public :safe_send + + def find_command(name, set = Pry::Commands) + command_match = set.find do |_, command| + (listing = command.options[:listing]) == name && listing != nil + end + command_match.last if command_match + end + + def not_a_real_file?(file) + file =~ /(\(.*\))|<.*>/ || file =~ /__unknown__/ || file == "" || file == "-e" + end + + def command_dependencies_met?(options) + return true if !options[:requires_gem] + Array(options[:requires_gem]).all? do |g| + Rubygem.installed?(g) + end + end + + def use_ansi_codes? + windows_ansi? || ENV['TERM'] && ENV['TERM'] != "dumb" + end + + def colorize_code(code) + CodeRay.scan(code, :ruby).term + end + + def highlight(string, regexp, highlight_color=:bright_yellow) + string.gsub(regexp) { |match| "<#{highlight_color}>#{match}" } + end + + # formatting + def heading(text) + text = "#{text}\n--" + "\e[1m#{text}\e[0m" + end + + # have fun on the Windows platform. + def windows? + RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ + end + + # are we able to use ansi on windows? + def windows_ansi? + defined?(Win32::Console) || ENV['ANSICON'] || (windows? && mri_2?) + end + + def jruby? + RbConfig::CONFIG['ruby_install_name'] == 'jruby' + end + + def jruby_19? + jruby? && RbConfig::CONFIG['ruby_version'] == '1.9' + end + + def rbx? + RbConfig::CONFIG['ruby_install_name'] == 'rbx' + end + + def mri? + RbConfig::CONFIG['ruby_install_name'] == 'ruby' + end + + def mri_19? + mri? && RUBY_VERSION =~ /^1\.9/ + end + + def mri_2? + mri? && RUBY_VERSION =~ /^2/ + end + + def mri_20? + mri? && RUBY_VERSION =~ /^2\.0/ + end + + def mri_21? + mri? && RUBY_VERSION =~ /^2\.1/ + end + + # Send the given text through the best available pager (if Pry.config.pager is + # enabled). Infers where to send the output if used as a mixin. + # DEPRECATED. + def stagger_output(text, out = nil) + Pry.new.pager.page text + end + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/helpers/command_helpers.rb b/.bundle/gems/pry-0.10.2/lib/pry/helpers/command_helpers.rb new file mode 100644 index 0000000..7f7e226 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/helpers/command_helpers.rb @@ -0,0 +1,156 @@ +class Pry + module Helpers + + module CommandHelpers + include OptionsHelpers + + module_function + + # Open a temp file and yield it to the block, closing it after + # @return [String] The path of the temp file + def temp_file(ext='.rb') + file = Tempfile.new(['pry', ext]) + yield file + ensure + file.close(true) if file + end + + def internal_binding?(target) + m = target.eval("::Kernel.__method__").to_s + # class_eval is here because of http://jira.codehaus.org/browse/JRUBY-6753 + ["__binding__", "__pry__", "class_eval"].include?(m) + end + + def get_method_or_raise(name, target, opts={}, omit_help=false) + meth = Pry::Method.from_str(name, target, opts) + + if name && !meth + command_error("The method '#{name}' could not be found.", omit_help, MethodNotFound) + end + + (opts[:super] || 0).times do + if meth.super + meth = meth.super + else + command_error("'#{meth.name_with_owner}' has no super method.", omit_help, MethodNotFound) + end + end + + if !meth || (!name && internal_binding?(target)) + command_error("No method name given, and context is not a method.", omit_help, MethodNotFound) + end + + set_file_and_dir_locals(meth.source_file) + meth + end + + def command_error(message, omit_help, klass=CommandError) + message += " Type `#{command_name} --help` for help." unless omit_help + raise klass, message + end + + # Remove any common leading whitespace from every line in `text`. + # + # This can be used to make a HEREDOC line up with the left margin, without + # sacrificing the indentation level of the source code. + # + # e.g. + # opt.banner unindent <<-USAGE + # Lorem ipsum dolor sit amet, consectetur adipisicing elit, + # sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + # "Ut enim ad minim veniam." + # USAGE + # + # Heavily based on textwrap.dedent from Python, which is: + # Copyright (C) 1999-2001 Gregory P. Ward. + # Copyright (C) 2002, 2003 Python Software Foundation. + # Written by Greg Ward + # + # Licensed under + # From + # + # @param [String] text The text from which to remove indentation + # @return [String] The text with indentation stripped. + def unindent(text, left_padding = 0) + # Empty blank lines + text = text.sub(/^[ \t]+$/, '') + + # Find the longest common whitespace to all indented lines + # Ignore lines containing just -- or ++ as these seem to be used by + # comment authors as delimeters. + margin = text.scan(/^[ \t]*(?!--\n|\+\+\n)(?=[^ \t\n])/).inject do |current_margin, next_indent| + if next_indent.start_with?(current_margin) + current_margin + elsif current_margin.start_with?(next_indent) + next_indent + else + "" + end + end + + text.gsub(/^#{margin}/, ' ' * left_padding) + end + + # Restrict a string to the given range of lines (1-indexed) + # @param [String] content The string. + # @param [Range, Fixnum] lines The line(s) to restrict it to. + # @return [String] The resulting string. + def restrict_to_lines(content, lines) + line_range = one_index_range_or_number(lines) + Array(content.lines.to_a[line_range]).join + end + + def one_index_number(line_number) + if line_number > 0 + line_number - 1 + else + line_number + end + end + + # convert a 1-index range to a 0-indexed one + def one_index_range(range) + Range.new(one_index_number(range.begin), one_index_number(range.end)) + end + + def one_index_range_or_number(range_or_number) + case range_or_number + when Range + one_index_range(range_or_number) + else + one_index_number(range_or_number) + end + end + + def absolute_index_number(line_number, array_length) + if line_number >= 0 + line_number + else + [array_length + line_number, 0].max + end + end + + def absolute_index_range(range_or_number, array_length) + case range_or_number + when Range + a = absolute_index_number(range_or_number.begin, array_length) + b = absolute_index_number(range_or_number.end, array_length) + else + a = b = absolute_index_number(range_or_number, array_length) + end + + Range.new(a, b) + end + + def set_file_and_dir_locals(file_name, _pry_=_pry_(), target=target()) + return if !target or !file_name + _pry_.last_file = File.expand_path(file_name) + _pry_.inject_local("_file_", _pry_.last_file, target) + + _pry_.last_dir = File.dirname(_pry_.last_file) + _pry_.inject_local("_dir_", _pry_.last_dir, target) + end + end + + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/helpers/documentation_helpers.rb b/.bundle/gems/pry-0.10.2/lib/pry/helpers/documentation_helpers.rb new file mode 100644 index 0000000..9f9870e --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/helpers/documentation_helpers.rb @@ -0,0 +1,75 @@ +class Pry + module Helpers + + # This class contains methods useful for extracting + # documentation from methods and classes. + module DocumentationHelpers + + module_function + + def process_rdoc(comment) + comment = comment.dup + comment.gsub(/(?:\s*\n)?(.*?)\s*<\/code>/m) { CodeRay.scan($1, :ruby).term }. + gsub(/(?:\s*\n)?(.*?)\s*<\/em>/m) { "\e[1m#{$1}\e[0m" }. + gsub(/(?:\s*\n)?(.*?)\s*<\/i>/m) { "\e[1m#{$1}\e[0m" }. + gsub(/\B\+(\w+?)\+\B/) { "\e[32m#{$1}\e[0m" }. + gsub(/((?:^[ \t]+.+(?:\n+|\Z))+)/) { CodeRay.scan($1, :ruby).term }. + gsub(/`(?:\s*\n)?([^\e]*?)\s*`/) { "`#{CodeRay.scan($1, :ruby).term}`" } + end + + def process_yardoc_tag(comment, tag) + in_tag_block = nil + comment.lines.map do |v| + if in_tag_block && v !~ /^\S/ + Pry::Helpers::Text.strip_color Pry::Helpers::Text.strip_color(v) + elsif in_tag_block + in_tag_block = false + v + else + in_tag_block = true if v =~ /^@#{tag}/ + v + end + end.join + end + + def process_yardoc(comment) + yard_tags = ["param", "return", "option", "yield", "attr", "attr_reader", "attr_writer", + "deprecate", "example", "raise"] + (yard_tags - ["example"]).inject(comment) { |a, v| process_yardoc_tag(a, v) }. + gsub(/^@(#{yard_tags.join("|")})/) { "\e[33m#{$1}\e[0m" } + end + + def process_comment_markup(comment) + process_yardoc process_rdoc(comment) + end + + # @param [String] code + # @return [String] + def strip_comments_from_c_code(code) + code.sub(/\A\s*\/\*.*?\*\/\s*/m, '') + end + + # Given a string that makes up a comment in a source-code file parse out the content + # that the user is intended to read. (i.e. without leading indentation, #-characters + # or shebangs) + # + # @param [String] comment + # @return [String] + def get_comment_content(comment) + comment = comment.dup + # Remove #!/usr/bin/ruby + comment.gsub!(/\A\#!.*$/, '') + # Remove leading empty comment lines + comment.gsub!(/\A\#+?$/, '') + comment.gsub!(/^\s*#/, '') + strip_leading_whitespace(comment) + end + + # @param [String] text + # @return [String] + def strip_leading_whitespace(text) + Pry::Helpers::CommandHelpers.unindent(text) + end + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/helpers/options_helpers.rb b/.bundle/gems/pry-0.10.2/lib/pry/helpers/options_helpers.rb new file mode 100644 index 0000000..e566d3b --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/helpers/options_helpers.rb @@ -0,0 +1,27 @@ +class Pry + module Helpers + module OptionsHelpers + module_function + + # Add method options to the Slop instance + def method_options(opt) + @method_target = target + opt.on :M, "instance-methods", "Operate on instance methods." + opt.on :m, :methods, "Operate on methods." + opt.on :s, :super, "Select the 'super' method. Can be repeated to traverse the ancestors.", :as => :count + opt.on :c, :context, "Select object context to run under.", :argument => true do |context| + @method_target = Pry.binding_for(target.eval(context)) + end + end + + # Get the method object parsed by the slop instance + def method_object + @method_object ||= get_method_or_raise(args.empty? ? nil : args.join(" "), @method_target, + :super => opts[:super], + :instance => opts.present?(:'instance-methods') && !opts.present?(:'methods'), + :methods => opts.present?(:'methods') && !opts.present?(:'instance-methods') + ) + end + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/helpers/table.rb b/.bundle/gems/pry-0.10.2/lib/pry/helpers/table.rb new file mode 100644 index 0000000..56e7e59 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/helpers/table.rb @@ -0,0 +1,109 @@ +class Pry + module Helpers + def self.tablify_or_one_line(heading, things) + plain_heading = Pry::Helpers::Text.strip_color(heading) + attempt = Table.new(things, :column_count => things.size) + if attempt.fits_on_line?(Terminal.width! - plain_heading.size - 2) + "#{heading}: #{attempt}\n" + else + "#{heading}: \n#{tablify_to_screen_width(things, :indent => ' ')}\n" + end + end + + def self.tablify_to_screen_width(things, options = {}) + things = things.compact + if indent = options[:indent] + usable_width = Terminal.width! - indent.size + tablify(things, usable_width).to_s.gsub(/^/, indent) + else + tablify(things, Terminal.width!).to_s + end + end + + def self.tablify(things, line_length) + table = Table.new(things, :column_count => things.size) + table.column_count -= 1 until 1 == table.column_count or + table.fits_on_line?(line_length) + table + end + + class Table + attr_reader :items, :column_count + def initialize items, args = {} + @column_count = args[:column_count] + self.items = items + end + + def to_s + rows_to_s.join("\n") + end + + def rows_to_s style = :color_on + widths = columns.map{|e| _max_width(e)} + @rows_without_colors.map do |r| + padded = [] + r.each_with_index do |e,i| + next unless e + item = e.ljust(widths[i]) + item.sub! e, _recall_color_for(e) if :color_on == style + padded << item + end + padded.join(Pry.config.ls.separator) + end + end + + def items= items + @items = items + _rebuild_colorless_cache + _recolumn + items + end + + def column_count= n + @column_count = n + _recolumn + end + + def fits_on_line? line_length + _max_width(rows_to_s :no_color) <= line_length + end + + def columns + @rows_without_colors.transpose + end + + def ==(other); items == other.to_a end + def to_a; items.to_a end + + private + def _max_width(things) + things.compact.map(&:size).max || 0 + end + + def _rebuild_colorless_cache + @colorless_cache = {} + @plain_items = [] + items.map do |e| + plain = Pry::Helpers::Text.strip_color(e) + @colorless_cache[plain] = e + @plain_items << plain + end + end + + def _recolumn + @rows_without_colors = [] + return if items.size.zero? + row_count = (items.size.to_f/column_count).ceil + row_count.times do |i| + row_indices = (0...column_count).map{|e| row_count*e+i} + @rows_without_colors << row_indices.map{|e| @plain_items[e]} + end + end + + def _recall_color_for thing + @colorless_cache[thing] + end + end + + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/helpers/text.rb b/.bundle/gems/pry-0.10.2/lib/pry/helpers/text.rb new file mode 100644 index 0000000..13867cf --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/helpers/text.rb @@ -0,0 +1,107 @@ +class Pry + module Helpers + + # The methods defined on {Text} are available to custom commands via {Pry::Command#text}. + module Text + + COLORS = + { + "black" => 0, + "red" => 1, + "green" => 2, + "yellow" => 3, + "blue" => 4, + "purple" => 5, + "magenta" => 5, + "cyan" => 6, + "white" => 7 + } + + class << self + + COLORS.each_pair do |color, value| + define_method color do |text| + "\033[0;#{30+value}m#{text}\033[0m" + end + + define_method "bright_#{color}" do |text| + "\033[1;#{30+value}m#{text}\033[0m" + end + end + + # Remove any color codes from _text_. + # + # @param [String, #to_s] text + # @return [String] _text_ stripped of any color codes. + def strip_color(text) + text.to_s.gsub(/\e\[.*?(\d)+m/ , '') + end + + # Returns _text_ as bold text for use on a terminal. + # + # @param [String, #to_s] text + # @return [String] _text_ + def bold(text) + "\e[1m#{text}\e[0m" + end + + # Returns `text` in the default foreground colour. + # Use this instead of "black" or "white" when you mean absence of colour. + # + # @param [String, #to_s] text + # @return [String] + def default(text) + text.to_s + end + alias_method :bright_default, :bold + + # Executes the block with `Pry.config.color` set to false. + # @yield + # @return [void] + def no_color(&block) + boolean = Pry.config.color + Pry.config.color = false + yield + ensure + Pry.config.color = boolean + end + + # Executes the block with `Pry.config.pager` set to false. + # @yield + # @return [void] + def no_pager(&block) + boolean = Pry.config.pager + Pry.config.pager = false + yield + ensure + Pry.config.pager = boolean + end + + # Returns _text_ in a numbered list, beginning at _offset_. + # + # @param [#each_line] text + # @param [Fixnum] offset + # @return [String] + def with_line_numbers(text, offset, color=:blue) + lines = text.each_line.to_a + max_width = (offset + lines.count).to_s.length + lines.each_with_index.map do |line, index| + adjusted_index = (index + offset).to_s.rjust(max_width) + "#{self.send(color, adjusted_index)}: #{line}" + end.join + end + + # Returns _text_ indented by _chars_ spaces. + # + # @param [String] text + # @param [Fixnum] chars + def indent(text, chars) + text.lines.map { |l| "#{' ' * chars}#{l}" }.join + end + end + + end + + end +end + diff --git a/.bundle/gems/pry-0.10.2/lib/pry/history.rb b/.bundle/gems/pry-0.10.2/lib/pry/history.rb new file mode 100644 index 0000000..81b7417 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/history.rb @@ -0,0 +1,127 @@ +class Pry + # The History class is responsible for maintaining the user's input history, + # both internally and within Readline. + class History + attr_accessor :loader, :saver, :pusher, :clearer + + # @return [Fixnum] Number of lines in history when Pry first loaded. + attr_reader :original_lines + + def initialize(options={}) + @history = [] + @original_lines = 0 + @file_path = options[:file_path] + restore_default_behavior + end + + # Assign the default methods for loading, saving, pushing, and clearing. + def restore_default_behavior + Pry.config.input # force Readline to load if applicable + + @loader = method(:read_from_file) + @saver = method(:save_to_file) + + if defined?(Readline) + @pusher = method(:push_to_readline) + @clearer = method(:clear_readline) + else + @pusher = proc { } + @clearer = proc { } + end + end + + # Load the input history using `History.loader`. + # @return [Integer] The number of lines loaded + def load + @loader.call do |line| + @pusher.call(line.chomp) + @history << line.chomp + @original_lines += 1 + end + end + + # Add a line to the input history, ignoring blank and duplicate lines. + # @param [String] line + # @return [String] The same line that was passed in + def push(line) + unless line.empty? || (@history.last && line == @history.last) + @pusher.call(line) + @history << line + @saver.call(line) if Pry.config.history.should_save + end + line + end + alias << push + + # Clear this session's history. This won't affect the contents of the + # history file. + def clear + @clearer.call + @history = [] + end + + # @return [Fixnum] The number of lines in history. + def history_line_count + @history.count + end + + # @return [Fixnum] The number of lines in history from just this session. + def session_line_count + @history.count - @original_lines + end + + # Return an Array containing all stored history. + # @return [Array] An Array containing all lines of history loaded + # or entered by the user in the current session. + def to_a + @history.dup + end + + private + + # The default loader. Yields lines from `Pry.history.config.file`. + def read_from_file + path = history_file_path + + if File.exists?(path) + File.foreach(path) { |line| yield(line) } + end + rescue => error + warn "History file not loaded: #{error.message}" + end + + # The default pusher. Appends the given line to Readline::HISTORY. + # @param [String] line + def push_to_readline(line) + Readline::HISTORY << line + end + + # The default clearer. Clears Readline::HISTORY. + def clear_readline + Readline::HISTORY.shift until Readline::HISTORY.empty? + end + + # The default saver. Appends the given line to `Pry.history.config.file`. + def save_to_file(line) + history_file.puts line if history_file + end + + # The history file, opened for appending. + def history_file + if defined?(@history_file) + @history_file + else + @history_file = File.open(history_file_path, 'a', 0600).tap do |file| + file.sync = true + end + end + rescue Errno::EACCES + warn 'History not saved; unable to open your history file for writing.' + @history_file = false + end + + def history_file_path + File.expand_path(@file_path || Pry.config.history.file) + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/history_array.rb b/.bundle/gems/pry-0.10.2/lib/pry/history_array.rb new file mode 100644 index 0000000..60e41bc --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/history_array.rb @@ -0,0 +1,121 @@ +class Pry + # A history array is an array to which you can only add elements. Older + # entries are removed progressively, so that the array never contains more than + # N elements. + # + # History arrays are used by Pry to store the output of the last commands. + # + # @example + # ary = Pry::HistoryArray.new 10 + # ary << 1 << 2 << 3 + # ary[0] # => 1 + # ary[1] # => 2 + # 10.times { |n| ary << n } + # ary[0] # => nil + # ary[-1] # => 9 + class HistoryArray + include Enumerable + + # @param [Integer] size Maximum amount of objects in the array + def initialize(size) + @max_size = size + + @hash = {} + @count = 0 + end + + # Pushes an object at the end of the array + # @param [Object] value Object to be added + def <<(value) + @hash[@count] = value + + if @hash.size > max_size + @hash.delete(@count - max_size) + end + + @count += 1 + + self + end + + # @overload [](index) + # @param [Integer] index Index of the item to access. + # @return [Object, nil] Item at that index or nil if it has been removed. + # @overload [](index, size) + # @param [Integer] index Index of the first item to access. + # @param [Integer] size Amount of items to access + # @return [Array, nil] The selected items. Nil if index is greater than + # the size of the array. + # @overload [](range) + # @param [Range] range Range of indices to access. + # @return [Array, nil] The selected items. Nil if index is greater than + # the size of the array. + def [](index_or_range, size = nil) + if index_or_range.is_a? Integer + index = convert_index(index_or_range) + + if size + end_index = index + size + index > @count ? nil : (index...[end_index, @count].min).map do |n| + @hash[n] + end + else + @hash[index] + end + else + range = convert_range(index_or_range) + range.begin > @count ? nil : range.map { |n| @hash[n] } + end + end + + # @return [Integer] Amount of objects in the array + def size + @count + end + alias count size + alias length size + + def empty? + size == 0 + end + + def each + ((@count - size)...@count).each do |n| + yield @hash[n] + end + end + + def to_a + ((@count - size)...@count).map { |n| @hash[n] } + end + + # Returns [Hash] copy of the internal @hash history + def to_h + @hash.dup + end + + def pop! + @hash.delete @count - 1 + @count -= 1 + end + + def inspect + "#<#{self.class} size=#{size} first=#{@count - size} max_size=#{max_size}>" + end + + # @return [Integer] Maximum amount of objects in the array + attr_reader :max_size + + private + def convert_index(n) + n >= 0 ? n : @count + n + end + + def convert_range(range) + end_index = convert_index(range.end) + end_index += 1 unless range.exclude_end? + + Range.new(convert_index(range.begin), [end_index, @count].min, true) + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/hooks.rb b/.bundle/gems/pry-0.10.2/lib/pry/hooks.rb new file mode 100644 index 0000000..48291ee --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/hooks.rb @@ -0,0 +1,230 @@ +class Pry + + # Implements a hooks system for Pry. A hook is a callable that is + # associated with an event. A number of events are currently + # provided by Pry, these include: `:when_started`, `:before_session`, `:after_session`. + # A hook must have a name, and is connected with an event by the + # `Pry::Hooks#add_hook` method. + # @example Adding a hook for the `:before_session` event. + # Pry.config.hooks.add_hook(:before_session, :say_hi) do + # puts "hello" + # end + class Hooks + + # Converts a hash to a `Pry::Hooks` instance. All hooks defined + # this way are anonymous. This functionality is primarily to + # provide backwards-compatibility with the old hash-based hook + # system in Pry versions < 0.9.8 + # @param [Hash] hash The hash to convert to `Pry::Hooks`. + # @return [Pry::Hooks] The resulting `Pry::Hooks` instance. + def self.from_hash(hash) + return hash if hash.instance_of?(self) + instance = new + hash.each do |k, v| + instance.add_hook(k, nil, v) + end + instance + end + + def initialize + @hooks = {} + end + + # Ensure that duplicates have their @hooks object + def initialize_copy(orig) + hooks_dup = @hooks.dup + @hooks.each do |k, v| + hooks_dup[k] = v.dup + end + + @hooks = hooks_dup + end + + def hooks + @hooks + end + protected :hooks + + def errors + @errors ||= [] + end + + # Destructively merge the contents of two `Pry:Hooks` instances. + # @param [Pry::Hooks] other The `Pry::Hooks` instance to merge + # @return [Pry:Hooks] Returns the receiver. + # @example + # hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" } + # Pry::Hooks.new.merge!(hooks) + def merge!(other) + @hooks.merge!(other.dup.hooks) do |key, v1, v2| + merge_arrays(v1, v2) + end + + self + end + + def merge_arrays(array1, array2) + uniq_keeping_last(array1 + array2, &:first) + end + private :merge_arrays + + def uniq_keeping_last(input, &block) + hash, output = {}, [] + input.reverse.each{ |i| hash[block[i]] ||= (output.unshift i) } + output + end + private :uniq_keeping_last + + # Return a new `Pry::Hooks` instance containing a merge of the contents of two `Pry:Hooks` instances, + # @param [Pry::Hooks] other The `Pry::Hooks` instance to merge + # @return [Pry::Hooks] The new hash. + # @example + # hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" } + # Pry::Hooks.new.merge(hooks) + def merge(other) + self.dup.tap do |v| + v.merge!(other) + end + end + + # Add a new hook to be executed for the `name` even. + # @param [Symbol] event_name The name of the event. + # @param [Symbol] hook_name The name of the hook. + # @param [#call] callable The callable. + # @yield The block to use as the callable (if `callable` parameter not provided) + # @return [Pry:Hooks] Returns the receiver. + # @example + # Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" } + def add_hook(event_name, hook_name, callable=nil, &block) + @hooks[event_name] ||= [] + + # do not allow duplicates, but allow multiple `nil` hooks + # (anonymous hooks) + if hook_exists?(event_name, hook_name) && !hook_name.nil? + raise ArgumentError, "Hook with name '#{hook_name}' already defined!" + end + + if !block && !callable + raise ArgumentError, "Must provide a block or callable." + end + + # ensure we only have one anonymous hook + @hooks[event_name].delete_if { |h, k| h.nil? } if hook_name.nil? + + if block + @hooks[event_name] << [hook_name, block] + elsif callable + @hooks[event_name] << [hook_name, callable] + end + + self + end + + # Execute the list of hooks for the `event_name` event. + # @param [Symbol] event_name The name of the event. + # @param [Array] args The arguments to pass to each hook function. + # @return [Object] The return value of the last executed hook. + # @example + # my_hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" } + # my_hooks.exec_hook(:before_session) #=> OUTPUT: "hi!" + def exec_hook(event_name, *args, &block) + @hooks[event_name] ||= [] + + @hooks[event_name].map do |hook_name, callable| + begin + callable.call(*args, &block) + rescue RescuableException => e + errors << e + e + end + end.last + end + + # Return the number of hook functions registered for the `event_name` event. + # @param [Symbol] event_name The name of the event. + # @return [Fixnum] The number of hook functions for `event_name`. + # @example + # my_hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" } + # my_hooks.count(:before_session) #=> 1 + def hook_count(event_name) + @hooks[event_name] ||= [] + @hooks[event_name].size + end + + # Return a specific hook for a given event. + # @param [Symbol] event_name The name of the event. + # @param [Symbol] hook_name The name of the hook + # @return [#call] The requested hook. + # @example + # my_hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" } + # my_hooks.get_hook(:before_session, :say_hi).call #=> "hi!" + def get_hook(event_name, hook_name) + @hooks[event_name] ||= [] + hook = @hooks[event_name].find { |current_hook_name, callable| current_hook_name == hook_name } + hook.last if hook + end + + # Return the hash of hook names / hook functions for a + # given event. (Note that modifying the returned hash does not + # alter the hooks, use add_hook/delete_hook for that). + # @param [Symbol] event_name The name of the event. + # @return [Hash] The hash of hook names / hook functions. + # @example + # my_hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" } + # my_hooks.get_hooks(:before_session) #=> {:say_hi=>#} + def get_hooks(event_name) + @hooks[event_name] ||= [] + Hash[@hooks[event_name]] + end + + # Delete a hook for an event. + # @param [Symbol] event_name The name of the event. + # @param [Symbol] hook_name The name of the hook. + # to delete. + # @return [#call] The deleted hook. + # @example + # my_hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" } + # my_hooks.delete_hook(:before_session, :say_hi) + def delete_hook(event_name, hook_name) + @hooks[event_name] ||= [] + deleted_callable = nil + + @hooks[event_name].delete_if do |current_hook_name, callable| + if current_hook_name == hook_name + deleted_callable = callable + true + else + false + end + end + deleted_callable + end + + # Clear all hooks functions for a given event. + # @param [String] event_name The name of the event. + # @example + # my_hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" } + # my_hooks.delete_hook(:before_session) + def delete_hooks(event_name) + @hooks[event_name] = [] + end + + alias_method :clear, :delete_hooks + + # Remove all events and hooks, clearing out the Pry::Hooks + # instance completely. + # @example + # my_hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" } + # my_hooks.clear_all + def clear_all + @hooks = {} + end + + # @param [Symbol] event_name Name of the event. + # @param [Symbol] hook_name Name of the hook. + # @return [Boolean] Whether the hook by the name `hook_name` + def hook_exists?(event_name, hook_name) + !!(@hooks[event_name] && @hooks[event_name].find { |name, _| name == hook_name }) + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/indent.rb b/.bundle/gems/pry-0.10.2/lib/pry/indent.rb new file mode 100644 index 0000000..72fbf69 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/indent.rb @@ -0,0 +1,406 @@ +require 'coderay' + +class Pry + ## + # Pry::Indent is a class that can be used to indent a number of lines + # containing Ruby code similar as to how IRB does it (but better). The class + # works by tokenizing a string using CodeRay and then looping over those + # tokens. Based on the tokens in a line of code that line (or the next one) + # will be indented or un-indented by correctly. + # + class Indent + include Helpers::BaseHelpers + + # Raised if {#module_nesting} would not work. + class UnparseableNestingError < StandardError; end + + # @return [String] String containing the spaces to be inserted before the next line. + attr_reader :indent_level + + # @return [Array] The stack of open tokens. + attr_reader :stack + + # The amount of spaces to insert for each indent level. + SPACES = ' ' + + # Hash containing all the tokens that should increase the indentation + # level. The keys of this hash are open tokens, the values the matching + # tokens that should prevent a line from being indented if they appear on + # the same line. + OPEN_TOKENS = { + 'def' => 'end', + 'class' => 'end', + 'module' => 'end', + 'do' => 'end', + 'if' => 'end', + 'unless' => 'end', + 'while' => 'end', + 'until' => 'end', + 'for' => 'end', + 'case' => 'end', + 'begin' => 'end', + '[' => ']', + '{' => '}', + '(' => ')' + } + + # Which tokens can either be open tokens, or appear as modifiers on + # a single-line. + SINGLELINE_TOKENS = %w(if while until unless rescue) + + # Which tokens can be followed by an optional "do" keyword. + OPTIONAL_DO_TOKENS = %w(for while until) + + # Collection of token types that should be ignored. Without this list + # keywords such as "class" inside strings would cause the code to be + # indented incorrectly. + # + # :pre_constant and :preserved_constant are the CodeRay 0.9.8 and 1.0.0 + # classifications of "true", "false", and "nil". + IGNORE_TOKENS = [:space, :content, :string, :method, :ident, + :constant, :pre_constant, :predefined_constant] + + # Tokens that indicate the end of a statement (i.e. that, if they appear + # directly before an "if" indicates that that if applies to the same line, + # not the next line) + # + # :reserved and :keywords are the CodeRay 0.9.8 and 1.0.0 respectively + # classifications of "super", "next", "return", etc. + STATEMENT_END_TOKENS = IGNORE_TOKENS + [:regexp, :integer, :float, :keyword, + :delimiter, :reserved] + + # Collection of tokens that should appear dedented even though they + # don't affect the surrounding code. + MIDWAY_TOKENS = %w(when else elsif ensure rescue) + + # Clean the indentation of a fragment of ruby. + # + # @param [String] str + # @return [String] + def self.indent(str) + new.indent(str) + end + + # Get the module nesting at the given point in the given string. + # + # NOTE If the line specified contains a method definition, then the nesting + # at the start of the method definition is used. Otherwise the nesting from + # the end of the line is used. + # + # @param [String] str The ruby code to analyze + # @param [Fixnum] line_number The line number (starting from 1) + # @return [Array] + def self.nesting_at(str, line_number) + indent = new + lines = str.split("\n") + n = line_number - 1 + to_indent = lines[0...n] << (lines[n] || "").split("def").first(1) + indent.indent(to_indent.join("\n") << "\n") + indent.module_nesting + end + + def initialize + reset + end + + # reset internal state + def reset + @stack = [] + @indent_level = '' + @heredoc_queue = [] + @close_heredocs = {} + @string_start = nil + @awaiting_class = false + @module_nesting = [] + self + end + + # Indents a string and returns it. This string can either be a single line + # or multiple ones. + # + # @example + # str = <] + def module_nesting + @module_nesting.map do |(kind, token)| + raise UnparseableNestingError, @module_nesting.inspect if token.nil? + + "#{kind} #{token}" + end + end + + # Return a string which, when printed, will rewrite the previous line with + # the correct indentation. Mostly useful for fixing 'end'. + # + # @param [String] prompt The user's prompt + # @param [String] code The code the user just typed in. + # @param [Fixnum] overhang (0) The number of chars to erase afterwards (i.e., + # the difference in length between the old line and the new one). + # @return [String] + def correct_indentation(prompt, code, overhang=0) + prompt = prompt.delete("\001\002") + line_to_measure = Pry::Helpers::Text.strip_color(prompt) << code + whitespace = ' ' * overhang + + _, cols = Terminal.screen_size + + cols = cols.to_i + lines = (cols != 0 ? (line_to_measure.length / cols + 1) : 1).to_i + + if Pry::Helpers::BaseHelpers.windows_ansi? + move_up = "\e[#{lines}F" + move_down = "\e[#{lines}E" + else + move_up = "\e[#{lines}A\e[0G" + move_down = "\e[#{lines}B\e[0G" + end + + "#{move_up}#{prompt}#{colorize_code(code)}#{whitespace}#{move_down}" + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/input_completer.rb b/.bundle/gems/pry-0.10.2/lib/pry/input_completer.rb new file mode 100644 index 0000000..363baa4 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/input_completer.rb @@ -0,0 +1,242 @@ +# taken from irb +# Implements tab completion for Readline in Pry +class Pry::InputCompleter + NUMERIC_REGEXP = /^(-?(0[dbo])?[0-9_]+(\.[0-9_]+)?([eE]-?[0-9]+)?)\.([^.]*)$/ + ARRAY_REGEXP = /^([^\]]*\])\.([^.]*)$/ + SYMBOL_REGEXP = /^(:[^:.]*)$/ + SYMBOL_METHOD_CALL_REGEXP = /^(:[^:.]+)\.([^.]*)$/ + REGEX_REGEXP = /^(\/[^\/]*\/)\.([^.]*)$/ + PROC_OR_HASH_REGEXP = /^([^\}]*\})\.([^.]*)$/ + TOPLEVEL_LOOKUP_REGEXP = /^::([A-Z][^:\.\(]*)$/ + CONSTANT_REGEXP = /^([A-Z][A-Za-z0-9]*)$/ + CONSTANT_OR_METHOD_REGEXP = /^([A-Z].*)::([^:.]*)$/ + HEX_REGEXP = /^(-?0x[0-9a-fA-F_]+)\.([^.]*)$/ + GLOBALVARIABLE_REGEXP = /^(\$[^.]*)$/ + VARIABLE_REGEXP = /^([^."].*)\.([^.]*)$/ + + ReservedWords = [ + "BEGIN", "END", + "alias", "and", + "begin", "break", + "case", "class", + "def", "defined", "do", + "else", "elsif", "end", "ensure", + "false", "for", + "if", "in", + "module", + "next", "nil", "not", + "or", + "redo", "rescue", "retry", "return", + "self", "super", + "then", "true", + "undef", "unless", "until", + "when", "while", + "yield" ] + + Operators = [ + "%", "&", "*", "**", "+", "-", "/", + "<", "<<", "<=", "<=>", "==", "===", "=~", ">", ">=", ">>", + "[]", "[]=", "^", "!", "!=", "!~" + ] + + WORD_ESCAPE_STR = " \t\n\"\\'`><=;|&{(" + + def initialize(input, pry = nil) + @pry = pry + @input = input + @input.basic_word_break_characters = WORD_ESCAPE_STR if @input.respond_to?(:basic_word_break_characters=) + @input.completion_append_character = nil if @input.respond_to?(:completion_append_character=) + end + + # + # Return a new completion proc for use by Readline. + # + def call(str, options = {}) + custom_completions = options[:custom_completions] || [] + # if there are multiple contexts e.g. cd 1/2/3 + # get new target for 1/2 and find candidates for 3 + path, input = build_path(str) + + if path.call.empty? + target = options[:target] + else + # Assume the user is tab-completing the 'cd' command + begin + target = Pry::ObjectPath.new(path.call, @pry.binding_stack).resolve.last + # but if that doesn't work, assume they're doing division with no spaces + rescue Pry::CommandError + target = options[:target] + end + end + + begin + bind = target + # Complete stdlib symbols + case input + when REGEX_REGEXP # Regexp + receiver = $1 + message = Regexp.quote($2) + candidates = Regexp.instance_methods.collect(&:to_s) + select_message(path, receiver, message, candidates) + when ARRAY_REGEXP # Array + receiver = $1 + message = Regexp.quote($2) + candidates = Array.instance_methods.collect(&:to_s) + select_message(path, receiver, message, candidates) + when PROC_OR_HASH_REGEXP # Proc or Hash + receiver = $1 + message = Regexp.quote($2) + candidates = Proc.instance_methods.collect(&:to_s) + candidates |= Hash.instance_methods.collect(&:to_s) + select_message(path, receiver, message, candidates) + when SYMBOL_REGEXP # Symbol + if Symbol.respond_to?(:all_symbols) + sym = Regexp.quote($1) + candidates = Symbol.all_symbols.collect{|s| ":" << s.id2name} + candidates.grep(/^#{sym}/) + else + [] + end + when TOPLEVEL_LOOKUP_REGEXP # Absolute Constant or class methods + receiver = $1 + candidates = Object.constants.collect(&:to_s) + candidates.grep(/^#{receiver}/).collect{|e| "::" << e} + when CONSTANT_REGEXP # Constant + message = $1 + begin + context = target.eval("self") + context = context.class unless context.respond_to? :constants + candidates = context.constants.collect(&:to_s) + rescue + candidates = [] + end + candidates = candidates.grep(/^#{message}/).collect(&path) + when CONSTANT_OR_METHOD_REGEXP # Constant or class methods + receiver = $1 + message = Regexp.quote($2) + begin + candidates = eval("#{receiver}.constants.collect(&:to_s)", bind) + candidates |= eval("#{receiver}.methods.collect(&:to_s)", bind) + rescue Pry::RescuableException + candidates = [] + end + candidates.grep(/^#{message}/).collect{|e| receiver + "::" + e} + when SYMBOL_METHOD_CALL_REGEXP # method call on a Symbol + receiver = $1 + message = Regexp.quote($2) + candidates = Symbol.instance_methods.collect(&:to_s) + select_message(path, receiver, message, candidates) + when NUMERIC_REGEXP + # Numeric + receiver = $1 + message = Regexp.quote($5) + begin + candidates = eval(receiver, bind).methods.collect(&:to_s) + rescue Pry::RescuableException + candidates = [] + end + select_message(path, receiver, message, candidates) + when HEX_REGEXP + # Numeric(0xFFFF) + receiver = $1 + message = Regexp.quote($2) + begin + candidates = eval(receiver, bind).methods.collect(&:to_s) + rescue Pry::RescuableException + candidates = [] + end + select_message(path, receiver, message, candidates) + when GLOBALVARIABLE_REGEXP # global + regmessage = Regexp.new(Regexp.quote($1)) + candidates = global_variables.collect(&:to_s).grep(regmessage) + when VARIABLE_REGEXP # variable + receiver = $1 + message = Regexp.quote($2) + + gv = eval("global_variables", bind).collect(&:to_s) + lv = eval("local_variables", bind).collect(&:to_s) + cv = eval("self.class.constants", bind).collect(&:to_s) + + if (gv | lv | cv).include?(receiver) or /^[A-Z]/ =~ receiver && /\./ !~ receiver + # foo.func and foo is local var. OR + # Foo::Bar.func + begin + candidates = eval("#{receiver}.methods", bind).collect(&:to_s) + rescue Pry::RescuableException + candidates = [] + end + else + # func1.func2 + candidates = [] + ObjectSpace.each_object(Module){|m| + begin + name = m.name.to_s + rescue Pry::RescuableException + name = "" + end + next if name != "IRB::Context" and + /^(IRB|SLex|RubyLex|RubyToken)/ =~ name + + # jruby doesn't always provide #instance_methods() on each + # object. + if m.respond_to?(:instance_methods) + candidates.concat m.instance_methods(false).collect(&:to_s) + end + } + candidates.sort! + candidates.uniq! + end + select_message(path, receiver, message, candidates) + when /^\.([^.]*)$/ + # Unknown(maybe String) + receiver = "" + message = Regexp.quote($1) + candidates = String.instance_methods(true).collect(&:to_s) + select_message(path, receiver, message, candidates) + else + candidates = eval( + "methods | private_methods | local_variables | " \ + "self.class.constants | instance_variables", + bind + ).collect(&:to_s) + + if eval("respond_to?(:class_variables)", bind) + candidates += eval("class_variables", bind).collect(&:to_s) + end + candidates = (candidates|ReservedWords|custom_completions).grep(/^#{Regexp.quote(input)}/) + candidates.collect(&path) + end + rescue Pry::RescuableException + [] + end + end + + def select_message(path, receiver, message, candidates) + candidates.grep(/^#{message}/).collect { |e| + case e + when /^[a-zA-Z_]/ + path.call(receiver + "." << e) + when /^[0-9]/ + when *Operators + #receiver + " " << e + end + }.compact + end + + # build_path seperates the input into two parts: path and input. + # input is the partial string that should be completed + # path is a proc that takes an input and builds a full path. + def build_path(input) + # check to see if the input is a regex + return proc {|i| i.to_s }, input if input[/\/\./] + trailing_slash = input.end_with?('/') + contexts = input.chomp('/').split(/\//) + input = contexts[-1] + path = proc do |i| + p = contexts[0..-2].push(i).join('/') + p += '/' if trailing_slash && !i.nil? + p + end + return path, input + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/input_lock.rb b/.bundle/gems/pry-0.10.2/lib/pry/input_lock.rb new file mode 100644 index 0000000..8adfed4 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/input_lock.rb @@ -0,0 +1,132 @@ +require 'thread' + +class Pry + # There is one InputLock per input (such as STDIN) as two REPLs on the same + # input makes things delirious. InputLock serializes accesses to the input so + # that threads to not conflict with each other. The latest thread to request + # ownership of the input wins. + class InputLock + class Interrupt < Exception; end + + class << self + attr_accessor :input_locks + attr_accessor :global_lock + end + + self.input_locks = {} + self.global_lock = Mutex.new + + def self.for(input) + # XXX This method leaks memory, as we never unregister an input once we + # are done with it. Fortunately, the leak is tiny (or so we hope). In + # usual scenarios, we would leak the StringIO that is passed to be + # evaluated from the command line. + global_lock.synchronize do + input_locks[input] ||= Pry::InputLock.new + end + end + + def initialize + @mutex = Mutex.new + @cond = ConditionVariable.new + @owners = [] + @interruptible = false + end + + # Adds ourselves to the ownership list. The last one in the list may access + # the input through interruptible_region(). + def __with_ownership(&block) + @mutex.synchronize do + # Three cases: + # 1) There are no owners, in this case we are good to go. + # 2) The current owner of the input is not reading the input (it might + # just be evaluating some ruby that the user typed). + # The current owner will figure out that it cannot go back to reading + # the input since we are adding ourselves to the @owners list, which + # in turns makes us the current owner. + # 3) The owner of the input is in the interruptible region, reading from + # the input. It's safe to send an Interrupt exception to interrupt + # the owner. It will then proceed like in case 2). + # We wait until the owner sets the interruptible flag back + # to false, meaning that he's out of the interruptible region. + # Note that the owner may receive multiple interrupts since, but that + # should be okay (and trying to avoid it is futile anyway). + while @interruptible + @owners.last.raise Interrupt + @cond.wait(@mutex) + end + @owners << Thread.current + end + + block.call + + ensure + @mutex.synchronize do + # We are releasing any desire to have the input ownership by removing + # ourselves from the list. + @owners.delete(Thread.current) + + # We need to wake up the thread at the end of the @owners list, but + # sadly Ruby doesn't allow us to choose which one we wake up, so we wake + # them all up. + @cond.broadcast + end + end + + def with_ownership(&block) + # If we are in a nested with_ownership() call (nested pry context), we do nothing. + nested = @mutex.synchronize { @owners.include?(Thread.current) } + nested ? block.call : __with_ownership(&block) + end + + def enter_interruptible_region + @mutex.synchronize do + # We patiently wait until we are the owner. This may happen as another + # thread calls with_ownership() because of a binding.pry happening in + # another thread. + @cond.wait(@mutex) until @owners.last == Thread.current + + # We are the legitimate owner of the input. We mark ourselves as + # interruptible, so other threads can send us an Interrupt exception + # while we are blocking from reading the input. + @interruptible = true + end + end + + def leave_interruptible_region + @mutex.synchronize do + # We check if we are still the owner, because we could have received an + # Interrupt right after the following @cond.broadcast, making us retry. + @interruptible = false if @owners.last == Thread.current + @cond.broadcast + end + rescue Interrupt + # We need to guard against a spurious interrupt delivered while we are + # trying to acquire the lock (the rescue block is no longer in our scope). + retry + end + + def interruptible_region(&block) + enter_interruptible_region + + # XXX Note that there is a chance that we get the interrupt right after + # the readline call succeeded, but we'll never know, and we will retry the + # call, discarding that piece of input. + block.call + + rescue Interrupt + # We were asked to back off. The one requesting the interrupt will be + # waiting on the conditional for the interruptible flag to change to false. + # Note that there can be some inefficiency, as we could immediately + # succeed in enter_interruptible_region(), even before the one requesting + # the ownership has the chance to register itself as an owner. + # To mitigate the issue, we sleep a little bit. + leave_interruptible_region + sleep 0.01 + retry + + ensure + leave_interruptible_region + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/inspector.rb b/.bundle/gems/pry-0.10.2/lib/pry/inspector.rb new file mode 100644 index 0000000..c56b02f --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/inspector.rb @@ -0,0 +1,27 @@ +class Pry::Inspector + MAP = { + "default" => { + value: Pry::DEFAULT_PRINT, + description: <<-DESCRIPTION.each_line.map(&:lstrip!) + The default Pry inspector. It has paging and color support, and uses + pretty_inspect when printing an object. + DESCRIPTION + }, + + "simple" => { + value: Pry::SIMPLE_PRINT, + description: <<-DESCRIPTION.each_line.map(&:lstrip) + A simple inspector that uses #puts and #inspect when printing an + object. It has no pager, color, or pretty_inspect support. + DESCRIPTION + }, + + "clipped" => { + value: Pry::CLIPPED_PRINT, + description: <<-DESCRIPTION.each_line.map(&:lstrip) + The clipped inspector has the same features as the 'simple' inspector + but prints large objects as a smaller string. + DESCRIPTION + } + } +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/last_exception.rb b/.bundle/gems/pry-0.10.2/lib/pry/last_exception.rb new file mode 100644 index 0000000..2841113 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/last_exception.rb @@ -0,0 +1,61 @@ +# +# {Pry::LastException} is a proxy class who wraps an Exception object for +# {Pry#last_exception}. it extends the exception object with methods that +# help pry commands be useful. +# +# the original exception object is not modified and method calls are forwarded +# to the wrapped exception object. +# +class Pry::LastException < BasicObject + attr_accessor :bt_index + + def initialize(e) + @e = e + @bt_index = 0 + @file, @line = bt_source_location_for(0) + end + + def method_missing(name, *args, &block) + if @e.respond_to?(name) + @e.public_send(name, *args, &block) + else + super + end + end + + def respond_to_missing?(name, include_private = false) + @e.respond_to?(name) + end + + # + # @return [String] + # returns the path to a file for the current backtrace. see {#bt_index}. + # + def file + @file + end + + # + # @return [Fixnum] + # returns the line for the current backtrace. see {#bt_index}. + # + def line + @line + end + + # @return [Exception] + # returns the wrapped exception + # + def wrapped_exception + @e + end + + def bt_source_location_for(index) + backtrace[index] =~ /(.*):(\d+)/ + [$1, $2.to_i] + end + + def inc_bt_index + @bt_index = (@bt_index + 1) % backtrace.size + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/method.rb b/.bundle/gems/pry-0.10.2/lib/pry/method.rb new file mode 100644 index 0000000..03eb60a --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/method.rb @@ -0,0 +1,546 @@ +require 'pry/helpers/documentation_helpers' + +class Pry + class << self + # If the given object is a `Pry::Method`, return it unaltered. If it's + # anything else, return it wrapped in a `Pry::Method` instance. + def Method(obj) + if obj.is_a? Pry::Method + obj + else + Pry::Method.new(obj) + end + end + end + + # This class wraps the normal `Method` and `UnboundMethod` classes + # to provide extra functionality useful to Pry. + class Method + require 'pry/method/weird_method_locator' + require 'pry/method/disowned' + require 'pry/method/patcher' + + extend Helpers::BaseHelpers + include Helpers::BaseHelpers + include Helpers::DocumentationHelpers + include CodeObject::Helpers + + class << self + # Given a string representing a method name and optionally a binding to + # search in, find and return the requested method wrapped in a `Pry::Method` + # instance. + # + # @param [String] name The name of the method to retrieve. + # @param [Binding] target The context in which to search for the method. + # @param [Hash] options + # @option options [Boolean] :instance Look for an instance method if `name` doesn't + # contain any context. + # @option options [Boolean] :methods Look for a bound/singleton method if `name` doesn't + # contain any context. + # @return [Pry::Method, nil] A `Pry::Method` instance containing the requested + # method, or `nil` if name is `nil` or no method could be located matching the parameters. + def from_str(name, target=TOPLEVEL_BINDING, options={}) + if name.nil? + nil + elsif name.to_s =~ /(.+)\#(\S+)\Z/ + context, meth_name = $1, $2 + from_module(target.eval(context), meth_name, target) + elsif name.to_s =~ /(.+)(\[\])\Z/ + context, meth_name = $1, $2 + from_obj(target.eval(context), meth_name, target) + elsif name.to_s =~ /(.+)(\.|::)(\S+)\Z/ + context, meth_name = $1, $3 + from_obj(target.eval(context), meth_name, target) + elsif options[:instance] + from_module(target.eval("self"), name, target) + elsif options[:methods] + from_obj(target.eval("self"), name, target) + else + from_str(name, target, :instance => true) or + from_str(name, target, :methods => true) + end + + rescue Pry::RescuableException + nil + end + + # Given a `Binding`, try to extract the `::Method` it originated from and + # use it to instantiate a `Pry::Method`. Return `nil` if this isn't + # possible. + # + # @param [Binding] b + # @return [Pry::Method, nil] + # + def from_binding(b) + meth_name = b.eval('::Kernel.__method__') + if [:__script__, nil].include?(meth_name) + nil + else + method = begin + if Object === b.eval('self') + new(Kernel.instance_method(:method).bind(b.eval("self")).call(meth_name)) + else + new(b.eval('class << self; self; end.instance_method(::Kernel.__method__).bind(self)')) + end + rescue NameError, NoMethodError + Disowned.new(b.eval('self'), meth_name.to_s) + end + + if WeirdMethodLocator.weird_method?(method, b) + WeirdMethodLocator.new(method, b).get_method || method + else + method + end + end + end + + # In order to support 2.0 Refinements we need to look up methods + # inside the relevant Binding. + # @param [Object] obj The owner/receiver of the method. + # @param [Symbol] method_name The name of the method. + # @param [Symbol] method_type The type of method: :method or :instance_method + # @param [Binding] target The binding where the method is looked up. + # @return [Method, UnboundMethod] The 'refined' method object. + def lookup_method_via_binding(obj, method_name, method_type, target=TOPLEVEL_BINDING) + Pry.current[:obj] = obj + Pry.current[:name] = method_name + receiver = obj.is_a?(Module) ? "Module" : "Kernel" + target.eval("::#{receiver}.instance_method(:#{method_type}).bind(Pry.current[:obj]).call(Pry.current[:name])") + ensure + Pry.current[:obj] = Pry.current[:name] = nil + end + + # Given a `Class` or `Module` and the name of a method, try to + # instantiate a `Pry::Method` containing the instance method of + # that name. Return `nil` if no such method exists. + # + # @param [Class, Module] klass + # @param [String] name + # @param [Binding] target The binding where the method is looked up. + # @return [Pry::Method, nil] + def from_class(klass, name, target=TOPLEVEL_BINDING) + new(lookup_method_via_binding(klass, name, :instance_method, target)) rescue nil + end + alias from_module from_class + + # Given an object and the name of a method, try to instantiate + # a `Pry::Method` containing the method of that name bound to + # that object. Return `nil` if no such method exists. + # + # @param [Object] obj + # @param [String] name + # @param [Binding] target The binding where the method is looked up. + # @return [Pry::Method, nil] + def from_obj(obj, name, target=TOPLEVEL_BINDING) + new(lookup_method_via_binding(obj, name, :method, target)) rescue nil + end + + # Get all of the instance methods of a `Class` or `Module` + # @param [Class,Module] klass + # @param [Boolean] include_super Whether to include methods from ancestors. + # @return [Array[Pry::Method]] + def all_from_class(klass, include_super=true) + %w(public protected private).map do |visibility| + safe_send(klass, :"#{visibility}_instance_methods", include_super).map do |method_name| + new(safe_send(klass, :instance_method, method_name), :visibility => visibility.to_sym) + end + end.flatten(1) + end + + # + # Get all of the methods on an `Object` + # + # @param [Object] obj + # + # @param [Boolean] include_super + # indicates whether or not to include methods from ancestors. + # + # @return [Array[Pry::Method]] + # + def all_from_obj(obj, include_super=true) + all_from_class(singleton_class_of(obj), include_super) + end + + # + # @deprecated + # please use {#all_from_obj} instead. + # the `method_type` argument is ignored. + # + def all_from_common(obj, method_type = nil, include_super=true) + all_from_obj(obj, include_super) + end + + # Get every `Class` and `Module`, in order, that will be checked when looking + # for an instance method to call on this object. + # @param [Object] obj + # @return [Array[Class, Module]] + def resolution_order(obj) + if Class === obj + singleton_class_resolution_order(obj) + instance_resolution_order(Class) + else + klass = singleton_class_of(obj) rescue obj.class + instance_resolution_order(klass) + end + end + + # Get every `Class` and `Module`, in order, that will be checked when looking + # for methods on instances of the given `Class` or `Module`. + # This does not treat singleton classes of classes specially. + # @param [Class, Module] klass + # @return [Array[Class, Module]] + def instance_resolution_order(klass) + # include klass in case it is a singleton class, + ([klass] + Pry::Method.safe_send(klass, :ancestors)).uniq + end + + def method_definition?(name, definition_line) + singleton_method_definition?(name, definition_line) || + instance_method_definition?(name, definition_line) + end + + def singleton_method_definition?(name, definition_line) + /^define_singleton_method\(?\s*[:\"\']#{Regexp.escape(name)}|^def\s*self\.#{Regexp.escape(name)}/ =~ definition_line.strip + end + + def instance_method_definition?(name, definition_line) + /^define_method\(?\s*[:\"\']#{Regexp.escape(name)}|^def\s*#{Regexp.escape(name)}/ =~ definition_line.strip + end + + # Get the singleton classes of superclasses that could define methods on + # the given class object, and any modules they include. + # If a module is included at multiple points in the ancestry, only + # the lowest copy will be returned. + def singleton_class_resolution_order(klass) + ancestors = Pry::Method.safe_send(klass, :ancestors) + resolution_order = ancestors.grep(Class).map do |anc| + [singleton_class_of(anc), *singleton_class_of(anc).included_modules] + end.flatten(1) + + resolution_order.reverse.uniq.reverse - Class.included_modules + end + + def singleton_class_of(obj) + begin + class << obj; self; end + rescue TypeError # can't define singleton. Fixnum, Symbol, Float, ... + obj.class + end + end + end + + # A new instance of `Pry::Method` wrapping the given `::Method`, `UnboundMethod`, or `Proc`. + # + # @param [::Method, UnboundMethod, Proc] method + # @param [Hash] known_info Can be used to pre-cache expensive to compute stuff. + # @return [Pry::Method] + def initialize(method, known_info={}) + @method = method + @visibility = known_info[:visibility] + end + + # Get the name of the method as a String, regardless of the underlying Method#name type. + # @return [String] + def name + @method.name.to_s + end + + # Get the owner of the method as a Pry::Module + # @return [Pry::Module] + def wrapped_owner + @wrapped_owner ||= Pry::WrappedModule.new(owner) + end + + # Get underlying object wrapped by this Pry::Method instance + # @return [Method, UnboundMethod, Proc] + def wrapped + @method + end + + # Is the method undefined? (aka `Disowned`) + # @return [Boolean] false + def undefined? + false + end + + # Get the name of the method including the class on which it was defined. + # @example + # method(:puts).method_name + # => "Kernel.puts" + # @return [String] + def name_with_owner + "#{wrapped_owner.method_prefix}#{name}" + end + + # @return [String, nil] The source code of the method, or `nil` if it's unavailable. + def source + @source ||= case source_type + when :c + c_source + when :ruby + ruby_source + end + end + + # Update the live copy of the method's source. + def redefine(source) + Patcher.new(self).patch_in_ram source + Pry::Method(owner.instance_method(name)) + end + + # Can we get the source code for this method? + # @return [Boolean] + def source? + !!source + rescue MethodSource::SourceNotFoundError + false + end + + # @return [String, nil] The documentation for the method, or `nil` if it's + # unavailable. + def doc + @doc ||= case source_type + when :c + info = pry_doc_info + info.docstring if info + when :ruby + get_comment_content(comment) + end + end + + # @return [Symbol] The source type of the method. The options are + # `:ruby` for Ruby methods or `:c` for methods written in C. + def source_type + source_location.nil? ? :c : :ruby + end + + # @return [String, nil] The name of the file the method is defined in, or + # `nil` if the filename is unavailable. + def source_file + if source_location.nil? + if !rbx? and source_type == :c + info = pry_doc_info + info.file if info + end + else + source_location.first + end + end + + # @return [Fixnum, nil] The line of code in `source_file` which begins + # the method's definition, or `nil` if that information is unavailable. + def source_line + source_location.nil? ? nil : source_location.last + end + + # @return [Range, nil] The range of lines in `source_file` which contain + # the method's definition, or `nil` if that information is unavailable. + def source_range + source_location.nil? ? nil : (source_line)..(source_line + source.lines.count - 1) + end + + # @return [Symbol] The visibility of the method. May be `:public`, + # `:protected`, or `:private`. + def visibility + @visibility ||= if owner.public_instance_methods.any? { |m| m.to_s == name } + :public + elsif owner.protected_instance_methods.any? { |m| m.to_s == name } + :protected + elsif owner.private_instance_methods.any? { |m| m.to_s == name } + :private + else + :none + end + end + + # @return [String] A representation of the method's signature, including its + # name and parameters. Optional and "rest" parameters are marked with `*` + # and block parameters with `&`. If the parameter names are unavailable, + # they're given numbered names instead. + # Paraphrased from `awesome_print` gem. + def signature + if respond_to?(:parameters) + args = parameters.inject([]) do |arr, (type, name)| + name ||= (type == :block ? 'block' : "arg#{arr.size + 1}") + arr << case type + when :req then name.to_s + when :opt then "#{name}=?" + when :rest then "*#{name}" + when :block then "&#{name}" + else '?' + end + end + else + args = (1..arity.abs).map { |i| "arg#{i}" } + args[-1] = "*#{args[-1]}" if arity < 0 + end + + "#{name}(#{args.join(', ')})" + end + + # @return [Pry::Method, nil] The wrapped method that is called when you + # use "super" in the body of this method. + def super(times=1) + if UnboundMethod === @method + sup = super_using_ancestors(Pry::Method.instance_resolution_order(owner), times) + else + sup = super_using_ancestors(Pry::Method.resolution_order(receiver), times) + sup &&= sup.bind(receiver) + end + Pry::Method.new(sup) if sup + end + + # @return [String, nil] The original name the method was defined under, + # before any aliasing, or `nil` if it can't be determined. + def original_name + return nil if source_type != :ruby + method_name_from_first_line(source.lines.first) + end + + # @return [Boolean] Was the method defined outside a source file? + def dynamically_defined? + !!(source_file and source_file =~ /(\(.*\))|<.*>/) + end + + # @return [Boolean] Whether the method is unbound. + def unbound_method? + is_a?(::UnboundMethod) + end + + # @return [Boolean] Whether the method is bound. + def bound_method? + is_a?(::Method) + end + + # @return [Boolean] Whether the method is a singleton method. + def singleton_method? + wrapped_owner.singleton_class? + end + + # @return [Boolean] Was the method defined within the Pry REPL? + def pry_method? + source_file == Pry.eval_path + end + + # @return [Array] All known aliases for the method. + def aliases + owner = @method.owner + # Avoid using `to_sym` on {Method#name}, which returns a `String`, because + # it won't be garbage collected. + name = @method.name + + all_methods_to_compare = owner.instance_methods | owner.private_instance_methods + alias_list = all_methods_to_compare.combination(2).select do |pair| + pair.include?(name) && + owner.instance_method(pair.first) == owner.instance_method(pair.last) + end.flatten + alias_list.delete(name) + + alias_list.map(&:to_s) + end + + # @return [Boolean] Is the method definitely an alias? + def alias? + name != original_name + end + + # @return [Boolean] + def ==(obj) + if obj.is_a? Pry::Method + obj == @method + else + @method == obj + end + end + + # @param [Class] klass + # @return [Boolean] + def is_a?(klass) + klass == Pry::Method or @method.is_a?(klass) + end + alias kind_of? is_a? + + # @param [String, Symbol] method_name + # @return [Boolean] + def respond_to?(method_name) + super or @method.respond_to?(method_name) + end + + # Delegate any unknown calls to the wrapped method. + def method_missing(method_name, *args, &block) + @method.send(method_name, *args, &block) + end + + def comment + Pry::Code.from_file(source_file).comment_describing(source_line) + end + + private + + # @return [YARD::CodeObjects::MethodObject] + # @raise [CommandError] when the method can't be found or `pry-doc` isn't installed. + def pry_doc_info + if Pry.config.has_pry_doc + Pry::MethodInfo.info_for(@method) or raise CommandError, "Cannot locate this method: #{name}. (source_location returns nil)" + else + fail_msg = "Cannot locate this method: #{name}." + if mri? + fail_msg += ' Try `gem-install pry-doc` to get access to Ruby Core documentation.' + end + raise CommandError, fail_msg + end + end + + # @param [Class, Module] ancestors The ancestors to investigate + # @return [Method] The unwrapped super-method + def super_using_ancestors(ancestors, times=1) + next_owner = self.owner + times.times do + i = ancestors.index(next_owner) + 1 + while ancestors[i] && !(ancestors[i].method_defined?(name) || ancestors[i].private_method_defined?(name)) + i += 1 + end + next_owner = ancestors[i] or return nil + end + + safe_send(next_owner, :instance_method, name) rescue nil + end + + # @param [String] first_ln The first line of a method definition. + # @return [String, nil] + def method_name_from_first_line(first_ln) + return nil if first_ln.strip !~ /^def / + + tokens = CodeRay.scan(first_ln, :ruby) + tokens = tokens.tokens.each_slice(2) if tokens.respond_to?(:tokens) + tokens.each_cons(2) do |t1, t2| + if t2.last == :method || t2.last == :ident && t1 == [".", :operator] + return t2.first + end + end + + nil + end + + def c_source + info = pry_doc_info + if info and info.source + strip_comments_from_c_code(info.source) + end + end + + def ruby_source + # clone of MethodSource.source_helper that knows to use our + # hacked version of source_location for rbx core methods, and + # our input buffer for methods defined in (pry) + file, line = *source_location + raise SourceNotFoundError, "Could not locate source for #{name_with_owner}!" unless file + + begin + code = Pry::Code.from_file(file).expression_at(line) + rescue SyntaxError => e + raise MethodSource::SourceNotFoundError.new(e.message) + end + strip_leading_whitespace(code) + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/method/disowned.rb b/.bundle/gems/pry-0.10.2/lib/pry/method/disowned.rb new file mode 100644 index 0000000..35908c9 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/method/disowned.rb @@ -0,0 +1,53 @@ +class Pry + class Method + # A Disowned Method is one that's been removed from the class on which it was defined. + # + # e.g. + # class C + # def foo + # C.send(:undefine_method, :foo) + # Pry::Method.from_binding(binding) + # end + # end + # + # In this case we assume that the "owner" is the singleton class of the receiver. + # + # This occurs mainly in Sinatra applications. + class Disowned < Method + attr_reader :receiver, :name + + # Create a new Disowned method. + # + # @param [Object] receiver + # @param [String] method_name + def initialize(receiver, method_name, binding=nil) + @receiver, @name = receiver, method_name + end + + # Is the method undefined? (aka `Disowned`) + # @return [Boolean] true + def undefined? + true + end + + # Can we get the source for this method? + # @return [Boolean] false + def source? + false + end + + # Get the hypothesized owner of the method. + # + # @return [Object] + def owner + class << receiver; self; end + end + + # Raise a more useful error message instead of trying to forward to nil. + def method_missing(meth_name, *args, &block) + raise "Cannot call '#{meth_name}' on an undef'd method." if method(:name).respond_to?(meth_name) + Object.instance_method(:method_missing).bind(self).call(meth_name, *args, &block) + end + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/method/patcher.rb b/.bundle/gems/pry-0.10.2/lib/pry/method/patcher.rb new file mode 100644 index 0000000..3f736f6 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/method/patcher.rb @@ -0,0 +1,125 @@ +class Pry + class Method + class Patcher + attr_accessor :method + + @@source_cache = {} + + def initialize(method) + @method = method + end + + def self.code_for(filename) + @@source_cache[filename] + end + + # perform the patch + def patch_in_ram(source) + if method.alias? + with_method_transaction do + redefine source + end + else + redefine source + end + end + + private + + def redefine(source) + @@source_cache[cache_key] = source + TOPLEVEL_BINDING.eval wrap(source), cache_key + end + + def cache_key + "pry-redefined(0x#{method.owner.object_id.to_s(16)}##{method.name})" + end + + # Run some code ensuring that at the end target#meth_name will not have changed. + # + # When we're redefining aliased methods we will overwrite the method at the + # unaliased name (so that super continues to work). By wrapping that code in a + # transation we make that not happen, which means that alias_method_chains, etc. + # continue to work. + # + # @param [String] meth_name The method name before aliasing + # @param [Module] target The owner of the method + + def with_method_transaction + temp_name = "__pry_#{method.original_name}__" + method = self.method + method.owner.class_eval do + alias_method temp_name, method.original_name + yield + alias_method method.name, method.original_name + alias_method method.original_name, temp_name + end + + ensure + method.send(:remove_method, temp_name) rescue nil + end + + # Update the definition line so that it can be eval'd directly on the Method's + # owner instead of from the original context. + # + # In particular this takes `def self.foo` and turns it into `def foo` so that we + # don't end up creating the method on the singleton class of the singleton class + # by accident. + # + # This is necessarily done by String manipulation because we can't find out what + # syntax is needed for the argument list by ruby-level introspection. + # + # @param [String] line The original definition line. e.g. def self.foo(bar, baz=1) + # @return [String] The new definition line. e.g. def foo(bar, baz=1) + def definition_for_owner(line) + if line =~ /\Adef (?:.*?\.)?#{Regexp.escape(method.original_name)}(?=[\(\s;]|$)/ + "def #{method.original_name}#{$'}" + else + raise CommandError, "Could not find original `def #{method.original_name}` line to patch." + end + end + + # Apply wrap_for_owner and wrap_for_nesting successively to `source` + # @param [String] source + # @return [String] The wrapped source. + def wrap(source) + wrap_for_nesting(wrap_for_owner(source)) + end + + # Update the source code so that when it has the right owner when eval'd. + # + # This (combined with definition_for_owner) is backup for the case that + # wrap_for_nesting fails, to ensure that the method will stil be defined in + # the correct place. + # + # @param [String] source The source to wrap + # @return [String] + def wrap_for_owner(source) + Pry.current[:pry_owner] = method.owner + owner_source = definition_for_owner(source) + visibility_fix = "#{method.visibility.to_s} #{method.name.to_sym.inspect}" + "Pry.current[:pry_owner].class_eval do; #{owner_source}\n#{visibility_fix}\nend" + end + + # Update the new source code to have the correct Module.nesting. + # + # This method uses syntactic analysis of the original source file to determine + # the new nesting, so that we can tell the difference between: + # + # class A; def self.b; end; end + # class << A; def b; end; end + # + # The resulting code should be evaluated in the TOPLEVEL_BINDING. + # + # @param [String] source The source to wrap. + # @return [String] + def wrap_for_nesting(source) + nesting = Pry::Code.from_file(method.source_file).nesting_at(method.source_line) + + (nesting + [source] + nesting.map{ "end" } + [""]).join(";") + rescue Pry::Indent::UnparseableNestingError + source + end + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/method/weird_method_locator.rb b/.bundle/gems/pry-0.10.2/lib/pry/method/weird_method_locator.rb new file mode 100644 index 0000000..08c0a36 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/method/weird_method_locator.rb @@ -0,0 +1,188 @@ +class Pry + class Method + + # This class is responsible for locating the *real* `Pry::Method` + # object captured by a binding. + # + # Given a `Binding` from inside a method and a 'seed' Pry::Method object, + # there are primarily two situations where the seed method doesn't match + # the Binding: + # 1. The Pry::Method is from a subclass 2. The Pry::Method represents a method of the same name + # while the original was renamed to something else. For 1. we + # search vertically up the inheritance chain, + # and for 2. we search laterally along the object's method table. + # + # When we locate the method that matches the Binding we wrap it in + # Pry::Method and return it, or return nil if we fail. + class WeirdMethodLocator + class << self + + # Whether the given method object matches the associated binding. + # If the method object does not match the binding, then it's + # most likely not the method captured by the binding, and we + # must commence a search. + # + # @param [Pry::Method] method + # @param [Binding] b + # @return [Boolean] + def normal_method?(method, b) + method && (method.source_file && method.source_range rescue false) && + File.expand_path(method.source_file) == File.expand_path(b.eval('__FILE__')) && + method.source_range.include?(b.eval('__LINE__')) + end + + def weird_method?(method, b) + !normal_method?(method, b) + end + end + + attr_accessor :method + attr_accessor :target + + # @param [Pry::Method] method The seed method. + # @param [Binding] target The Binding that captures the method + # we want to locate. + def initialize(method, target) + @method, @target = method, target + end + + # @return [Pry::Method, nil] The Pry::Method that matches the + # given binding. + def get_method + find_method_in_superclass || find_renamed_method + end + + # @return [Boolean] Whether the Pry::Method is unrecoverable + # This usually happens when the method captured by the Binding + # has been subsequently deleted. + def lost_method? + !!(get_method.nil? && renamed_method_source_location) + end + + private + + def normal_method?(method) + self.class.normal_method?(method, target) + end + + def target_self + target.eval('self') + end + + def target_file + pry_file? ? target.eval('__FILE__') : File.expand_path(target.eval('__FILE__')) + end + + def target_line + target.eval('__LINE__') + end + + def pry_file? + Pry.eval_path == target.eval('__FILE__') + end + + # it's possible in some cases that the method we find by this approach is a sub-method of + # the one we're currently in, consider: + # + # class A; def b; binding.pry; end; end + # class B < A; def b; super; end; end + # + # Given that we can normally find the source_range of methods, and that we know which + # __FILE__ and __LINE__ the binding is at, we can hope to disambiguate these cases. + # + # This obviously won't work if the source is unavaiable for some reason, or if both + # methods have the same __FILE__ and __LINE__, or if we're in rbx where b.eval('__LINE__') + # is broken. + # + # @return [Pry::Method, nil] The Pry::Method representing the + # superclass method. + def find_method_in_superclass + guess = method + + while guess + # needs rescue if this is a Disowned method or a C method or something... + # TODO: Fix up the exception handling so we don't need a bare rescue + if normal_method?(guess) + return guess + elsif guess != guess.super + guess = guess.super + else + break + end + end + + # Uhoh... none of the methods in the chain had the right __FILE__ and __LINE__ + # This may be caused by rbx https://github.com/rubinius/rubinius/issues/953, + # or other unknown circumstances (TODO: we should warn the user when this happens) + nil + end + + # This is the case where the name of a method has changed + # (via alias_method) so we locate the Method object for the + # renamed method. + # + # @return [Pry::Method, nil] The Pry::Method representing the + # renamed method + def find_renamed_method + return if !valid_file?(target_file) + alias_name = all_methods_for(target_self).find do |v| + expanded_source_location(target_self.method(v).source_location) == renamed_method_source_location + end + + alias_name && Pry::Method(target_self.method(alias_name)) + end + + def expanded_source_location(sl) + return if !sl + + if pry_file? + sl + else + [File.expand_path(sl.first), sl.last] + end + end + + # Use static analysis to locate the start of the method definition. + # We have the `__FILE__` and `__LINE__` from the binding and the + # original name of the method so we search up until we find a + # def/define_method, etc defining a method of the appropriate name. + # + # @return [Array] The `source_location` of the + # renamed method + def renamed_method_source_location + return @original_method_source_location if defined?(@original_method_source_location) + + source_index = lines_for_file(target_file)[0..(target_line - 1)].rindex do |v| + Pry::Method.method_definition?(method.name, v) + end + + @original_method_source_location = source_index && + [target_file, index_to_line_number(source_index)] + end + + def index_to_line_number(index) + # Pry.line_buffer is 0-indexed + pry_file? ? index : index + 1 + end + + def valid_file?(file) + (File.exist?(file) && !File.directory?(file)) || Pry.eval_path == file + end + + def lines_for_file(file) + @lines_for_file ||= {} + @lines_for_file[file] ||= if Pry.eval_path == file + Pry.line_buffer + else + File.readlines(file) + end + end + + def all_methods_for(obj) + obj.public_methods(false) + + obj.private_methods(false) + + obj.protected_methods(false) + end + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/module_candidate.rb b/.bundle/gems/pry-0.10.2/lib/pry/module_candidate.rb new file mode 100644 index 0000000..4c97f13 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/module_candidate.rb @@ -0,0 +1,136 @@ +require 'pry/helpers/documentation_helpers' +require 'forwardable' + +class Pry + class WrappedModule + + # This class represents a single candidate for a module/class definition. + # It provides access to the source, documentation, line and file + # for a monkeypatch (reopening) of a class/module. + class Candidate + include Pry::Helpers::DocumentationHelpers + include Pry::CodeObject::Helpers + extend Forwardable + + # @return [String] The file where the module definition is located. + attr_reader :file + alias_method :source_file, :file + + # @return [Fixnum] The line where the module definition is located. + attr_reader :line + alias_method :source_line, :line + + # Methods to delegate to associated `Pry::WrappedModule + # instance`. + private_delegates = [:lines_for_file, :method_candidates, + :yard_docs?] + + public_delegates = [:wrapped, :module?, :class?, :name, :nonblank_name, + :number_of_candidates] + + def_delegators :@wrapper, *(private_delegates + public_delegates) + private(*private_delegates) + public(*public_delegates) + + # @raise [Pry::CommandError] If `rank` is out of bounds. + # @param [Pry::WrappedModule] wrapper The associated + # `Pry::WrappedModule` instance that owns the candidates. + # @param [Fixnum] rank The rank of the candidate to + # retrieve. Passing 0 returns 'primary candidate' (the candidate with largest + # number of methods), passing 1 retrieves candidate with + # second largest number of methods, and so on, up to + # `Pry::WrappedModule#number_of_candidates() - 1` + def initialize(wrapper, rank) + @wrapper = wrapper + + if number_of_candidates <= 0 + raise CommandError, "Cannot find a definition for #{name} module!" + elsif rank > (number_of_candidates - 1) + raise CommandError, "No such module candidate. Allowed candidates range is from 0 to #{number_of_candidates - 1}" + end + + @rank = rank + @file, @line = source_location + end + + # @raise [Pry::CommandError] If source code cannot be found. + # @return [String] The source for the candidate, i.e the + # complete module/class definition. + def source + return nil if file.nil? + return @source if @source + + @source = strip_leading_whitespace(Pry::Code.from_file(file).expression_at(line, number_of_lines_in_first_chunk)) + end + + # @raise [Pry::CommandError] If documentation cannot be found. + # @return [String] The documentation for the candidate. + def doc + return nil if file.nil? + return @doc if @doc + + @doc = get_comment_content(Pry::Code.from_file(file).comment_describing(line)) + end + + # @return [Array, nil] A `[String, Fixnum]` pair representing the + # source location (file and line) for the candidate or `nil` + # if no source location found. + def source_location + return @source_location if @source_location + + file, line = first_method_source_location + return nil if !file.is_a?(String) + + @source_location = [file, first_line_of_module_definition(file, line)] + rescue Pry::RescuableException + nil + end + + private + + # Locate the first line of the module definition. + # @param [String] file The file that contains the module + # definition (somewhere). + # @param [Fixnum] line The module definition should appear + # before this line (if it exists). + # @return [Fixnum] The line where the module is defined. This + # line number is one-indexed. + def first_line_of_module_definition(file, line) + searchable_lines = lines_for_file(file)[0..(line - 2)] + searchable_lines.rindex { |v| class_regexes.any? { |r| r =~ v } } + 1 + end + + def class_regexes + mod_type_string = wrapped.class.to_s.downcase + [/^\s*#{mod_type_string}\s+(?:(?:\w*)::)*?#{wrapped.name.split(/::/).last}/, + /^\s*(::)?#{wrapped.name.split(/::/).last}\s*?=\s*?#{wrapped.class}/, + /^\s*(::)?#{wrapped.name.split(/::/).last}\.(class|instance)_eval/] + end + + # This method is used by `Candidate#source_location` as a + # starting point for the search for the candidate's definition. + # @return [Array] The source location of the base method used to + # calculate the source location of the candidate. + def first_method_source_location + @first_method_source_location ||= method_candidates[@rank].first.source_location + end + + # @return [Array] The source location of the last method in this + # candidate's module definition. + def last_method_source_location + @end_method_source_location ||= method_candidates[@rank].last.source_location + end + + # Return the number of lines between the start of the class definition + # and the start of the last method. We use this value so we can + # quickly grab these lines from the file (without having to + # check each intervening line for validity, which is expensive) speeding up source extraction. + # @return [Fixum] Number of lines. + def number_of_lines_in_first_chunk + end_method_line = last_method_source_location.last + + end_method_line - line + end + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/object_path.rb b/.bundle/gems/pry-0.10.2/lib/pry/object_path.rb new file mode 100644 index 0000000..5bffb02 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/object_path.rb @@ -0,0 +1,82 @@ +class Pry + # `ObjectPath` implements the resolution of "object paths", which are strings + # that are similar to filesystem paths but meant for traversing Ruby objects. + # Examples of valid object paths include: + # + # x + # @foo/@bar + # "string"/upcase + # Pry/Method + # + # Object paths are mostly relevant in the context of the `cd` command. + # @see https://github.com/pry/pry/wiki/State-navigation + class ObjectPath + SPECIAL_TERMS = ["", "::", ".", ".."] + + # @param [String] path_string The object path expressed as a string. + # @param [Array] current_stack The current state of the binding + # stack. + def initialize(path_string, current_stack) + @path_string = path_string + @current_stack = current_stack + end + + # @return [Array] a new stack resulting from applying the given + # path to the current stack. + def resolve + scanner = StringScanner.new(@path_string.strip) + stack = @current_stack.dup + + begin + next_segment = "" + + loop do + # Scan for as long as we don't see a slash + next_segment << scanner.scan(/[^\/]*/) + + if complete?(next_segment) || scanner.eos? + scanner.getch # consume the slash + break + else + next_segment << scanner.getch # append the slash + end + end + + case next_segment.chomp + when "" + stack = [stack.first] + when "::" + stack.push(TOPLEVEL_BINDING) + when "." + next + when ".." + stack.pop unless stack.size == 1 + else + stack.push(Pry.binding_for(stack.last.eval(next_segment))) + end + rescue RescuableException => e + return handle_failure(next_segment, e) + end until scanner.eos? + + stack + end + + private + + def complete?(segment) + SPECIAL_TERMS.include?(segment) || Pry::Code.complete_expression?(segment) + end + + def handle_failure(context, err) + msg = [ + "Bad object path: #{@path_string.inspect}", + "Failed trying to resolve: #{context.inspect}", + "Exception: #{err.inspect}" + ].join("\n") + + raise CommandError.new(msg).tap { |e| + e.set_backtrace err.backtrace + } + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/output.rb b/.bundle/gems/pry-0.10.2/lib/pry/output.rb new file mode 100644 index 0000000..b5f6bb3 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/output.rb @@ -0,0 +1,50 @@ +class Pry + class Output + attr_reader :_pry_ + + def initialize(_pry_) + @_pry_ = _pry_ + end + + def puts(*objs) + return print "\n" if objs.empty? + + objs.each do |obj| + if ary = Array.try_convert(obj) + puts(*ary) + else + print "#{obj.to_s.chomp}\n" + end + end + + nil + end + + def print(*objs) + objs.each do |obj| + _pry_.config.output.print decolorize_maybe(obj.to_s) + end + + nil + end + alias << print + alias write print + + # If _pry_.config.color is currently false, removes ansi escapes from the string. + def decolorize_maybe(str) + if _pry_.config.color + str + else + Helpers::Text.strip_color str + end + end + + def method_missing(name, *args, &block) + _pry_.config.output.send(name, *args, &block) + end + + def respond_to_missing?(*a) + _pry_.config.respond_to?(*a) + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/pager.rb b/.bundle/gems/pry-0.10.2/lib/pry/pager.rb new file mode 100644 index 0000000..e5451d2 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/pager.rb @@ -0,0 +1,236 @@ +require 'pry/terminal' + +# A pager is an `IO`-like object that accepts text and either prints it +# immediately, prints it one page at a time, or streams it to an external +# program to print one page at a time. +class Pry::Pager + class StopPaging < StandardError + end + + attr_reader :_pry_ + + def initialize(_pry_) + @_pry_ = _pry_ + end + + # Send the given text through the best available pager (if `Pry.config.pager` is + # enabled). + # If you want to send text through in chunks as you generate it, use `open` to + # get a writable object instead. + # @param [String] text A piece of text to run through a pager. + # @param [IO] output (`$stdout`) An object to send output to. + def page(text) + open do |pager| + pager << text + end + end + + # Yields a pager object (`NullPager`, `SimplePager`, or `SystemPager`). All + # pagers accept output with `#puts`, `#print`, `#write`, and `#<<`. + # @param [IO] output (`$stdout`) An object to send output to. + def open + pager = best_available + yield pager + rescue StopPaging + ensure + pager.close if pager + end + + private + + def enabled?; !!@enabled; end + + def output; @output; end + + # Return an instance of the "best" available pager class -- `SystemPager` if + # possible, `SimplePager` if `SystemPager` isn't available, and `NullPager` + # if the user has disabled paging. All pagers accept output with `#puts`, + # `#print`, `#write`, and `#<<`. You must call `#close` when you're done + # writing output to a pager, and you must rescue `Pry::Pager::StopPaging`. + # These requirements can be avoided by using `.open` instead. + # @param [#<<] output ($stdout) An object to send output to. + def best_available + if !_pry_.config.pager + NullPager.new(_pry_.output) + elsif !SystemPager.available? || Pry::Helpers::BaseHelpers.jruby? + SimplePager.new(_pry_.output) + else + SystemPager.new(_pry_.output) + end + end + + # `NullPager` is a "pager" that actually just prints all output as it comes + # in. Used when `Pry.config.pager` is false. + class NullPager + def initialize(out) + @out = out + end + + def puts(str) + print "#{str.chomp}\n" + end + + def print(str) + write str + end + alias << print + + def write(str) + @out.write str + end + + def close + end + + private + + def height + @height ||= Pry::Terminal.height! + end + + def width + @width ||= Pry::Terminal.width! + end + end + + # `SimplePager` is a straightforward pure-Ruby pager. We use it on JRuby and + # when we can't find a usable external pager. + class SimplePager < NullPager + def initialize(*) + super + @tracker = PageTracker.new(height - 3, width) + end + + def write(str) + str.lines.each do |line| + @out.print line + @tracker.record line + + if @tracker.page? + @out.print "\n" + @out.print "\e[0m" + @out.print " --- Press enter to continue " \ + "( q to break ) --- \n" + raise StopPaging if Readline.readline("").chomp == "q" + @tracker.reset + end + end + end + end + + # `SystemPager` buffers output until we're pretty sure it's at least a page + # long, then invokes an external pager and starts streaming output to it. If + # `#close` is called before then, it just prints out the buffered content. + class SystemPager < NullPager + def self.default_pager + pager = ENV["PAGER"] || "" + + # Default to less, and make sure less is being passed the correct options + if pager.strip.empty? or pager =~ /^less\b/ + pager = "less -R -F -X" + end + + pager + end + + def self.available? + if @system_pager.nil? + @system_pager = begin + pager_executable = default_pager.split(' ').first + `which #{pager_executable}` + $?.success? + rescue + false + end + else + @system_pager + end + end + + def initialize(*) + super + @tracker = PageTracker.new(height, width) + @buffer = "" + end + + def write(str) + if invoked_pager? + write_to_pager str + else + @tracker.record str + @buffer << str + + if @tracker.page? + write_to_pager @buffer + end + end + rescue Errno::EPIPE + raise StopPaging + end + + def close + if invoked_pager? + pager.close + else + @out.puts @buffer + end + end + + private + + def write_to_pager(text) + pager.write @out.decolorize_maybe(text) + end + + def invoked_pager? + @pager + end + + def pager + @pager ||= IO.popen(self.class.default_pager, 'w') + end + end + + # `PageTracker` tracks output to determine whether it's likely to take up a + # whole page. This doesn't need to be super precise, but we can use it for + # `SimplePager` and to avoid invoking the system pager unnecessarily. + # + # One simplifying assumption is that we don't need `#page?` to return `true` + # on the basis of an incomplete line. Long lines should be counted as + # multiple lines, but we don't have to transition from `false` to `true` + # until we see a newline. + class PageTracker + def initialize(rows, cols) + @rows, @cols = rows, cols + reset + end + + def record(str) + str.lines.each do |line| + if line.end_with? "\n" + @row += ((@col + line_length(line) - 1) / @cols) + 1 + @col = 0 + else + @col += line_length(line) + end + end + end + + def page? + @row >= @rows + end + + def reset + @row = 0 + @col = 0 + end + + private + + # Approximation of the printable length of a given line, without the + # newline and without ANSI color codes. + def line_length(line) + line.chomp.gsub(/\e\[[\d;]*m/, '').length + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/plugins.rb b/.bundle/gems/pry-0.10.2/lib/pry/plugins.rb new file mode 100644 index 0000000..1d05195 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/plugins.rb @@ -0,0 +1,103 @@ +class Pry + class PluginManager + PRY_PLUGIN_PREFIX = /^pry-/ + + # Placeholder when no associated gem found, displays warning + class NoPlugin + def initialize(name) + @name = name + end + + def method_missing(*args) + warn "Warning: The plugin '#{@name}' was not found! (no gem found)" + end + end + + class Plugin + attr_accessor :name, :gem_name, :enabled, :spec, :active + + def initialize(name, gem_name, spec, enabled) + @name, @gem_name, @enabled, @spec = name, gem_name, enabled, spec + end + + # Disable a plugin. (prevents plugin from being loaded, cannot + # disable an already activated plugin) + def disable! + self.enabled = false + end + + # Enable a plugin. (does not load it immediately but puts on + # 'white list' to be loaded) + def enable! + self.enabled = true + end + + # Load the Command line options defined by this plugin (if they exist) + def load_cli_options + cli_options_file = File.join(spec.full_gem_path, "lib/#{spec.name}/cli.rb") + require cli_options_file if File.exist?(cli_options_file) + end + # Activate the plugin (require the gem - enables/loads the + # plugin immediately at point of call, even if plugin is + # disabled) + # Does not reload plugin if it's already active. + def activate! + # Create the configuration object for the plugin. + Pry.config.send("#{gem_name.gsub('-', '_')}=", Pry::Config.from_hash({})) + + begin + require gem_name if !active? + rescue LoadError => e + warn "Found plugin #{gem_name}, but could not require '#{gem_name}'" + warn e + rescue => e + warn "require '#{gem_name}' # Failed, saying: #{e}" + end + + self.active = true + self.enabled = true + end + + alias active? active + alias enabled? enabled + end + + def initialize + @plugins = [] + end + + # Find all installed Pry plugins and store them in an internal array. + def locate_plugins + Gem.refresh + (Gem::Specification.respond_to?(:each) ? Gem::Specification : Gem.source_index.find_name('')).each do |gem| + next if gem.name !~ PRY_PLUGIN_PREFIX + plugin_name = gem.name.split('-', 2).last + @plugins << Plugin.new(plugin_name, gem.name, gem, true) if !gem_located?(gem.name) + end + @plugins + end + + # @return [Hash] A hash with all plugin names (minus the 'pry-') as + # keys and Plugin objects as values. + def plugins + h = Hash.new { |_, key| NoPlugin.new(key) } + @plugins.each do |plugin| + h[plugin.name] = plugin + end + h + end + + # Require all enabled plugins, disabled plugins are skipped. + def load_plugins + @plugins.each do |plugin| + plugin.activate! if plugin.enabled? + end + end + + private + def gem_located?(gem_name) + @plugins.any? { |plugin| plugin.gem_name == gem_name } + end + end + +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/prompt.rb b/.bundle/gems/pry-0.10.2/lib/pry/prompt.rb new file mode 100644 index 0000000..62f0bc1 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/prompt.rb @@ -0,0 +1,26 @@ +class Pry::Prompt + MAP = { + "default" => { + value: Pry::DEFAULT_PROMPT, + description: "The default Pry prompt. Includes information about the\n" \ + "current expression number, evaluation context, and nesting\n" \ + "level, plus a reminder that you're using Pry." + }, + + "simple" => { + value: Pry::SIMPLE_PROMPT, + description: "A simple '>>'." + }, + + "nav" => { + value: Pry::NAV_PROMPT, + description: "A prompt that displays the binding stack as a path and\n" \ + "includes information about _in_ and _out_." + }, + + "none" => { + value: Pry::NO_PROMPT, + description: "Wave goodbye to the Pry prompt." + } + } +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/pry_class.rb b/.bundle/gems/pry-0.10.2/lib/pry/pry_class.rb new file mode 100644 index 0000000..69f68e4 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/pry_class.rb @@ -0,0 +1,375 @@ +require 'pry/config' +class Pry + + HOME_RC_FILE = ENV["PRYRC"] || "~/.pryrc" + LOCAL_RC_FILE = "./.pryrc" + + class << self + extend Forwardable + attr_accessor :custom_completions + attr_accessor :current_line + attr_accessor :line_buffer + attr_accessor :eval_path + attr_accessor :cli + attr_accessor :quiet + attr_accessor :last_internal_error + attr_accessor :config + attr_writer :history + + def_delegators :@plugin_manager, :plugins, :load_plugins, :locate_plugins + + extend Pry::Config::Convenience + config_shortcut(*Pry::Config.shortcuts) + + def prompt=(value) + config.prompt = value + end + + def prompt + config.prompt + end + + def history + @history ||= History.new + end + end + + # + # @return [main] + # returns the special instance of Object, "main". + # + def self.main + @main ||= TOPLEVEL_BINDING.eval "self" + end + + # + # @return [Pry::Config] + # Returns a value store for an instance of Pry running on the current thread. + # + def self.current + Thread.current[:__pry__] ||= Pry::Config.from_hash({}, nil) + end + + # Load the given file in the context of `Pry.toplevel_binding` + # @param [String] file The unexpanded file path. + def self.load_file_at_toplevel(file) + toplevel_binding.eval(File.read(file), file) + rescue RescuableException => e + puts "Error loading #{file}: #{e}\n#{e.backtrace.first}" + end + + # Load HOME_RC_FILE and LOCAL_RC_FILE if appropriate + # This method can also be used to reload the files if they have changed. + def self.load_rc_files + rc_files_to_load.each do |file| + critical_section do + load_file_at_toplevel(file) + end + end + end + + # Load the local RC file (./.pryrc) + def self.rc_files_to_load + files = [] + files << HOME_RC_FILE if Pry.config.should_load_rc + files << LOCAL_RC_FILE if Pry.config.should_load_local_rc + files.map { |file| real_path_to(file) }.compact.uniq + end + + # Expand a file to its canonical name (following symlinks as appropriate) + def self.real_path_to(file) + expanded = Pathname.new(File.expand_path(file)).realpath.to_s + # For rbx 1.9 mode [see rubinius issue #2165] + File.exist?(expanded) ? expanded : nil + rescue Errno::ENOENT + nil + end + + # Load any Ruby files specified with the -r flag on the command line. + def self.load_requires + Pry.config.requires.each do |file| + require file + end + end + + # Trap interrupts on jruby, and make them behave like MRI so we can + # catch them. + def self.load_traps + trap('INT'){ raise Interrupt } + end + + def self.load_win32console + begin + require 'win32console' + # The mswin and mingw versions of pry require win32console, so this should + # only fail on jruby (where win32console doesn't work). + # Instead we'll recommend ansicon, which does. + rescue LoadError + warn <<-WARNING if Pry.config.windows_console_warning +For a better Pry experience on Windows, please use ansicon: + https://github.com/adoxa/ansicon +If you use an alternative to ansicon and don't want to see this warning again, +you can add "Pry.config.windows_console_warning = false" to your .pryrc. + WARNING + end + end + + # Do basic setup for initial session. + # Including: loading .pryrc, loading plugins, loading requires, and + # loading history. + def self.initial_session_setup + return unless initial_session? + @initial_session = false + + # note these have to be loaded here rather than in pry_instance as + # we only want them loaded once per entire Pry lifetime. + load_rc_files + load_plugins if Pry.config.should_load_plugins + load_requires if Pry.config.should_load_requires + load_history if Pry.config.history.should_load + load_traps if Pry.config.should_trap_interrupts + load_win32console if Pry::Helpers::BaseHelpers.windows? && !Pry::Helpers::BaseHelpers.windows_ansi? + end + + # Start a Pry REPL. + # This method also loads `~/.pryrc` and `./.pryrc` as necessary the + # first time it is invoked. + # @param [Object, Binding] target The receiver of the Pry session + # @param [Hash] options + # @option options (see Pry#initialize) + # @example + # Pry.start(Object.new, :input => MyInput.new) + def self.start(target=nil, options={}) + return if ENV['DISABLE_PRY'] + options = options.to_hash + + if in_critical_section? + output.puts "ERROR: Pry started inside Pry." + output.puts "This can happen if you have a binding.pry inside a #to_s or #inspect function." + return + end + + options[:target] = Pry.binding_for(target || toplevel_binding) + options[:hooks] = Pry::Hooks.from_hash options.delete(:hooks) if options.key?(:hooks) + initial_session_setup + + # Unless we were given a backtrace, save the current one + if options[:backtrace].nil? + options[:backtrace] = caller + + # If Pry was started via `binding.pry`, elide that from the backtrace + if options[:backtrace].first =~ /pry.*core_extensions.*pry/ + options[:backtrace].shift + end + end + + driver = options[:driver] || Pry::REPL + + # Enter the matrix + driver.start(options) + rescue Pry::TooSafeException + puts "ERROR: Pry cannot work with $SAFE > 0" + raise + end + + # Execute the file through the REPL loop, non-interactively. + # @param [String] file_name File name to load through the REPL. + def self.load_file_through_repl(file_name) + require "pry/repl_file_loader" + REPLFileLoader.new(file_name).load + end + + # + # An inspector that clips the output to `max_length` chars. + # In case of > `max_length` chars the `# notation is used. + # + # @param [Object] obj + # The object to view. + # + # @param [Hash] options + # @option options [Integer] :max_length (60) + # The maximum number of chars before clipping occurs. + # + # @option options [Boolean] :id (false) + # Boolean to indicate whether or not a hex reprsentation of the object ID + # is attached to the return value when the length of inspect is greater than + # value of `:max_length`. + # + # @return [String] + # The string representation of `obj`. + # + def self.view_clip(obj, options = {}) + max = options.fetch :max_length, 60 + id = options.fetch :id, false + if obj.kind_of?(Module) && obj.name.to_s != "" && obj.name.to_s.length <= max + obj.name.to_s + elsif Pry.main == obj + # special-case to support jruby. + # fixed as of https://github.com/jruby/jruby/commit/d365ebd309cf9df3dde28f5eb36ea97056e0c039 + # we can drop in the future. + obj.to_s + elsif Pry.config.prompt_safe_objects.any? { |v| v === obj } && obj.inspect.length <= max + obj.inspect + else + id == true ? "#<#{obj.class}:0x%x>" % (obj.object_id << 1) : "#<#{obj.class}>" + end + rescue RescuableException + "unknown" + end + + # Load Readline history if required. + def self.load_history + Pry.history.load + end + + # @return [Boolean] Whether this is the first time a Pry session has + # been started since loading the Pry class. + def self.initial_session? + @initial_session + end + + # Run a Pry command from outside a session. The commands available are + # those referenced by `Pry.config.commands` (the default command set). + # @param [String] command_string The Pry command (including arguments, + # if any). + # @param [Hash] options Optional named parameters. + # @return [Object] The return value of the Pry command. + # @option options [Object, Binding] :target The object to run the + # command under. Defaults to `TOPLEVEL_BINDING` (main). + # @option options [Boolean] :show_output Whether to show command + # output. Defaults to true. + # @example Run at top-level with no output. + # Pry.run_command "ls" + # @example Run under Pry class, returning only public methods. + # Pry.run_command "ls -m", :target => Pry + # @example Display command output. + # Pry.run_command "ls -av", :show_output => true + def self.run_command(command_string, options={}) + options = { + :target => TOPLEVEL_BINDING, + :show_output => true, + :output => Pry.config.output, + :commands => Pry.config.commands + }.merge!(options) + + # :context for compatibility with <= 0.9.11.4 + target = options[:context] || options[:target] + output = options[:show_output] ? options[:output] : StringIO.new + + pry = Pry.new(:output => output, :target => target, :commands => options[:commands]) + pry.eval command_string + end + + def self.default_editor_for_platform + return ENV['VISUAL'] if ENV['VISUAL'] and not ENV['VISUAL'].empty? + return ENV['EDITOR'] if ENV['EDITOR'] and not ENV['EDITOR'].empty? + if Helpers::BaseHelpers.windows? + 'notepad' + else + %w(editor nano vi).detect do |editor| + system("which #{editor} > /dev/null 2>&1") + end + end + end + + def self.auto_resize! + Pry.config.input # by default, load Readline + + if !defined?(Readline) || Pry.config.input != Readline + warn "Sorry, you must be using Readline for Pry.auto_resize! to work." + return + end + + if Readline::VERSION =~ /edit/i + warn <<-EOT +Readline version #{Readline::VERSION} detected - will not auto_resize! correctly. + For the fix, use GNU Readline instead: + https://github.com/guard/guard/wiki/Add-proper-Readline-support-to-Ruby-on-Mac-OS-X + EOT + return + end + + trap :WINCH do + begin + Readline.set_screen_size(*Terminal.size!) + rescue => e + warn "\nPry.auto_resize!'s Readline.set_screen_size failed: #{e}" + end + begin + Readline.refresh_line + rescue => e + warn "\nPry.auto_resize!'s Readline.refresh_line failed: #{e}" + end + end + end + + # Set all the configurable options back to their default values + def self.reset_defaults + @initial_session = true + self.config = Pry::Config.new Pry::Config::Default.new + self.cli = false + self.current_line = 1 + self.line_buffer = [""] + self.eval_path = "(pry)" + end + + # Basic initialization. + def self.init + @plugin_manager ||= PluginManager.new + reset_defaults + locate_plugins + end + + # Return a `Binding` object for `target` or return `target` if it is + # already a `Binding`. + # In the case where `target` is top-level then return `TOPLEVEL_BINDING` + # @param [Object] target The object to get a `Binding` object for. + # @return [Binding] The `Binding` object. + def self.binding_for(target) + if Binding === target + target + else + if Pry.main == target + TOPLEVEL_BINDING + else + target.__binding__ + end + end + end + + def self.toplevel_binding + unless defined?(@toplevel_binding) && @toplevel_binding + # Grab a copy of the TOPLEVEL_BINDING without any local variables. + # This binding has a default definee of Object, and new methods are + # private (just as in TOPLEVEL_BINDING). + TOPLEVEL_BINDING.eval <<-RUBY + def self.__pry__ + binding + end + Pry.toplevel_binding = __pry__ + class << self; undef __pry__; end + RUBY + end + @toplevel_binding.eval('private') + @toplevel_binding + end + + def self.toplevel_binding=(binding) + @toplevel_binding = binding + end + + def self.in_critical_section? + Thread.current[:pry_critical_section] ||= 0 + Thread.current[:pry_critical_section] > 0 + end + + def self.critical_section(&block) + Thread.current[:pry_critical_section] ||= 0 + Thread.current[:pry_critical_section] += 1 + yield + ensure + Thread.current[:pry_critical_section] -= 1 + end +end + +Pry.init diff --git a/.bundle/gems/pry-0.10.2/lib/pry/pry_instance.rb b/.bundle/gems/pry-0.10.2/lib/pry/pry_instance.rb new file mode 100644 index 0000000..0877ab2 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/pry_instance.rb @@ -0,0 +1,664 @@ +# -*- coding: utf-8 -*- +## +# Pry is a powerful alternative to the standard IRB shell for Ruby. It +# features syntax highlighting, a flexible plugin architecture, runtime +# invocation and source and documentation browsing. +# +# Pry can be started similar to other command line utilities by simply running +# the following command: +# +# pry +# +# Once inside Pry you can invoke the help message: +# +# help +# +# This will show a list of available commands and their usage. For more +# information about Pry you can refer to the following resources: +# +# * http://pry.github.com/ +# * https://github.com/pry/pry +# * the IRC channel, which is #pry on the Freenode network +# + +class Pry + attr_accessor :binding_stack + attr_accessor :custom_completions + attr_accessor :eval_string + attr_accessor :backtrace + attr_accessor :suppress_output + attr_accessor :last_result + attr_accessor :last_file + attr_accessor :last_dir + + attr_reader :last_exception + attr_reader :command_state + attr_reader :exit_value + attr_reader :input_array + attr_reader :output_array + attr_reader :config + + extend Pry::Config::Convenience + config_shortcut(*Pry::Config.shortcuts) + EMPTY_COMPLETIONS = [].freeze + + # Create a new {Pry} instance. + # @param [Hash] options + # @option options [#readline] :input + # The object to use for input. + # @option options [#puts] :output + # The object to use for output. + # @option options [Pry::CommandBase] :commands + # The object to use for commands. + # @option options [Hash] :hooks + # The defined hook Procs. + # @option options [Array] :prompt + # The array of Procs to use for prompts. + # @option options [Proc] :print + # The Proc to use for printing return values. + # @option options [Boolean] :quiet + # Omit the `whereami` banner when starting. + # @option options [Array] :backtrace + # The backtrace of the session's `binding.pry` line, if applicable. + # @option options [Object] :target + # The initial context for this session. + def initialize(options={}) + @binding_stack = [] + @indent = Pry::Indent.new + @command_state = {} + @eval_string = "" + @backtrace = options.delete(:backtrace) || caller + target = options.delete(:target) + @config = Pry::Config.new + config.merge!(options) + push_prompt(config.prompt) + @input_array = Pry::HistoryArray.new config.memory_size + @output_array = Pry::HistoryArray.new config.memory_size + @custom_completions = config.command_completions + set_last_result nil + @input_array << nil + push_initial_binding(target) + exec_hook(:when_started, target, options, self) + end + + # The current prompt. + # This is the prompt at the top of the prompt stack. + # + # @example + # self.prompt = Pry::SIMPLE_PROMPT + # self.prompt # => Pry::SIMPLE_PROMPT + # + # @return [Array] Current prompt. + def prompt + prompt_stack.last + end + + def prompt=(new_prompt) + if prompt_stack.empty? + push_prompt new_prompt + else + prompt_stack[-1] = new_prompt + end + end + + # Initialize this instance by pushing its initial context into the binding + # stack. If no target is given, start at the top level. + def push_initial_binding(target=nil) + push_binding(target || Pry.toplevel_binding) + end + + # The currently active `Binding`. + # @return [Binding] The currently active `Binding` for the session. + def current_binding + binding_stack.last + end + alias current_context current_binding # support previous API + + # Push a binding for the given object onto the stack. If this instance is + # currently stopped, mark it as usable again. + def push_binding(object) + @stopped = false + binding_stack << Pry.binding_for(object) + end + + # + # Generate completions. + # + # @param [String] input + # What the user has typed so far + # + # @return [Array] + # Possible completions + # + def complete(str) + return EMPTY_COMPLETIONS unless config.completer + Pry.critical_section do + completer = config.completer.new(config.input, self) + completer.call str, target: current_binding, custom_completions: custom_completions.call.push(*sticky_locals.keys) + end + end + + # + # Injects a local variable into the provided binding. + # + # @param [String] name + # The name of the local to inject. + # + # @param [Object] value + # The value to set the local to. + # + # @param [Binding] b + # The binding to set the local on. + # + # @return [Object] + # The value the local was set to. + # + def inject_local(name, value, b) + value = Proc === value ? value.call : value + if b.respond_to?(:local_variable_set) + b.local_variable_set name, value + else # < 2.1 + begin + Pry.current[:pry_local] = value + b.eval "#{name} = ::Pry.current[:pry_local]" + ensure + Pry.current[:pry_local] = nil + end + end + end + + undef :memory_size if method_defined? :memory_size + # @return [Integer] The maximum amount of objects remembered by the inp and + # out arrays. Defaults to 100. + def memory_size + @output_array.max_size + end + + undef :memory_size= if method_defined? :memory_size= + def memory_size=(size) + @input_array = Pry::HistoryArray.new(size) + @output_array = Pry::HistoryArray.new(size) + end + + # Inject all the sticky locals into the current binding. + def inject_sticky_locals! + sticky_locals.each_pair do |name, value| + inject_local(name, value, current_binding) + end + end + + # Add a sticky local to this Pry instance. + # A sticky local is a local that persists between all bindings in a session. + # @param [Symbol] name The name of the sticky local. + # @yield The block that defines the content of the local. The local + # will be refreshed at each tick of the repl loop. + def add_sticky_local(name, &block) + config.extra_sticky_locals[name] = block + end + + def sticky_locals + { _in_: input_array, + _out_: output_array, + _pry_: self, + _ex_: last_exception && last_exception.wrapped_exception, + _file_: last_file, + _dir_: last_dir, + _: proc { last_result }, + __: proc { output_array[-2] } + }.merge(config.extra_sticky_locals) + end + + # Reset the current eval string. If the user has entered part of a multiline + # expression, this discards that input. + def reset_eval_string + @eval_string = "" + end + + # Pass a line of input to Pry. + # + # This is the equivalent of `Binding#eval` but with extra Pry! + # + # In particular: + # 1. Pry commands will be executed immediately if the line matches. + # 2. Partial lines of input will be queued up until a complete expression has + # been accepted. + # 3. Output is written to `#output` in pretty colours, not returned. + # + # Once this method has raised an exception or returned false, this instance + # is no longer usable. {#exit_value} will return the session's breakout + # value if applicable. + # + # @param [String?] line The line of input; `nil` if the user types `` + # @option options [Boolean] :generated Whether this line was generated automatically. + # Generated lines are not stored in history. + # @return [Boolean] Is Pry ready to accept more input? + # @raise [Exception] If the user uses the `raise-up` command, this method + # will raise that exception. + def eval(line, options={}) + return false if @stopped + + exit_value = nil + exception = catch(:raise_up) do + exit_value = catch(:breakout) do + handle_line(line, options) + # We use 'return !@stopped' here instead of 'return true' so that if + # handle_line has stopped this pry instance (e.g. by opening _pry_.repl and + # then popping all the bindings) we still exit immediately. + return !@stopped + end + exception = false + end + + @stopped = true + @exit_value = exit_value + + # TODO: make this configurable? + raise exception if exception + return false + end + + def handle_line(line, options) + if line.nil? + config.control_d_handler.call(@eval_string, self) + return + end + + ensure_correct_encoding!(line) + Pry.history << line unless options[:generated] + + @suppress_output = false + inject_sticky_locals! + begin + if !process_command_safely(line.lstrip) + @eval_string << "#{line.chomp}\n" if !line.empty? || !@eval_string.empty? + end + rescue RescuableException => e + self.last_exception = e + result = e + + Pry.critical_section do + show_result(result) + end + return + end + + # This hook is supposed to be executed after each line of ruby code + # has been read (regardless of whether eval_string is yet a complete expression) + exec_hook :after_read, eval_string, self + + begin + complete_expr = Pry::Code.complete_expression?(@eval_string) + rescue SyntaxError => e + output.puts "SyntaxError: #{e.message.sub(/.*syntax error, */m, '')}" + reset_eval_string + end + + if complete_expr + if @eval_string =~ /;\Z/ || @eval_string.empty? || @eval_string =~ /\A *#.*\n\z/ + @suppress_output = true + end + + # A bug in jruby makes java.lang.Exception not rescued by + # `rescue Pry::RescuableException` clause. + # + # * https://github.com/pry/pry/issues/854 + # * https://jira.codehaus.org/browse/JRUBY-7100 + # + # Until that gets fixed upstream, treat java.lang.Exception + # as an additional exception to be rescued explicitly. + # + # This workaround has a side effect: java exceptions specified + # in `Pry.config.exception_whitelist` are ignored. + jruby_exceptions = [] + if Pry::Helpers::BaseHelpers.jruby? + jruby_exceptions << Java::JavaLang::Exception + end + + begin + # Reset eval string, in case we're evaluating Ruby that does something + # like open a nested REPL on this instance. + eval_string = @eval_string + reset_eval_string + + result = evaluate_ruby(eval_string) + rescue RescuableException, *jruby_exceptions => e + # Eliminate following warning: + # warning: singleton on non-persistent Java type X + # (http://wiki.jruby.org/Persistence) + if Pry::Helpers::BaseHelpers.jruby? && e.class.respond_to?('__persistent__') + e.class.__persistent__ = true + end + self.last_exception = e + result = e + end + + Pry.critical_section do + show_result(result) + end + end + + throw(:breakout) if current_binding.nil? + end + private :handle_line + + # Potentially deprecated — Use `Pry::REPL.new(pry, :target => target).start` + # (If nested sessions are going to exist, this method is fine, but a goal is + # to come up with an alternative to nested sessions altogether.) + def repl(target = nil) + Pry::REPL.new(self, :target => target).start + end + + def evaluate_ruby(code) + inject_sticky_locals! + exec_hook :before_eval, code, self + + result = current_binding.eval(code, Pry.eval_path, Pry.current_line) + set_last_result(result, code) + ensure + update_input_history(code) + exec_hook :after_eval, result, self + end + + # Output the result or pass to an exception handler (if result is an exception). + def show_result(result) + if last_result_is_exception? + exception_handler.call(output, result, self) + elsif should_print? + print.call(output, result, self) + else + # nothin' + end + rescue RescuableException => e + # Being uber-paranoid here, given that this exception arose because we couldn't + # serialize something in the user's program, let's not assume we can serialize + # the exception either. + begin + output.puts "(pry) output error: #{e.inspect}" + rescue RescuableException => e + if last_result_is_exception? + output.puts "(pry) output error: failed to show exception" + else + output.puts "(pry) output error: failed to show result" + end + end + ensure + output.flush if output.respond_to?(:flush) + end + + # Force `eval_string` into the encoding of `val`. [Issue #284] + def ensure_correct_encoding!(val) + if @eval_string.empty? && + val.respond_to?(:encoding) && + val.encoding != @eval_string.encoding + @eval_string.force_encoding(val.encoding) + end + end + private :ensure_correct_encoding! + + # If the given line is a valid command, process it in the context of the + # current `eval_string` and binding. + # @param [String] val The line to process. + # @return [Boolean] `true` if `val` is a command, `false` otherwise + def process_command(val) + val = val.chomp + result = commands.process_line(val, + :target => current_binding, + :output => output, + :eval_string => @eval_string, + :pry_instance => self + ) + + # set a temporary (just so we can inject the value we want into eval_string) + Pry.current[:pry_cmd_result] = result + + # note that `result` wraps the result of command processing; if a + # command was matched and invoked then `result.command?` returns true, + # otherwise it returns false. + if result.command? + if !result.void_command? + # the command that was invoked was non-void (had a return value) and so we make + # the value of the current expression equal to the return value + # of the command. + @eval_string.replace "::Pry.current[:pry_cmd_result].retval\n" + end + true + else + false + end + end + + # Same as process_command, but outputs exceptions to `#output` instead of + # raising. + # @param [String] val The line to process. + # @return [Boolean] `true` if `val` is a command, `false` otherwise + def process_command_safely(val) + process_command(val) + rescue CommandError, Slop::InvalidOptionError, MethodSource::SourceNotFoundError => e + Pry.last_internal_error = e + output.puts "Error: #{e.message}" + true + end + + # Run the specified command. + # @param [String] val The command (and its params) to execute. + # @return [Pry::Command::VOID_VALUE] + # @example + # pry_instance.run_command("ls -m") + def run_command(val) + commands.process_line(val, + :eval_string => @eval_string, + :target => current_binding, + :pry_instance => self, + :output => output + ) + Pry::Command::VOID_VALUE + end + + # Execute the specified hook. + # @param [Symbol] name The hook name to execute + # @param [*Object] args The arguments to pass to the hook + # @return [Object, Exception] The return value of the hook or the exception raised + # + # If executing a hook raises an exception, we log that and then continue sucessfully. + # To debug such errors, use the global variable $pry_hook_error, which is set as a + # result. + def exec_hook(name, *args, &block) + e_before = hooks.errors.size + hooks.exec_hook(name, *args, &block).tap do + hooks.errors[e_before..-1].each do |e| + output.puts "#{name} hook failed: #{e.class}: #{e.message}" + output.puts "#{e.backtrace.first}" + output.puts "(see _pry_.hooks.errors to debug)" + end + end + end + + # Set the last result of an eval. + # This method should not need to be invoked directly. + # @param [Object] result The result. + # @param [String] code The code that was run. + def set_last_result(result, code="") + @last_result_is_exception = false + @output_array << result + + self.last_result = result unless code =~ /\A\s*\z/ + end + + # + # Set the last exception for a session. + # + # @param [Exception] e + # the last exception. + # + def last_exception=(e) + last_exception = Pry::LastException.new(e) + @last_result_is_exception = true + @output_array << last_exception + @last_exception = last_exception + end + + # Update Pry's internal state after evalling code. + # This method should not need to be invoked directly. + # @param [String] code The code we just eval'd + def update_input_history(code) + # Always push to the @input_array as the @output_array is always pushed to. + @input_array << code + if code + Pry.line_buffer.push(*code.each_line) + Pry.current_line += code.lines.count + end + end + + # @return [Boolean] True if the last result is an exception that was raised, + # as opposed to simply an instance of Exception (like the result of + # Exception.new) + def last_result_is_exception? + @last_result_is_exception + end + + # Whether the print proc should be invoked. + # Currently only invoked if the output is not suppressed. + # @return [Boolean] Whether the print proc should be invoked. + def should_print? + !@suppress_output + end + + # Returns the appropriate prompt to use. + # @return [String] The prompt. + def select_prompt + object = current_binding.eval('self') + + open_token = @indent.open_delimiters.any? ? @indent.open_delimiters.last : + @indent.stack.last + + c = Pry::Config.from_hash({ + :object => object, + :nesting_level => binding_stack.size - 1, + :open_token => open_token, + :session_line => Pry.history.session_line_count + 1, + :history_line => Pry.history.history_line_count + 1, + :expr_number => input_array.count, + :_pry_ => self, + :binding_stack => binding_stack, + :input_array => input_array, + :eval_string => @eval_string, + :cont => !@eval_string.empty?}) + + Pry.critical_section do + # If input buffer is empty then use normal prompt + if eval_string.empty? + generate_prompt(Array(prompt).first, c) + + # Otherwise use the wait prompt (indicating multi-line expression) + else + generate_prompt(Array(prompt).last, c) + end + end + end + + def generate_prompt(prompt_proc, conf) + if prompt_proc.arity == 1 + prompt_proc.call(conf) + else + prompt_proc.call(conf.object, conf.nesting_level, conf._pry_) + end + end + private :generate_prompt + + # the array that the prompt stack is stored in + def prompt_stack + @prompt_stack ||= Array.new + end + private :prompt_stack + + # Pushes the current prompt onto a stack that it can be restored from later. + # Use this if you wish to temporarily change the prompt. + # @param [Array] new_prompt + # @return [Array] new_prompt + # @example + # new_prompt = [ proc { '>' }, proc { '>>' } ] + # push_prompt(new_prompt) # => new_prompt + def push_prompt(new_prompt) + prompt_stack.push new_prompt + end + + # Pops the current prompt off of the prompt stack. + # If the prompt you are popping is the last prompt, it will not be popped. + # Use this to restore the previous prompt. + # @return [Array] Prompt being popped. + # @example + # prompt1 = [ proc { '>' }, proc { '>>' } ] + # prompt2 = [ proc { '$' }, proc { '>' } ] + # pry = Pry.new :prompt => prompt1 + # pry.push_prompt(prompt2) + # pry.pop_prompt # => prompt2 + # pry.pop_prompt # => prompt1 + # pry.pop_prompt # => prompt1 + def pop_prompt + prompt_stack.size > 1 ? prompt_stack.pop : prompt + end + + undef :pager if method_defined? :pager + # Returns the currently configured pager + # @example + # _pry_.pager.page text + def pager + Pry::Pager.new(self) + end + + undef :output if method_defined? :output + # Returns an output device + # @example + # _pry_.output.puts "ohai!" + def output + Pry::Output.new(self) + end + + # Raise an exception out of Pry. + # + # See Kernel#raise for documentation of parameters. + # See rb_make_exception for the inbuilt implementation. + # + # This is necessary so that the raise-up command can tell the + # difference between an exception the user has decided to raise, + # and a mistake in specifying that exception. + # + # (i.e. raise-up RunThymeError.new should not be the same as + # raise-up NameError, "unititialized constant RunThymeError") + # + def raise_up_common(force, *args) + exception = if args == [] + last_exception || RuntimeError.new + elsif args.length == 1 && args.first.is_a?(String) + RuntimeError.new(args.first) + elsif args.length > 3 + raise ArgumentError, "wrong number of arguments" + elsif !args.first.respond_to?(:exception) + raise TypeError, "exception class/object expected" + elsif args.length === 1 + args.first.exception + else + args.first.exception(args[1]) + end + + raise TypeError, "exception object expected" unless exception.is_a? Exception + + exception.set_backtrace(args.length === 3 ? args[2] : caller(1)) + + if force || binding_stack.one? + binding_stack.clear + throw :raise_up, exception + else + binding_stack.pop + raise exception + end + end + def raise_up(*args); raise_up_common(false, *args); end + def raise_up!(*args); raise_up_common(true, *args); end + + # Convenience accessor for the `quiet` config key. + # @return [Boolean] + def quiet? + config.quiet + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/rbx_path.rb b/.bundle/gems/pry-0.10.2/lib/pry/rbx_path.rb new file mode 100644 index 0000000..bd969c6 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/rbx_path.rb @@ -0,0 +1,22 @@ +class Pry + module RbxPath + module_function + def is_core_path?(path) + Pry::Helpers::BaseHelpers.rbx? && (path.start_with?("kernel") || path.start_with?("lib")) && File.exist?(convert_path_to_full(path)) + end + + def convert_path_to_full(path) + if path.start_with?("kernel") + File.join File.dirname(Rubinius::KERNEL_PATH), path + elsif path.start_with?("lib") + File.join File.dirname(Rubinius::LIB_PATH), path + else + path + end + end + + def rvm_ruby?(path) + !!(path =~ /\.rvm/) + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/repl.rb b/.bundle/gems/pry-0.10.2/lib/pry/repl.rb new file mode 100644 index 0000000..4748785 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/repl.rb @@ -0,0 +1,202 @@ +require 'forwardable' + +class Pry + class REPL + extend Forwardable + def_delegators :@pry, :input, :output + + # @return [Pry] The instance of {Pry} that the user is controlling. + attr_accessor :pry + + # Instantiate a new {Pry} instance with the given options, then start a + # {REPL} instance wrapping it. + # @option options See {Pry#initialize} + def self.start(options) + new(Pry.new(options)).start + end + + # Create an instance of {REPL} wrapping the given {Pry}. + # @param [Pry] pry The instance of {Pry} that this {REPL} will control. + # @param [Hash] options Options for this {REPL} instance. + # @option options [Object] :target The initial target of the session. + def initialize(pry, options = {}) + @pry = pry + @indent = Pry::Indent.new + + if options[:target] + @pry.push_binding options[:target] + end + end + + # Start the read-eval-print loop. + # @return [Object?] If the session throws `:breakout`, return the value + # thrown with it. + # @raise [Exception] If the session throws `:raise_up`, raise the exception + # thrown with it. + def start + prologue + Pry::InputLock.for(:all).with_ownership { repl } + ensure + epilogue + end + + private + + # Set up the repl session. + # @return [void] + def prologue + pry.exec_hook :before_session, pry.output, pry.current_binding, pry + + # Clear the line before starting Pry. This fixes issue #566. + if pry.config.correct_indent + Kernel.print Pry::Helpers::BaseHelpers.windows_ansi? ? "\e[0F" : "\e[0G" + end + end + + # The actual read-eval-print loop. + # + # The {REPL} instance is responsible for reading and looping, whereas the + # {Pry} instance is responsible for evaluating user input and printing + # return values and command output. + # + # @return [Object?] If the session throws `:breakout`, return the value + # thrown with it. + # @raise [Exception] If the session throws `:raise_up`, raise the exception + # thrown with it. + def repl + loop do + case val = read + when :control_c + output.puts "" + pry.reset_eval_string + when :no_more_input + output.puts "" if output.tty? + break + else + output.puts "" if val.nil? && output.tty? + return pry.exit_value unless pry.eval(val) + end + end + end + + # Clean up after the repl session. + # @return [void] + def epilogue + pry.exec_hook :after_session, pry.output, pry.current_binding, pry + end + + # Read a line of input from the user. + # @return [String] The line entered by the user. + # @return [nil] On ``. + # @return [:control_c] On ``. + # @return [:no_more_input] On EOF. + def read + @indent.reset if pry.eval_string.empty? + current_prompt = pry.select_prompt + indentation = pry.config.auto_indent ? @indent.current_prefix : '' + + val = read_line("#{current_prompt}#{indentation}") + + # Return nil for EOF, :no_more_input for error, or :control_c for + return val unless String === val + + if pry.config.auto_indent + original_val = "#{indentation}#{val}" + indented_val = @indent.indent(val) + + if output.tty? && pry.config.correct_indent && Pry::Helpers::BaseHelpers.use_ansi_codes? + output.print @indent.correct_indentation( + current_prompt, indented_val, + original_val.length - indented_val.length + ) + output.flush + end + else + indented_val = val + end + + indented_val + end + + # Manage switching of input objects on encountering `EOFError`s. + # @return [Object] Whatever the given block returns. + # @return [:no_more_input] Indicates that no more input can be read. + def handle_read_errors + should_retry = true + exception_count = 0 + + begin + yield + rescue EOFError + pry.config.input = Pry.config.input + if !should_retry + output.puts "Error: Pry ran out of things to read from! " \ + "Attempting to break out of REPL." + return :no_more_input + end + should_retry = false + retry + + # Handle like Bash: empty the current input buffer, but don't + # quit. This is only for MRI 1.9; other versions of Ruby don't let you + # send Interrupt from within Readline. + rescue Interrupt + return :control_c + + # If we get a random error when trying to read a line we don't want to + # automatically retry, as the user will see a lot of error messages + # scroll past and be unable to do anything about it. + rescue RescuableException => e + puts "Error: #{e.message}" + output.puts e.backtrace + exception_count += 1 + if exception_count < 5 + retry + end + puts "FATAL: Pry failed to get user input using `#{input}`." + puts "To fix this you may be able to pass input and output file " \ + "descriptors to pry directly. e.g." + puts " Pry.config.input = STDIN" + puts " Pry.config.output = STDOUT" + puts " binding.pry" + return :no_more_input + end + end + + # Returns the next line of input to be sent to the {Pry} instance. + # @param [String] current_prompt The prompt to use for input. + # @return [String?] The next line of input, or `nil` on . + def read_line(current_prompt) + handle_read_errors do + if defined? Coolline and input.is_a? Coolline + input.completion_proc = proc do |cool| + completions = @pry.complete cool.completed_word + completions.compact + end + elsif input.respond_to? :completion_proc= + input.completion_proc = proc do |input| + @pry.complete input + end + end + + if defined?(Readline) and input == Readline + input_readline(current_prompt, false) # false since we'll add it manually + elsif defined? Coolline and input.is_a? Coolline + input_readline(current_prompt) + else + if input.method(:readline).arity == 1 + input_readline(current_prompt) + else + input_readline + end + end + end + end + + def input_readline(*args) + Pry::InputLock.for(:all).interruptible_region do + input.readline(*args) + end + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/repl_file_loader.rb b/.bundle/gems/pry-0.10.2/lib/pry/repl_file_loader.rb new file mode 100644 index 0000000..cd8de9a --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/repl_file_loader.rb @@ -0,0 +1,74 @@ +class Pry + + # A class to manage the loading of files through the REPL loop. + # This is an interesting trick as it processes your file as if it + # was user input in an interactive session. As a result, all Pry + # commands are available, and they are executed non-interactively. Furthermore + # the session becomes interactive when the repl loop processes a + # 'make-interactive' command in the file. The session also becomes + # interactive when an exception is encountered, enabling you to fix + # the error before returning to non-interactive processing with the + # 'make-non-interactive' command. + + class REPLFileLoader + def initialize(file_name) + full_name = File.expand_path(file_name) + raise RuntimeError, "No such file: #{full_name}" if !File.exists?(full_name) + + define_additional_commands + @content = File.read(full_name) + end + + # Switch to interactive mode, i.e take input from the user + # and use the regular print and exception handlers. + # @param [Pry] _pry_ the Pry instance to make interactive. + def interactive_mode(_pry_) + _pry_.config.input = Pry.config.input + _pry_.config.print = Pry.config.print + _pry_.config.exception_handler = Pry.config.exception_handler + Pry::REPL.new(_pry_).start + end + + # Switch to non-interactive mode. Essentially + # this means there is no result output + # and that the session becomes interactive when an exception is encountered. + # @param [Pry] _pry_ the Pry instance to make non-interactive. + def non_interactive_mode(_pry_, content) + _pry_.print = proc {} + _pry_.exception_handler = proc do |o, e, _p_| + _p_.run_command "cat --ex" + o.puts "...exception encountered, going interactive!" + interactive_mode(_pry_) + end + + content.lines.each do |line| + break unless _pry_.eval line, :generated => true + end + + unless _pry_.eval_string.empty? + _pry_.output.puts "#{_pry_.eval_string}...exception encountered, going interactive!" + interactive_mode(_pry_) + end + end + + # Define a few extra commands useful for flipping back & forth + # between interactive/non-interactive modes + def define_additional_commands + s = self + + Pry::Commands.command "make-interactive", "Make the session interactive" do + s.interactive_mode(_pry_) + end + + Pry::Commands.command "load-file", "Load another file through the repl" do |file_name| + s.non_interactive_mode(_pry_, File.read(File.expand_path(file_name))) + end + end + + # Actually load the file through the REPL by setting file content + # as the REPL input stream. + def load + non_interactive_mode(Pry.new, @content) + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/rubygem.rb b/.bundle/gems/pry-0.10.2/lib/pry/rubygem.rb new file mode 100644 index 0000000..36f788d --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/rubygem.rb @@ -0,0 +1,82 @@ +require 'rubygems' + +class Pry + module Rubygem + + class << self + def installed?(name) + if Gem::Specification.respond_to?(:find_all_by_name) + Gem::Specification.find_all_by_name(name).any? + else + Gem.source_index.find_name(name).first + end + end + + # Get the gem spec object for the given gem name. + # + # @param [String] name + # @return [Gem::Specification] + def spec(name) + specs = if Gem::Specification.respond_to?(:each) + Gem::Specification.find_all_by_name(name) + else + Gem.source_index.find_name(name) + end + + first_spec = specs.sort_by{ |spec| Gem::Version.new(spec.version) }.last + + first_spec or raise CommandError, "Gem `#{name}` not found" + end + + # List gems matching a pattern. + # + # @param [Regexp] pattern + # @return [Array] + def list(pattern = /.*/) + if Gem::Specification.respond_to?(:each) + Gem::Specification.select{|spec| spec.name =~ pattern } + else + Gem.source_index.gems.values.select{|spec| spec.name =~ pattern } + end + end + + # Completion function for gem-cd and gem-open. + # + # @param [String] so_far what the user's typed so far + # @return [Array] completions + def complete(so_far) + if so_far =~ / ([^ ]*)\z/ + self.list(%r{\A#{$2}}).map(&:name) + else + self.list.map(&:name) + end + end + + # Installs a gem with all its dependencies. + # + # @param [String] name + # @return [void] + def install(name) + gemrc_opts = Gem.configuration['gem'].split(' ') + destination = if gemrc_opts.include?('--user-install') + Gem.user_dir + elsif File.writable?(Gem.dir) + Gem.dir + else + Gem.user_dir + end + installer = Gem::DependencyInstaller.new(:install_dir => destination) + installer.install(name) + rescue Errno::EACCES + raise CommandError, + "Insufficient permissions to install #{ Pry::Helpers::Text.green(name) }." + rescue Gem::GemNotFoundException + raise CommandError, + "Gem #{ Pry::Helpers::Text.green(name) } not found. Aborting installation." + else + Gem.refresh + end + end + + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/terminal.rb b/.bundle/gems/pry-0.10.2/lib/pry/terminal.rb new file mode 100644 index 0000000..d04f7bd --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/terminal.rb @@ -0,0 +1,79 @@ +class Pry::Terminal + class << self + # Return a pair of [rows, columns] which gives the size of the window. + # + # If the window size cannot be determined, return nil. + def screen_size + rows, cols = actual_screen_size + if rows.to_i != 0 && cols.to_i != 0 + [rows.to_i, cols.to_i] + else + nil + end + end + + # Return a screen size or a default if that fails. + def size! default = [27, 80] + screen_size || default + end + + # Return a screen width or the default if that fails. + def width! + size![1] + end + + # Return a screen height or the default if that fails. + def height! + size![0] + end + + def actual_screen_size + # The best way, if possible (requires non-jruby ≥1.9 or io-console gem) + screen_size_according_to_io_console or + # Fall back to the old standby, though it might be stale: + screen_size_according_to_env or + # Fall further back, though this one is also out of date without something + # calling Readline.set_screen_size + screen_size_according_to_readline or + # Windows users can otherwise run ansicon and get a decent answer: + screen_size_according_to_ansicon_env + end + + def screen_size_according_to_io_console + return if Pry::Helpers::BaseHelpers.jruby? + require 'io/console' + $stdout.winsize if $stdout.tty? and $stdout.respond_to?(:winsize) + rescue LoadError + # They probably don't have the io/console stdlib or the io-console gem. + # We'll keep trying. + end + + def screen_size_according_to_env + size = [ENV['LINES'] || ENV['ROWS'], ENV['COLUMNS']] + size if nonzero_column?(size) + end + + def screen_size_according_to_readline + if defined?(Readline) && Readline.respond_to?(:get_screen_size) + size = Readline.get_screen_size + size if nonzero_column?(size) + end + rescue Java::JavaLang::NullPointerException + # This rescue won't happen on jrubies later than: + # https://github.com/jruby/jruby/pull/436 + nil + end + + def screen_size_according_to_ansicon_env + return unless ENV['ANSICON'] =~ /\((.*)x(.*)\)/ + size = [$2, $1] + size if nonzero_column?(size) + end + + private + + def nonzero_column?(size) + size[1].to_i > 0 + end + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/test/helper.rb b/.bundle/gems/pry-0.10.2/lib/pry/test/helper.rb new file mode 100644 index 0000000..8ddf144 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/test/helper.rb @@ -0,0 +1,170 @@ +require 'pry' + +# in case the tests call reset_defaults, ensure we reset them to +# amended (test friendly) values +class << Pry + alias_method :orig_reset_defaults, :reset_defaults + def reset_defaults + orig_reset_defaults + + Pry.config.color = false + Pry.config.pager = false + Pry.config.should_load_rc = false + Pry.config.should_load_local_rc= false + Pry.config.should_load_plugins = false + Pry.config.history.should_load = false + Pry.config.history.should_save = false + Pry.config.correct_indent = false + Pry.config.hooks = Pry::Hooks.new + Pry.config.collision_warning = false + end +end +Pry.reset_defaults + +# A global space for storing temporary state during tests. + +module PryTestHelpers + + module_function + + # inject a variable into a binding + def inject_var(name, value, b) + Pry.current[:pry_local] = value + b.eval("#{name} = ::Pry.current[:pry_local]") + ensure + Pry.current[:pry_local] = nil + end + + def constant_scope(*names) + names.each do |name| + Object.remove_const name if Object.const_defined?(name) + end + + yield + ensure + names.each do |name| + Object.remove_const name if Object.const_defined?(name) + end + end + + # Open a temp file and yield it to the block, closing it after + # @return [String] The path of the temp file + def temp_file(ext='.rb') + file = Tempfile.new(['pry', ext]) + yield file + ensure + file.close(true) if file + File.unlink("#{file.path}c") if File.exists?("#{file.path}c") # rbx + end + + def unindent(*args) + Pry::Helpers::CommandHelpers.unindent(*args) + end + + def mock_command(cmd, args=[], opts={}) + output = StringIO.new + pry = Pry.new(output: output) + ret = cmd.new(opts.merge(pry_instance: pry, :output => output)).call_safely(*args) + Struct.new(:output, :return).new(output.string, ret) + end + + def mock_exception(*mock_backtrace) + StandardError.new.tap do |e| + e.define_singleton_method(:backtrace) { mock_backtrace } + end + end +end + +def pry_tester(*args, &block) + if args.length == 0 || args[0].is_a?(Hash) + args.unshift(Pry.toplevel_binding) + end + + PryTester.new(*args).tap do |t| + (class << t; self; end).class_eval(&block) if block + end +end + +def pry_eval(*eval_strs) + if eval_strs.first.is_a? String + binding = Pry.toplevel_binding + else + binding = Pry.binding_for(eval_strs.shift) + end + + pry_tester(binding).eval(*eval_strs) +end + +class PryTester + extend Forwardable + + attr_reader :pry, :out + + def_delegators :@pry, :eval_string, :eval_string= + + def initialize(target = TOPLEVEL_BINDING, options = {}) + @pry = Pry.new(options.merge(:target => target)) + @history = options[:history] + + @pry.inject_sticky_locals! + reset_output + end + + def eval(*strs) + reset_output + result = nil + + strs.flatten.each do |str| + str = "#{str.strip}\n" + @history.push str if @history + + if @pry.process_command(str) + result = last_command_result_or_output + else + result = @pry.evaluate_ruby(str) + end + end + + result + end + + def push(*lines) + Array(lines).flatten.each do |line| + @pry.eval(line) + end + end + + def push_binding(context) + @pry.push_binding context + end + + def last_output + @out.string if @out + end + + def process_command(command_str) + @pry.process_command(command_str) or raise "Not a valid command" + last_command_result_or_output + end + + def last_command_result + result = Pry.current[:pry_cmd_result] + result.retval if result + end + + protected + + def last_command_result_or_output + result = last_command_result + if result != Pry::Command::VOID_VALUE + result + else + last_output + end + end + + def reset_output + @out = StringIO.new + @pry.output = @out + end +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/version.rb b/.bundle/gems/pry-0.10.2/lib/pry/version.rb new file mode 100644 index 0000000..f7d2ab1 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/version.rb @@ -0,0 +1,3 @@ +class Pry + VERSION = "0.10.2" +end diff --git a/.bundle/gems/pry-0.10.2/lib/pry/wrapped_module.rb b/.bundle/gems/pry-0.10.2/lib/pry/wrapped_module.rb new file mode 100644 index 0000000..bfa5793 --- /dev/null +++ b/.bundle/gems/pry-0.10.2/lib/pry/wrapped_module.rb @@ -0,0 +1,377 @@ +require 'pry/module_candidate' + +class Pry + class << self + # If the given object is a `Pry::WrappedModule`, return it unaltered. If it's + # anything else, return it wrapped in a `Pry::WrappedModule` instance. + def WrappedModule(obj) + if obj.is_a? Pry::WrappedModule + obj + else + Pry::WrappedModule.new(obj) + end + end + end + + class WrappedModule + include Helpers::BaseHelpers + include CodeObject::Helpers + + attr_reader :wrapped + + # Convert a string to a module. + # + # @param [String] mod_name + # @param [Binding] target The binding where the lookup takes place. + # @return [Module, nil] The module or `nil` (if conversion failed). + # @example + # Pry::WrappedModule.from_str("Pry::Code") + def self.from_str(mod_name, target=TOPLEVEL_BINDING) + if safe_to_evaluate?(mod_name, target) + Pry::WrappedModule.new(target.eval(mod_name)) + else + nil + end + rescue RescuableException + nil + end + + class << self + private + + # We use this method to decide whether code is safe to eval. Method's are + # generally not, but everything else is. + # TODO: is just checking != "method" enough?? + # TODO: see duplication of this method in Pry::CodeObject + # @param [String] str The string to lookup. + # @param [Binding] target Where the lookup takes place. + # @return [Boolean] + def safe_to_evaluate?(str, target) + return true if str.strip == "self" + kind = target.eval("defined?(#{str})") + kind =~ /variable|constant/ + end + end + + # @raise [ArgumentError] if the argument is not a `Module` + # @param [Module] mod + def initialize(mod) + raise ArgumentError, "Tried to initialize a WrappedModule with a non-module #{mod.inspect}" unless ::Module === mod + @wrapped = mod + @memoized_candidates = [] + @host_file_lines = nil + @source = nil + @source_location = nil + @doc = nil + end + + # Returns an array of the names of the constants accessible in the wrapped + # module. This avoids the problem of accidentally calling the singleton + # method `Module.constants`. + # @param [Boolean] inherit Include the names of constants from included + # modules? + def constants(inherit = true) + Module.instance_method(:constants).bind(@wrapped).call(inherit) + end + + # The prefix that would appear before methods defined on this class. + # + # i.e. the "String." or "String#" in String.new and String#initialize. + # + # @return String + def method_prefix + if singleton_class? + if Module === singleton_instance + "#{WrappedModule.new(singleton_instance).nonblank_name}." + else + "self." + end + else + "#{nonblank_name}#" + end + end + + # The name of the Module if it has one, otherwise #. + # + # @return [String] + def nonblank_name + if name.to_s == "" + wrapped.inspect + else + name + end + end + + # Is this a singleton class? + # @return [Boolean] + def singleton_class? + if Pry::Method.safe_send(wrapped, :respond_to?, :singleton_class?) + Pry::Method.safe_send(wrapped, :singleton_class?) + elsif defined?(Rubinius) + # https://github.com/rubinius/rubinius/commit/2e71722dba53d1a92c54d5e3968d64d1042486fe singleton_class? added 30 Jul 2014 + # https://github.com/rubinius/rubinius/commit/4310f6b2ef3c8fc88135affe697db4e29e4621c4 has been around since 2011 + !!Rubinius::Type.singleton_class_object(wrapped) + else + wrapped != Pry::Method.safe_send(wrapped, :ancestors).first + end + end + + # Is this strictly a module? (does not match classes) + # @return [Boolean] + def module? + wrapped.instance_of?(Module) + end + + # Is this strictly a class? + # @return [Boolean] + def class? + wrapped.instance_of?(Class) + end + + # Get the instance associated with this singleton class. + # + # @raise ArgumentError: tried to get instance of non singleton class + # + # @return [Object] + def singleton_instance + raise ArgumentError, "tried to get instance of non singleton class" unless singleton_class? + + if Helpers::BaseHelpers.jruby? + wrapped.to_java.attached + else + @singleton_instance ||= ObjectSpace.each_object(wrapped).detect{ |x| (class << x; self; end) == wrapped } + end + end + + # Forward method invocations to the wrapped module + def method_missing(method_name, *args, &block) + wrapped.send(method_name, *args, &block) + end + + def respond_to?(method_name) + super || wrapped.respond_to?(method_name) + end + + # Retrieve the source location of a module. Return value is in same + # format as Method#source_location. If the source location + # cannot be found this method returns `nil`. + # + # @param [Module] mod The module (or class). + # @return [Array, nil] The source location of the + # module (or class), or `nil` if no source location found. + def source_location + @source_location ||= primary_candidate.source_location + rescue Pry::RescuableException + nil + end + + # @return [String, nil] The associated file for the module (i.e + # the primary candidate: highest ranked monkeypatch). + def file + Array(source_location).first + end + alias_method :source_file, :file + + # @return [Fixnum, nil] The associated line for the module (i.e + # the primary candidate: highest ranked monkeypatch). + def line + Array(source_location).last + end + alias_method :source_line, :line + + # Returns documentation for the module. + # This documentation is for the primary candidate, if + # you would like documentation for other candidates use + # `WrappedModule#candidate` to select the candidate you're + # interested in. + # @raise [Pry::CommandError] If documentation cannot be found. + # @return [String] The documentation for the module. + def doc + @doc ||= primary_candidate.doc + end + + # Returns the source for the module. + # This source is for the primary candidate, if + # you would like source for other candidates use + # `WrappedModule#candidate` to select the candidate you're + # interested in. + # @raise [Pry::CommandError] If source cannot be found. + # @return [String] The source for the module. + def source + @source ||= primary_candidate.source + end + + # @return [String] Return the associated file for the + # module from YARD, if one exists. + def yard_file + YARD::Registry.at(name).file if yard_docs? + end + + # @return [Fixnum] Return the associated line for the + # module from YARD, if one exists. + def yard_line + YARD::Registry.at(name).line if yard_docs? + end + + # @return [String] Return the YARD docs for this module. + def yard_doc + YARD::Registry.at(name).docstring.to_s if yard_docs? + end + + # Return a candidate for this module of specified rank. A `rank` + # of 0 is equivalent to the 'primary candidate', which is the + # module definition with the highest number of methods. A `rank` + # of 1 is the module definition with the second highest number of + # methods, and so on. Module candidates are necessary as modules + # can be reopened multiple times and in multiple places in Ruby, + # the candidate API gives you access to the module definition + # representing each of those reopenings. + # @raise [Pry::CommandError] If the `rank` is out of range. That + # is greater than `number_of_candidates - 1`. + # @param [Fixnum] rank + # @return [Pry::WrappedModule::Candidate] + def candidate(rank) + @memoized_candidates[rank] ||= Candidate.new(self, rank) + end + + # @return [Fixnum] The number of candidate definitions for the + # current module. + def number_of_candidates + method_candidates.count + end + + # @note On JRuby 1.9 and higher, in certain conditions, this method chucks + # away its ability to be quick (when there are lots of monkey patches, + # like in Rails). However, it should be efficient enough on other rubies. + # @see https://github.com/jruby/jruby/issues/525 + # @return [Enumerator, Array] on JRuby 1.9 and higher returns Array, on + # other rubies returns Enumerator + def candidates + enum = Enumerator.new do |y| + (0...number_of_candidates).each do |num| + y.yield candidate(num) + end + end + Pry::Helpers::BaseHelpers.jruby_19? ? enum.to_a : enum + end + + # @return [Boolean] Whether YARD docs are available for this module. + def yard_docs? + !!(defined?(YARD) && YARD::Registry.at(name)) + end + + # @param [Fixnum] times How far to travel up the ancestor chain. + # @return [Pry::WrappedModule, nil] The wrapped module that is the + # superclass. + # When `self` is a `Module` then return the + # nth ancestor, otherwise (in the case of classes) return the + # nth ancestor that is a class. + def super(times=1) + return self if times.zero? + + if wrapped.is_a?(Class) + sup = ancestors.select { |v| v.is_a?(Class) }[times] + else + sup = ancestors[times] + end + + Pry::WrappedModule(sup) if sup + end + + private + + # @return [Pry::WrappedModule::Candidate] The candidate with the + # highest rank, that is the 'monkey patch' of this module with the + # highest number of methods, which contains a source code line that + # defines the module. It is considered the 'canonical' definition + # for the module. In the absense of a suitable candidate, the + # candidate of rank 0 will be returned, or a CommandError raised if + # there are no candidates at all. + def primary_candidate + @primary_candidate ||= candidates.find { |c| c.file } || + # This will raise an exception if there is no candidate at all. + candidate(0) + end + + # @return [Array>] The array of `Pry::Method` objects, + # there are two associated with each candidate. The first is the 'base + # method' for a candidate and it serves as the start point for + # the search in uncovering the module definition. The second is + # the last method defined for that candidate and it is used to + # speed up source code extraction. + def method_candidates + @method_candidates ||= all_source_locations_by_popularity.map do |group| + methods_sorted_by_source_line = group.last.sort_by(&:source_line) + [methods_sorted_by_source_line.first, methods_sorted_by_source_line.last] + end + end + + # A helper method. + def all_source_locations_by_popularity + return @all_source_locations_by_popularity if @all_source_locations_by_popularity + + ims = all_relevant_methods_for(wrapped) + @all_source_locations_by_popularity = ims.group_by { |v| Array(v.source_location).first }. + sort_by do |path, methods| + expanded = File.expand_path(path) + load_order = $LOADED_FEATURES.index{ |file| expanded.end_with?(file) } + + [-methods.size, load_order || (1.0 / 0.0)] + end + end + + # We only want methods that have a non-nil `source_location`. We also + # skip some spooky internal methods. + # (i.e we skip `__class_init__` because it's an odd rbx specific thing that causes tests to fail.) + # @return [Array] + def all_relevant_methods_for(mod) + methods = all_methods_for(mod).select(&:source_location). + reject{ |x| x.name == '__class_init__' || method_defined_by_forwardable_module?(x) } + + return methods unless methods.empty? + + safe_send(mod, :constants).map do |const_name| + if const = nested_module?(mod, const_name) + all_relevant_methods_for(const) + else + [] + end + end.flatten + end + + # Return all methods (instance methods and class methods) for a + # given module. + # @return [Array] + def all_methods_for(mod) + Pry::Method.all_from_obj(mod, false) + Pry::Method.all_from_class(mod, false) + end + + def nested_module?(parent, name) + return if safe_send(parent, :autoload?, name) + child = safe_send(parent, :const_get, name) + return unless Module === child + return unless safe_send(child, :name) == "#{safe_send(parent, :name)}::#{name}" + child + end + + # Detect methods that are defined with `def_delegator` from the Forwardable + # module. We want to reject these methods as they screw up module + # extraction since the `source_location` for such methods points at forwardable.rb + # TODO: make this more robust as valid user-defined files called + # forwardable.rb are also skipped. + def method_defined_by_forwardable_module?(method) + method.source_location.first =~ /forwardable\.rb/ + end + + # memoized lines for file + def lines_for_file(file) + @lines_for_file ||= {} + + if file == Pry.eval_path + @lines_for_file[file] ||= Pry.line_buffer.drop(1) + else + @lines_for_file[file] ||= File.readlines(file) + end + end + end +end diff --git a/.bundle/gems/rspec-3.3.0/License.txt b/.bundle/gems/rspec-3.3.0/License.txt new file mode 100644 index 0000000..02bc06c --- /dev/null +++ b/.bundle/gems/rspec-3.3.0/License.txt @@ -0,0 +1,24 @@ +(The MIT License) + +Copyright (c) 2009 Chad Humphries, David Chelimsky +Copyright (c) 2006 David Chelimsky, The RSpec Development Team +Copyright (c) 2005 Steven Baker + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/.bundle/gems/rspec-3.3.0/README.md b/.bundle/gems/rspec-3.3.0/README.md new file mode 100644 index 0000000..a425898 --- /dev/null +++ b/.bundle/gems/rspec-3.3.0/README.md @@ -0,0 +1,34 @@ +# RSpec + +Behaviour Driven Development for Ruby + +# Description + +rspec is a meta-gem, which depends on the [rspec-core](https://github.com/rspec/rspec-core), [rspec-expectations](https://github.com/rspec/rspec-expectations) +and [rspec-mocks](https://github.com/rspec/rspec-mocks) gems. Each of these can be installed separately and loaded in +isolation using `require`. Among other benefits, this allows you to use +rspec-expectations, for example, in Test::Unit::TestCase if you happen to +prefer that style. + +Conversely, if you like RSpec's approach to declaring example groups and +examples (`describe` and `it`) but prefer Test::Unit assertions and mocha, rr +or flexmock for mocking, you'll be able to do that without having to install or load the +components of RSpec that you're not using. + +## Documentation + +See http://rspec.info/documentation/ for links to documentation for all gems. + +## Install + + gem install rspec + +## Contribute + +* [http://github.com/rspec/rspec-dev](http://github.com/rspec/rspec-dev) + +## Also see + +* +* +* diff --git a/.bundle/gems/rspec-3.3.0/lib/rspec.rb b/.bundle/gems/rspec-3.3.0/lib/rspec.rb new file mode 100644 index 0000000..36149e0 --- /dev/null +++ b/.bundle/gems/rspec-3.3.0/lib/rspec.rb @@ -0,0 +1,3 @@ +require 'rspec/core' +require 'rspec/version' + diff --git a/.bundle/gems/rspec-3.3.0/lib/rspec/version.rb b/.bundle/gems/rspec-3.3.0/lib/rspec/version.rb new file mode 100644 index 0000000..1114390 --- /dev/null +++ b/.bundle/gems/rspec-3.3.0/lib/rspec/version.rb @@ -0,0 +1,5 @@ +module RSpec # :nodoc: + module Version # :nodoc: + STRING = '3.3.0' + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/.document b/.bundle/gems/rspec-core-3.3.2/.document new file mode 100644 index 0000000..050e204 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/.document @@ -0,0 +1,5 @@ +lib/**/*.rb +- +README.md +License.txt +Changelog.md diff --git a/.bundle/gems/rspec-core-3.3.2/.yardopts b/.bundle/gems/rspec-core-3.3.2/.yardopts new file mode 100644 index 0000000..0ab6943 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/.yardopts @@ -0,0 +1,8 @@ +--exclude features +--no-private +--markup markdown +--default-return void +- +Filtering.md +Changelog.md +License.txt diff --git a/.bundle/gems/rspec-core-3.3.2/Changelog.md b/.bundle/gems/rspec-core-3.3.2/Changelog.md new file mode 100644 index 0000000..44e4e2a --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/Changelog.md @@ -0,0 +1,1856 @@ +### 3.3.2 / 2015-07-15 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v3.3.1...v3.3.2) + +Bug Fixes: + +* Fix formatters to handle exceptions for which `backtrace` returns `nil`. + (Myron Marston, #2023) +* Fix duplicate formatter detection so that it allows subclasses of formatters + to be added. (Sebastián Tello, #2019) + +### 3.3.1 / 2015-06-18 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v3.3.0...v3.3.1) + +Bug Fixes: + +* Correctly run `before(:suite)` (and friends) in the context of an example + group instance, thus making the expected RSpec environment available. + (Jon Rowe, #1986) + +### 3.3.0 / 2015-06-12 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v3.2.3...v3.3.0) + +Enhancements: + +* Expose the reporter used to run examples via `RSpec::Core::Example#reporter`. + (Jon Rowe, #1866) +* Make `RSpec::Core::Reporter#message` a public supported API. (Jon Rowe, #1866) +* Allow custom formatter events to be published via + `RSpec::Core::Reporter#publish(event_name, hash_of_attributes)`. (Jon Rowe, #1869) +* Remove dependency on the standard library `Set` and replace with `RSpec::Core::Set`. + (Jon Rowe, #1870) +* Assign a unique id to each example and group so that they can be + uniquely identified, even for shared examples (and similar situations) + where the location isn't unique. (Myron Marston, #1884) +* Use the example id in the rerun command printed for failed examples + when the location is not unique. (Myron Marston, #1884) +* Add `config.example_status_persistence_file_path` option, which is + used to persist the last run status of each example. (Myron Marston, #1888) +* Add `:last_run_status` metadata to each example, which indicates what + happened the last time an example ran. (Myron Marston, #1888) +* Add `--only-failures` CLI option which filters to only the examples + that failed the last time they ran. (Myron Marston, #1888) +* Add `--next-failure` CLI option which allows you to repeatedly focus + on just one of the currently failing examples, then move on to the + next failure, etc. (Myron Marston, #1888) +* Make `--order random` ordering stable, so that when you rerun a + subset with a given seed, the examples will be order consistently + relative to each other. (Myron Marston, #1908) +* Set example group constant earlier so errors when evaluating the context + include the example group name (Myron Marson, #1911) +* Make `let` and `subject` threadsafe. (Josh Cheek, #1858) +* Add version information into the JSON formatter. (Mark Swinson, #1883) +* Add `--bisect` CLI option, which will repeatedly run your suite in + order to isolate the failures to the smallest reproducible case. + (Myron Marston, #1917) +* For `config.include`, `config.extend` and `config.prepend`, apply the + module to previously defined matching example groups. (Eugene Kenny, #1935) +* When invalid options are parsed, notify users where they came from + (e.g. `.rspec` or `~/.rspec` or `ENV['SPEC_OPTS']`) so they can + easily find the source of the problem. (Myron Marston, #1940) +* Add pending message contents to the json formatter output. (Jon Rowe, #1949) +* Add shared group backtrace to the output displayed by the built-in + formatters for pending examples that have been fixed. (Myron Marston, #1946) +* Add support for `:aggregate_failures` metadata. Tag an example or + group with this metadata and it'll use rspec-expectations' + `aggregate_failures` feature to allow multiple failures in an example + and list them all, rather than aborting on the first failure. (Myron + Marston, #1946) +* When no formatter implements #message add a fallback to prevent those + messages being lost. (Jon Rowe, #1980) +* Profiling examples now takes into account time spent in `before(:context)` + hooks. (Denis Laliberté, Jon Rowe, #1971) +* Improve failure output when an example has multiple exceptions, such + as one from an `it` block and one from an `after` block. (Myron Marston, #1985) + +Bug Fixes: + +* Handle invalid UTF-8 strings within exception methods. (Benjamin Fleischer, #1760) +* Fix Rake Task quoting of file names with quotes to work properly on + Windows. (Myron Marston, #1887) +* Fix `RSpec::Core::RakeTask#failure_message` so that it gets printed + when the task failed. (Myron Marston, #1905) +* Make `let` work properly when defined in a shared context that is applied + to an individual example via metadata. (Myron Marston, #1912) +* Ensure `rspec/autorun` respects configuration defaults. (Jon Rowe, #1933) +* Prevent modules overriding example group defined methods when included, + prepended or extended by config defined after an example group. (Eugene Kenny, #1935) +* Fix regression which caused shared examples to be mistakenly run when specs + where filtered to a particular location. (Ben Axnick, #1963) +* Fix time formatting logic so that it displays 70 seconds as "1 minute, + 10 seconds" rather than "1 minute, 1 second". (Paul Brennan, #1984) +* Fix regression where the formatter loader would allow duplicate formatters. + (Jon Rowe, #1990) + +### 3.2.3 / 2015-04-06 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v3.2.2...v3.2.3) + +Bug Fixes: + +* Fix how the DSL methods are defined so that RSpec is compatible with + gems that define methods of the same name on `Kernel` (such as + the `its-it` gem). (Alex Kwiatkowski, Ryan Ong, #1907) +* Fix `before(:context) { skip }` so that it does not wrongly cause the + spec suite to exit with a non-zero status when no examples failed. + (Myron Marston, #1926) + +### 3.2.2 / 2015-03-11 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v3.2.1...v3.2.2) + +Bug Fixes: + +* Fix regression in 3.2.0 that allowed tag-filtered examples to + run even if there was a location filter applied to the spec + file that was intended to limit the file to other examples. + (#1894, Myron Marston) + +### 3.2.1 / 2015-02-23 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v3.2.0...v3.2.1) + +Bug Fixes: + +* Notify start-of-run seed _before_ `start` notification rather than + _after_ so that formatters like Fuubar work properly. (Samuel Esposito, #1882) + +### 3.2.0 / 2015-02-03 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v3.1.7...v3.2.0) + +Enhancements: + +* Improve the `inspect` output of example groups. (Mike Dalton, #1687) +* When rake task fails, only output the command if `verbose` flag is + set. (Ben Snape, #1704) +* Add `RSpec.clear_examples` as a clear way to reset examples in between + spec runs, whilst retaining user configuration. (Alexey Fedorov, #1706) +* Reduce string allocations when defining and running examples by 70% + and 50% respectively. (Myron Marston, #1738) +* Removed dependency on pathname from stdlib. (Sam Phippen, #1703) +* Improve the message presented when a user hits Ctrl-C. + (Alex Chaffee #1717, #1742) +* Improve shared example group inclusion backtrace displayed + in failed example output so that it works for all methods + of including shared example groups and shows all inclusion + locations. (Myron Marston, #1763) +* Issue seed notification at start (as well as the end) of the reporter + run. (Arlandis Word, #1761) +* Improve the documentation of around hooks. (Jim Kingdon, #1772) +* Support prepending of modules into example groups from config and allow + filtering based on metadata. (Arlandis Word, #1806) +* Emit warnings when `:suite` hooks are registered on an example group + (where it has always been ignored) or are registered with metadata + (which has always been ignored). (Myron Marston, #1805) +* Provide a friendly error message when users call RSpec example group + APIs (e.g. `context`, `describe`, `it`, `let`, `before`, etc) from + within an example where those APIs are unavailable. (Myron Marston, #1819) +* Provide a friendly error message when users call RSpec example + APIs (e.g. `expect`, `double`, `stub_const`, etc) from + within an example group where those APIs are unavailable. + (Myron Marston, #1819) +* Add new `RSpec::Core::Sandbox.sandboxed { }` API that facilitates + testing RSpec with RSpec, allowing you to define example groups + and example from within an example without affecting the global + `RSpec.world` state. (Tyler Ball, 1808) +* Apply line-number filters only to the files they are scoped to, + allowing you to mix filtered and unfiltered files. (Myron Marston, #1839) +* When dumping pending examples, include the failure details so that you + don't have to un-pend the example to see it. (Myron Marston, #1844) +* Make `-I` option support multiple values when separated by + `File::PATH_SEPARATOR`, such as `rspec -I foo:bar`. This matches + the behavior of Ruby's `-I` option. (Fumiaki Matsushima, #1855). +* Treat each example as having a singleton example group for the + purposes of applying metadata-based features that normally apply + to example groups to individually tagged examples. For example, + `RSpec.shared_context "Uses redis", :uses_redis` will now apply + to individual examples tagged with `:uses_redis`, as will + `config.include RedisHelpers, :uses_redis`, and + `config.before(:context, :uses_redis) { }`, etc. (Myron Marston, #1749) + +Bug Fixes: + +* When assigning generated example descriptions, surface errors + raised by `matcher.description` in the example description. + (Myron Marston, #1771) +* Don't consider expectations from `after` hooks when generating + example descriptions. (Myron Marston, #1771) +* Don't apply metadata-filtered config hooks to examples in groups + with matching metadata when those examples override the parent + metadata value to not match. (Myron Marston, #1796) +* Fix `config.expect_with :minitest` so that `skip` uses RSpec's + implementation rather than Minitest's. (Jonathan Rochkind, #1822) +* Fix `NameError` caused when duplicate example group aliases are defined and + the DSL is not globally exposed. (Aaron Kromer, #1825) +* When a shared example defined in an external file fails, use the host + example group (from a loaded spec file) for the re-run command to + ensure the command will actually work. (Myron Marston, #1835) +* Fix location filtering to work properly for examples defined in + a nested example group within a shared example group defined in + an external file. (Bradley Schaefer, Xavier Shay, Myron Marston, #1837) +* When a pending example fails (as expected) due to a mock expectation, + set `RSpec::Core::Example::ExecutionResult#pending_exception` -- + previously it was not being set but should have been. (Myron Marston, #1844) +* Fix rake task to work when `rspec-core` is installed in a directory + containing a space. (Guido Günther, #1845) +* Fix regression in 3.1 that caused `describe Regexp` to raise errors. + (Durran Jordan, #1853) +* Fix regression in 3.x that caused the profile information to be printed + after the summary. (Max Lincoln, #1857) +* Apply `--seed` before loading `--require` files so that required files + can access the provided seed. (Myron Marston, #1745) +* Handle `RSpec::Core::Formatters::DeprecationFormatter::FileStream` being + reopened with an IO stream, which sometimes happens with spring. + (Kevin Mook, #1757) + +### 3.1.7 / 2014-10-11 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v3.1.6...v3.1.7) + +Bug Fixes: + +* Fix `Metadata.relative_path` so that for a current directory of + `/foo/bar`, `/foo/bar_1` is not wrongly converted to `._1`. + (Akos Vandra, #1730) +* Prevent constant lookup mistakenly finding `RSpec::ExampleGroups` generated + constants on 1.9.2 by appending a trailing `_` to the generated names. + (Jon Rowe, #1737) +* Fix bug in `:pending` metadata. If it got set in any way besides passing + it as part of the metadata literal passed to `it` (such as by using + `define_derived_metadata`), it did not have the desired effect, + instead marking the example as `:passed`. (Myron Marston, #1739) + +### 3.1.6 / 2014-10-08 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v3.1.5...v3.1.6) + +Bug Fixes: + +* Fix regression in rake task pattern handling, that prevented patterns + that were relative from the current directory rather than from `spec` + from working properly. (Myron Marston, #1734) +* Prevent rake task from generating duplicate load path entries. + (Myron Marston, #1735) + +### 3.1.5 / 2014-09-29 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v3.1.4...v3.1.5) + +Bug Fixes: + +* Fix issue with the rake task incorrectly escaping strings on Windows. + (Jon Rowe #1718) +* Support absolute path patterns. While this wasn't officially supported + previously, setting `rake_task.pattern` to an absolute path pattern in + RSpec 3.0 and before worked since it delegated to `FileList` internally + (but now just forwards the pattern on to the `rspec` command). + (Myron Marston, #1726) + +### 3.1.4 / 2014-09-18 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v3.1.3...v3.1.4) + +Bug Fixes: + +* Fix implicit `subject` when using `describe false` or `describe nil` + so that it returns the provided primitive rather than the string + representation. (Myron Marston, #1710) +* Fix backtrace filtering to allow code in subdirectories of your + current working directory (such as vendor/bundle/...) to be filtered + from backtraces. (Myron Marston, #1708) + +### 3.1.3 / 2014-09-15 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v3.1.2...v3.1.3) + +Bug Fixes: + +* Fix yet another regression in rake task pattern handling, to allow + `task.pattern = FileList["..."]` to work. That was never intended + to be supported but accidentally worked in 3.0 and earlier. + (Myron Marston, #1701) +* Fix pattern handling so that files are normalized to absolute paths + before subtracting the `--exclude-pattern` matched files from the + `--pattern` matched files so that it still works even if the patterns + are in slightly different forms (e.g. one starting with `./`). + (Christian Nelson, #1698) + +### 3.1.2 / 2014-09-08 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v3.1.1...v3.1.2) + +Bug Fixes: + +* Fix another regression in rake task pattern handling, so that patterns + that start with `./` still work. (Christian Nelson, #1696) + +### 3.1.1 / 2014-09-05 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v3.1.0...v3.1.1) + +Bug Fixes: + +* Fix a regression in rake task pattern handling, so that `rake_task.pattern = array` + works again. While we never intended to support array values (or even knew that worked!), + the implementation from 3.0 and earlier used `FileList` internally, which allows arrays. + The fix restores the old behavior. (Myron Marston, #1694) + +### 3.1.0 / 2014-09-04 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v3.0.4...v3.1.0) + +Enhancements: + +* Update files generated by `rspec --init` so that warnings are enabled + in commented out section of `spec_helper` rather than `.rspec` so users + have to consciously opt-in to the setting. (Andrew Hooker, #1572) +* Update `spec_helper` generated by `rspec --init` so that it sets the new + rspec-expectations `include_chain_clauses_in_custom_matcher_descriptions` + config option (which will be on by default in RSpec 4) and also sets the + rspec-mocks `verify_partial_doubles` option (which will also default + to on in RSpec 4). (Myron Marston, #1647) +* Provide an `inspect` output for example procsy objects (used in around + hooks) that doesn't make them look like procs. (Jon Rowe, #1620) +* Remove a few unneeded `require` statements from + `rspec/core/rake_task.rb`, making it even more lighterweight. + (Myron Marston, #1640) +* Allow rspec-core to be used when neither rspec-mocks or + rspec-expectations are installed, without requiring any + user configuration. (Sam Phippen, Myron Marston, #1615) +* Don't filter out gems from backtraces by default. (The RSpec + gems will still be filtered). User feedback has indicated + that including gems in default backtraces will be useful. + (Myron Marston, #1641) +* Add new `config.filter_gems_from_backtrace "rack", "rake"` API + to easily filter the named gems from backtraces. (Myron Marston, #1682) +* Fix default backtrace filters so that the RSpec binary is + excluded when installing RSpec as a bundler `:git` dependency. + (Myron Marston, #1648) +* Simplify command generated by the rake task so that it no longer + includes unnecessary `-S`. (Myron Marston, #1559) +* Add `--exclude-pattern` CLI option, `config.exclude_pattern =` config + option and `task.exclude_pattern =` rake task config option. Matching + files will be excluded. (John Gesimondo, Myron Marston, #1651, #1671) +* When an around hook fails to execute the example, mark it as + pending (rather than passing) so the user is made aware of the + fact that the example did not actually run. (Myron Marston, #1660) +* Remove dependency on `FileUtils` from the standard library so that users do + not get false positives where their code relies on it but they are not + requiring it. (Sam Phippen, #1565) + +Bug Fixes: + +* Fix rake task `t.pattern =` option so that it does not run all specs + when it matches no files, by passing along a `--pattern` option to + the `rspec` command, rather than resolving the file list and passing + along the files individually. (Evgeny Zislis, #1653) +* Fix rake task default pattern so that it follows symlinks properly. + (Myron Marston, #1672) +* Fix default pattern used with `rspec` command so that it follows + symlinks properly. (Myron Marston, #1672) +* Change how we assign constant names to example group classes so that + it avoids a problem with `describe "Core"`. (Daniela Wellisz, #1679) +* Handle rendering exceptions that have a different encoding than that + of their original source file. (Jon Rowe, #1681) +* Allow access to message_lines without colour for failed examples even + when they're part of a shared example group. (tomykaira, #1689) + +### 3.0.4 / 2014-08-14 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v3.0.3...v3.0.4) + +Bug Fixes: + +* Fix processing order of CLI options so that if `config.files_to_run` + is accessed from a file loaded by `--require`, `--pattern` is still + applied. (Myron Marston, #1652) +* Fix `config.pattern=` so that it still takes affect even if + `config.files_to_run` has already been accessed. (Myron Marston, #1652) + +### 3.0.3 / 2014-07-21 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v3.0.2...v3.0.3) + +Bug Fixes: + +* Properly convert both parts of a description into strings before + concatenation. (@nicklink483, #1636) +* Exclude the working directory when figuring out folders to ignore. + (Jon Rowe, Myron Marston, #1616) +* Allow `::RSpec::Core::Notifications::FailedExampleNotification#message_lines` + to be accessed without a colouriser. (@tomykaira, #1637) + +### 3.0.2 / 2014-06-19 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v3.0.1...v3.0.2) + +Bug Fixes: + +* Fix regression in CLI option handling that prevented `--tag slow` + passed at the command line from overriding `--tag ~slow` in `.rspec`. + (Colin Jones, #1602) +* Fix metadata `:example_group` deprecation warning so that it gets + issued at the call site of the configuration that specified it as + a filter rather than later when an example group is defined. + (Myron Marston, #1562) +* Make the line that is printed when a shared example group fails indicating + where the concrete example group is white, separating it from the stack trace + that is produced for the failure. (Sam Phippen, Jon Rowe, #1606) + +### 3.0.1 / 2014-06-12 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v3.0.0...v3.0.1) + +Bug Fixes: + +* Fix a couple ruby warnings caused by rspec-core when loaded. + (Prem Sichanugrist, #1584) +* Example groups named `Config` will no longer cause a Ruby warning to be + issued. (Jimmy Cuadra, #1580) + +### 3.0.0 / 2014-06-01 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v3.0.0.rc1...v3.0.0) + +Bug Fixes: + +* Fix `BaseTextFormatter` so that it does not re-close a closed output + stream. (Myron Marston) +* Fix regression in metadata that caused the metadata hash of a top-level + example group to have a `:parent_example_group` key even though it has + no parent example group. (Myron Marston) + +Enhancements: + +* Alter the default `spec_helper.rb` to no longer recommend + `config.full_backtrace = true` see #1536 for discussion. (Jon Rowe) + +### 3.0.0.rc1 / 2014-05-18 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v3.0.0.beta2...v3.0.0.rc1) + +Breaking Changes for 3.0.0: + +* Change `described_class` so that in a nested group like `describe + MyClass`, it returns `MyClass` rather than the outer group's described + class. (Myron Marston) +* Refactor filter manager so that it no longer subclasses Hash and has a + tighter, more domain-specific interface. (Sergey Pchelincev) +* Remove legacy colours definitions from `BaseTextFormatter`. (Jon Rowe) +* Remove console color definitions from `BaseTextFormatter`. (Jon Rowe) +* Restructure example group metadata so that the computed keys are + exposed directly off of the metadata hash rather than being on + a nested `:example_group` subhash. In addition, the parent example + group metadata is now available as `[:parent_example_group]` rather + than `[:example_group][:example_group]`. Deprecated access via the + old key structure is still provided. (Myron Marston) +* Remove `:describes` metadata key. It duplicates `:described_class` + for no good reason. Deprecated access via `:describes` is still + provided. (Myron Marston) +* Rename `:example_group_block` metadata key to `:block`. + (Myron Marston) +* Remove deprecated `RSpec::Core::Example#options`. (Myron Marston) +* Move `BaseTextFormatter#colorize_summary` to `SummaryNotification#colorize_with` + (Jon Rowe). +* `describe some_hash` treated `some_hash` as metadata in RSpec 2.x but + will treat it as the described object in RSpec 3.0. Metadata must + always come after the description args. (Myron Marston) +* Remove deprecated `display_name` alias of `ExampleGroup.description`. + (Myron Marston) +* Remove deprecated `describes` alias of `ExampleGroup.described_class`. + (Myron Marston) +* Remove deprecated `RSpec::Core::ExampleGroup.alias_it_behaves_like_to`. + Use `RSpec::Core::Configuration#alias_it_behaves_like_to` instead. + (Myron Marston) +* Remove deprecated `RSpec::Core::ExampleGroup.alias_example_to`. + Use `RSpec::Core::Configuration#alias_example_to` instead. + (Myron Marston) +* Removed `focused` example alias and change example/group aliases + `fit`, `focus`, `fcontext` and `fdescribe` to no longer include + `:focused => true` metadata. They only contain `:focus => true` + metadata now. This means that you will need to filter them with + `filter_run :focus`, not `filter_run :focused`. (Myron Marston) +* Remove `--line-number` filtering. It's semantically dubious since it's + a global filter (potentially applied to multiple files) but there's no + meaningful connection between the same line number in multiple files. + Instead use the `rspec path/to/spec.rb:23:46` form, which is terser + and makes more sense as it is scoped to a file. (Myron Marston) +* Remove `--default_path` as an alias for `--default-path`. (Jon Rowe) +* Remove deprecated `share_examples_for`. There's still + `shared_examples` and `shared_examples_for`. (Myron Marston) +* Rename `RSpec::Core::Configuration#warnings` to + `RSpec::Core::Configuration#warnings?` since it's a boolean flag. + (Myron Marston) +* RSpec's global state is no longer reset after a spec run. This gives + more flexibility to alternate runners to decide when and if they + want the state reset. Alternate runners are now responsible for + calling this (or doing a similar reset) if they are going to run + the spec suite multiple times in the same process. (Sam Phippen) +* Merge `RSpec::Core::CommandLine` (never formally declared public) + into `RSpec::Core::Runner`. (Myron Marston) +* Remove `color_enabled` as an alias of `color`. (Jon Rowe) +* Remove `backtrace_cleaner` as an alias of `backtrace_formatter`. (Jon Rowe) +* Remove `filename_pattern` as an alias of `pattern`. (Jon Rowe) +* Extract support for legacy formatters to `rspec-legacy_formatters`. (Jon Rowe) +* `RSpec::Configuration#formatters` now returns a dup to prevent mutation. (Jon Rowe) +* Replace `stdlib` as an available expectation framework with `test_unit` and + `minitest`. (Aaron Kromer) +* Remove backtrace formatting helpers from `BaseTextFormatter`. (Jon Rowe) +* Extract profiler support to `ProfileFormatter` and `ProfileNotification`. + Formatters should implement `dump_profile` if they wish to respond to `--profile`. + (Jon Rowe) +* Extract remaining formatter state to reporter and notifications. Introduce + `ExamplesNotification` to share information about examples that was previously + held in `BaseFormatter`. (Jon Rowe) + +Enhancements: + +* Add `config.default_formatter` attribute, which can be used to set a + formatter which will only be used if no other formatter is set + (e.g. via `--formatter`). (Myron Marston) +* Support legacy colour definitions in `LegacyFormatterAdaptor`. (Jon Rowe) +* Migrate `execution_result` (exposed by metadata) from a hash to a + first-class object with appropriate attributes. `status` is now + stored and returned as a symbol rather than a string. It retains + deprecated hash behavior for backwards compatibility. (Myron Marston) +* Provide console code helper for formatters. (Jon Rowe) +* Use raw ruby hashes for the metadata hashes rather than a subclass of + a hash. Computed metadata entries are now computed in advance rather + than being done lazily on first access. (Myron Marston) +* Add `:block` metadata entry to the example metadata, bringing + parity with `:block` in the example group metadata. (Myron Marston) +* Add `fspecify` and `fexample` as aliases of `specify` and `example` + with `:focus => true` metadata for parity with `fit`. (Myron Marston) +* Add legacy support for `colorize_summary`. (Jon Rowe) +* Restructure runner so it can be more easily customized in a subclass + for an alternate runner. (Ben Hoskings) +* Document `RSpec::Core::ConfigurationOptions` as an officially + supported public API. (Myron Marston) +* Add `--deprecation-out` CLI option which directs deprecation warnings + to the named file. (Myron Marston) +* Minitest 5 compatability for `expect_with :stdlib` (now available as + `expect_with :minitest`). (Xavier Shay) +* Reporter now notifies formatters of the load time of RSpec and your + specs via `StartNotification` and `SummaryNotification`. (Jon Rowe) +* Add `disable_monkey_patching!` config option that disables all monkey + patching from whatever pieces of RSpec you use. (Alexey Fedorov) +* Add `Pathname` support for setting all output streams. (Aaron Kromer) +* Add `config.define_derived_metadata`, which can be used to apply + additional metadata to all groups or examples that match a given + filter. (Myron Marston) +* Provide formatted and colorized backtraces via `FailedExampleNotification` + and send `PendingExampleFixedNotifications` when the error is due to a + passing spec you expect to fail. (Jon Rowe) +* Add `dump_profile` to formatter API to allow formatters to implement + support for `--profile`. (Jon Rowe) +* Allow colourising text via `ConsoleCodes` with RSpec 'states' + (e.g. `:success`, `:failure`) rather than direct colour codes. (Jon Rowe) +* Expose `fully_formatted` methods off the formatter notification objects + that make it easy for a custom formatter to produce formatted output + like rspec-core's. (Myron Marston) + +Bug Fixes: + +* Fix `spec_helper.rb` file generated by `rspec --init` so that the + recommended settings correctly use the documentation formatter + when running one file. (Myron Marston) +* Fix ordering problem where descriptions were generated after + tearing down mocks, which resulted in unexpected exceptions. + (Bradley Schaefer, Aaron Kromer, Andrey Savchenko) +* Allow a symbol to be used as an implicit subject (e.g. `describe + :foo`). (Myron Marston) +* Prevent creating an isolated context (i.e. using `RSpec.describe`) when + already inside a context. There is no reason to do this, and it could + potentially cause unexpected bugs. (Xavier Shay) +* Fix shared example group scoping so that when two shared example + groups share the same name at different levels of nested contexts, + the one in the nearest context is used. (Myron Marston) +* Fix `--warnings` option so that it enables warnings immediately so + that it applies to files loaded by `--require`. (Myron Marston) +* Issue a warning when you set `config.deprecation_stream` too late for + it to take effect because the reporter has already been setup. (Myron Marston) +* Add the full `RSpec::Core::Example` interface to the argument yielded + to `around` hooks. (Myron Marston) +* Line number always takes precendence when running specs with filters. + (Xavier Shay) +* Ensure :if and :unless metadata filters are treated as a special case + and are always in-effect. (Bradley Schaefer) +* Ensure the currently running installation of RSpec is used when + the rake task shells out to `rspec`, even if a newer version is also + installed. (Postmodern) +* Using a legacy formatter as default no longer causes an infinite loop. + (Xavier Shay) + +### 3.0.0.beta2 / 2014-02-17 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v3.0.0.beta1...v3.0.0.beta2) + +Breaking Changes for 3.0.0: + +* Make `mock_with` option more strict. Strings are no longer supported + (e.g. `mock_with "mocha"`) -- use a symbol instead. Also, unrecognized + values will now result in an error rather than falling back to the + null mocking adapter. If you want to use the null mocking adapter, + use `mock_with :nothing` (as has been documented for a long time). + (Myron Marston) +* Remove support for overriding RSpec's built-in `:if` and `:unless` + filters. (Ashish Dixit) +* Custom formatters are now required to call + `RSpec::Core::Formatters.register(formatter_class, *notifications)` + where `notifications` is the list of events the formatter wishes to + be notified about. Notifications are handled by methods matching the + names on formatters. This allows us to add or remove notifications + without breaking existing formatters. (Jon Rowe) +* Change arguments passed to formatters. Rather than passing multiple + arguments (which limits are ability to add additional arguments as + doing so would break existing formatters), we now pass a notification + value object that exposes the same data via attributes. This will + allow us to add new bits of data to a notification event without + breaking existing formatters. (Jon Rowe) +* Remove support for deprecated `:alias` option for + `RSpec.configuration.add_setting`. (Myron Marston) +* Remove support for deprecated `RSpec.configuration.requires = [...]`. + (Myron Marston) +* Remove support for deprecated `--formatter` CLI option. (Myron Marston) +* Remove support for deprecated `--configure` CLI option. (Myron Marston) +* Remove support for deprecated `RSpec::Core::RakeTask#spec_opts=`. + (Myron Marston) +* An example group level `pending` block or `:pending` metadata now executes + the example and cause a failure if it passes, otherwise it will be pending if + it fails. The old "never run" behaviour is still used for `xexample`, `xit`, + and `xspecify`, or via a new `skip` method or `:skip` metadata option. + (Xavier Shay) +* After calling `pending` inside an example, the remainder of the example will + now be run. If it passes a failure is raised, otherwise the example is marked + pending. The old "never run" behaviour is provided a by a new `skip` method. + (Xavier Shay) +* Pending blocks inside an example have been removed as a feature with no + direct replacement. Use `skip` or `pending` without a block. (Xavier Shay) +* Pending statement is no longer allowed in `before(:all)` hooks. Use `skip` + instead. (Xavier Shay) +* Remove `show_failures_in_pending_blocks` configuration option. (Xavier Shay) +* Remove support for specifying the documentation formatter using + 's', 'n', 'spec' or 'nested'. (Jon Rowe) + +Enhancements: + +* Add example run time to JSON formatter output. (Karthik Kastury) +* Add more suggested settings to the files generated by + `rspec --init`. (Myron Marston) +* Add `config.alias_example_group_to`, which can be used to define a + new method that defines an example group with the provided metadata. + (Michi Huber) +* Add `xdescribe` and `xcontext` as shortcuts to skip an example group. + (Myron Marston) +* Add `fdescribe` and `fcontext` as shortcuts to focus an example group. + (Myron Marston) +* Don't autorun specs via `#at_exit` by default. `require 'rspec/autorun'` + is only needed when running specs via `ruby`, as it always has been. + Running specs via `rake` or `rspec` are both unaffected. (Ben Hoskings) +* Add `expose_dsl_globally` config option, defaulting to true. When disabled + it will remove the monkey patches rspec-core adds to `main` and `Module` + (e.g. `describe`, `shared_examples_for`, etc). (Jon Rowe) +* Expose RSpec DSL entry point methods (`describe`, + `shared_examples_for`, etc) on the `RSpec` constant. Intended for use + when `expose_dsl_globally` is set to `false`. (Jon Rowe) +* For consistency, expose all example group aliases (including + `context`) on the `RSpec` constant. If `expose_dsl_globally` is set to + `true`, also expose them on `main` and `Module`. Historically, only `describe` + was exposed. (Jon Rowe, Michi Huber) +* Add hook scope `:example` as an alias for `:each`, and `:context` as an alias + for `:all`. (John Feminella) + +Bug Fixes: + +* Fix failure (undefined method `path`) in end-of-run summary + when `raise_errors_for_deprecations!` is configured. (Myron Marston) +* Issue error when attempting to use `-i` or `--I` on command line, + too close to `-I` to be considered short hand for `--init`. (Jon Rowe) +* Prevent adding formatters to an output target if the same + formatter has already been added to that output. (Alex Peattie) +* Allow a matcher-generated example description to be used when + the example is pending. (Myron Marston) +* Ensure the configured `failure_exit_code` is used by the rake + task when there is a failure. (Jon Rowe) +* Restore behaviour whereby system exclusion filters take priority over working + directory (was broken in beta1). (Jon Rowe) +* Prevent RSpec mangling file names that have substrings containing `line_number` + or `default_path`. (Matijs van Zuijlen) +* Fix failure line detection so that it handles relative file paths + (which can happen when running specs through `ruby` using `rspec/autorun`). + (Myron Marston, #1829) + +### 3.0.0.beta1 / 2013-11-07 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.99.1...v3.0.0.beta1) + +Breaking Changes for 3.0.0: + +* Remove explicit support for 1.8.6. (Jon Rowe) +* Remove `RSpec::Core::ExampleGroup#example` and + `RSpec::Core::ExampleGroup#running_example` methods. If you need + access to the example (e.g. to get its metadata), use a block arg + instead. (David Chelimsky) +* Remove `TextMateFormatter`, it has been moved to `rspec-tmbundle`. + (Aaron Kromer) +* Remove RCov integration. (Jon Rowe) +* Remove deprecated support for RSpec 1 constructs (Myron Marston): + * The `Spec` and `Rspec` constants (rather than `RSpec`). + * `Spec::Runner.configure` rather than `RSpec.configure`. + * `Rake::SpecTask` rather than `RSpec::Core::RakeTask`. +* Remove deprecated support for `share_as`. (Myron Marston) +* Remove `--debug` option (and corresponding option on + `RSpec::Core::Configuration`). Instead, use `-r` to + load whichever debugger gem you wish to use (e.g. `ruby-debug`, + `debugger`, or `pry`). (Myron Marston) +* Extract Autotest support to a seperate gem. (Jon Rowe) +* Raise an error when a `let` or `subject` declaration is + accessed in a `before(:all)` or `after(:all)` hook. (Myron Marston) +* Extract `its` support to a separate gem. (Peter Alfvin) +* Disallow use of a shared example group from sibling contexts, making them + fully isolated. 2.14 and 2.99 allowed this but printed a deprecation warning. + (Jon Rowe) +* Remove `RSpec::Core::Configuration#output` and + `RSpec::Core::Configuration#out` aliases of + `RSpec::Core::Configuration#output_stream`. (Myron Marston) +* Remove legacy ordering APIs deprecated in 2.99.0.beta1. (Myron + Marston) + +Enhancements: + +* Replace unmaintained syntax gem with coderay gem. (Xavier Shay) +* Times in profile output are now bold instead of `failure_color`. + (Matthew Boedicker) +* Add `--no-fail-fast` command line option. (Gonzalo Rodríguez-Baltanás Díaz) +* Runner now considers the local system ip address when running under Drb. + (Adrian CB) +* JsonFormatter now includes `--profile` information. (Alex / @MasterLambaster) +* Always treat symbols passed as metadata args as hash + keys with true values. RSpec 2 supported this with the + `treat_symbols_as_metadata_keys_with_true_values` but + now this behavior is always enabled. (Myron Marston) +* Add `--dry-run` option, which prints the formatter output + of your suite without running any examples or hooks. + (Thomas Stratmann, Myron Marston) +* Document the configuration options and default values in the `spec_helper.rb` + file that is generated by RSpec. (Parker Selbert) +* Give generated example group classes a friendly name derived + from the docstring, rather than something like "Nested_2". + (Myron Marston) +* Avoid affecting randomization of user code when shuffling + examples so that users can count on their own seeds + working. (Travis Herrick) +* Ordering is no longer a single global property of the test suite. + Each group can pick an ordering using `:order` metadata. (Andy + Lindeman, Sam Phippen, Myron Marston) +* Allow named custom ordering strategies to be registered, which can + then be used on individual example groups. (Andy Lindeman, Sam + Phippen, Myron Marston) + +Deprecations: + +* `treat_symbols_as_metadata_keys_with_true_values` is deprecated and no + longer has an affect now that the behavior it enabled is always + enabled. (Myron Marston) + +### 2.99.2 / 2014-08-19 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.99.1...v2.99.2) + +Enhancements: + +* Improve deprecation warning for RSpec 3 change in `describe ` + behavior. (Jon Rowe, #1667) + +### 2.99.1 / 2014-06-19 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.99.0...v2.99.1) + +Bug Fixes: + +* Add missing deprecation warning for when `RSpec::Core::Runner` is used + multiple times in the same process. In 2.x RSpec's global state was + automatically cleared between runs but in 3.0 you need to call `RSpec.reset` + manually in these situations. (Sam Phippen, #1587) +* Prevent deprecation being accidentally issues when doubles used with `be_` + matchers due to automatically generated descriptions. (Jon Rowe, #1573) +* Load `rspec/core` when loading `rspec/core/rake_task` to ensure we can + issue deprecations correctly. (Jon Rowe, #1612) + +### 2.99.0 / 2014-06-01 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.99.0.rc1...v2.99.0) + +Bug Fixes: + +* Fix `BaseTextFormatter` so that it does not re-close a closed output + stream. (Myron Marston) +* Use `RSpec::Configuration#backtrace_exclusion_patterns` rather than the + deprecated `RSpec::Configuration#backtrace_clean_patterns` when mocking + with rr. (David Dollar) + +### 2.99.0.rc1 / 2014-05-18 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.99.0.beta2...v2.99.0.rc1) + +Enhancements: + +* Add `--deprecation-out` CLI option which directs deprecation warnings + to the named file. (Myron Marston) +* Backport support for `skip` in metadata to skip execution of an example. + (Xavier Shay, #1472) +* Add `Pathname` support for setting all output streams. (Aaron Kromer) +* Add `test_unit` and `minitest` expectation frameworks. (Aaron Kromer) + +Deprecations: + +* Deprecate `RSpec::Core::Pending::PendingDeclaredInExample`, use + `SkipDeclaredInExample` instead. (Xavier Shay) +* Issue a deprecation when `described_class` is accessed from within + a nested `describe ` example group, since `described_class` + will return the innermost described class in RSpec 3 rather than the + outermost described class, as it behaved in RSpec 2. (Myron Marston) +* Deprecate `RSpec::Core::FilterManager::DEFAULT_EXCLUSIONS`, + `RSpec::Core::FilterManager::STANDALONE_FILTERS` and use of + `#empty_without_conditional_filters?` on those filters. (Sergey Pchelincev) +* Deprecate `RSpec::Core::Example#options` in favor of + `RSpec::Core::Example#metadata`. (Myron Marston) +* Issue warning when passing a symbol or hash to `describe` or `context` + as the first argument. In RSpec 2.x this would be treated as metadata + but in RSpec 3 it'll be treated as the described object. To continue + having it treated as metadata, pass a description before the symbol or + hash. (Myron Marston) +* Deprecate `RSpec::Core::BaseTextFormatter::VT100_COLORS` and + `RSpec::Core::BaseTextFormatter::VT100_COLOR_CODES` in favour + of `RSpec::Core::BaseTextFormatter::ConsoleCodes::VT100_CODES` and + `RSpec::Core::BaseTextFormatter::ConsoleCodes::VT100_CODE_VALUES`. + (Jon Rowe) +* Deprecate `RSpec::Core::ExampleGroup.display_name` in favor of + `RSpec::Core::ExampleGroup.description`. (Myron Marston) +* Deprecate `RSpec::Core::ExampleGroup.describes` in favor of + `RSpec::Core::ExampleGroup.described_class`. (Myron Marston) +* Deprecate `RSpec::Core::ExampleGroup.alias_example_to` in favor of + `RSpec::Core::Configuration#alias_example_to`. (Myron Marston) +* Deprecate `RSpec::Core::ExampleGroup.alias_it_behaves_like_to` in favor + of `RSpec::Core::Configuration#alias_it_behaves_like_to`. (Myron Marston) +* Deprecate `RSpec::Core::ExampleGroup.focused` in favor of + `RSpec::Core::ExampleGroup.focus`. (Myron Marston) +* Add deprecation warning for `config.filter_run :focused` since + example aliases `fit` and `focus` will no longer include + `:focused` metadata but will continue to include `:focus`. (Myron Marston) +* Deprecate filtering by `:line_number` (e.g. `--line-number` from the + CLI). Use location filtering instead. (Myron Marston) +* Deprecate `--default_path` as an alternative to `--default-path`. (Jon Rowe) +* Deprecate `RSpec::Core::Configuration#warnings` in favor of + `RSpec::Core::Configuration#warnings?`. (Myron Marston) +* Deprecate `share_examples_for` in favor of `shared_examples_for` or + just `shared_examples`. (Myron Marston) +* Deprecate `RSpec::Core::CommandLine` in favor of + `RSpec::Core::Runner`. (Myron Marston) +* Deprecate `#color_enabled`, `#color_enabled=` and `#color?` in favour of + `#color`, `#color=` and `#color_enabled? output`. (Jon Rowe) +* Deprecate `#filename_pattern` in favour of `#pattern`. (Jon Rowe) +* Deprecate `#backtrace_cleaner` in favour of `#backtrace_formatter`. (Jon Rowe) +* Deprecate mutating `RSpec::Configuration#formatters`. (Jon Rowe) +* Deprecate `stdlib` as an available expectation framework in favour of + `test_unit` and `minitest`. (Aaron Kromer) + +Bug Fixes: + +* Issue a warning when you set `config.deprecation_stream` too late for + it to take effect because the reporter has already been setup. (Myron Marston) +* `skip` with a block should not execute the block. (Xavier Shay) + +### 2.99.0.beta2 / 2014-02-17 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.99.0.beta1...v2.99.0.beta2) + +Enhancements: + +* Add `is_expected` for one-liners that read well with the + `expect`-based syntax. `is_expected` is simply defined as + `expect(subject)` and can be used in an expression like: + `it { is_expected.to read_well }`. (Myron Marston) +* Backport `skip` from RSpec 3, which acts like `pending` did in RSpec 2 + when not given a block, since the behavior of `pending` is changing in + RSpec 3. (Xavier Shay) + +Deprecations: + +* Deprecate inexact `mock_with` config options. RSpec 3 will only support + the exact symbols `:rspec`, `:mocha`, `:flexmock`, `:rr` or `:nothing` + (or any module that implements the adapter interface). RSpec 2 did + fuzzy matching but this will not be supported going forward. + (Myron Marston) +* Deprecate `show_failures_in_pending_blocks` config option. To achieve + the same behavior as the option enabled, you can use a custom + formatter instead. (Xavier Shay) +* Add a deprecation warning for the fact that the behavior of `pending` + is changing in RSpec 3 -- rather than skipping the example (as it did + in 2.x when no block was provided), it will run the example and mark + it as failed if no exception is raised. Use `skip` instead to preserve + the old behavior. (Xavier Shay) +* Deprecate 's', 'n', 'spec' and 'nested' as aliases for documentation + formatter. (Jon Rowe) +* Deprecate `RSpec::Core::Reporter#abort` in favor of + `RSpec::Core::Reporter#finish`. (Jon Rowe) + +Bug Fixes: + +* Fix failure (undefined method `path`) in end-of-run summary + when `raise_errors_for_deprecations!` is configured. (Myron Marston) +* Fix issue were overridding spec ordering from the command line wasn't + fully recognised interally. (Jon Rowe) + +### 2.99.0.beta1 / 2013-11-07 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.14.7...v2.99.0.beta1) + +Enhancements + +* Block-based DSL methods that run in the context of an example + (`it`, `before(:each)`, `after(:each)`, `let` and `subject`) + now yield the example as a block argument. (David Chelimsky) +* Warn when the name of more than one example group is submitted to + `include_examples` and it's aliases. (David Chelimsky) +* Add `expose_current_running_example_as` config option for + use during the upgrade process when external gems use the + deprecated `RSpec::Core::ExampleGroup#example` and + `RSpec::Core::ExampleGroup#running_example` methods. (Myron Marston) +* Limit spamminess of deprecation messages. (Bradley Schaefer, Loren Segal) +* Add `config.raise_errors_for_deprecations!` option, which turns + deprecations warnings into errors to surface the full backtrace + of the call site. (Myron Marston) + +Deprecations + +* Deprecate `RSpec::Core::ExampleGroup#example` and + `RSpec::Core::ExampleGroup#running_example` methods. If you need + access to the example (e.g. to get its metadata), use a block argument + instead. (David Chelimsky) +* Deprecate use of `autotest/rspec2` in favour of `rspec-autotest`. (Jon Rowe) +* Deprecate RSpec's built-in debugger support. Use a CLI option like + `-rruby-debug` (for the ruby-debug gem) or `-rdebugger` (for the + debugger gem) instead. (Myron Marston) +* Deprecate `RSpec.configuration.treat_symbols_as_metadata_keys_with_true_values = false`. + RSpec 3 will not support having this option set to `false`. (Myron Marston) +* Deprecate accessing a `let` or `subject` declaration in + a `after(:all)` hook. (Myron Marston, Jon Rowe) +* Deprecate built-in `its` usage in favor of `rspec-its` gem due to planned + removal in RSpec 3. (Peter Alfvin) +* Deprecate `RSpec::Core::PendingExampleFixedError` in favor of + `RSpec::Core::Pending::PendingExampleFixedError`. (Myron Marston) +* Deprecate `RSpec::Core::Configuration#out` and + `RSpec::Core::Configuration#output` in favor of + `RSpec::Core::Configuration#output_stream`. (Myron Marston) +* Deprecate legacy ordering APIs. + * You should use `register_ordering(:global)` instead of these: + * `RSpec::Core::Configuration#order_examples` + * `RSpec::Core::Configuration#order_groups` + * `RSpec::Core::Configuration#order_groups_and_examples` + * These are deprecated with no replacement because in RSpec 3 + ordering is a property of individual example groups rather than + just a global property of the entire test suite: + * `RSpec::Core::Configuration#order` + * `RSpec::Core::Configuration#randomize?` + * `--order default` is deprecated in favor of `--order defined` + (Myron Marston) + +### 2.14.8 / 2014-02-27 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.14.7...v2.14.8) + +Bug fixes: + +* Fix regression with the `textmateformatter` that prevented backtrace links + from being clickable. (Stefan Daschek) + +### 2.14.7 / 2013-10-29 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.14.6...v2.14.7) + +Bug fixes: + +* Fix regression in 2.14.6 that broke the Fivemat formatter. + It depended upon either + `example.execution_result[:exception].pending_fixed?` (which + was removed in 2.14.6 to fix an issue with frozen error objects) + or `RSpec::Core::PendingExampleFixedError` (which was renamed + to `RSpec::Core::Pending::PendingExampleFixedError` in 2.8. + This fix makes a constant alias for the old error name. + (Myron Marston) + +### 2.14.6 / 2013-10-15 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.14.5...v2.14.6) + +Bug fixes: + +* Format stringified numbers correctly when mathn library is loaded. + (Jay Hayes) +* Fix an issue that prevented the use of frozen error objects. (Lars + Gierth) + +### 2.14.5 / 2013-08-13 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.14.4...v2.14.5) + +Bug fixes: + +* Fix a `NoMethodError` that was being raised when there were no shared + examples or contexts declared and `RSpec.world.reset` is invoked. + (thepoho, Jon Rowe, Myron Marston) +* Fix a deprecation warning that was being incorrectly displayed when + `shared_examples` are declared at top level in a `module` scope. + (Jon Rowe) +* Fix after(:all) hooks so consecutive (same context) scopes will run even if + one raises an error. (Jon Rowe, Trejkaz) +* JsonFormatter no longer dies if `dump_profile` isn't defined (Alex / @MasterLambaster, Jon Rowe) + +### 2.14.4 / 2013-07-21 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.14.3...v2.14.4) + +Bug fixes + +* Fix regression in 2.14: ensure configured requires (via `-r` option) + are loaded before spec files are loaded. This allows the spec files + to programatically change the file pattern (Jon Rowe). +* Autoload `RSpec::Mocks` and `RSpec::Expectations` when referenced if + they are not already loaded (`RSpec::Matches` has been autoloaded + for a while). In the `rspec` gem, we changed it recently to stop + loading `rspec/mocks` and `rspec/expectations` by default, as some + users reported problems where they were intending to use mocha, + not rspec-mocks, but rspec-mocks was loaded and causing a conflict. + rspec-core loads mocks and expectations at the appropriate time, so + it seemed like a safe change -- but caused a problem for some authors + of libraries that integrate with RSpec. This fixes that problem. + (Myron Marston) +* Gracefully handle a command like `rspec --profile path/to/spec.rb`: + the `path/to/spec.rb` arg was being wrongly treated as the `profile` + integer arg, which got cast `0` using `to_i`, causing no profiled + examples to be printed. (Jon Rowe) + +### 2.14.3 / 2013-07-13 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.14.2...v2.14.3) + +Bug fixes + +* Fix deprecation notices issued from `RSpec::Core::RakeTask` so + that they work properly when all of rspec-core is not loaded. + (This was a regression in 2.14) (Jon Rowe) + +### 2.14.2 / 2013-07-09 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.14.1...v2.14.2) + +Bug fixes + +* Fix regression caused by 2.14.1 release: formatters that + report that they `respond_to?` a notification, but had + no corresponding method would raise an error when registered. + The new fix is to just implement `start` on the deprecation + formatter to fix the original JRuby/ruby-debug issue. + (Jon Rowe) + +### 2.14.1 / 2013-07-08 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.14.0...v2.14.1) + +Bug fixes + +* Address deprecation formatter failure when using `ruby-debug` on + JRuby: fix `RSpec::Core::Reporter` to not send a notification + when the formatter's implementation of the notification method + comes from `Kernel` (Alex Portnov, Jon Rowe). + +### 2.14.0 / 2013-07-06 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.14.0.rc1...v2.14.0) + +Enhancements + +* Apply focus to examples defined with `fit` (equivalent of + `it "description", focus: true`) (Michael de Silva) + +Bug fix + +* Ensure methods defined by `let` take precedence over others + when there is a name collision (e.g. from an included module). + (Jon Rowe, Andy Lindeman and Myron Marston) + +### 2.14.0.rc1 / 2013-05-27 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.13.1...v2.14.0.rc1) + +Enhancements + +* Improved Windows detection inside Git Bash, for better `--color` handling. +* Add profiling of the slowest example groups to `--profile` option. + The output is sorted by the slowest average example groups. +* Don't show slow examples if there's a failure and both `--fail-fast` + and `--profile` options are used (Paweł Gościcki). +* Rather than always adding `spec` to the load path, add the configured + `--default-path` to the load path (which defaults to `spec`). This + better supports folks who choose to put their specs in a different + directory (John Feminella). +* Add some logic to test time duration precision. Make it a + function of time, dropping precision as the time increases. (Aaron Kromer) +* Add new `backtrace_inclusion_patterns` config option. Backtrace lines + that match one of these patterns will _always_ be included in the + backtrace, even if they match an exclusion pattern, too (Sam Phippen). +* Support ERB trim mode using the `-` when parsing `.rspec` as ERB + (Gabor Garami). +* Give a better error message when let and subject are called without a block. + (Sam Phippen). +* List the precedence of `.rspec-local` in the configuration documentation + (Sam Phippen) +* Support `{a,b}` shell expansion syntax in `--pattern` option + (Konstantin Haase). +* Add cucumber documentation for --require command line option + (Bradley Schaefer) +* Expose configuration options via config: + * `config.libs` returns the libs configured to be added onto the load path + * `full_backtrace?` returns the state of the backtrace cleaner + * `debug?` returns true when the debugger is loaded + * `line_numbers` returns the line numbers we are filtering by (if any) + * `full_description` returns the RegExp used to filter descriptions + (Jon Rowe) +* Add setters for RSpec.world and RSpec.configuration (Alex Soulim) +* Configure ruby's warning behaviour with `--warnings` (Jon Rowe) +* Fix an obscure issue on old versions of `1.8.7` where `Time.dup` wouldn't + allow access to `Time.now` (Jon Rowe) +* Make `shared_examples_for` context aware, so that keys may be safely reused + in multiple contexts without colliding. (Jon Rowe) +* Add a configurable `deprecation_stream` (Jon Rowe) +* Publish deprecations through a formatter (David Chelimsky) + +Bug fixes + +* Make JSON formatter behave the same when it comes to `--profile` as + the text formatter (Paweł Gościcki). +* Fix named subjects so that if an inner group defines a method that + overrides the named method, `subject` still retains the originally + declared value (Myron Marston). +* Fix random ordering so that it does not cause `rand` in examples in + nested sibling contexts to return the same value (Max Shytikov). +* Use the new `backtrace_inclusion_patterns` config option to ensure + that folks who develop code in a directory matching one of the default + exclusion patterns (e.g. `gems`) still get the normal backtrace + filtering (Sam Phippen). +* Fix ordering of `before` hooks so that `before` hooks declared in + `RSpec.configure` run before `before` hooks declared in a shared + context (Michi Huber and Tejas Dinkar). +* Fix `Example#full_description` so that it gets filled in by the last + matcher description (as `Example#description` already did) when no + doc string has been provided (David Chelimsky). +* Fix the memoized methods (`let` and `subject`) leaking `define_method` + as a `public` method. (Thomas Holmes and Jon Rowe) (#873) +* Fix warnings coming from the test suite. (Pete Higgins) + +Deprecations + +* Deprecate `Configuration#backtrace_clean_patterns` in favor of + `Configuration#backtrace_exclusion_patterns` for greater consistency + and symmetry with new `backtrace_inclusion_patterns` config option + (Sam Phippen). +* Deprecate `Configuration#requires=` in favor of using ruby's + `require`. Requires specified by the command line can still be + accessed by the `Configuration#require` reader. (Bradley Schaefer) +* Deprecate calling `SharedExampleGroups` defined across sibling contexts + (Jon Rowe) + +### 2.13.1 / 2013-03-12 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.13.0...v2.13.1) + +Bug fixes + +* Use hook classes as proxies rather than extending hook blocks to support + lambdas for before/after/around hooks. (David Chelimsky) +* Fix regression in 2.13.0 that caused confusing behavior when overriding + a named subject with an unnamed subject in an inner group and then + referencing the outer group subject's name. The fix for this required + us to disallow using `super` in a named subject (which is confusing, + anyway -- named subjects create 2 methods, so which method on the + parent example group are you `super`ing to?) but `super` in an unnamed + subject continues to work (Myron Marston). +* Do not allow a referenced `let` or `subject` in `before(:all)` to cause + other `let` declarations to leak across examples (Myron Marston). +* Work around odd ruby 1.9 bug with `String#match` that was triggered + by passing it a regex from a `let` declaration. For more info, see + http://bugs.ruby-lang.org/issues/8059 (Aaron Kromer). +* Add missing `require 'set'` to `base_text_formatter.rb` (Tom + Anderson). + +Deprecations + +* Deprecate accessing `let` or `subject` declarations in `before(:all)`. + These were not intended to be called in a `before(:all)` hook, as + they exist to define state that is reset between each example, while + `before(:all)` exists to define state that is shared across examples + in an example group (Myron Marston). + +### 2.13.0 / 2013-02-23 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.12.2...v2.13.0) + +Enhancements + +* Allow `--profile` option to take a count argument that + determines the number of slow examples to dump + (Greggory Rothmeier). +* Add `subject!` that is the analog to `let!`. It defines an + explicit subject and sets a `before` hook that will invoke + the subject (Zubin Henner). +* Fix `let` and `subject` declaration so that `super` + and `return` can be used in them, just like in a normal + method. (Myron Marston) +* Allow output colors to be configured individually. + (Charlie Maffitt) +* Always dump slow examples when `--profile` option is given, + even when an example failed (Myron Marston). + +Bug fixes + +* Don't blow up when dumping error output for instances + of anonymous error classes (Myron Marston). +* Fix default backtrace filters so lines from projects + containing "gems" in the name are not filtered, but + lines from installed gems still are (Myron Marston). +* Fix autotest command so that is uses double quotes + rather than single quotes for windows compatibility + (Jonas Tingeborn). +* Fix `its` so that uses of `subject` in a `before` or `let` + declaration in the parent group continue to reference the + parent group's subject. (Olek Janiszewski) + +### 2.12.2 / 2012-12-13 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.12.1...v2.12.2) + +Bug fixes + +* Fix `RSpec::Core::RakeTask` so that it is compatible with rake 0.8.7 + on ruby 1.8.7. We had accidentally broke it in the 2.12 release + (Myron Marston). +* Fix `RSpec::Core::RakeTask` so it is tolerant of the `Rspec` constant + for backwards compatibility (Patrick Van Stee) + +### 2.12.1 / 2012-12-01 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.12.0...v2.12.1) + +Bug fixes + +* Specs are run even if another at\_exit hook calls `exit`. This allows + Test::Unit and RSpec to run together. (Suraj N. Kurapati) +* Fix full doc string concatenation so that it handles the case of a + method string (e.g. "#foo") being nested under a context string + (e.g. "when it is tuesday"), so that we get "when it is tuesday #foo" + rather than "when it is tuesday#foo". (Myron Marston) +* Restore public API I unintentionally broke in 2.12.0: + `RSpec::Core::Formatters::BaseFormatter#format_backtrce(backtrace, example)` + (Myron Marston). + +### 2.12.0 / 2012-11-12 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.11.1...v2.12.0) + +Enhancements + +* Add support for custom ordering strategies for groups and examples. + (Myron Marston) +* JSON Formatter (Alex Chaffee) +* Refactor rake task internals (Sam Phippen) +* Refactor HtmlFormatter (Pete Hodgson) +* Autotest supports a path to Ruby that contains spaces (dsisnero) +* Provide a helpful warning when a shared example group is redefined. + (Mark Burns). +* `--default_path` can be specified as `--default-line`. `--line_number` can be + specified as `--line-number`. Hyphens are more idiomatic command line argument + separators (Sam Phippen). +* A more useful error message is shown when an invalid command line option is + used (Jordi Polo). +* Add `format_docstrings { |str| }` config option. It can be used to + apply formatting rules to example group and example docstrings. + (Alex Tan) +* Add support for an `.rspec-local` options file. This is intended to + allow individual developers to set options in a git-ignored file that + override the common project options in `.rspec`. (Sam Phippen) +* Support for mocha 0.13.0. (Andy Lindeman) + +Bug fixes + +* Remove override of `ExampleGroup#ancestors`. This is a core ruby method that + RSpec shouldn't override. Instead, define `ExampleGroup#parent_groups`. (Myron + Marston) +* Limit monkey patching of shared example/context declaration methods + (`shared_examples_for`, etc.) to just the objects that need it rather than + every object in the system (Myron Marston). +* Fix Metadata#fetch to support computed values (Sam Goldman). +* Named subject can now be referred to from within subject block in a nested + group (tomykaira). +* Fix `fail_fast` so that it properly exits when an error occurs in a + `before(:all) hook` (Bradley Schaefer). +* Make the order spec files are loaded consistent, regardless of the + order of the files returned by the OS or the order passed at + the command line (Jo Liss and Sam Phippen). +* Ensure instance variables from `before(:all)` are always exposed + from `after(:all)`, even if an error occurs in `before(:all)` + (Sam Phippen). +* `rspec --init` no longer generates an incorrect warning about `--configure` + being deprecated (Sam Phippen). +* Fix pluralization of `1 seconds` (Odin Dutton) +* Fix ANSICON url (Jarmo Pertman) +* Use dup of Time so reporting isn't clobbered by examples that modify Time + without properly restoring it. (David Chelimsky) + +Deprecations + +* `share_as` is no longer needed. `shared_context` and/or + `RSpec::SharedContext` provide better mechanisms (Sam Phippen). +* Deprecate `RSpec.configuration` with a block (use `RSpec.configure`). + + +### 2.11.1 / 2012-07-18 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.11.0...v2.11.1) + +Bug fixes + +* Fix the way we autoload RSpec::Matchers so that custom matchers can be + defined before rspec-core has been configured to definitely use + rspec-expectations. (Myron Marston) +* Fix typo in --help message printed for -e option. (Jo Liss) +* Fix ruby warnings. (Myron Marston) +* Ignore mock expectation failures when the example has already failed. + Mock expectation failures have always been ignored in this situation, + but due to my changes in 27059bf1 it was printing a confusing message. + (Myron Marston). + +### 2.11.0 / 2012-07-07 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.10.1...v2.11.0) + +Enhancements + +* Support multiple `--example` options. (Daniel Doubrovkine @dblock) +* Named subject e.g. `subject(:article) { Article.new }` + * see [http://blog.davidchelimsky.net/2012/05/13/spec-smell-explicit-use-of-subject/](http://blog.davidchelimsky.net/2012/05/13/spec-smell-explicit-use-of-subject/) + for background. + * thanks to Bradley Schaefer for suggesting it and Avdi Grimm for almost + suggesting it. +* `config.mock_with` and `config.expect_with` yield custom config object to a + block if given + * aids decoupling from rspec-core's configuation +* `include_context` and `include_examples` support a block, which gets eval'd + in the current context (vs the nested context generated by `it_behaves_like`). +* Add `config.order = 'random'` to the `spec_helper.rb` generated by `rspec + --init`. +* Delay the loading of DRb (Myron Marston). +* Limit monkey patching of `describe` onto just the objects that need it rather + than every object in the system (Myron Marston). + +Bug fixes + +* Support alternative path separators. For example, on Windows, you can now do + this: `rspec spec\subdir`. (Jarmo Pertman @jarmo) +* When an example raises an error and an after or around hook does as + well, print out the hook error. Previously, the error was silenced and + the user got no feedback about what happened. (Myron Marston) +* `--require` and `-I` are merged among different configuration sources (Andy + Lindeman) +* Delegate to mocha methods instead of aliasing them in mocha adapter. + +### 2.10.1 / 2012-05-19 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.10.0...v2.10.1) + +Bug fixes + +* `RSpec.reset` properly reinits configuration and world +* Call `to_s` before `split` on exception messages that might not always be + Strings (slyphon) + +### 2.10.0 / 2012-05-03 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.9.0...v2.10.0) + +Enhancements + +* Add `prepend_before` and `append_after` hooks (preethiramdev) + * intended for extension libs + * restores rspec-1 behavior +* Reporting of profiled examples (moro) + * Report the total amount of time taken for the top slowest examples. + * Report what percentage the slowest examples took from the total runtime. + +Bug fixes + +* Properly parse `SPEC_OPTS` options. +* `example.description` returns the location of the example if there is no + explicit description or matcher-generated description. +* RDoc fixes (Grzegorz Świrski) +* Do not modify example ancestry when dumping errors (Michael Grosser) + +### 2.9.0 / 2012-03-17 +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.8.0...v2.9.0) + +Enhancements + +* Support for "X minutes X seconds" spec run duration in formatter. (uzzz) +* Strip whitespace from group and example names in doc formatter. +* Removed spork-0.9 shim. If you're using spork-0.8.x, you'll need to upgrade + to 0.9.0. + +Bug fixes + +* Restore `--full_backtrace` option +* Ensure that values passed to `config.filter_run` are respected when running + over DRb (using spork). +* Ensure shared example groups are reset after a run (as example groups are). +* Remove `rescue false` from calls to filters represented as Procs +* Ensure `described_class` gets the closest constant (pyromaniac) +* In "autorun", don't run the specs in the `at_exit` hook if there was an + exception (most likely due to a SyntaxError). (sunaku) +* Don't extend groups with modules already used to extend ancestor groups. +* `its` correctly memoizes nil or false values (Yamada Masaki) + +### 2.8.0 / 2012-01-04 + +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.8.0.rc2...v2.8.0) + +Bug fixes + +* For metadata filtering, restore passing the entire array to the proc, rather + than each item in the array (weidenfreak) +* Ensure each spec file is loaded only once + * Fixes a bug that caused all the examples in a file to be run when + referenced twice with line numbers in a command, e.g. + * `rspec path/to/file:37 path/to/file:42` + +### 2.8.0.rc2 / 2011-12-19 + +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.8.0.rc1...v2.8.0.rc2) + +Enhancments + +* new `--init` command (Peter Schröder) + * generates `spec/spec_helper.rb` + * deletes obsolete files (on confirmation) + * merged with and deprecates `--configure` command, which generated + `.rspec` +* use `require_relative` when available (Ian Leitch) +* `include_context` and `include_examples` accept params (Calvin Bascom) +* print the time for every example in the html formatter (Richie Vos) +* several tasty refactoring niblets (Sasha) +* `it "does something", :x => [:foo,'bar',/baz/] (Ivan Neverov) + * supports matching n command line tag values with an example or group + +### 2.8.0.rc1 / 2011-11-06 + +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.7.1...v2.8.0.rc1) + +Enhancements + +* `--order` (Justin Ko) + * run examples in random order: `--order rand` + * specify the seed: `--order rand:123` +* `--seed SEED` + * equivalent of `--order rand:SEED` +* SharedContext supports `let` (David Chelimsky) +* Filter improvements (David Chelimsky) + * override opposing tags from the command line + * override RSpec.configure tags from the command line + * `--line_number 37` overrides all other filters + * `path/to/file.rb:37` overrides all other filters + * refactor: consolidate filter management in a FilterManger object +* Eliminate Ruby warnings (Matijs van Zuijlen) +* Make reporter.report an API (David Chelimsky) + * supports extension tools like interative_rspec + +Changes + +* change `config.color_enabled` (getter/setter/predicate) to `color` to align + with `--[no]-color` CLI option. + * `color_enabled` is still supported for now, but will likley be deprecated + in a 2.x release so we can remove it in 3.0. + +Bug fixes + +* Make sure the `bar` in `--tag foo:bar` makes it to DRb (Aaron Gibralter) +* Fix bug where full descriptions of groups nested 3 deep were repeated. +* Restore report of time to run to start after files are loaded. + * fixes bug where run times were cumalitive in spork + * fixes compatibility with time-series metrics +* Don't error out when `config.mock_with` or `expect_with` is re-specifying the + current config (Myron Marston) + +* Deprecations + * :alias option on `configuration.add_setting`. Use `:alias_with` on the + original setting declaration instead. + +### 2.7.1 / 2011-10-20 + +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.7.0...v2.7.1) + +Bug fixes + +* tell autotest the correct place to find the rspec executable + +### 2.7.0 / 2011-10-16 + +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.6.4...v2.7.0) + +NOTE: RSpec's release policy dictates that there should not be any backward +incompatible changes in minor releases, but we're making an exception to +release a change to how RSpec interacts with other command line tools. + +As of 2.7.0, you must explicity `require "rspec/autorun"` unless you use the +`rspec` command (which already does this for you). + +Enhancements + +* Add `example.exception` (David Chelimsky) +* `--default_path` command line option (Justin Ko) +* support multiple `--line_number` options (David J. Hamilton) + * also supports `path/to/file.rb:5:9` (runs examples on lines 5 and 9) +* Allow classes/modules to be used as shared example group identifiers (Arthur + Gunn) +* Friendly error message when shared context cannot be found (Sławosz + Sławiński) +* Clear formatters when resetting config (John Bintz) +* Add `xspecify` and xexample as temp-pending methods (David Chelimsky) +* Add `--no-drb` option (Iain Hecker) +* Provide more accurate run time by registering start time before code is + loaded (David Chelimsky) + * reverted in 2.8.0 +* Rake task default pattern finds specs in symlinked dirs (Kelly Felkins) +* Rake task no longer does anything to invoke bundler since Bundler already + handles it for us. Thanks to Andre Arko for the tip. +* Add `--failure-exit-code` option (Chris Griego) + +Bug fixes + +* Include `Rake::DSL` to remove deprecation warnings in Rake > 0.8.7 (Pivotal + Casebook) +* Only eval `let` block once even if it returns `nil` (Adam Meehan) +* Fix `--pattern` option (wasn't being recognized) (David Chelimsky) +* Only implicitly `require "rspec/autorun"` with the `rspec` command (David + Chelimsky) +* Ensure that rspec's `at_exit` defines the exit code (Daniel Doubrovkine) +* Show the correct snippet in the HTML and TextMate formatters (Brian Faherty) + +### 2.6.4 / 2011-06-06 + +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.6.3...v2.6.4) + +NOTE: RSpec's release policy dictates that there should not be new +functionality in patch releases, but this minor enhancement slipped in by +accident. As it doesn't add a new API, we decided to leave it in rather than +roll back this release. + +Enhancements + +* Add summary of commands to run individual failed examples. + +Bug fixes + +* Support exclusion filters in DRb. (Yann Lugrin) +* Fix --example escaping when run over DRb. (Elliot Winkler) +* Use standard ANSI codes for color formatting so colors work in a wider set of + color schemes. + +### 2.6.3 / 2011-05-24 + +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.6.2...v2.6.3) + +Bug fixes + +* Explicitly convert exit code to integer, avoiding TypeError when return + value of run is IO object proxied by `DRb::DRbObject` (Julian Scheid) +* Clarify behavior of `--example` command line option +* Build using a rubygems-1.6.2 to avoid downstream yaml parsing error + +### 2.6.2 / 2011-05-21 + +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.6.1...v2.6.2) + +Bug fixes + +* Warn rather than raise when HOME env var is not defined +* Properly merge command-line exclusions with default :if and :unless (joshcooper) + +### 2.6.1 / 2011-05-19 + +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.6.0...v2.6.1) + +Bug fixes + +* Don't extend nil when filters are nil +* `require 'rspec/autorun'` when running rcov. + +### 2.6.0 / 2011-05-12 + +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.5.1...v2.6.0) + +Enhancements + +* `shared_context` (Damian Nurzynski) + * extend groups matching specific metadata with: + * method definitions + * subject declarations + * let/let! declarations + * etc (anything you can do in a group) +* `its([:key])` works for any subject with #[]. (Peter Jaros) +* `treat_symbols_as_metadata_keys_with_true_values` (Myron Marston) +* Print a deprecation warning when you configure RSpec after defining an + example. All configuration should happen before any examples are defined. + (Myron Marston) +* Pass the exit status of a DRb run to the invoking process. This causes specs + run via DRb to not just return true or false. (Ilkka Laukkanen) +* Refactoring of `ConfigurationOptions#parse_options` (Rodrigo Rosenfeld Rosas) +* Report excluded filters in runner output (tip from andyl) +* Clean up messages for filters/tags. +* Restore --pattern/-P command line option from rspec-1 +* Support false as well as true in config.full_backtrace= (Andreas Tolf + Tolfsen) + +Bug fixes + +* Don't stumble over an exception without a message (Hans Hasselberg) +* Remove non-ascii characters from comments that were choking rcov (Geoffrey + Byers) +* Fixed backtrace so it doesn't include lines from before the autorun at_exit + hook (Myron Marston) +* Include RSpec::Matchers when first example group is defined, rather than just + before running the examples. This works around an obscure bug in ruby 1.9 + that can cause infinite recursion. (Myron Marston) +* Don't send `example_group_[started|finished]` to formatters for empty groups. +* Get specs passing on jruby (Sidu Ponnappa) +* Fix bug where mixing nested groups and outer-level examples gave + unpredictable :line_number behavior (Artur Małecki) +* Regexp.escape the argument to --example (tip from Elliot Winkler) +* Correctly pass/fail pending block with message expectations +* CommandLine returns exit status (0/1) instead of true/false +* Create path to formatter output file if it doesn't exist (marekj). + + +### 2.5.1 / 2011-02-06 + +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.5.0...v2.5.1) + +NOTE: this release breaks compatibility with rspec/autotest/bundler +integration, but does so in order to greatly simplify it. + +With this release, if you want the generated autotest command to include +'bundle exec', require Autotest's bundler plugin in a .autotest file in the +project's root directory or in your home directory: + + require "autotest/bundler" + +Now you can just type 'autotest' on the commmand line and it will work as you expect. + +If you don't want 'bundle exec', there is nothing you have to do. + +### 2.5.0 / 2011-02-05 + +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.4.0...v2.5.0) + +Enhancements + +* Autotest::Rspec2 parses command line args passed to autotest after '--' +* --skip-bundler option for autotest command +* Autotest regexp fixes (Jon Rowe) +* Add filters to html and textmate formatters (Daniel Quimper) +* Explicit passing of block (need for JRuby 1.6) (John Firebaugh) + +Bug fixes + +* fix dom IDs in HTML formatter (Brian Faherty) +* fix bug with --drb + formatters when not running in drb +* include --tag options in drb args (monocle) +* fix regression so now SPEC_OPTS take precedence over CLI options again (Roman + Chernyatchik) +* only call its(:attribute) once (failing example from Brian Dunn) +* fix bizarre bug where rspec would hang after String.alias :to_int :to_i + (Damian Nurzynski) + +Deprecations + +* implicit inclusion of 'bundle exec' when Gemfile present (use autotest's + bundler plugin instead) + +### 2.4.0 / 2011-01-02 + +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.3.1...v2.4.0) + +Enhancements + +* start the debugger on -d so the stack trace is visible when it stops + (Clifford Heath) +* apply hook filtering to examples as well as groups (Myron Marston) +* support multiple formatters, each with their own output +* show exception classes in failure messages unless they come from RSpec + matchers or message expectations +* before(:all) { pending } sets all examples to pending + +Bug fixes + +* fix bug due to change in behavior of reject in Ruby 1.9.3-dev (Shota + Fukumori) +* fix bug when running in jruby: be explicit about passing block to super (John + Firebaugh) +* rake task doesn't choke on paths with quotes (Janmejay Singh) +* restore --options option from rspec-1 +* require 'ostruct' to fix bug with its([key]) (Kim Burgestrand) +* --configure option generates .rspec file instead of autotest/discover.rb + +### 2.3.1 / 2010-12-16 + +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.3.0...v2.3.1) + +Bug fixes + +* send debugger warning message to $stdout if RSpec.configuration.error_stream + has not been defined yet. +* HTML Formatter _finally_ properly displays nested groups (Jarmo Pertman) +* eliminate some warnings when running RSpec's own suite (Jarmo Pertman) + +### 2.3.0 / 2010-12-12 + +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.2.1...v2.3.0) + +Enhancements + +* tell autotest to use "rspec2" if it sees a .rspec file in the project's root + directory + * replaces the need for ./autotest/discover.rb, which will not work with + all versions of ZenTest and/or autotest +* config.expect_with + * :rspec # => rspec/expectations + * :stdlib # => test/unit/assertions + * :rspec, :stdlib # => both + +Bug fixes + +* fix dev Gemfile to work on non-mac-os machines (Lake Denman) +* ensure explicit subject is only eval'd once (Laszlo Bacsi) + +### 2.2.1 / 2010-11-28 + +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.2.0...v2.2.1) + +Bug fixes +* alias_method instead of override Kernel#method_missing (John Wilger) +* changed --autotest to --tty in generated command (MIKAMI Yoshiyuki) +* revert change to debugger (had introduced conflict with Rails) + * also restored --debugger/-debug option + +### 2.2.0 / 2010-11-28 + +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.1.0...v2.2.0) + +Deprecations/changes + +* --debug/-d on command line is deprecated and now has no effect +* win32console is now ignored; Windows users must use ANSICON for color support + (Bosko Ivanisevic) + +Enhancements + +* When developing locally rspec-core now works with the rspec-dev setup or your + local gems +* Raise exception with helpful message when rspec-1 is loaded alongside rspec-2 + (Justin Ko) +* debugger statements _just work_ as long as ruby-debug is installed + * otherwise you get warned, but not fired +* Expose example.metadata in around hooks +* Performance improvments (much faster now) + +Bug fixes + +* Make sure --fail-fast makes it across drb +* Pass -Ilib:spec to rcov + +### 2.1.0 / 2010-11-07 + +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.0.1...v2.1.0) + +Enhancments + +* Add skip_bundler option to rake task to tell rake task to ignore the presence + of a Gemfile (jfelchner) +* Add gemfile option to rake task to tell rake task what Gemfile to look for + (defaults to 'Gemfile') +* Allow passing caller trace into Metadata to support extensions (Glenn + Vanderburg) +* Add deprecation warning for Spec::Runner.configure to aid upgrade from + RSpec-1 +* Add deprecated Spec::Rake::SpecTask to aid upgrade from RSpec-1 +* Add 'autospec' command with helpful message to aid upgrade from RSpec-1 +* Add support for filtering with tags on CLI (Lailson Bandeira) +* Add a helpful message about RUBYOPT when require fails in bin/rspec (slyphon) +* Add "-Ilib" to the default rcov options (Tianyi Cui) +* Make the expectation framework configurable (default rspec, of course) + (Justin Ko) +* Add 'pending' to be conditional (Myron Marston) +* Add explicit support for :if and :unless as metadata keys for conditional run + of examples (Myron Marston) +* Add --fail-fast command line option (Jeff Kreeftmeijer) + +Bug fixes + +* Eliminate stack overflow with "subject { self }" +* Require 'rspec/core' in the Raketask (ensures it required when running rcov) + +### 2.0.1 / 2010-10-18 + +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.0.0...v2.0.1) + +Bug fixes + +* Restore color when using spork + autotest +* Pending examples without docstrings render the correct message (Josep M. + Bach) +* Fixed bug where a failure in a spec file ending in anything but _spec.rb + would fail in a confusing way. +* Support backtrace lines from erb templates in html formatter (Alex Crichton) + +### 2.0.0 / 2010-10-10 + +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.0.0.rc...v2.0.0) + +RSpec-1 compatibility + +* Rake task uses ENV["SPEC"] as file list if present + +Bug fixes + +* Bug Fix: optparse --out foo.txt (Leonardo Bessa) +* Suppress color codes for non-tty output (except autotest) + +### 2.0.0.rc / 2010-10-05 + +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.0.0.beta.22...v2.0.0.rc) + +Enhancements + +* implicitly require unknown formatters so you don't have to require the file + explicitly on the commmand line (Michael Grosser) +* add --out/-o option to assign output target +* added fail_fast configuration option to abort on first failure +* support a Hash subject (its([:key]) { should == value }) (Josep M. Bach) + +Bug fixes + +* Explicitly require rspec version to fix broken rdoc task (Hans de Graaff) +* Ignore backtrace lines that come from other languages, like Java or + Javascript (Charles Lowell) +* Rake task now does what is expected when setting (or not setting) + fail_on_error and verbose +* Fix bug in which before/after(:all) hooks were running on excluded nested + groups (Myron Marston) +* Fix before(:all) error handling so that it fails examples in nested groups, + too (Myron Marston) + +### 2.0.0.beta.22 / 2010-09-12 + +[Full Changelog](http://github.com/rspec/rspec-core/compare/v2.0.0.beta.20...v2.0.0.beta.22) + +Enhancements + +* removed at_exit hook +* CTRL-C stops the run (almost) immediately + * first it cleans things up by running the appropriate after(:all) and + after(:suite) hooks + * then it reports on any examples that have already run +* cleaned up rake task + * generate correct task under variety of conditions + * options are more consistent + * deprecated redundant options +* run 'bundle exec autotest' when Gemfile is present +* support ERB in .rspec options files (Justin Ko) +* depend on bundler for development tasks (Myron Marston) +* add example_group_finished to formatters and reporter (Roman Chernyatchik) + +Bug fixes + +* support paths with spaces when using autotest (Andreas Neuhaus) +* fix module_exec with ruby 1.8.6 (Myron Marston) +* remove context method from top-level + * was conflicting with irb, for example +* errors in before(:all) are now reported correctly (Chad Humphries) + +Removals + +* removed -o --options-file command line option + * use ./.rspec and ~/.rspec diff --git a/.bundle/gems/rspec-core-3.3.2/License.txt b/.bundle/gems/rspec-core-3.3.2/License.txt new file mode 100644 index 0000000..4bd202e --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/License.txt @@ -0,0 +1,25 @@ +(The MIT License) + +Copyright (c) 2012 Chad Humphries, David Chelimsky, Myron Marston +Copyright (c) 2009 Chad Humphries, David Chelimsky +Copyright (c) 2006 David Chelimsky, The RSpec Development Team +Copyright (c) 2005 Steven Baker + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/.bundle/gems/rspec-core-3.3.2/README.md b/.bundle/gems/rspec-core-3.3.2/README.md new file mode 100644 index 0000000..1045ca6 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/README.md @@ -0,0 +1,369 @@ +# rspec-core [![Build Status](https://secure.travis-ci.org/rspec/rspec-core.svg?branch=master)](http://travis-ci.org/rspec/rspec-core) [![Code Climate](https://codeclimate.com/github/rspec/rspec-core.svg)](https://codeclimate.com/github/rspec/rspec-core) + +rspec-core provides the structure for writing executable examples of how your +code should behave, and an `rspec` command with tools to constrain which +examples get run and tailor the output. + +## Install + + gem install rspec # for rspec-core, rspec-expectations, rspec-mocks + gem install rspec-core # for rspec-core only + rspec --help + +Want to run against the `master` branch? You'll need to include the dependent +RSpec repos as well. Add the following to your `Gemfile`: + +```ruby +%w[rspec rspec-core rspec-expectations rspec-mocks rspec-support].each do |lib| + gem lib, :git => "git://github.com/rspec/#{lib}.git", :branch => 'master' +end +``` + +## Basic Structure + +RSpec uses the words "describe" and "it" so we can express concepts like a conversation: + + "Describe an order." + "It sums the prices of its line items." + +```ruby +RSpec.describe Order do + it "sums the prices of its line items" do + order = Order.new + + order.add_entry(LineItem.new(:item => Item.new( + :price => Money.new(1.11, :USD) + ))) + order.add_entry(LineItem.new(:item => Item.new( + :price => Money.new(2.22, :USD), + :quantity => 2 + ))) + + expect(order.total).to eq(Money.new(5.55, :USD)) + end +end +``` + +The `describe` method creates an [ExampleGroup](http://rubydoc.info/gems/rspec-core/RSpec/Core/ExampleGroup). Within the +block passed to `describe` you can declare examples using the `it` method. + +Under the hood, an example group is a class in which the block passed to +`describe` is evaluated. The blocks passed to `it` are evaluated in the +context of an _instance_ of that class. + +## Nested Groups + +You can also declare nested nested groups using the `describe` or `context` +methods: + +```ruby +RSpec.describe Order do + context "with no items" do + it "behaves one way" do + # ... + end + end + + context "with one item" do + it "behaves another way" do + # ... + end + end +end +``` + +Nested groups are subclasses of the outer example group class, providing +the inheritance semantics you'd want for free. + +## Aliases + +You can declare example groups using either `describe` or `context`. +For a top level example group, `describe` and `context` are available +off of `RSpec`. For backwards compatibility, they are also available +off of the `main` object and `Module` unless you disable monkey +patching. + +You can declare examples within a group using any of `it`, `specify`, or +`example`. + +## Shared Examples and Contexts + +Declare a shared example group using `shared_examples`, and then include it +in any group using `include_examples`. + +```ruby +RSpec.shared_examples "collections" do |collection_class| + it "is empty when first created" do + expect(collection_class.new).to be_empty + end +end + +RSpec.describe Array do + include_examples "collections", Array +end + +RSpec.describe Hash do + include_examples "collections", Hash +end +``` + +Nearly anything that can be declared within an example group can be declared +within a shared example group. This includes `before`, `after`, and `around` +hooks, `let` declarations, and nested groups/contexts. + +You can also use the names `shared_context` and `include_context`. These are +pretty much the same as `shared_examples` and `include_examples`, providing +more accurate naming when you share hooks, `let` declarations, helper methods, +etc, but no examples. + +## Metadata + +rspec-core stores a metadata hash with every example and group, which +contains their descriptions, the locations at which they were +declared, etc, etc. This hash powers many of rspec-core's features, +including output formatters (which access descriptions and locations), +and filtering before and after hooks. + +Although you probably won't ever need this unless you are writing an +extension, you can access it from an example like this: + +```ruby +it "does something" do |example| + expect(example.metadata[:description]).to eq("does something") +end +``` + +### `described_class` + +When a class is passed to `describe`, you can access it from an example +using the `described_class` method, which is a wrapper for +`example.metadata[:described_class]`. + +```ruby +RSpec.describe Widget do + example do + expect(described_class).to equal(Widget) + end +end +``` + +This is useful in extensions or shared example groups in which the specific +class is unknown. Taking the collections shared example group from above, we can +clean it up a bit using `described_class`: + +```ruby +RSpec.shared_examples "collections" do + it "is empty when first created" do + expect(described_class.new).to be_empty + end +end + +RSpec.describe Array do + include_examples "collections" +end + +RSpec.describe Hash do + include_examples "collections" +end +``` + +## A Word on Scope + +RSpec has two scopes: + +* **Example Group**: Example groups are defined by a `describe` or + `context` block, which is eagerly evaluated when the spec file is + loaded. The block is evaluated in the context of a subclass of + `RSpec::Core::ExampleGroup`, or a subclass of the parent example group + when you're nesting them. +* **Example**: Examples -- typically defined by an `it` block -- and any other + blocks with per-example semantics -- such as a `before(:example)` hook -- are + evaluated in the context of + an _instance_ of the example group class to which the example belongs. + Examples are _not_ executed when the spec file is loaded; instead, + RSpec waits to run any examples until all spec files have been loaded, + at which point it can apply filtering, randomization, etc. + +To make this more concrete, consider this code snippet: + +``` ruby +RSpec.describe "Using an array as a stack" do + def build_stack + [] + end + + before(:example) do + @stack = build_stack + end + + it 'is initially empty' do + expect(@stack).to be_empty + end + + context "after an item has been pushed" do + before(:example) do + @stack.push :item + end + + it 'allows the pushed item to be popped' do + expect(@stack.pop).to eq(:item) + end + end +end +``` + +Under the covers, this is (roughly) equivalent to: + +``` ruby +class UsingAnArrayAsAStack < RSpec::Core::ExampleGroup + def build_stack + [] + end + + def before_example_1 + @stack = build_stack + end + + def it_is_initially_empty + expect(@stack).to be_empty + end + + class AfterAnItemHasBeenPushed < self + def before_example_2 + @stack.push :item + end + + def it_allows_the_pushed_item_to_be_popped + expect(@stack.pop).to eq(:item) + end + end +end +``` + +To run these examples, RSpec would (roughly) do the following: + +``` ruby +example_1 = UsingAnArrayAsAStack.new +example_1.before_example_1 +example_1.it_is_initially_empty + +example_2 = UsingAnArrayAsAStack::AfterAnItemHasBeenPushed.new +example_2.before_example_1 +example_2.before_example_2 +example_2.it_allows_the_pushed_item_to_be_popped +``` + +## The `rspec` Command + +When you install the rspec-core gem, it installs the `rspec` executable, +which you'll use to run rspec. The `rspec` command comes with many useful +options. +Run `rspec --help` to see the complete list. + +## Store Command Line Options `.rspec` + +You can store command line options in a `.rspec` file in the project's root +directory, and the `rspec` command will read them as though you typed them on +the command line. + +## Get Started + +Start with a simple example of behavior you expect from your system. Do +this before you write any implementation code: + +```ruby +# in spec/calculator_spec.rb +RSpec.describe Calculator do + describe '#add' do + it 'returns the sum of its arguments' do + expect(Calculator.new.add(1, 2)).to eq(3) + end + end +end +``` + +Run this with the rspec command, and watch it fail: + +``` +$ rspec spec/calculator_spec.rb +./spec/calculator_spec.rb:1: uninitialized constant Calculator +``` + +Address the failure by defining a skeleton of the `Calculator` class: + +```ruby +# in lib/calculator.rb +class Calculator + def add(a, b) + end +end +``` + +Be sure to require the implementation file in the spec: + +```ruby +# in spec/calculator_spec.rb +# - RSpec adds ./lib to the $LOAD_PATH +require "calculator" +``` + +Now run the spec again, and watch the expectation fail: + +``` +$ rspec spec/calculator_spec.rb +F + +Failures: + + 1) Calculator#add returns the sum of its arguments + Failure/Error: expect(Calculator.new.add(1, 2)).to eq(3) + + expected: 3 + got: nil + + (compared using ==) + # ./spec/calcalator_spec.rb:6:in `block (3 levels) in ' + +Finished in 0.00131 seconds (files took 0.10968 seconds to load) +1 example, 1 failure + +Failed examples: + +rspec ./spec/calcalator_spec.rb:5 # Calculator#add returns the sum of its arguments +``` + +Implement the simplest solution, by changing the definition of `Calculator#add` to: + +```ruby +def add(a, b) + a + b +end +``` + +Now run the spec again, and watch it pass: + +``` +$ rspec spec/calculator_spec.rb +. + +Finished in 0.000315 seconds +1 example, 0 failures +``` + +Use the `documentation` formatter to see the resulting spec: + +``` +$ rspec spec/calculator_spec.rb --format doc +Calculator + #add + returns the sum of its arguments + +Finished in 0.000379 seconds +1 example, 0 failures +``` + +## Also see + +* [http://github.com/rspec/rspec](http://github.com/rspec/rspec) +* [http://github.com/rspec/rspec-expectations](http://github.com/rspec/rspec-expectations) +* [http://github.com/rspec/rspec-mocks](http://github.com/rspec/rspec-mocks) diff --git a/.bundle/gems/rspec-core-3.3.2/exe/rspec b/.bundle/gems/rspec-core-3.3.2/exe/rspec new file mode 100755 index 0000000..7ee5fd8 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/exe/rspec @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby + +require 'rspec/core' +RSpec::Core::Runner.invoke diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/autorun.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/autorun.rb new file mode 100644 index 0000000..3080cfd --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/autorun.rb @@ -0,0 +1,3 @@ +require 'rspec/core' +# Ensure the default config is loaded +RSpec::Core::Runner.autorun diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core.rb new file mode 100644 index 0000000..ccb424c --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core.rb @@ -0,0 +1,181 @@ +# rubocop:disable Style/GlobalVars +$_rspec_core_load_started_at = Time.now +# rubocop:enable Style/GlobalVars + +require "rspec/support" +RSpec::Support.require_rspec_support "caller_filter" + +RSpec::Support.define_optimized_require_for_rspec(:core) { |f| require_relative f } + +%w[ + version + warnings + + set + flat_map + filter_manager + dsl + notifications + reporter + + hooks + memoized_helpers + metadata + metadata_filter + pending + formatters + ordering + + world + configuration + option_parser + configuration_options + runner + example + shared_example_group + example_group +].each { |name| RSpec::Support.require_rspec_core name } + +# Namespace for all core RSpec code. +module RSpec + autoload :SharedContext, 'rspec/core/shared_context' + + extend RSpec::Core::Warnings + + class << self + # Setters for shared global objects + # @api private + attr_writer :configuration, :world + end + + # Used to ensure examples get reloaded and user configuration gets reset to + # defaults between multiple runs in the same process. + # + # Users must invoke this if they want to have the configuration reset when + # they use the runner multiple times within the same process. Users must deal + # themselves with re-configuration of RSpec before run. + def self.reset + @world = nil + @configuration = nil + end + + # Used to ensure examples get reloaded between multiple runs in the same + # process and ensures user configuration is persisted. + # + # Users must invoke this if they want to clear all examples but preserve + # current configuration when they use the runner multiple times within the + # same process. + def self.clear_examples + world.reset + configuration.reporter.reset + configuration.start_time = ::RSpec::Core::Time.now + configuration.reset_filters + end + + # Returns the global [Configuration](RSpec/Core/Configuration) object. While + # you _can_ use this method to access the configuration, the more common + # convention is to use [RSpec.configure](RSpec#configure-class_method). + # + # @example + # RSpec.configuration.drb_port = 1234 + # @see RSpec.configure + # @see Core::Configuration + def self.configuration + @configuration ||= RSpec::Core::Configuration.new + end + configuration.expose_dsl_globally = true + + # Yields the global configuration to a block. + # @yield [Configuration] global configuration + # + # @example + # RSpec.configure do |config| + # config.add_formatter 'documentation' + # end + # @see Core::Configuration + def self.configure + yield configuration if block_given? + end + + # The example being executed. + # + # The primary audience for this method is library authors who need access + # to the example currently being executed and also want to support all + # versions of RSpec 2 and 3. + # + # @example + # + # RSpec.configure do |c| + # # context.example is deprecated, but RSpec.current_example is not + # # available until RSpec 3.0. + # fetch_current_example = RSpec.respond_to?(:current_example) ? + # proc { RSpec.current_example } : proc { |context| context.example } + # + # c.before(:example) do + # example = fetch_current_example.call(self) + # + # # ... + # end + # end + # + def self.current_example + RSpec::Support.thread_local_data[:current_example] + end + + # Set the current example being executed. + # @api private + def self.current_example=(example) + RSpec::Support.thread_local_data[:current_example] = example + end + + # @private + # Internal container for global non-configuration data. + def self.world + @world ||= RSpec::Core::World.new + end + + # Namespace for the rspec-core code. + module Core + autoload :ExampleStatusPersister, "rspec/core/example_status_persister" + autoload :Profiler, "rspec/core/profiler" + + # @private + # This avoids issues with reporting time caused by examples that + # change the value/meaning of Time.now without properly restoring + # it. + class Time + class << self + define_method(:now, &::Time.method(:now)) + end + end + + # @private path to executable file. + def self.path_to_executable + @path_to_executable ||= File.expand_path('../../../exe/rspec', __FILE__) + end + end + + # @private + MODULES_TO_AUTOLOAD = { + :Matchers => "rspec/expectations", + :Expectations => "rspec/expectations", + :Mocks => "rspec/mocks" + } + + # @private + def self.const_missing(name) + # Load rspec-expectations when RSpec::Matchers is referenced. This allows + # people to define custom matchers (using `RSpec::Matchers.define`) before + # rspec-core has loaded rspec-expectations (since it delays the loading of + # it to allow users to configure a different assertion/expectation + # framework). `autoload` can't be used since it works with ruby's built-in + # require (e.g. for files that are available relative to a load path dir), + # but not with rubygems' extended require. + # + # As of rspec 2.14.1, we no longer require `rspec/mocks` and + # `rspec/expectations` when `rspec` is required, so we want + # to make them available as an autoload. + require MODULES_TO_AUTOLOAD.fetch(name) { return super } + ::RSpec.const_get(name) + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/backtrace_formatter.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/backtrace_formatter.rb new file mode 100644 index 0000000..74617ec --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/backtrace_formatter.rb @@ -0,0 +1,64 @@ +module RSpec + module Core + # @private + class BacktraceFormatter + # @private + attr_accessor :exclusion_patterns, :inclusion_patterns + + def initialize + @full_backtrace = false + + patterns = %w[ /lib\d*/ruby/ bin/ exe/rspec ] + patterns << "org/jruby/" if RUBY_PLATFORM == 'java' + patterns.map! { |s| Regexp.new(s.gsub("/", File::SEPARATOR)) } + + @exclusion_patterns = [Regexp.union(RSpec::CallerFilter::IGNORE_REGEX, *patterns)] + @inclusion_patterns = [] + + return unless matches?(@exclusion_patterns, File.join(Dir.getwd, "lib", "foo.rb:13")) + inclusion_patterns << Regexp.new(Dir.getwd) + end + + attr_writer :full_backtrace + + def full_backtrace? + @full_backtrace || exclusion_patterns.empty? + end + + def filter_gem(gem_name) + sep = File::SEPARATOR + exclusion_patterns << /#{sep}#{gem_name}(-[^#{sep}]+)?#{sep}/ + end + + def format_backtrace(backtrace, options={}) + return backtrace if options[:full_backtrace] || backtrace.empty? + + backtrace.map { |l| backtrace_line(l) }.compact. + tap do |filtered| + if filtered.empty? + filtered.concat backtrace + filtered << "" + filtered << " Showing full backtrace because every line was filtered out." + filtered << " See docs for RSpec::Configuration#backtrace_exclusion_patterns and" + filtered << " RSpec::Configuration#backtrace_inclusion_patterns for more information." + end + end + end + + def backtrace_line(line) + Metadata.relative_path(line) unless exclude?(line) + end + + def exclude?(line) + return false if @full_backtrace + matches?(exclusion_patterns, line) && !matches?(inclusion_patterns, line) + end + + private + + def matches?(patterns, line) + patterns.any? { |p| line =~ p } + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/bisect/coordinator.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/bisect/coordinator.rb new file mode 100644 index 0000000..16448c1 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/bisect/coordinator.rb @@ -0,0 +1,66 @@ +RSpec::Support.require_rspec_core "bisect/server" +RSpec::Support.require_rspec_core "bisect/runner" +RSpec::Support.require_rspec_core "bisect/example_minimizer" +RSpec::Support.require_rspec_core "formatters/bisect_progress_formatter" + +module RSpec + module Core + module Bisect + # @private + # The main entry point into the bisect logic. Coordinates among: + # - Bisect::Server: Receives suite results. + # - Bisect::Runner: Runs a set of examples and directs the results + # to the server. + # - Bisect::ExampleMinimizer: Contains the core bisect logic. + # - Formatters::BisectProgressFormatter: provides progress updates + # to the user. + class Coordinator + def self.bisect_with(original_cli_args, configuration, formatter) + new(original_cli_args, configuration, formatter).bisect + end + + def initialize(original_cli_args, configuration, formatter) + @original_cli_args = original_cli_args + @configuration = configuration + @formatter = formatter + end + + def bisect + @configuration.add_formatter @formatter + + reporter.close_after do + repro = Server.run do |server| + runner = Runner.new(server, @original_cli_args) + minimizer = ExampleMinimizer.new(runner, reporter) + + gracefully_abort_on_sigint(minimizer) + minimizer.find_minimal_repro + minimizer.repro_command_for_currently_needed_ids + end + + reporter.publish(:bisect_repro_command, :repro => repro) + end + + true + rescue BisectFailedError => e + reporter.publish(:bisect_failed, :failure_explanation => e.message) + false + end + + private + + def reporter + @configuration.reporter + end + + def gracefully_abort_on_sigint(minimizer) + trap('INT') do + repro = minimizer.repro_command_for_currently_needed_ids + reporter.publish(:bisect_aborted, :repro => repro) + exit(1) + end + end + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/bisect/example_minimizer.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/bisect/example_minimizer.rb new file mode 100644 index 0000000..f8a6022 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/bisect/example_minimizer.rb @@ -0,0 +1,130 @@ +RSpec::Support.require_rspec_core "bisect/subset_enumerator" + +module RSpec + module Core + module Bisect + # @private + # Contains the core bisect logic. Searches for examples we can ignore by + # repeatedly running different subsets of the suite. + class ExampleMinimizer + attr_reader :runner, :reporter, :all_example_ids, :failed_example_ids + attr_accessor :remaining_ids + + def initialize(runner, reporter) + @runner = runner + @reporter = reporter + end + + def find_minimal_repro + prep + + self.remaining_ids = non_failing_example_ids + + each_bisect_round do |subsets| + ids_to_ignore = subsets.find do |ids| + get_expected_failures_for?(remaining_ids - ids) + end + + next :done unless ids_to_ignore + + self.remaining_ids -= ids_to_ignore + notify(:bisect_ignoring_ids, :ids_to_ignore => ids_to_ignore, :remaining_ids => remaining_ids) + end + + currently_needed_ids + end + + def currently_needed_ids + remaining_ids + failed_example_ids + end + + def repro_command_for_currently_needed_ids + return runner.repro_command_from(currently_needed_ids) if remaining_ids + "(Not yet enough information to provide any repro command)" + end + + private + + def prep + notify(:bisect_starting, :original_cli_args => runner.original_cli_args) + + _, duration = track_duration do + original_results = runner.original_results + @all_example_ids = original_results.all_example_ids + @failed_example_ids = original_results.failed_example_ids + end + + if @failed_example_ids.empty? + raise BisectFailedError, "\n\nNo failures found. Bisect only works " \ + "in the presence of one or more failing examples." + else + notify(:bisect_original_run_complete, :failed_example_ids => failed_example_ids, + :non_failing_example_ids => non_failing_example_ids, + :duration => duration) + end + end + + def non_failing_example_ids + @non_failing_example_ids ||= all_example_ids - failed_example_ids + end + + def get_expected_failures_for?(ids) + ids_to_run = ids + failed_example_ids + notify(:bisect_individual_run_start, :command => runner.repro_command_from(ids_to_run)) + + results, duration = track_duration { runner.run(ids_to_run) } + notify(:bisect_individual_run_complete, :duration => duration, :results => results) + + abort_if_ordering_inconsistent(results) + (failed_example_ids & results.failed_example_ids) == failed_example_ids + end + + INFINITY = (1.0 / 0) # 1.8.7 doesn't define Float::INFINITY so we define our own... + + def each_bisect_round(&block) + last_round, duration = track_duration do + 1.upto(INFINITY) do |round| + break if :done == bisect_round(round, &block) + end + end + + notify(:bisect_complete, :round => last_round, :duration => duration, + :original_non_failing_count => non_failing_example_ids.size, + :remaining_count => remaining_ids.size) + end + + def bisect_round(round) + value, duration = track_duration do + subsets = SubsetEnumerator.new(remaining_ids) + notify(:bisect_round_started, :round => round, + :subset_size => subsets.subset_size, + :remaining_count => remaining_ids.size) + + yield subsets + end + + notify(:bisect_round_finished, :duration => duration, :round => round) + value + end + + def track_duration + start = ::RSpec::Core::Time.now + [yield, ::RSpec::Core::Time.now - start] + end + + def abort_if_ordering_inconsistent(results) + expected_order = all_example_ids & results.all_example_ids + return if expected_order == results.all_example_ids + + raise BisectFailedError, "\n\nThe example ordering is inconsistent. " \ + "`--bisect` relies upon consistent ordering (e.g. by passing " \ + "`--seed` if you're using random ordering) to work properly." + end + + def notify(*args) + reporter.publish(*args) + end + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/bisect/runner.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/bisect/runner.rb new file mode 100644 index 0000000..a9d07dc --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/bisect/runner.rb @@ -0,0 +1,139 @@ +RSpec::Support.require_rspec_core "shell_escape" +require 'open3' + +module RSpec + module Core + module Bisect + # Provides an API to run the suite for a set of locations, using + # the given bisect server to capture the results. + # @private + class Runner + attr_reader :original_cli_args + + def initialize(server, original_cli_args) + @server = server + @original_cli_args = original_cli_args.reject { |arg| arg.start_with?("--bisect") } + end + + def run(locations) + run_locations(locations, original_results.failed_example_ids) + end + + def command_for(locations) + parts = [] + + parts << RUBY << load_path + parts << open3_safe_escape(RSpec::Core.path_to_executable) + + parts << "--format" << "bisect" + parts << "--drb-port" << @server.drb_port + parts.concat reusable_cli_options + parts.concat locations.map { |l| open3_safe_escape(l) } + + parts.join(" ") + end + + def repro_command_from(locations) + parts = [] + + parts << "rspec" + parts.concat Formatters::Helpers.organize_ids(locations) + parts.concat original_cli_args_without_locations + + parts.join(" ") + end + + def original_results + @original_results ||= run_locations(original_locations) + end + + private + + include RSpec::Core::ShellEscape + # On JRuby, Open3.popen3 does not handle shellescaped args properly: + # https://github.com/jruby/jruby/issues/2767 + if RSpec::Support::Ruby.jruby? + # :nocov: + alias open3_safe_escape quote + # :nocov: + else + alias open3_safe_escape escape + end + + def run_locations(locations, *capture_args) + @server.capture_run_results(*capture_args) do + run_command command_for(locations) + end + end + + # `Open3.capture2e` does not work on JRuby: + # https://github.com/jruby/jruby/issues/2766 + if Open3.respond_to?(:capture2e) && !RSpec::Support::Ruby.jruby? + def run_command(cmd) + Open3.capture2e(cmd).first + end + else # for 1.8.7 + # :nocov: + def run_command(cmd) + out = err = nil + + Open3.popen3(cmd) do |_, stdout, stderr| + # Reading the streams blocks until the process is complete + out = stdout.read + err = stderr.read + end + + "Stdout:\n#{out}\n\nStderr:\n#{err}" + end + # :nocov: + end + + def reusable_cli_options + @reusable_cli_options ||= begin + opts = original_cli_args_without_locations + + if (port = parsed_original_cli_options[:drb_port]) + opts -= %W[ --drb-port #{port} ] + end + + parsed_original_cli_options.fetch(:formatters) { [] }.each do |(name, out)| + opts -= %W[ --format #{name} -f -f#{name} ] + opts -= %W[ --out #{out} -o -o#{out} ] + end + + opts + end + end + + def original_cli_args_without_locations + @original_cli_args_without_locations ||= begin + files_or_dirs = parsed_original_cli_options.fetch(:files_or_directories_to_run) + @original_cli_args - files_or_dirs + end + end + + def parsed_original_cli_options + @parsed_original_cli_options ||= Parser.parse(@original_cli_args) + end + + def original_locations + parsed_original_cli_options.fetch(:files_or_directories_to_run) + end + + def load_path + @load_path ||= "-I#{$LOAD_PATH.map { |p| open3_safe_escape(p) }.join(':')}" + end + + # Path to the currently running Ruby executable, borrowed from Rake: + # https://github.com/ruby/rake/blob/v10.4.2/lib/rake/file_utils.rb#L8-L12 + # Note that we skip `ENV['RUBY']` because we don't have to deal with running + # RSpec from within a MRI source repository: + # https://github.com/ruby/rake/commit/968682759b3b65e42748cd2befb2ff3e982272d9 + RUBY = File.join( + RbConfig::CONFIG['bindir'], + RbConfig::CONFIG['ruby_install_name'] + RbConfig::CONFIG['EXEEXT']). + sub(/.*\s.*/m, '"\&"') + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/bisect/server.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/bisect/server.rb new file mode 100644 index 0000000..35fe97d --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/bisect/server.rb @@ -0,0 +1,61 @@ +require 'drb/drb' +require 'drb/acl' + +module RSpec + module Core + # @private + module Bisect + # @private + BisectFailedError = Class.new(StandardError) + + # @private + # A DRb server that receives run results from a separate RSpec process + # started by the bisect process. + class Server + def self.run + server = new + server.start + yield server + ensure + server.stop + end + + def capture_run_results(expected_failures=[]) + self.expected_failures = expected_failures + self.latest_run_results = nil + run_output = yield + latest_run_results || raise_bisect_failed(run_output) + end + + def start + # Only allow remote DRb requests from this machine. + DRb.install_acl ACL.new(%w[ deny all allow localhost allow 127.0.0.1 ]) + + # We pass `nil` as the first arg to allow it to pick a DRb port. + @drb = DRb.start_service(nil, self) + end + + def stop + @drb.stop_service + end + + def drb_port + @drb_port ||= Integer(@drb.uri[/\d+$/]) + end + + # Fetched via DRb by the BisectFormatter to determine when to abort. + attr_accessor :expected_failures + + # Set via DRb by the BisectFormatter with the results of the run. + attr_accessor :latest_run_results + + private + + def raise_bisect_failed(run_output) + raise BisectFailedError, "Failed to get results from the spec " \ + "run. Spec run output:\n\n#{run_output}" + end + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/bisect/subset_enumerator.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/bisect/subset_enumerator.rb new file mode 100644 index 0000000..7dc52cf --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/bisect/subset_enumerator.rb @@ -0,0 +1,39 @@ +module RSpec + module Core + module Bisect + # Enumerates each subset of the given list of ids that is half the + # size of the total list, so that hopefully we can discard half the + # list each repeatedly in order to our minimal repro case. + # @private + class SubsetEnumerator + include Enumerable + + def initialize(ids) + @ids = ids + end + + def subset_size + @subset_size ||= (@ids.size / 2.0).ceil + end + + def each + yielded = Set.new + slice_size = subset_size + combo_count = 1 + + while slice_size > 0 + @ids.each_slice(slice_size).to_a.combination(combo_count) do |combos| + subset = combos.flatten + next if yielded.include?(subset) + yield subset + yielded << subset + end + + slice_size /= 2 + combo_count *= 2 + end + end + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/configuration.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/configuration.rb new file mode 100644 index 0000000..2834d75 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/configuration.rb @@ -0,0 +1,1807 @@ +RSpec::Support.require_rspec_core "backtrace_formatter" +RSpec::Support.require_rspec_core "ruby_project" +RSpec::Support.require_rspec_core "formatters/deprecation_formatter" + +module RSpec + module Core + # rubocop:disable Style/ClassLength + + # Stores runtime configuration information. + # + # Configuration options are loaded from `~/.rspec`, `.rspec`, + # `.rspec-local`, command line switches, and the `SPEC_OPTS` environment + # variable (listed in lowest to highest precedence; for example, an option + # in `~/.rspec` can be overridden by an option in `.rspec-local`). + # + # @example Standard settings + # RSpec.configure do |c| + # c.drb = true + # c.drb_port = 1234 + # c.default_path = 'behavior' + # end + # + # @example Hooks + # RSpec.configure do |c| + # c.before(:suite) { establish_connection } + # c.before(:example) { log_in_as :authorized } + # c.around(:example) { |ex| Database.transaction(&ex) } + # end + # + # @see RSpec.configure + # @see Hooks + class Configuration + include RSpec::Core::Hooks + + # Module that holds `attr_reader` declarations. It's in a separate + # module to allow us to override those methods and use `super`. + # @private + Readers = Module.new + include Readers + + # @private + class MustBeConfiguredBeforeExampleGroupsError < StandardError; end + + # @private + def self.define_reader(name) + Readers.class_eval do + remove_method name if method_defined?(name) + attr_reader name + end + + define_method(name) { value_for(name) { super() } } + end + + # @private + def self.define_aliases(name, alias_name) + alias_method alias_name, name + alias_method "#{alias_name}=", "#{name}=" + define_predicate_for alias_name + end + + # @private + def self.define_predicate_for(*names) + names.each { |name| alias_method "#{name}?", name } + end + + # @private + # + # Invoked by the `add_setting` instance method. Use that method on a + # `Configuration` instance rather than this class method. + def self.add_setting(name, opts={}) + raise "Use the instance add_setting method if you want to set a default" if opts.key?(:default) + attr_writer name + add_read_only_setting name + + Array(opts[:alias_with]).each do |alias_name| + define_aliases(name, alias_name) + end + end + + # @private + # + # As `add_setting` but only add the reader. + def self.add_read_only_setting(name, opts={}) + raise "Use the instance add_setting method if you want to set a default" if opts.key?(:default) + define_reader name + define_predicate_for name + end + + # @macro [attach] add_setting + # @!attribute [rw] $1 + # @!method $1=(value) + # + # @macro [attach] define_reader + # @!attribute [r] $1 + + # @macro add_setting + # Path to use if no path is provided to the `rspec` command (default: + # `"spec"`). Allows you to just type `rspec` instead of `rspec spec` to + # run all the examples in the `spec` directory. + # + # @note Other scripts invoking `rspec` indirectly will ignore this + # setting. + add_setting :default_path + + # @macro add_setting + # Run examples over DRb (default: `false`). RSpec doesn't supply the DRb + # server, but you can use tools like spork. + add_setting :drb + + # @macro add_setting + # The drb_port (default: nil). + add_setting :drb_port + + # @macro add_setting + # Default: `$stderr`. + add_setting :error_stream + + # Indicates if the DSL has been exposed off of modules and `main`. + # Default: true + def expose_dsl_globally? + Core::DSL.exposed_globally? + end + + # Use this to expose the core RSpec DSL via `Module` and the `main` + # object. It will be set automatically but you can override it to + # remove the DSL. + # Default: true + def expose_dsl_globally=(value) + if value + Core::DSL.expose_globally! + Core::SharedExampleGroup::TopLevelDSL.expose_globally! + else + Core::DSL.remove_globally! + Core::SharedExampleGroup::TopLevelDSL.remove_globally! + end + end + + # Determines where deprecation warnings are printed. + # Defaults to `$stderr`. + # @return [IO, String] IO to write to or filename to write to + define_reader :deprecation_stream + + # Determines where deprecation warnings are printed. + # @param value [IO, String] IO to write to or filename to write to + def deprecation_stream=(value) + if @reporter && !value.equal?(@deprecation_stream) + warn "RSpec's reporter has already been initialized with " \ + "#{deprecation_stream.inspect} as the deprecation stream, so your change to "\ + "`deprecation_stream` will be ignored. You should configure it earlier for " \ + "it to take effect, or use the `--deprecation-out` CLI option. " \ + "(Called from #{CallerFilter.first_non_rspec_line})" + else + @deprecation_stream = value + end + end + + # @macro define_reader + # The file path to use for persisting example statuses. Necessary for the + # `--only-failures` and `--next-failures` CLI options. + # + # @overload example_status_persistence_file_path + # @return [String] the file path + # @overload example_status_persistence_file_path=(value) + # @param value [String] the file path + define_reader :example_status_persistence_file_path + + # Sets the file path to use for persisting example statuses. Necessary for the + # `--only-failures` and `--next-failures` CLI options. + def example_status_persistence_file_path=(value) + @example_status_persistence_file_path = value + clear_values_derived_from_example_status_persistence_file_path + end + + # @macro define_reader + # Indicates if the `--only-failures` (or `--next-failure`) flag is being used. + define_reader :only_failures + alias_method :only_failures?, :only_failures + + # @private + def only_failures_but_not_configured? + only_failures? && !example_status_persistence_file_path + end + + # @macro add_setting + # Clean up and exit after the first failure (default: `false`). + add_setting :fail_fast + + # @macro add_setting + # Prints the formatter output of your suite without running any + # examples or hooks. + add_setting :dry_run + + # @macro add_setting + # The exit code to return if there are any failures (default: 1). + add_setting :failure_exit_code + + # @macro define_reader + # Indicates files configured to be required. + define_reader :requires + + # @macro define_reader + # Returns dirs that have been prepended to the load path by the `-I` + # command line option. + define_reader :libs + + # @macro add_setting + # Determines where RSpec will send its output. + # Default: `$stdout`. + define_reader :output_stream + + # Set the output stream for reporter. + # @attr value [IO] value for output, defaults to $stdout + def output_stream=(value) + if @reporter && !value.equal?(@output_stream) + warn "RSpec's reporter has already been initialized with " \ + "#{output_stream.inspect} as the output stream, so your change to "\ + "`output_stream` will be ignored. You should configure it earlier for " \ + "it to take effect. (Called from #{CallerFilter.first_non_rspec_line})" + else + @output_stream = value + end + end + + # @macro define_reader + # Load files matching this pattern (default: `'**{,/*/**}/*_spec.rb'`). + define_reader :pattern + + # Set pattern to match files to load. + # @attr value [String] the filename pattern to filter spec files by + def pattern=(value) + update_pattern_attr :pattern, value + end + + # @macro define_reader + # Exclude files matching this pattern. + define_reader :exclude_pattern + + # Set pattern to match files to exclude. + # @attr value [String] the filename pattern to exclude spec files by + def exclude_pattern=(value) + update_pattern_attr :exclude_pattern, value + end + + # @macro add_setting + # Report the times for the slowest examples (default: `false`). + # Use this to specify the number of examples to include in the profile. + add_setting :profile_examples + + # @macro add_setting + # Run all examples if none match the configured filters + # (default: `false`). + add_setting :run_all_when_everything_filtered + + # @macro add_setting + # Color to use to indicate success. + # @param color [Symbol] defaults to `:green` but can be set to one of the + # following: `[:black, :white, :red, :green, :yellow, :blue, :magenta, + # :cyan]` + add_setting :success_color + + # @macro add_setting + # Color to use to print pending examples. + # @param color [Symbol] defaults to `:yellow` but can be set to one of the + # following: `[:black, :white, :red, :green, :yellow, :blue, :magenta, + # :cyan]` + add_setting :pending_color + + # @macro add_setting + # Color to use to indicate failure. + # @param color [Symbol] defaults to `:red` but can be set to one of the + # following: `[:black, :white, :red, :green, :yellow, :blue, :magenta, + # :cyan]` + add_setting :failure_color + + # @macro add_setting + # The default output color. + # @param color [Symbol] defaults to `:white` but can be set to one of the + # following: `[:black, :white, :red, :green, :yellow, :blue, :magenta, + # :cyan]` + add_setting :default_color + + # @macro add_setting + # Color used when a pending example is fixed. + # @param color [Symbol] defaults to `:blue` but can be set to one of the + # following: `[:black, :white, :red, :green, :yellow, :blue, :magenta, + # :cyan]` + add_setting :fixed_color + + # @macro add_setting + # Color used to print details. + # @param color [Symbol] defaults to `:cyan` but can be set to one of the + # following: `[:black, :white, :red, :green, :yellow, :blue, :magenta, + # :cyan]` + add_setting :detail_color + + # Deprecated. This config option was added in RSpec 2 to pave the way + # for this being the default behavior in RSpec 3. Now this option is + # a no-op. + def treat_symbols_as_metadata_keys_with_true_values=(_value) + RSpec.deprecate( + "RSpec::Core::Configuration#treat_symbols_as_metadata_keys_with_true_values=", + :message => "RSpec::Core::Configuration#treat_symbols_as_metadata_keys_with_true_values= " \ + "is deprecated, it is now set to true as default and " \ + "setting it to false has no effect." + ) + end + + # Record the start time of the spec suite to measure load time. + add_setting :start_time + + # @macro add_setting + # Use threadsafe options where available. + # Currently this will place a mutex around memoized values such as let blocks. + add_setting :threadsafe + + # @private + add_setting :tty + # @private + attr_writer :files_to_run + # @private + attr_accessor :filter_manager + # @private + attr_accessor :static_config_filter_manager + # @private + attr_reader :backtrace_formatter, :ordering_manager, :loaded_spec_files + + def initialize + # rubocop:disable Style/GlobalVars + @start_time = $_rspec_core_load_started_at || ::RSpec::Core::Time.now + # rubocop:enable Style/GlobalVars + @expectation_frameworks = [] + @include_modules = FilterableItemRepository::QueryOptimized.new(:any?) + @extend_modules = FilterableItemRepository::QueryOptimized.new(:any?) + @prepend_modules = FilterableItemRepository::QueryOptimized.new(:any?) + + @before_suite_hooks = [] + @after_suite_hooks = [] + + @mock_framework = nil + @files_or_directories_to_run = [] + @loaded_spec_files = Set.new + @color = false + @pattern = '**{,/*/**}/*_spec.rb' + @exclude_pattern = '' + @failure_exit_code = 1 + @spec_files_loaded = false + + @backtrace_formatter = BacktraceFormatter.new + + @default_path = 'spec' + @deprecation_stream = $stderr + @output_stream = $stdout + @reporter = nil + @reporter_buffer = nil + @filter_manager = FilterManager.new + @static_config_filter_manager = FilterManager.new + @ordering_manager = Ordering::ConfigurationManager.new + @preferred_options = {} + @failure_color = :red + @success_color = :green + @pending_color = :yellow + @default_color = :white + @fixed_color = :blue + @detail_color = :cyan + @profile_examples = false + @requires = [] + @libs = [] + @derived_metadata_blocks = FilterableItemRepository::QueryOptimized.new(:any?) + @threadsafe = true + + define_built_in_hooks + end + + # @private + # + # Used to set higher priority option values from the command line. + def force(hash) + ordering_manager.force(hash) + @preferred_options.merge!(hash) + + return unless hash.key?(:example_status_persistence_file_path) + clear_values_derived_from_example_status_persistence_file_path + end + + # @private + def reset + @spec_files_loaded = false + @reporter = nil + @formatter_loader = nil + end + + # @private + def reset_filters + self.filter_manager = FilterManager.new + filter_manager.include_only( + Metadata.deep_hash_dup(static_config_filter_manager.inclusions.rules) + ) + filter_manager.exclude_only( + Metadata.deep_hash_dup(static_config_filter_manager.exclusions.rules) + ) + end + + # @overload add_setting(name) + # @overload add_setting(name, opts) + # @option opts [Symbol] :default + # + # Set a default value for the generated getter and predicate methods: + # + # add_setting(:foo, :default => "default value") + # + # @option opts [Symbol] :alias_with + # + # Use `:alias_with` to alias the setter, getter, and predicate to + # another name, or names: + # + # add_setting(:foo, :alias_with => :bar) + # add_setting(:foo, :alias_with => [:bar, :baz]) + # + # Adds a custom setting to the RSpec.configuration object. + # + # RSpec.configuration.add_setting :foo + # + # Used internally and by extension frameworks like rspec-rails, so they + # can add config settings that are domain specific. For example: + # + # RSpec.configure do |c| + # c.add_setting :use_transactional_fixtures, + # :default => true, + # :alias_with => :use_transactional_examples + # end + # + # `add_setting` creates three methods on the configuration object, a + # setter, a getter, and a predicate: + # + # RSpec.configuration.foo=(value) + # RSpec.configuration.foo + # RSpec.configuration.foo? # Returns true if foo returns anything but nil or false. + def add_setting(name, opts={}) + default = opts.delete(:default) + (class << self; self; end).class_exec do + add_setting(name, opts) + end + __send__("#{name}=", default) if default + end + + # Returns the configured mock framework adapter module. + def mock_framework + if @mock_framework.nil? + begin + mock_with :rspec + rescue LoadError + mock_with :nothing + end + end + @mock_framework + end + + # Delegates to mock_framework=(framework). + def mock_framework=(framework) + mock_with framework + end + + # Regexps used to exclude lines from backtraces. + # + # Excludes lines from ruby (and jruby) source, installed gems, anything + # in any "bin" directory, and any of the RSpec libs (outside gem + # installs) by default. + # + # You can modify the list via the getter, or replace it with the setter. + # + # To override this behaviour and display a full backtrace, use + # `--backtrace` on the command line, in a `.rspec` file, or in the + # `rspec_options` attribute of RSpec's rake task. + def backtrace_exclusion_patterns + @backtrace_formatter.exclusion_patterns + end + + # Set regular expressions used to exclude lines in backtrace. + # @param patterns [Regexp] set the backtrace exlusion pattern + def backtrace_exclusion_patterns=(patterns) + @backtrace_formatter.exclusion_patterns = patterns + end + + # Regexps used to include lines in backtraces. + # + # Defaults to [Regexp.new Dir.getwd]. + # + # Lines that match an exclusion _and_ an inclusion pattern + # will be included. + # + # You can modify the list via the getter, or replace it with the setter. + def backtrace_inclusion_patterns + @backtrace_formatter.inclusion_patterns + end + + # Set regular expressions used to include lines in backtrace. + # @attr patterns [Regexp] set backtrace_formatter inclusion_patterns + def backtrace_inclusion_patterns=(patterns) + @backtrace_formatter.inclusion_patterns = patterns + end + + # Adds {#backtrace_exclusion_patterns} that will filter lines from + # the named gems from backtraces. + # + # @param gem_names [Array] Names of the gems to filter + # + # @example + # RSpec.configure do |config| + # config.filter_gems_from_backtrace "rack", "rake" + # end + # + # @note The patterns this adds will match the named gems in their common + # locations (e.g. system gems, vendored with bundler, installed as a + # :git dependency with bundler, etc) but is not guaranteed to work for + # all possible gem locations. For example, if you have the gem source + # in a directory with a completely unrelated name, and use bundler's + # :path option, this will not filter it. + def filter_gems_from_backtrace(*gem_names) + gem_names.each do |name| + @backtrace_formatter.filter_gem(name) + end + end + + # @private + MOCKING_ADAPTERS = { + :rspec => :RSpec, + :flexmock => :Flexmock, + :rr => :RR, + :mocha => :Mocha, + :nothing => :Null + } + + # Sets the mock framework adapter module. + # + # `framework` can be a Symbol or a Module. + # + # Given any of `:rspec`, `:mocha`, `:flexmock`, or `:rr`, configures the + # named framework. + # + # Given `:nothing`, configures no framework. Use this if you don't use + # any mocking framework to save a little bit of overhead. + # + # Given a Module, includes that module in every example group. The module + # should adhere to RSpec's mock framework adapter API: + # + # setup_mocks_for_rspec + # - called before each example + # + # verify_mocks_for_rspec + # - called after each example if the example hasn't yet failed. + # Framework should raise an exception when expectations fail + # + # teardown_mocks_for_rspec + # - called after verify_mocks_for_rspec (even if there are errors) + # + # If the module responds to `configuration` and `mock_with` receives a + # block, it will yield the configuration object to the block e.g. + # + # config.mock_with OtherMockFrameworkAdapter do |mod_config| + # mod_config.custom_setting = true + # end + def mock_with(framework) + framework_module = + if framework.is_a?(Module) + framework + else + const_name = MOCKING_ADAPTERS.fetch(framework) do + raise ArgumentError, + "Unknown mocking framework: #{framework.inspect}. " \ + "Pass a module or one of #{MOCKING_ADAPTERS.keys.inspect}" + end + + RSpec::Support.require_rspec_core "mocking_adapters/#{const_name.to_s.downcase}" + RSpec::Core::MockingAdapters.const_get(const_name) + end + + new_name, old_name = [framework_module, @mock_framework].map do |mod| + mod.respond_to?(:framework_name) ? mod.framework_name : :unnamed + end + + unless new_name == old_name + assert_no_example_groups_defined(:mock_framework) + end + + if block_given? + raise "#{framework_module} must respond to `configuration` so that " \ + "mock_with can yield it." unless framework_module.respond_to?(:configuration) + yield framework_module.configuration + end + + @mock_framework = framework_module + end + + # Returns the configured expectation framework adapter module(s) + def expectation_frameworks + if @expectation_frameworks.empty? + begin + expect_with :rspec + rescue LoadError + expect_with Module.new + end + end + @expectation_frameworks + end + + # Delegates to expect_with(framework). + def expectation_framework=(framework) + expect_with(framework) + end + + # Sets the expectation framework module(s) to be included in each example + # group. + # + # `frameworks` can be `:rspec`, `:test_unit`, `:minitest`, a custom + # module, or any combination thereof: + # + # config.expect_with :rspec + # config.expect_with :test_unit + # config.expect_with :minitest + # config.expect_with :rspec, :minitest + # config.expect_with OtherExpectationFramework + # + # RSpec will translate `:rspec`, `:minitest`, and `:test_unit` into the + # appropriate modules. + # + # ## Configuration + # + # If the module responds to `configuration`, `expect_with` will + # yield the `configuration` object if given a block: + # + # config.expect_with OtherExpectationFramework do |custom_config| + # custom_config.custom_setting = true + # end + def expect_with(*frameworks) + modules = frameworks.map do |framework| + case framework + when Module + framework + when :rspec + require 'rspec/expectations' + + # Tag this exception class so our exception formatting logic knows + # that it satisfies the `MultipleExceptionError` interface. + ::RSpec::Expectations::MultipleExpectationsNotMetError.__send__( + :include, MultipleExceptionError::InterfaceTag + ) + + ::RSpec::Matchers + when :test_unit + require 'rspec/core/test_unit_assertions_adapter' + ::RSpec::Core::TestUnitAssertionsAdapter + when :minitest + require 'rspec/core/minitest_assertions_adapter' + ::RSpec::Core::MinitestAssertionsAdapter + else + raise ArgumentError, "#{framework.inspect} is not supported" + end + end + + if (modules - @expectation_frameworks).any? + assert_no_example_groups_defined(:expect_with) + end + + if block_given? + raise "expect_with only accepts a block with a single argument. " \ + "Call expect_with #{modules.length} times, " \ + "once with each argument, instead." if modules.length > 1 + raise "#{modules.first} must respond to `configuration` so that " \ + "expect_with can yield it." unless modules.first.respond_to?(:configuration) + yield modules.first.configuration + end + + @expectation_frameworks.push(*modules) + end + + # Check if full backtrace is enabled. + # @return [Boolean] is full backtrace enabled + def full_backtrace? + @backtrace_formatter.full_backtrace? + end + + # Toggle full backtrace. + # @attr true_or_false [Boolean] toggle full backtrace display + def full_backtrace=(true_or_false) + @backtrace_formatter.full_backtrace = true_or_false + end + + # Returns the configuration option for color, but should not + # be used to check if color is supported. + # + # @see color_enabled? + # @return [Boolean] + def color + value_for(:color) { @color } + end + + # Check if color is enabled for a particular output. + # @param output [IO] an output stream to use, defaults to the current + # `output_stream` + # @return [Boolean] + def color_enabled?(output=output_stream) + output_to_tty?(output) && color + end + + # Toggle output color. + # @attr true_or_false [Boolean] toggle color enabled + def color=(true_or_false) + return unless true_or_false + + if RSpec::Support::OS.windows? && !ENV['ANSICON'] + RSpec.warning "You must use ANSICON 1.31 or later " \ + "(http://adoxa.3eeweb.com/ansicon/) to use colour " \ + "on Windows" + @color = false + else + @color = true + end + end + + # @private + def libs=(libs) + libs.map do |lib| + @libs.unshift lib + $LOAD_PATH.unshift lib + end + end + + # Run examples matching on `description` in all files to run. + # @param description [String, Regexp] the pattern to filter on + def full_description=(description) + filter_run :full_description => Regexp.union(*Array(description).map { |d| Regexp.new(d) }) + end + + # @return [Array] full description filter + def full_description + filter.fetch :full_description, nil + end + + # @overload add_formatter(formatter) + # + # Adds a formatter to the formatters collection. `formatter` can be a + # string representing any of the built-in formatters (see + # `built_in_formatter`), or a custom formatter class. + # + # ### Note + # + # For internal purposes, `add_formatter` also accepts the name of a class + # and paths to use for output streams, but you should consider that a + # private api that may change at any time without notice. + def add_formatter(formatter_to_use, *paths) + paths << output_stream if paths.empty? + formatter_loader.add formatter_to_use, *paths + end + alias_method :formatter=, :add_formatter + + # The formatter that will be used if no formatter has been set. + # Defaults to 'progress'. + def default_formatter + formatter_loader.default_formatter + end + + # Sets a fallback formatter to use if none other has been set. + # + # @example + # + # RSpec.configure do |rspec| + # rspec.default_formatter = 'doc' + # end + def default_formatter=(value) + formatter_loader.default_formatter = value + end + + # Returns a duplicate of the formatters currently loaded in + # the `FormatterLoader` for introspection. + # + # Note as this is a duplicate, any mutations will be disregarded. + # + # @return [Array] the formatters currently loaded + def formatters + formatter_loader.formatters.dup + end + + # @private + def formatter_loader + @formatter_loader ||= Formatters::Loader.new(Reporter.new(self)) + end + + # @private + # + # This buffer is used to capture all messages sent to the reporter during + # reporter initialization. It can then replay those messages after the + # formatter is correctly initialized. Otherwise, deprecation warnings + # during formatter initialization can cause an infinite loop. + class DeprecationReporterBuffer + def initialize + @calls = [] + end + + def deprecation(*args) + @calls << args + end + + def play_onto(reporter) + @calls.each do |args| + reporter.deprecation(*args) + end + end + end + + # @private + def reporter + # @reporter_buffer should only ever be set in this method to cover + # initialization of @reporter. + @reporter_buffer || @reporter ||= + begin + @reporter_buffer = DeprecationReporterBuffer.new + formatter_loader.setup_default output_stream, deprecation_stream + @reporter_buffer.play_onto(formatter_loader.reporter) + @reporter_buffer = nil + formatter_loader.reporter + end + end + + # @api private + # + # Defaults `profile_examples` to 10 examples when `@profile_examples` is + # `true`. + def profile_examples + profile = value_for(:profile_examples) { @profile_examples } + if profile && !profile.is_a?(Integer) + 10 + else + profile + end + end + + # @private + def files_or_directories_to_run=(*files) + files = files.flatten + + if (command == 'rspec' || Runner.running_in_drb?) && default_path && files.empty? + files << default_path + end + + @files_or_directories_to_run = files + @files_to_run = nil + end + + # The spec files RSpec will run. + # @return [Array] specified files about to run + def files_to_run + @files_to_run ||= get_files_to_run(@files_or_directories_to_run) + end + + # @private + def last_run_statuses + @last_run_statuses ||= Hash.new(UNKNOWN_STATUS).tap do |statuses| + if (path = example_status_persistence_file_path) + begin + ExampleStatusPersister.load_from(path).inject(statuses) do |hash, example| + hash[example.fetch(:example_id)] = example.fetch(:status) + hash + end + rescue SystemCallError => e + RSpec.warning "Could not read from #{path.inspect} (configured as " \ + "`config.example_status_persistence_file_path`) due " \ + "to a system error: #{e.inspect}. Please check that " \ + "the config option is set to an accessible, valid " \ + "file path", :call_site => nil + end + end + end + end + + # @private + UNKNOWN_STATUS = "unknown".freeze + + # @private + FAILED_STATUS = "failed".freeze + + # @private + def spec_files_with_failures + @spec_files_with_failures ||= last_run_statuses.inject(Set.new) do |files, (id, status)| + files << id.split(ON_SQUARE_BRACKETS).first if status == FAILED_STATUS + files + end.to_a + end + + # Creates a method that delegates to `example` including the submitted + # `args`. Used internally to add variants of `example` like `pending`: + # @param name [String] example name alias + # @param args [Array, Hash] metadata for the generated example + # + # @note The specific example alias below (`pending`) is already + # defined for you. + # @note Use with caution. This extends the language used in your + # specs, but does not add any additional documentation. We use this + # in RSpec to define methods like `focus` and `xit`, but we also add + # docs for those methods. + # + # @example + # RSpec.configure do |config| + # config.alias_example_to :pending, :pending => true + # end + # + # # This lets you do this: + # + # describe Thing do + # pending "does something" do + # thing = Thing.new + # end + # end + # + # # ... which is the equivalent of + # + # describe Thing do + # it "does something", :pending => true do + # thing = Thing.new + # end + # end + def alias_example_to(name, *args) + extra_options = Metadata.build_hash_from(args) + RSpec::Core::ExampleGroup.define_example_method(name, extra_options) + end + + # Creates a method that defines an example group with the provided + # metadata. Can be used to define example group/metadata shortcuts. + # + # @example + # RSpec.configure do |config| + # config.alias_example_group_to :describe_model, :type => :model + # end + # + # shared_context_for "model tests", :type => :model do + # # define common model test helper methods, `let` declarations, etc + # end + # + # # This lets you do this: + # + # RSpec.describe_model User do + # end + # + # # ... which is the equivalent of + # + # RSpec.describe User, :type => :model do + # end + # + # @note The defined aliased will also be added to the top level + # (e.g. `main` and from within modules) if + # `expose_dsl_globally` is set to true. + # @see #alias_example_to + # @see #expose_dsl_globally= + def alias_example_group_to(new_name, *args) + extra_options = Metadata.build_hash_from(args) + RSpec::Core::ExampleGroup.define_example_group_method(new_name, extra_options) + end + + # Define an alias for it_should_behave_like that allows different + # language (like "it_has_behavior" or "it_behaves_like") to be + # employed when including shared examples. + # + # @example + # RSpec.configure do |config| + # config.alias_it_behaves_like_to(:it_has_behavior, 'has behavior:') + # end + # + # # allows the user to include a shared example group like: + # + # describe Entity do + # it_has_behavior 'sortability' do + # let(:sortable) { Entity.new } + # end + # end + # + # # which is reported in the output as: + # # Entity + # # has behavior: sortability + # # ...sortability examples here + # + # @note Use with caution. This extends the language used in your + # specs, but does not add any additional documentation. We use this + # in RSpec to define `it_should_behave_like` (for backward + # compatibility), but we also add docs for that method. + def alias_it_behaves_like_to(new_name, report_label='') + RSpec::Core::ExampleGroup.define_nested_shared_group_method(new_name, report_label) + end + alias_method :alias_it_should_behave_like_to, :alias_it_behaves_like_to + + # Adds key/value pairs to the `inclusion_filter`. If `args` + # includes any symbols that are not part of the hash, each symbol + # is treated as a key in the hash with the value `true`. + # + # ### Note + # + # Filters set using this method can be overridden from the command line + # or config files (e.g. `.rspec`). + # + # @example + # # Given this declaration. + # describe "something", :foo => 'bar' do + # # ... + # end + # + # # Any of the following will include that group. + # config.filter_run_including :foo => 'bar' + # config.filter_run_including :foo => /^ba/ + # config.filter_run_including :foo => lambda {|v| v == 'bar'} + # config.filter_run_including :foo => lambda {|v,m| m[:foo] == 'bar'} + # + # # Given a proc with an arity of 1, the lambda is passed the value + # # related to the key, e.g. + # config.filter_run_including :foo => lambda {|v| v == 'bar'} + # + # # Given a proc with an arity of 2, the lambda is passed the value + # # related to the key, and the metadata itself e.g. + # config.filter_run_including :foo => lambda {|v,m| m[:foo] == 'bar'} + # + # filter_run_including :foo # same as filter_run_including :foo => true + def filter_run_including(*args) + meta = Metadata.build_hash_from(args, :warn_about_example_group_filtering) + filter_manager.include_with_low_priority meta + static_config_filter_manager.include_with_low_priority Metadata.deep_hash_dup(meta) + end + + alias_method :filter_run, :filter_run_including + + # Clears and reassigns the `inclusion_filter`. Set to `nil` if you don't + # want any inclusion filter at all. + # + # ### Warning + # + # This overrides any inclusion filters/tags set on the command line or in + # configuration files. + def inclusion_filter=(filter) + meta = Metadata.build_hash_from([filter], :warn_about_example_group_filtering) + filter_manager.include_only meta + end + + alias_method :filter=, :inclusion_filter= + + # Returns the `inclusion_filter`. If none has been set, returns an empty + # hash. + def inclusion_filter + filter_manager.inclusions + end + + alias_method :filter, :inclusion_filter + + # Adds key/value pairs to the `exclusion_filter`. If `args` + # includes any symbols that are not part of the hash, each symbol + # is treated as a key in the hash with the value `true`. + # + # ### Note + # + # Filters set using this method can be overridden from the command line + # or config files (e.g. `.rspec`). + # + # @example + # # Given this declaration. + # describe "something", :foo => 'bar' do + # # ... + # end + # + # # Any of the following will exclude that group. + # config.filter_run_excluding :foo => 'bar' + # config.filter_run_excluding :foo => /^ba/ + # config.filter_run_excluding :foo => lambda {|v| v == 'bar'} + # config.filter_run_excluding :foo => lambda {|v,m| m[:foo] == 'bar'} + # + # # Given a proc with an arity of 1, the lambda is passed the value + # # related to the key, e.g. + # config.filter_run_excluding :foo => lambda {|v| v == 'bar'} + # + # # Given a proc with an arity of 2, the lambda is passed the value + # # related to the key, and the metadata itself e.g. + # config.filter_run_excluding :foo => lambda {|v,m| m[:foo] == 'bar'} + # + # filter_run_excluding :foo # same as filter_run_excluding :foo => true + def filter_run_excluding(*args) + meta = Metadata.build_hash_from(args, :warn_about_example_group_filtering) + filter_manager.exclude_with_low_priority meta + static_config_filter_manager.exclude_with_low_priority Metadata.deep_hash_dup(meta) + end + + # Clears and reassigns the `exclusion_filter`. Set to `nil` if you don't + # want any exclusion filter at all. + # + # ### Warning + # + # This overrides any exclusion filters/tags set on the command line or in + # configuration files. + def exclusion_filter=(filter) + meta = Metadata.build_hash_from([filter], :warn_about_example_group_filtering) + filter_manager.exclude_only meta + end + + # Returns the `exclusion_filter`. If none has been set, returns an empty + # hash. + def exclusion_filter + filter_manager.exclusions + end + + # Tells RSpec to include `mod` in example groups. Methods defined in + # `mod` are exposed to examples (not example groups). Use `filters` to + # constrain the groups or examples in which to include the module. + # + # @example + # + # module AuthenticationHelpers + # def login_as(user) + # # ... + # end + # end + # + # module UserHelpers + # def users(username) + # # ... + # end + # end + # + # RSpec.configure do |config| + # config.include(UserHelpers) # included in all modules + # config.include(AuthenticationHelpers, :type => :request) + # end + # + # describe "edit profile", :type => :request do + # it "can be viewed by owning user" do + # login_as users(:jdoe) + # get "/profiles/jdoe" + # assert_select ".username", :text => 'jdoe' + # end + # end + # + # @note Filtered module inclusions can also be applied to + # individual examples that have matching metadata. Just like + # Ruby's object model is that every object has a singleton class + # which has only a single instance, RSpec's model is that every + # example has a singleton example group containing just the one + # example. + # + # @see #extend + # @see #prepend + def include(mod, *filters) + meta = Metadata.build_hash_from(filters, :warn_about_example_group_filtering) + @include_modules.append(mod, meta) + configure_existing_groups(mod, meta, :safe_include) + end + + # Tells RSpec to extend example groups with `mod`. Methods defined in + # `mod` are exposed to example groups (not examples). Use `filters` to + # constrain the groups to extend. + # + # Similar to `include`, but behavior is added to example groups, which + # are classes, rather than the examples, which are instances of those + # classes. + # + # @example + # + # module UiHelpers + # def run_in_browser + # # ... + # end + # end + # + # RSpec.configure do |config| + # config.extend(UiHelpers, :type => :request) + # end + # + # describe "edit profile", :type => :request do + # run_in_browser + # + # it "does stuff in the client" do + # # ... + # end + # end + # + # @see #include + # @see #prepend + def extend(mod, *filters) + meta = Metadata.build_hash_from(filters, :warn_about_example_group_filtering) + @extend_modules.append(mod, meta) + configure_existing_groups(mod, meta, :safe_extend) + end + + if RSpec::Support::RubyFeatures.module_prepends_supported? + # Tells RSpec to prepend example groups with `mod`. Methods defined in + # `mod` are exposed to examples (not example groups). Use `filters` to + # constrain the groups in which to prepend the module. + # + # Similar to `include`, but module is included before the example group's class + # in the ancestor chain. + # + # @example + # + # module OverrideMod + # def override_me + # "overridden" + # end + # end + # + # RSpec.configure do |config| + # config.prepend(OverrideMod, :method => :prepend) + # end + # + # describe "overriding example's class", :method => :prepend do + # it "finds the user" do + # self.class.class_eval do + # def override_me + # end + # end + # override_me # => "overridden" + # # ... + # end + # end + # + # @see #include + # @see #extend + def prepend(mod, *filters) + meta = Metadata.build_hash_from(filters, :warn_about_example_group_filtering) + @prepend_modules.append(mod, meta) + configure_existing_groups(mod, meta, :safe_prepend) + end + end + + # @private + # + # Used internally to extend a group with modules using `include`, `prepend` and/or + # `extend`. + def configure_group(group) + configure_group_with group, @include_modules, :safe_include + configure_group_with group, @extend_modules, :safe_extend + configure_group_with group, @prepend_modules, :safe_prepend + end + + # @private + def configure_group_with(group, module_list, application_method) + module_list.items_for(group.metadata).each do |mod| + __send__(application_method, mod, group) + end + end + + # @private + def configure_existing_groups(mod, meta, application_method) + RSpec.world.all_example_groups.each do |group| + next unless meta.empty? || MetadataFilter.apply?(:any?, meta, group.metadata) + __send__(application_method, mod, group) + end + end + + # @private + # + # Used internally to extend the singleton class of a single example's + # example group instance with modules using `include` and/or `extend`. + def configure_example(example) + singleton_group = example.example_group_instance.singleton_class + + # We replace the metadata so that SharedExampleGroupModule#included + # has access to the example's metadata[:location]. + singleton_group.with_replaced_metadata(example.metadata) do + modules = @include_modules.items_for(example.metadata) + modules.each do |mod| + safe_include(mod, example.example_group_instance.singleton_class) + end + + MemoizedHelpers.define_helpers_on(singleton_group) unless modules.empty? + end + end + + if RSpec::Support::RubyFeatures.module_prepends_supported? + # @private + def safe_prepend(mod, host) + host.__send__(:prepend, mod) unless host < mod + end + end + + # @private + def requires=(paths) + directories = ['lib', default_path].select { |p| File.directory? p } + RSpec::Core::RubyProject.add_to_load_path(*directories) + paths.each { |path| require path } + @requires += paths + end + + # @private + if RUBY_VERSION.to_f >= 1.9 + # @private + def safe_include(mod, host) + host.__send__(:include, mod) unless host < mod + end + + # @private + def safe_extend(mod, host) + host.extend(mod) unless host.singleton_class < mod + end + else # for 1.8.7 + # :nocov: + # @private + def safe_include(mod, host) + host.__send__(:include, mod) unless host.included_modules.include?(mod) + end + + # @private + def safe_extend(mod, host) + host.extend(mod) unless (class << host; self; end).included_modules.include?(mod) + end + # :nocov: + end + + # @private + def configure_mock_framework + RSpec::Core::ExampleGroup.__send__(:include, mock_framework) + conditionally_disable_mocks_monkey_patching + end + + # @private + def configure_expectation_framework + expectation_frameworks.each do |framework| + RSpec::Core::ExampleGroup.__send__(:include, framework) + end + conditionally_disable_expectations_monkey_patching + end + + # @private + def load_spec_files + files_to_run.uniq.each do |f| + file = File.expand_path(f) + load file + loaded_spec_files << file + end + + @spec_files_loaded = true + end + + # @private + DEFAULT_FORMATTER = lambda { |string| string } + + # Formats the docstring output using the block provided. + # + # @example + # # This will strip the descriptions of both examples and example + # # groups. + # RSpec.configure do |config| + # config.format_docstrings { |s| s.strip } + # end + def format_docstrings(&block) + @format_docstrings_block = block_given? ? block : DEFAULT_FORMATTER + end + + # @private + def format_docstrings_block + @format_docstrings_block ||= DEFAULT_FORMATTER + end + + # @private + # @macro [attach] delegate_to_ordering_manager + # @!method $1 + def self.delegate_to_ordering_manager(*methods) + methods.each do |method| + define_method method do |*args, &block| + ordering_manager.__send__(method, *args, &block) + end + end + end + + # @macro delegate_to_ordering_manager + # + # Sets the seed value and sets the default global ordering to random. + delegate_to_ordering_manager :seed= + + # @macro delegate_to_ordering_manager + # Seed for random ordering (default: generated randomly each run). + # + # When you run specs with `--order random`, RSpec generates a random seed + # for the randomization and prints it to the `output_stream` (assuming + # you're using RSpec's built-in formatters). If you discover an ordering + # dependency (i.e. examples fail intermittently depending on order), set + # this (on Configuration or on the command line with `--seed`) to run + # using the same seed while you debug the issue. + # + # We recommend, actually, that you use the command line approach so you + # don't accidentally leave the seed encoded. + delegate_to_ordering_manager :seed + + # @macro delegate_to_ordering_manager + # + # Sets the default global order and, if order is `'rand:'`, also + # sets the seed. + delegate_to_ordering_manager :order= + + # @macro delegate_to_ordering_manager + # Registers a named ordering strategy that can later be + # used to order an example group's subgroups by adding + # `:order => ` metadata to the example group. + # + # @param name [Symbol] The name of the ordering. + # @yield Block that will order the given examples or example groups + # @yieldparam list [Array, + # Array] The examples or groups to order + # @yieldreturn [Array, + # Array] The re-ordered examples or groups + # + # @example + # RSpec.configure do |rspec| + # rspec.register_ordering :reverse do |list| + # list.reverse + # end + # end + # + # describe MyClass, :order => :reverse do + # # ... + # end + # + # @note Pass the symbol `:global` to set the ordering strategy that + # will be used to order the top-level example groups and any example + # groups that do not have declared `:order` metadata. + delegate_to_ordering_manager :register_ordering + + # @private + delegate_to_ordering_manager :seed_used?, :ordering_registry + + # Set Ruby warnings on or off. + def warnings=(value) + $VERBOSE = !!value + end + + # @return [Boolean] Whether or not ruby warnings are enabled. + def warnings? + $VERBOSE + end + + # Exposes the current running example via the named + # helper method. RSpec 2.x exposed this via `example`, + # but in RSpec 3.0, the example is instead exposed via + # an arg yielded to `it`, `before`, `let`, etc. However, + # some extension gems (such as Capybara) depend on the + # RSpec 2.x's `example` method, so this config option + # can be used to maintain compatibility. + # + # @param method_name [Symbol] the name of the helper method + # + # @example + # + # RSpec.configure do |rspec| + # rspec.expose_current_running_example_as :example + # end + # + # describe MyClass do + # before do + # # `example` can be used here because of the above config. + # do_something if example.metadata[:type] == "foo" + # end + # end + def expose_current_running_example_as(method_name) + ExposeCurrentExample.module_exec do + extend RSpec::SharedContext + let(method_name) { |ex| ex } + end + + include ExposeCurrentExample + end + + # @private + module ExposeCurrentExample; end + + # Turns deprecation warnings into errors, in order to surface + # the full backtrace of the call site. This can be useful when + # you need more context to address a deprecation than the + # single-line call site normally provided. + # + # @example + # + # RSpec.configure do |rspec| + # rspec.raise_errors_for_deprecations! + # end + def raise_errors_for_deprecations! + self.deprecation_stream = Formatters::DeprecationFormatter::RaiseErrorStream.new + end + + # Enables zero monkey patching mode for RSpec. It removes monkey + # patching of the top-level DSL methods (`describe`, + # `shared_examples_for`, etc) onto `main` and `Module`, instead + # requiring you to prefix these methods with `RSpec.`. It enables + # expect-only syntax for rspec-mocks and rspec-expectations. It + # simply disables monkey patching on whatever pieces of RSpec + # the user is using. + # + # @note It configures rspec-mocks and rspec-expectations only + # if the user is using those (either explicitly or implicitly + # by not setting `mock_with` or `expect_with` to anything else). + # + # @note If the user uses this options with `mock_with :mocha` + # (or similiar) they will still have monkey patching active + # in their test environment from mocha. + # + # @example + # + # # It disables all monkey patching. + # RSpec.configure do |config| + # config.disable_monkey_patching! + # end + # + # # Is an equivalent to + # RSpec.configure do |config| + # config.expose_dsl_globally = false + # + # config.mock_with :rspec do |mocks| + # mocks.syntax = :expect + # mocks.patch_marshal_to_support_partial_doubles = false + # end + # + # config.mock_with :rspec do |expectations| + # expectations.syntax = :expect + # end + # end + def disable_monkey_patching! + self.expose_dsl_globally = false + self.disable_monkey_patching = true + conditionally_disable_mocks_monkey_patching + conditionally_disable_expectations_monkey_patching + end + + # @private + attr_accessor :disable_monkey_patching + + # Defines a callback that can assign derived metadata values. + # + # @param filters [Array, Hash] metadata filters that determine + # which example or group metadata hashes the callback will be triggered + # for. If none are given, the callback will be run against the metadata + # hashes of all groups and examples. + # @yieldparam metadata [Hash] original metadata hash from an example or + # group. Mutate this in your block as needed. + # + # @example + # RSpec.configure do |config| + # # Tag all groups and examples in the spec/unit directory with + # # :type => :unit + # config.define_derived_metadata(:file_path => %r{/spec/unit/}) do |metadata| + # metadata[:type] = :unit + # end + # end + def define_derived_metadata(*filters, &block) + meta = Metadata.build_hash_from(filters, :warn_about_example_group_filtering) + @derived_metadata_blocks.append(block, meta) + end + + # @private + def apply_derived_metadata_to(metadata) + @derived_metadata_blocks.items_for(metadata).each do |block| + block.call(metadata) + end + end + + # Defines a `before` hook. See {Hooks#before} for full docs. + # + # This method differs from {Hooks#before} in only one way: it supports + # the `:suite` scope. Hooks with the `:suite` scope will be run once before + # the first example of the entire suite is executed. + # + # @see #prepend_before + # @see #after + # @see #append_after + def before(*args, &block) + handle_suite_hook(args, @before_suite_hooks, :push, + Hooks::BeforeHook, block) || super(*args, &block) + end + alias_method :append_before, :before + + # Adds `block` to the start of the list of `before` blocks in the same + # scope (`:example`, `:context`, or `:suite`), in contrast to {#before}, + # which adds the hook to the end of the list. + # + # See {Hooks#before} for full `before` hook docs. + # + # This method differs from {Hooks#prepend_before} in only one way: it supports + # the `:suite` scope. Hooks with the `:suite` scope will be run once before + # the first example of the entire suite is executed. + # + # @see #before + # @see #after + # @see #append_after + def prepend_before(*args, &block) + handle_suite_hook(args, @before_suite_hooks, :unshift, + Hooks::BeforeHook, block) || super(*args, &block) + end + + # Defines a `after` hook. See {Hooks#after} for full docs. + # + # This method differs from {Hooks#after} in only one way: it supports + # the `:suite` scope. Hooks with the `:suite` scope will be run once after + # the last example of the entire suite is executed. + # + # @see #append_after + # @see #before + # @see #prepend_before + def after(*args, &block) + handle_suite_hook(args, @after_suite_hooks, :unshift, + Hooks::AfterHook, block) || super(*args, &block) + end + alias_method :prepend_after, :after + + # Adds `block` to the end of the list of `after` blocks in the same + # scope (`:example`, `:context`, or `:suite`), in contrast to {#after}, + # which adds the hook to the start of the list. + # + # See {Hooks#after} for full `after` hook docs. + # + # This method differs from {Hooks#append_after} in only one way: it supports + # the `:suite` scope. Hooks with the `:suite` scope will be run once after + # the last example of the entire suite is executed. + # + # @see #append_after + # @see #before + # @see #prepend_before + def append_after(*args, &block) + handle_suite_hook(args, @after_suite_hooks, :push, + Hooks::AfterHook, block) || super(*args, &block) + end + + # @private + def with_suite_hooks + return yield if dry_run? + + hook_context = SuiteHookContext.new + begin + run_hooks_with(@before_suite_hooks, hook_context) + yield + ensure + run_hooks_with(@after_suite_hooks, hook_context) + end + end + + # @private + # Holds the various registered hooks. Here we use a FilterableItemRepository + # implementation that is specifically optimized for the read/write patterns + # of the config object. + def hooks + @hooks ||= HookCollections.new(self, FilterableItemRepository::QueryOptimized) + end + + private + + def handle_suite_hook(args, collection, append_or_prepend, hook_type, block) + scope, meta = *args + return nil unless scope == :suite + + if meta + # TODO: in RSpec 4, consider raising an error here. + # We warn only for backwards compatibility. + RSpec.warn_with "WARNING: `:suite` hooks do not support metadata since " \ + "they apply to the suite as a whole rather than " \ + "any individual example or example group that has metadata. " \ + "The metadata you have provided (#{meta.inspect}) will be ignored." + end + + collection.__send__(append_or_prepend, hook_type.new(block, {})) + end + + def run_hooks_with(hooks, hook_context) + hooks.each { |h| h.run(hook_context) } + end + + def get_files_to_run(paths) + files = FlatMap.flat_map(paths_to_check(paths)) do |path| + path = path.gsub(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR + File.directory?(path) ? gather_directories(path) : extract_location(path) + end.sort.uniq + + return files unless only_failures? + relative_files = files.map { |f| Metadata.relative_path(File.expand_path f) } + intersection = (relative_files & spec_files_with_failures.to_a) + intersection.empty? ? files : intersection + end + + def paths_to_check(paths) + return paths if pattern_might_load_specs_from_vendored_dirs? + paths + [Dir.getwd] + end + + def pattern_might_load_specs_from_vendored_dirs? + pattern.split(File::SEPARATOR).first.include?('**') + end + + def gather_directories(path) + include_files = get_matching_files(path, pattern) + exclude_files = get_matching_files(path, exclude_pattern) + (include_files - exclude_files).sort.uniq + end + + def get_matching_files(path, pattern) + Dir[file_glob_from(path, pattern)].map { |file| File.expand_path(file) } + end + + def file_glob_from(path, pattern) + stripped = "{#{pattern.gsub(/\s*,\s*/, ',')}}" + return stripped if pattern =~ /^(\.\/)?#{Regexp.escape path}/ || absolute_pattern?(pattern) + File.join(path, stripped) + end + + if RSpec::Support::OS.windows? + # :nocov: + def absolute_pattern?(pattern) + pattern =~ /\A[A-Z]:\\/ || windows_absolute_network_path?(pattern) + end + + def windows_absolute_network_path?(pattern) + return false unless ::File::ALT_SEPARATOR + pattern.start_with?(::File::ALT_SEPARATOR + ::File::ALT_SEPARATOR) + end + # :nocov: + else + def absolute_pattern?(pattern) + pattern.start_with?(File::Separator) + end + end + + # @private + ON_SQUARE_BRACKETS = /[\[\]]/ + + def extract_location(path) + match = /^(.*?)((?:\:\d+)+)$/.match(path) + + if match + captures = match.captures + path, lines = captures[0], captures[1][1..-1].split(":").map { |n| n.to_i } + filter_manager.add_location path, lines + else + path, scoped_ids = path.split(ON_SQUARE_BRACKETS) + filter_manager.add_ids(path, scoped_ids.split(/\s*,\s*/)) if scoped_ids + end + + return [] if path == default_path + path + end + + def command + $0.split(File::SEPARATOR).last + end + + def value_for(key) + @preferred_options.fetch(key) { yield } + end + + def define_built_in_hooks + around(:example, :aggregate_failures => true) do |procsy| + begin + aggregate_failures(nil, :hide_backtrace => true, &procsy) + rescue Exception => exception + procsy.example.set_aggregate_failures_exception(exception) + end + end + end + + def assert_no_example_groups_defined(config_option) + return unless RSpec.world.example_groups.any? + + raise MustBeConfiguredBeforeExampleGroupsError.new( + "RSpec's #{config_option} configuration option must be configured before " \ + "any example groups are defined, but you have already defined a group." + ) + end + + def output_to_tty?(output=output_stream) + tty? || (output.respond_to?(:tty?) && output.tty?) + end + + def conditionally_disable_mocks_monkey_patching + return unless disable_monkey_patching && rspec_mocks_loaded? + + RSpec::Mocks.configuration.tap do |config| + config.syntax = :expect + config.patch_marshal_to_support_partial_doubles = false + end + end + + def conditionally_disable_expectations_monkey_patching + return unless disable_monkey_patching && rspec_expectations_loaded? + + RSpec::Expectations.configuration.syntax = :expect + end + + def rspec_mocks_loaded? + defined?(RSpec::Mocks.configuration) + end + + def rspec_expectations_loaded? + defined?(RSpec::Expectations.configuration) + end + + def update_pattern_attr(name, value) + if @spec_files_loaded + RSpec.warning "Configuring `#{name}` to #{value} has no effect since " \ + "RSpec has already loaded the spec files." + end + + instance_variable_set(:"@#{name}", value) + @files_to_run = nil + end + + def clear_values_derived_from_example_status_persistence_file_path + @last_run_statuses = nil + @spec_files_with_failures = nil + end + end + # rubocop:enable Style/ClassLength + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/configuration_options.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/configuration_options.rb new file mode 100644 index 0000000..86dee41 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/configuration_options.rb @@ -0,0 +1,191 @@ +require 'erb' +require 'shellwords' + +module RSpec + module Core + # Responsible for utilizing externally provided configuration options, + # whether via the command line, `.rspec`, `~/.rspec`, `.rspec-local` + # or a custom options file. + class ConfigurationOptions + # @param args [Array] command line arguments + def initialize(args) + @args = args.dup + organize_options + end + + # Updates the provided {Configuration} instance based on the provided + # external configuration options. + # + # @param config [Configuration] the configuration instance to update + def configure(config) + process_options_into config + configure_filter_manager config.filter_manager + load_formatters_into config + end + + # @api private + # Updates the provided {FilterManager} based on the filter options. + # @param filter_manager [FilterManager] instance to update + def configure_filter_manager(filter_manager) + @filter_manager_options.each do |command, value| + filter_manager.__send__ command, value + end + end + + # @return [Hash] the final merged options, drawn from all external sources + attr_reader :options + + private + + def organize_options + @filter_manager_options = [] + + @options = (file_options << command_line_options << env_options).each do |opts| + @filter_manager_options << [:include, opts.delete(:inclusion_filter)] if opts.key?(:inclusion_filter) + @filter_manager_options << [:exclude, opts.delete(:exclusion_filter)] if opts.key?(:exclusion_filter) + end + + @options = @options.inject(:libs => [], :requires => []) do |hash, opts| + hash.merge(opts) do |key, oldval, newval| + [:libs, :requires].include?(key) ? oldval + newval : newval + end + end + end + + UNFORCED_OPTIONS = Set.new([ + :requires, :profile, :drb, :libs, :files_or_directories_to_run, + :full_description, :full_backtrace, :tty + ]) + + UNPROCESSABLE_OPTIONS = Set.new([:formatters]) + + def force?(key) + !UNFORCED_OPTIONS.include?(key) + end + + def order(keys) + OPTIONS_ORDER.reverse.each do |key| + keys.unshift(key) if keys.delete(key) + end + keys + end + + OPTIONS_ORDER = [ + # It's important to set this before anything that might issue a + # deprecation (or otherwise access the reporter). + :deprecation_stream, + + # load paths depend on nothing, but must be set before `requires` + # to support load-path-relative requires. + :libs, + + # `files_or_directories_to_run` uses `default_path` so it must be + # set before it. + :default_path, :only_failures, + + # These must be set before `requires` to support checking + # `config.files_to_run` from within `spec_helper.rb` when a + # `-rspec_helper` option is used. + :files_or_directories_to_run, :pattern, :exclude_pattern, + + # Necessary so that the `--seed` option is applied before requires, + # in case required files do something with the provided seed. + # (such as seed global randomization with it). + :order, + + # In general, we want to require the specified files as early as + # possible. The `--require` option is specifically intended to allow + # early requires. For later requires, they can just put the require in + # their spec files, but `--require` provides a unique opportunity for + # users to instruct RSpec to load an extension file early for maximum + # flexibility. + :requires + ] + + def process_options_into(config) + opts = options.reject { |k, _| UNPROCESSABLE_OPTIONS.include? k } + + order(opts.keys).each do |key| + force?(key) ? config.force(key => opts[key]) : config.__send__("#{key}=", opts[key]) + end + end + + def load_formatters_into(config) + options[:formatters].each { |pair| config.add_formatter(*pair) } if options[:formatters] + end + + def file_options + custom_options_file ? [custom_options] : [global_options, project_options, local_options] + end + + def env_options + return {} unless ENV['SPEC_OPTS'] + + parse_args_ignoring_files_or_dirs_to_run( + Shellwords.split(ENV["SPEC_OPTS"]), + "ENV['SPEC_OPTS']" + ) + end + + def command_line_options + @command_line_options ||= Parser.parse(@args) + end + + def custom_options + options_from(custom_options_file) + end + + def local_options + @local_options ||= options_from(local_options_file) + end + + def project_options + @project_options ||= options_from(project_options_file) + end + + def global_options + @global_options ||= options_from(global_options_file) + end + + def options_from(path) + args = args_from_options_file(path) + parse_args_ignoring_files_or_dirs_to_run(args, path) + end + + def parse_args_ignoring_files_or_dirs_to_run(args, source) + options = Parser.parse(args, source) + options.delete(:files_or_directories_to_run) + options + end + + def args_from_options_file(path) + return [] unless path && File.exist?(path) + config_string = options_file_as_erb_string(path) + FlatMap.flat_map(config_string.split(/\n+/), &:shellsplit) + end + + def options_file_as_erb_string(path) + ERB.new(File.read(path), nil, '-').result(binding) + end + + def custom_options_file + command_line_options[:custom_options_file] + end + + def project_options_file + "./.rspec" + end + + def local_options_file + "./.rspec-local" + end + + def global_options_file + File.join(File.expand_path("~"), ".rspec") + rescue ArgumentError + RSpec.warning "Unable to find ~/.rspec because the HOME environment variable is not set" + nil + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/drb.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/drb.rb new file mode 100644 index 0000000..55e6392 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/drb.rb @@ -0,0 +1,111 @@ +require 'drb/drb' + +module RSpec + module Core + # @private + class DRbRunner + def initialize(options, configuration=RSpec.configuration) + @options = options + @configuration = configuration + end + + def drb_port + @options.options[:drb_port] || ENV['RSPEC_DRB'] || 8989 + end + + def run(err, out) + begin + DRb.start_service("druby://localhost:0") + rescue SocketError, Errno::EADDRNOTAVAIL + DRb.start_service("druby://:0") + end + spec_server = DRbObject.new_with_uri("druby://127.0.0.1:#{drb_port}") + spec_server.run(drb_argv, err, out) + end + + def drb_argv + @drb_argv ||= begin + @options.configure_filter_manager(@configuration.filter_manager) + DRbOptions.new(@options.options, @configuration.filter_manager).options + end + end + end + + # @private + class DRbOptions + def initialize(submitted_options, filter_manager) + @submitted_options = submitted_options + @filter_manager = filter_manager + end + + def options + argv = [] + argv << "--color" if @submitted_options[:color] + argv << "--profile" if @submitted_options[:profile_examples] + argv << "--backtrace" if @submitted_options[:full_backtrace] + argv << "--tty" if @submitted_options[:tty] + argv << "--fail-fast" if @submitted_options[:fail_fast] + argv << "--options" << @submitted_options[:custom_options_file] if @submitted_options[:custom_options_file] + argv << "--order" << @submitted_options[:order] if @submitted_options[:order] + + add_failure_exit_code(argv) + add_full_description(argv) + add_filter(argv, :inclusion, @filter_manager.inclusions) + add_filter(argv, :exclusion, @filter_manager.exclusions) + add_formatters(argv) + add_libs(argv) + add_requires(argv) + + argv + @submitted_options[:files_or_directories_to_run] + end + + def add_failure_exit_code(argv) + return unless @submitted_options[:failure_exit_code] + + argv << "--failure-exit-code" << @submitted_options[:failure_exit_code].to_s + end + + def add_full_description(argv) + return unless @submitted_options[:full_description] + + # The argument to --example is regexp-escaped before being stuffed + # into a regexp when received for the first time (see OptionParser). + # Hence, merely grabbing the source of this regexp will retain the + # backslashes, so we must remove them. + @submitted_options[:full_description].each do |description| + argv << "--example" << description.source.delete('\\') + end + end + + CONDITIONAL_FILTERS = [:if, :unless] + + def add_filter(argv, name, hash) + hash.each_pair do |k, v| + next if CONDITIONAL_FILTERS.include?(k) + tag = name == :inclusion ? k.to_s : "~#{k}" + tag << ":#{v}" if v.is_a?(String) + argv << "--tag" << tag + end unless hash.empty? + end + + def add_formatters(argv) + @submitted_options[:formatters].each do |pair| + argv << "--format" << pair[0] + argv << "--out" << pair[1] if pair[1] + end if @submitted_options[:formatters] + end + + def add_libs(argv) + @submitted_options[:libs].each do |path| + argv << "-I" << path + end if @submitted_options[:libs] + end + + def add_requires(argv) + @submitted_options[:requires].each do |path| + argv << "--require" << path + end if @submitted_options[:requires] + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/dsl.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/dsl.rb new file mode 100644 index 0000000..9f290b9 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/dsl.rb @@ -0,0 +1,96 @@ +module RSpec + module Core + # DSL defines methods to group examples, most notably `describe`, + # and exposes them as class methods of {RSpec}. They can also be + # exposed globally (on `main` and instances of `Module`) through + # the {Configuration} option `expose_dsl_globally`. + # + # By default the methods `describe`, `context` and `example_group` + # are exposed. These methods define a named context for one or + # more examples. The given block is evaluated in the context of + # a generated subclass of {RSpec::Core::ExampleGroup}. + # + # ## Examples: + # + # RSpec.describe "something" do + # context "when something is a certain way" do + # it "does something" do + # # example code goes here + # end + # end + # end + # + # @see ExampleGroup + # @see ExampleGroup.example_group + module DSL + # @private + def self.example_group_aliases + @example_group_aliases ||= [] + end + + # @private + def self.exposed_globally? + @exposed_globally ||= false + end + + # @private + def self.expose_example_group_alias(name) + return if example_group_aliases.include?(name) + + example_group_aliases << name + + (class << RSpec; self; end).__send__(:define_method, name) do |*args, &example_group_block| + RSpec.world.register RSpec::Core::ExampleGroup.__send__(name, *args, &example_group_block) + end + + expose_example_group_alias_globally(name) if exposed_globally? + end + + class << self + # @private + attr_accessor :top_level + end + + # Adds the describe method to Module and the top level binding. + # @api private + def self.expose_globally! + return if exposed_globally? + + example_group_aliases.each do |method_name| + expose_example_group_alias_globally(method_name) + end + + @exposed_globally = true + end + + # Removes the describe method from Module and the top level binding. + # @api private + def self.remove_globally! + return unless exposed_globally? + + example_group_aliases.each do |method_name| + change_global_dsl { undef_method method_name } + end + + @exposed_globally = false + end + + # @private + def self.expose_example_group_alias_globally(method_name) + change_global_dsl do + remove_method(method_name) if method_defined?(method_name) + define_method(method_name) { |*a, &b| ::RSpec.__send__(method_name, *a, &b) } + end + end + + # @private + def self.change_global_dsl(&changes) + (class << top_level; self; end).class_exec(&changes) + Module.class_exec(&changes) + end + end + end +end + +# Capture main without an eval. +::RSpec::Core::DSL.top_level = self diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/example.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/example.rb new file mode 100644 index 0000000..3b46ed8 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/example.rb @@ -0,0 +1,573 @@ +module RSpec + module Core + # Wrapper for an instance of a subclass of {ExampleGroup}. An instance of + # `RSpec::Core::Example` is returned by example definition methods + # such as {ExampleGroup.it it} and is yielded to the {ExampleGroup.it it}, + # {Hooks#before before}, {Hooks#after after}, {Hooks#around around}, + # {MemoizedHelpers::ClassMethods#let let} and + # {MemoizedHelpers::ClassMethods#subject subject} blocks. + # + # This allows us to provide rich metadata about each individual + # example without adding tons of methods directly to the ExampleGroup + # that users may inadvertantly redefine. + # + # Useful for configuring logging and/or taking some action based + # on the state of an example's metadata. + # + # @example + # + # RSpec.configure do |config| + # config.before do |example| + # log example.description + # end + # + # config.after do |example| + # log example.description + # end + # + # config.around do |example| + # log example.description + # example.run + # end + # end + # + # shared_examples "auditable" do + # it "does something" do + # log "#{example.full_description}: #{auditable.inspect}" + # auditable.should do_something + # end + # end + # + # @see ExampleGroup + # @note Example blocks are evaluated in the context of an instance + # of an `ExampleGroup`, not in the context of an instance of `Example`. + class Example + # @private + # + # Used to define methods that delegate to this example's metadata. + def self.delegate_to_metadata(key) + define_method(key) { @metadata[key] } + end + + # @return [ExecutionResult] represents the result of running this example. + delegate_to_metadata :execution_result + # @return [String] the relative path to the file where this example was + # defined. + delegate_to_metadata :file_path + # @return [String] the full description (including the docstrings of + # all parent example groups). + delegate_to_metadata :full_description + # @return [String] the exact source location of this example in a form + # like `./path/to/spec.rb:17` + delegate_to_metadata :location + # @return [Boolean] flag that indicates that the example is not expected + # to pass. It will be run and will either have a pending result (if a + # failure occurs) or a failed result (if no failure occurs). + delegate_to_metadata :pending + # @return [Boolean] flag that will cause the example to not run. + # The {ExecutionResult} status will be `:pending`. + delegate_to_metadata :skip + + # Returns the string submitted to `example` or its aliases (e.g. + # `specify`, `it`, etc). If no string is submitted (e.g. + # `it { is_expected.to do_something }`) it returns the message generated + # by the matcher if there is one, otherwise returns a message including + # the location of the example. + def description + description = if metadata[:description].to_s.empty? + location_description + else + metadata[:description] + end + + RSpec.configuration.format_docstrings_block.call(description) + end + + # Returns a description of the example that always includes the location. + def inspect_output + inspect_output = "\"#{description}\"" + unless metadata[:description].to_s.empty? + inspect_output << " (#{location})" + end + inspect_output + end + + # Returns the location-based argument that can be passed to the `rspec` command to rerun this example. + def location_rerun_argument + @location_rerun_argument ||= begin + loaded_spec_files = RSpec.configuration.loaded_spec_files + + Metadata.ascending(metadata) do |meta| + return meta[:location] if loaded_spec_files.include?(meta[:absolute_file_path]) + end + end + end + + # Returns the location-based argument that can be passed to the `rspec` command to rerun this example. + # + # @deprecated Use {#location_rerun_argument} instead. + # @note If there are multiple examples identified by this location, they will use {#id} + # to rerun instead, but this method will still return the location (that's why it is deprecated!). + def rerun_argument + location_rerun_argument + end + + # @return [String] the unique id of this example. Pass + # this at the command line to re-run this exact example. + def id + @id ||= Metadata.id_from(metadata) + end + + # @attr_reader + # + # Returns the first exception raised in the context of running this + # example (nil if no exception is raised). + attr_reader :exception + + # @attr_reader + # + # Returns the metadata object associated with this example. + attr_reader :metadata + + # @attr_reader + # @private + # + # Returns the example_group_instance that provides the context for + # running this example. + attr_reader :example_group_instance + + # @attr + # @private + attr_accessor :clock + + # Creates a new instance of Example. + # @param example_group_class [Class] the subclass of ExampleGroup in which + # this Example is declared + # @param description [String] the String passed to the `it` method (or + # alias) + # @param user_metadata [Hash] additional args passed to `it` to be used as + # metadata + # @param example_block [Proc] the block of code that represents the + # example + # @api private + def initialize(example_group_class, description, user_metadata, example_block=nil) + @example_group_class = example_group_class + @example_block = example_block + + @metadata = Metadata::ExampleHash.create( + @example_group_class.metadata, user_metadata, + example_group_class.method(:next_runnable_index_for), + description, example_block + ) + + # This should perhaps be done in `Metadata::ExampleHash.create`, + # but the logic there has no knowledge of `RSpec.world` and we + # want to keep it that way. It's easier to just assign it here. + @metadata[:last_run_status] = RSpec.configuration.last_run_statuses[id] + + @example_group_instance = @exception = nil + @clock = RSpec::Core::Time + @reporter = RSpec::Core::NullReporter + end + + # @return [RSpec::Core::Reporter] the current reporter for the example + attr_reader :reporter + + # Returns the example group class that provides the context for running + # this example. + def example_group + @example_group_class + end + + alias_method :pending?, :pending + alias_method :skipped?, :skip + + # @api private + # instance_execs the block passed to the constructor in the context of + # the instance of {ExampleGroup}. + # @param example_group_instance the instance of an ExampleGroup subclass + def run(example_group_instance, reporter) + @example_group_instance = example_group_instance + @reporter = reporter + hooks.register_global_singleton_context_hooks(self, RSpec.configuration.hooks) + RSpec.configuration.configure_example(self) + RSpec.current_example = self + + start(reporter) + Pending.mark_pending!(self, pending) if pending? + + begin + if skipped? + Pending.mark_pending! self, skip + elsif !RSpec.configuration.dry_run? + with_around_and_singleton_context_hooks do + begin + run_before_example + @example_group_instance.instance_exec(self, &@example_block) + + if pending? + Pending.mark_fixed! self + + raise Pending::PendingExampleFixedError, + 'Expected example to fail since it is pending, but it passed.', + [location] + end + rescue Pending::SkipDeclaredInExample + # no-op, required metadata has already been set by the `skip` + # method. + rescue Exception => e + set_exception(e) + ensure + run_after_example + end + end + end + rescue Exception => e + set_exception(e) + ensure + @example_group_instance = nil # if you love something... let it go + end + + finish(reporter) + ensure + RSpec.current_example = nil + end + + # Wraps both a `Proc` and an {Example} for use in {Hooks#around + # around} hooks. In around hooks we need to yield this special + # kind of object (rather than the raw {Example}) because when + # there are multiple `around` hooks we have to wrap them recursively. + # + # @example + # + # RSpec.configure do |c| + # c.around do |ex| # Procsy which wraps the example + # if ex.metadata[:key] == :some_value && some_global_condition + # raise "some message" + # end + # ex.run # run delegates to ex.call. + # end + # end + # + # @note This class also exposes the instance methods of {Example}, + # proxying them through to the wrapped {Example} instance. + class Procsy + # The {Example} instance. + attr_reader :example + + Example.public_instance_methods(false).each do |name| + next if name.to_sym == :run || name.to_sym == :inspect + + define_method(name) { |*a, &b| @example.__send__(name, *a, &b) } + end + + Proc.public_instance_methods(false).each do |name| + next if name.to_sym == :call || name.to_sym == :inspect || name.to_sym == :to_proc + + define_method(name) { |*a, &b| @proc.__send__(name, *a, &b) } + end + + # Calls the proc and notes that the example has been executed. + def call(*args, &block) + @executed = true + @proc.call(*args, &block) + end + alias run call + + # Provides a wrapped proc that will update our `executed?` state when + # executed. + def to_proc + method(:call).to_proc + end + + def initialize(example, &block) + @example = example + @proc = block + @executed = false + end + + # @private + def wrap(&block) + self.class.new(example, &block) + end + + # Indicates whether or not the around hook has executed the example. + def executed? + @executed + end + + # @private + def inspect + @example.inspect.gsub('Example', 'ExampleProcsy') + end + end + + # @private + # + # The exception that will be displayed to the user -- either the failure of + # the example or the `pending_exception` if the example is pending. + def display_exception + @exception || execution_result.pending_exception + end + + # @private + # + # Assigns the exception that will be displayed to the user -- either the failure of + # the example or the `pending_exception` if the example is pending. + def display_exception=(ex) + if pending? && !(Pending::PendingExampleFixedError === ex) + @exception = nil + execution_result.pending_fixed = false + execution_result.pending_exception = ex + else + @exception = ex + end + end + + # rubocop:disable Style/AccessorMethodName + + # @private + # + # Used internally to set an exception in an after hook, which + # captures the exception but doesn't raise it. + def set_exception(exception) + return self.display_exception = exception unless display_exception + + unless RSpec::Core::MultipleExceptionError === display_exception + self.display_exception = RSpec::Core::MultipleExceptionError.new(display_exception) + end + + display_exception.add exception + end + + # @private + # + # Used to set the exception when `aggregate_failures` fails. + def set_aggregate_failures_exception(exception) + return set_exception(exception) unless display_exception + + exception = RSpec::Core::MultipleExceptionError::InterfaceTag.for(exception) + exception.add display_exception + self.display_exception = exception + end + + # rubocop:enable Style/AccessorMethodName + + # @private + # + # Used internally to set an exception and fail without actually executing + # the example when an exception is raised in before(:context). + def fail_with_exception(reporter, exception) + start(reporter) + set_exception(exception) + finish(reporter) + end + + # @private + # + # Used internally to skip without actually executing the example when + # skip is used in before(:context). + def skip_with_exception(reporter, exception) + start(reporter) + Pending.mark_skipped! self, exception.argument + finish(reporter) + end + + # @private + def instance_exec(*args, &block) + @example_group_instance.instance_exec(*args, &block) + end + + private + + def hooks + example_group_instance.singleton_class.hooks + end + + def with_around_example_hooks + hooks.run(:around, :example, self) { yield } + rescue Exception => e + set_exception(e) + end + + def start(reporter) + reporter.example_started(self) + execution_result.started_at = clock.now + end + + def finish(reporter) + pending_message = execution_result.pending_message + + if @exception + record_finished :failed + execution_result.exception = @exception + reporter.example_failed self + false + elsif pending_message + record_finished :pending + execution_result.pending_message = pending_message + reporter.example_pending self + true + else + record_finished :passed + reporter.example_passed self + true + end + end + + def record_finished(status) + execution_result.record_finished(status, clock.now) + end + + def run_before_example + @example_group_instance.setup_mocks_for_rspec + hooks.run(:before, :example, self) + end + + def with_around_and_singleton_context_hooks + singleton_context_hooks_host = example_group_instance.singleton_class + singleton_context_hooks_host.run_before_context_hooks(example_group_instance) + with_around_example_hooks { yield } + ensure + singleton_context_hooks_host.run_after_context_hooks(example_group_instance) + end + + def run_after_example + assign_generated_description if defined?(::RSpec::Matchers) + hooks.run(:after, :example, self) + verify_mocks + ensure + @example_group_instance.teardown_mocks_for_rspec + end + + def verify_mocks + @example_group_instance.verify_mocks_for_rspec if mocks_need_verification? + rescue Exception => e + set_exception(e) + end + + def mocks_need_verification? + exception.nil? || execution_result.pending_fixed? + end + + def assign_generated_description + if metadata[:description].empty? && (description = generate_description) + metadata[:description] = description + metadata[:full_description] << description + end + ensure + RSpec::Matchers.clear_generated_description + end + + def generate_description + RSpec::Matchers.generated_description + rescue Exception => e + location_description + " (Got an error when generating description " \ + "from matcher: #{e.class}: #{e.message} -- #{e.backtrace.first})" + end + + def location_description + "example at #{location}" + end + + # Represents the result of executing an example. + # Behaves like a hash for backwards compatibility. + class ExecutionResult + include HashImitatable + + # @return [Symbol] `:passed`, `:failed` or `:pending`. + attr_accessor :status + + # @return [Exception, nil] The failure, if there was one. + attr_accessor :exception + + # @return [Time] When the example started. + attr_accessor :started_at + + # @return [Time] When the example finished. + attr_accessor :finished_at + + # @return [Float] How long the example took in seconds. + attr_accessor :run_time + + # @return [String, nil] The reason the example was pending, + # or nil if the example was not pending. + attr_accessor :pending_message + + # @return [Exception, nil] The exception triggered while + # executing the pending example. If no exception was triggered + # it would no longer get a status of `:pending` unless it was + # tagged with `:skip`. + attr_accessor :pending_exception + + # @return [Boolean] For examples tagged with `:pending`, + # this indicates whether or not it now passes. + attr_accessor :pending_fixed + + alias pending_fixed? pending_fixed + + # @return [Boolean] Indicates if the example was completely skipped + # (typically done via `:skip` metadata or the `skip` method). Skipped examples + # will have a `:pending` result. A `:pending` result can also come from examples + # that were marked as `:pending`, which causes them to be run, and produces a + # `:failed` result if the example passes. + def example_skipped? + status == :pending && !pending_exception + end + + # @api private + # Records the finished status of the example. + def record_finished(status, finished_at) + self.status = status + self.finished_at = finished_at + self.run_time = (finished_at - started_at).to_f + end + + private + + # For backwards compatibility we present `status` as a string + # when presenting the legacy hash interface. + def hash_for_delegation + super.tap do |hash| + hash[:status] &&= status.to_s + end + end + + def set_value(name, value) + value &&= value.to_sym if name == :status + super(name, value) + end + + def get_value(name) + if name == :status + status.to_s if status + else + super + end + end + + def issue_deprecation(_method_name, *_args) + RSpec.deprecate("Treating `metadata[:execution_result]` as a hash", + :replacement => "the attributes methods to access the data") + end + end + end + + # @private + # Provides an execution context for before/after :suite hooks. + class SuiteHookContext < Example + def initialize + super(AnonymousExampleGroup, "", {}) + @example_group_instance = AnonymousExampleGroup.new + end + + # rubocop:disable Style/AccessorMethodName + + # To ensure we don't silence errors. + def set_exception(exception) + raise exception + end + # rubocop:enable Style/AccessorMethodName + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/example_group.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/example_group.rb new file mode 100644 index 0000000..9752955 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/example_group.rb @@ -0,0 +1,796 @@ +RSpec::Support.require_rspec_support 'recursive_const_methods' + +module RSpec + module Core + # ExampleGroup and {Example} are the main structural elements of + # rspec-core. Consider this example: + # + # describe Thing do + # it "does something" do + # end + # end + # + # The object returned by `describe Thing` is a subclass of ExampleGroup. + # The object returned by `it "does something"` is an instance of Example, + # which serves as a wrapper for an instance of the ExampleGroup in which it + # is declared. + # + # Example group bodies (e.g. `describe` or `context` blocks) are evaluated + # in the context of a new subclass of ExampleGroup. Individual examples are + # evaluated in the context of an instance of the specific ExampleGroup + # subclass to which they belong. + # + # Besides the class methods defined here, there are other interesting macros + # defined in {Hooks}, {MemoizedHelpers::ClassMethods} and + # {SharedExampleGroup}. There are additional instance methods available to + # your examples defined in {MemoizedHelpers} and {Pending}. + class ExampleGroup + extend Hooks + + include MemoizedHelpers + extend MemoizedHelpers::ClassMethods + include Pending + extend SharedExampleGroup + + # @private + def self.idempotently_define_singleton_method(name, &definition) + (class << self; self; end).module_exec do + remove_method(name) if method_defined?(name) && instance_method(name).owner == self + define_method(name, &definition) + end + end + + # @!group Metadata + + # The [Metadata](Metadata) object associated with this group. + # @see Metadata + def self.metadata + @metadata ||= nil + end + + # Temporarily replace the provided metadata. + # Intended primarily to allow an example group's singleton class + # to return the metadata of the example that it exists for. This + # is necessary for shared example group inclusion to work properly + # with singleton example groups. + # @private + def self.with_replaced_metadata(meta) + orig_metadata = metadata + @metadata = meta + yield + ensure + @metadata = orig_metadata + end + + # @private + # @return [Metadata] belonging to the parent of a nested {ExampleGroup} + def self.superclass_metadata + @superclass_metadata ||= superclass.respond_to?(:metadata) ? superclass.metadata : nil + end + + # @private + def self.delegate_to_metadata(*names) + names.each do |name| + idempotently_define_singleton_method(name) { metadata.fetch(name) } + end + end + + delegate_to_metadata :described_class, :file_path, :location + + # @return [String] the current example group description + def self.description + description = metadata[:description] + RSpec.configuration.format_docstrings_block.call(description) + end + + # Returns the class or module passed to the `describe` method (or alias). + # Returns nil if the subject is not a class or module. + # @example + # describe Thing do + # it "does something" do + # described_class == Thing + # end + # end + # + def described_class + self.class.described_class + end + + # @!endgroup + + # @!group Defining Examples + + # @private + # @macro [attach] define_example_method + # @!scope class + # @overload $1 + # @overload $1(&example_implementation) + # @param example_implementation [Block] The implementation of the example. + # @overload $1(doc_string, *metadata_keys, metadata={}) + # @param doc_string [String] The example's doc string. + # @param metadata [Hash] Metadata for the example. + # @param metadata_keys [Array] Metadata tags for the example. + # Will be transformed into hash entries with `true` values. + # @overload $1(doc_string, *metadata_keys, metadata={}, &example_implementation) + # @param doc_string [String] The example's doc string. + # @param metadata [Hash] Metadata for the example. + # @param metadata_keys [Array] Metadata tags for the example. + # Will be transformed into hash entries with `true` values. + # @param example_implementation [Block] The implementation of the example. + # @yield [Example] the example object + # @example + # $1 do + # end + # + # $1 "does something" do + # end + # + # $1 "does something", :slow, :uses_js do + # end + # + # $1 "does something", :with => 'additional metadata' do + # end + # + # $1 "does something" do |ex| + # # ex is the Example object that contains metadata about the example + # end + def self.define_example_method(name, extra_options={}) + idempotently_define_singleton_method(name) do |*all_args, &block| + desc, *args = *all_args + + options = Metadata.build_hash_from(args) + options.update(:skip => RSpec::Core::Pending::NOT_YET_IMPLEMENTED) unless block + options.update(extra_options) + + example = RSpec::Core::Example.new(self, desc, options, block) + examples << example + example + end + end + + # Defines an example within a group. + define_example_method :example + # Defines an example within a group. + # This is the primary API to define a code example. + define_example_method :it + # Defines an example within a group. + # Useful for when your docstring does not read well off of `it`. + # @example + # RSpec.describe MyClass do + # specify "#do_something is deprecated" do + # # ... + # end + # end + define_example_method :specify + + # Shortcut to define an example with `:focus => true`. + # @see example + define_example_method :focus, :focus => true + # Shortcut to define an example with `:focus => true`. + # @see example + define_example_method :fexample, :focus => true + # Shortcut to define an example with `:focus => true`. + # @see example + define_example_method :fit, :focus => true + # Shortcut to define an example with `:focus => true`. + # @see example + define_example_method :fspecify, :focus => true + # Shortcut to define an example with `:skip => 'Temporarily skipped with xexample'`. + # @see example + define_example_method :xexample, :skip => 'Temporarily skipped with xexample' + # Shortcut to define an example with `:skip => 'Temporarily skipped with xit'`. + # @see example + define_example_method :xit, :skip => 'Temporarily skipped with xit' + # Shortcut to define an example with `:skip => 'Temporarily skipped with xspecify'`. + # @see example + define_example_method :xspecify, :skip => 'Temporarily skipped with xspecify' + # Shortcut to define an example with `:skip => true` + # @see example + define_example_method :skip, :skip => true + # Shortcut to define an example with `:pending => true` + # @see example + define_example_method :pending, :pending => true + + # @!endgroup + + # @!group Defining Example Groups + + # @private + # @macro [attach] define_example_group_method + # @!scope class + # @overload $1 + # @overload $1(&example_group_definition) + # @param example_group_definition [Block] The definition of the example group. + # @overload $1(doc_string, *metadata_keys, metadata={}, &example_implementation) + # @param doc_string [String] The group's doc string. + # @param metadata [Hash] Metadata for the group. + # @param metadata_keys [Array] Metadata tags for the group. + # Will be transformed into hash entries with `true` values. + # @param example_group_definition [Block] The definition of the example group. + # + # Generates a subclass of this example group which inherits + # everything except the examples themselves. + # + # @example + # + # RSpec.describe "something" do # << This describe method is defined in + # # << RSpec::Core::DSL, included in the + # # << global namespace (optional) + # before do + # do_something_before + # end + # + # let(:thing) { Thing.new } + # + # $1 "attribute (of something)" do + # # examples in the group get the before hook + # # declared above, and can access `thing` + # end + # end + # + # @see DSL#describe + def self.define_example_group_method(name, metadata={}) + idempotently_define_singleton_method(name) do |*args, &example_group_block| + thread_data = RSpec::Support.thread_local_data + top_level = self == ExampleGroup + + if top_level + if thread_data[:in_example_group] + raise "Creating an isolated context from within a context is " \ + "not allowed. Change `RSpec.#{name}` to `#{name}` or " \ + "move this to a top-level scope." + end + + thread_data[:in_example_group] = true + end + + begin + + description = args.shift + combined_metadata = metadata.dup + combined_metadata.merge!(args.pop) if args.last.is_a? Hash + args << combined_metadata + + subclass(self, description, args, &example_group_block).tap do |child| + children << child + end + + ensure + thread_data.delete(:in_example_group) if top_level + end + end + + RSpec::Core::DSL.expose_example_group_alias(name) + end + + define_example_group_method :example_group + + # An alias of `example_group`. Generally used when grouping examples by a + # thing you are describing (e.g. an object, class or method). + # @see example_group + define_example_group_method :describe + + # An alias of `example_group`. Generally used when grouping examples + # contextually (e.g. "with xyz", "when xyz" or "if xyz"). + # @see example_group + define_example_group_method :context + + # Shortcut to temporarily make an example group skipped. + # @see example_group + define_example_group_method :xdescribe, :skip => "Temporarily skipped with xdescribe" + + # Shortcut to temporarily make an example group skipped. + # @see example_group + define_example_group_method :xcontext, :skip => "Temporarily skipped with xcontext" + + # Shortcut to define an example group with `:focus => true`. + # @see example_group + define_example_group_method :fdescribe, :focus => true + + # Shortcut to define an example group with `:focus => true`. + # @see example_group + define_example_group_method :fcontext, :focus => true + + # @!endgroup + + # @!group Including Shared Example Groups + + # @private + # @macro [attach] define_nested_shared_group_method + # @!scope class + # + # @see SharedExampleGroup + def self.define_nested_shared_group_method(new_name, report_label="it should behave like") + idempotently_define_singleton_method(new_name) do |name, *args, &customization_block| + # Pass :caller so the :location metadata is set properly. + # Otherwise, it'll be set to the next line because that's + # the block's source_location. + group = example_group("#{report_label} #{name}", :caller => (the_caller = caller)) do + find_and_eval_shared("examples", name, the_caller.first, *args, &customization_block) + end + group.metadata[:shared_group_name] = name + group + end + end + + # Generates a nested example group and includes the shared content + # mapped to `name` in the nested group. + define_nested_shared_group_method :it_behaves_like, "behaves like" + # Generates a nested example group and includes the shared content + # mapped to `name` in the nested group. + define_nested_shared_group_method :it_should_behave_like + + # Includes shared content mapped to `name` directly in the group in which + # it is declared, as opposed to `it_behaves_like`, which creates a nested + # group. If given a block, that block is also eval'd in the current + # context. + # + # @see SharedExampleGroup + def self.include_context(name, *args, &block) + find_and_eval_shared("context", name, caller.first, *args, &block) + end + + # Includes shared content mapped to `name` directly in the group in which + # it is declared, as opposed to `it_behaves_like`, which creates a nested + # group. If given a block, that block is also eval'd in the current + # context. + # + # @see SharedExampleGroup + def self.include_examples(name, *args, &block) + find_and_eval_shared("examples", name, caller.first, *args, &block) + end + + # @private + def self.find_and_eval_shared(label, name, inclusion_location, *args, &customization_block) + shared_block = RSpec.world.shared_example_group_registry.find(parent_groups, name) + + unless shared_block + raise ArgumentError, "Could not find shared #{label} #{name.inspect}" + end + + SharedExampleGroupInclusionStackFrame.with_frame(name, Metadata.relative_path(inclusion_location)) do + module_exec(*args, &shared_block) + module_exec(&customization_block) if customization_block + end + end + + # @!endgroup + + # @private + def self.subclass(parent, description, args, &example_group_block) + subclass = Class.new(parent) + subclass.set_it_up(description, *args, &example_group_block) + subclass.module_exec(&example_group_block) if example_group_block + + # The LetDefinitions module must be included _after_ other modules + # to ensure that it takes precedence when there are name collisions. + # Thus, we delay including it until after the example group block + # has been eval'd. + MemoizedHelpers.define_helpers_on(subclass) + + subclass + end + + # @private + def self.set_it_up(description, *args, &example_group_block) + # Ruby 1.9 has a bug that can lead to infinite recursion and a + # SystemStackError if you include a module in a superclass after + # including it in a subclass: https://gist.github.com/845896 + # To prevent this, we must include any modules in + # RSpec::Core::ExampleGroup before users create example groups and have + # a chance to include the same module in a subclass of + # RSpec::Core::ExampleGroup. So we need to configure example groups + # here. + ensure_example_groups_are_configured + + user_metadata = Metadata.build_hash_from(args) + + @metadata = Metadata::ExampleGroupHash.create( + superclass_metadata, user_metadata, + superclass.method(:next_runnable_index_for), + description, *args, &example_group_block + ) + ExampleGroups.assign_const(self) + + hooks.register_globals(self, RSpec.configuration.hooks) + RSpec.configuration.configure_group(self) + end + + # @private + def self.examples + @examples ||= [] + end + + # @private + def self.filtered_examples + RSpec.world.filtered_examples[self] + end + + # @private + def self.descendant_filtered_examples + @descendant_filtered_examples ||= filtered_examples + + FlatMap.flat_map(children, &:descendant_filtered_examples) + end + + # @private + def self.children + @children ||= [] + end + + # @private + def self.next_runnable_index_for(file) + if self == ExampleGroup + RSpec.world.num_example_groups_defined_in(file) + else + children.count + examples.count + end + 1 + end + + # @private + def self.descendants + @_descendants ||= [self] + FlatMap.flat_map(children, &:descendants) + end + + ## @private + def self.parent_groups + @parent_groups ||= ancestors.select { |a| a < RSpec::Core::ExampleGroup } + end + + # @private + def self.top_level? + superclass == ExampleGroup + end + + # @private + def self.ensure_example_groups_are_configured + unless defined?(@@example_groups_configured) + RSpec.configuration.configure_mock_framework + RSpec.configuration.configure_expectation_framework + # rubocop:disable Style/ClassVars + @@example_groups_configured = true + # rubocop:enable Style/ClassVars + end + end + + # @private + def self.before_context_ivars + @before_context_ivars ||= {} + end + + # @private + def self.store_before_context_ivars(example_group_instance) + each_instance_variable_for_example(example_group_instance) do |ivar| + before_context_ivars[ivar] = example_group_instance.instance_variable_get(ivar) + end + end + + # @private + def self.run_before_context_hooks(example_group_instance) + set_ivars(example_group_instance, superclass_before_context_ivars) + + ContextHookMemoized::Before.isolate_for_context_hook(example_group_instance) do + hooks.run(:before, :context, example_group_instance) + end + ensure + store_before_context_ivars(example_group_instance) + end + + if RUBY_VERSION.to_f >= 1.9 + # @private + def self.superclass_before_context_ivars + superclass.before_context_ivars + end + else # 1.8.7 + # :nocov: + # @private + def self.superclass_before_context_ivars + if superclass.respond_to?(:before_context_ivars) + superclass.before_context_ivars + else + # `self` must be the singleton class of an ExampleGroup instance. + # On 1.8.7, the superclass of a singleton class of an instance of A + # is A's singleton class. On 1.9+, it's A. On 1.8.7, the first ancestor + # is A, so we can mirror 1.8.7's behavior here. Note that we have to + # search for the first that responds to `before_context_ivars` + # in case a module has been included in the singleton class. + ancestors.find { |a| a.respond_to?(:before_context_ivars) }.before_context_ivars + end + end + # :nocov: + end + + # @private + def self.run_after_context_hooks(example_group_instance) + set_ivars(example_group_instance, before_context_ivars) + + ContextHookMemoized::After.isolate_for_context_hook(example_group_instance) do + hooks.run(:after, :context, example_group_instance) + end + ensure + before_context_ivars.clear + end + + # Runs all the examples in this group. + def self.run(reporter=RSpec::Core::NullReporter) + return if RSpec.world.wants_to_quit + reporter.example_group_started(self) + + should_run_context_hooks = descendant_filtered_examples.any? + begin + run_before_context_hooks(new('before(:context) hook')) if should_run_context_hooks + result_for_this_group = run_examples(reporter) + results_for_descendants = ordering_strategy.order(children).map { |child| child.run(reporter) }.all? + result_for_this_group && results_for_descendants + rescue Pending::SkipDeclaredInExample => ex + for_filtered_examples(reporter) { |example| example.skip_with_exception(reporter, ex) } + true + rescue Exception => ex + RSpec.world.wants_to_quit = true if fail_fast? + for_filtered_examples(reporter) { |example| example.fail_with_exception(reporter, ex) } + false + ensure + run_after_context_hooks(new('after(:context) hook')) if should_run_context_hooks + reporter.example_group_finished(self) + end + end + + # @private + def self.ordering_strategy + order = metadata.fetch(:order, :global) + registry = RSpec.configuration.ordering_registry + + registry.fetch(order) do + warn <<-WARNING.gsub(/^ +\|/, '') + |WARNING: Ignoring unknown ordering specified using `:order => #{order.inspect}` metadata. + | Falling back to configured global ordering. + | Unrecognized ordering specified at: #{location} + WARNING + + registry.fetch(:global) + end + end + + # @private + def self.run_examples(reporter) + ordering_strategy.order(filtered_examples).map do |example| + next if RSpec.world.wants_to_quit + instance = new(example.inspect_output) + set_ivars(instance, before_context_ivars) + succeeded = example.run(instance, reporter) + RSpec.world.wants_to_quit = true if fail_fast? && !succeeded + succeeded + end.all? + end + + # @private + def self.for_filtered_examples(reporter, &block) + filtered_examples.each(&block) + + children.each do |child| + reporter.example_group_started(child) + child.for_filtered_examples(reporter, &block) + reporter.example_group_finished(child) + end + false + end + + # @private + def self.fail_fast? + RSpec.configuration.fail_fast? + end + + # @private + def self.declaration_line_numbers + @declaration_line_numbers ||= [metadata[:line_number]] + + examples.map { |e| e.metadata[:line_number] } + + FlatMap.flat_map(children, &:declaration_line_numbers) + end + + # @return [String] the unique id of this example group. Pass + # this at the command line to re-run this exact example group. + def self.id + Metadata.id_from(metadata) + end + + # @private + def self.top_level_description + parent_groups.last.description + end + + # @private + def self.set_ivars(instance, ivars) + ivars.each { |name, value| instance.instance_variable_set(name, value) } + end + + if RUBY_VERSION.to_f < 1.9 + # :nocov: + # @private + INSTANCE_VARIABLE_TO_IGNORE = '@__inspect_output'.freeze + # :nocov: + else + # @private + INSTANCE_VARIABLE_TO_IGNORE = :@__inspect_output + end + + # @private + def self.each_instance_variable_for_example(group) + group.instance_variables.each do |ivar| + yield ivar unless ivar == INSTANCE_VARIABLE_TO_IGNORE + end + end + + def initialize(inspect_output=nil) + @__inspect_output = inspect_output || '(no description provided)' + super() # no args get passed + end + + # @private + def inspect + "#<#{self.class} #{@__inspect_output}>" + end + + unless method_defined?(:singleton_class) # for 1.8.7 + # :nocov: + # @private + def singleton_class + class << self; self; end + end + # :nocov: + end + + # Raised when an RSpec API is called in the wrong scope, such as `before` + # being called from within an example rather than from within an example + # group block. + WrongScopeError = Class.new(NoMethodError) + + def self.method_missing(name, *args) + if method_defined?(name) + raise WrongScopeError, + "`#{name}` is not available on an example group (e.g. a " \ + "`describe` or `context` block). It is only available from " \ + "within individual examples (e.g. `it` blocks) or from " \ + "constructs that run in the scope of an example (e.g. " \ + "`before`, `let`, etc)." + end + + super + end + private_class_method :method_missing + + private + + def method_missing(name, *args) + if self.class.respond_to?(name) + raise WrongScopeError, + "`#{name}` is not available from within an example (e.g. an " \ + "`it` block) or from constructs that run in the scope of an " \ + "example (e.g. `before`, `let`, etc). It is only available " \ + "on an example group (e.g. a `describe` or `context` block)." + end + + super + end + end + + # @private + # Unnamed example group used by `SuiteHookContext`. + class AnonymousExampleGroup < ExampleGroup + def self.metadata + {} + end + end + + # Contains information about the inclusion site of a shared example group. + class SharedExampleGroupInclusionStackFrame + # @return [String] the name of the shared example group + attr_reader :shared_group_name + # @return [String] the location where the shared example was included + attr_reader :inclusion_location + + def initialize(shared_group_name, inclusion_location) + @shared_group_name = shared_group_name + @inclusion_location = inclusion_location + end + + # @return [String] The {#inclusion_location}, formatted for display by a formatter. + def formatted_inclusion_location + @formatted_inclusion_location ||= begin + RSpec.configuration.backtrace_formatter.backtrace_line( + inclusion_location.sub(/(:\d+):in .+$/, '\1') + ) + end + end + + # @return [String] Description of this stack frame, in the form used by + # RSpec's built-in formatters. + def description + @description ||= "Shared Example Group: #{shared_group_name.inspect} " \ + "called from #{formatted_inclusion_location}" + end + + # @private + def self.current_backtrace + shared_example_group_inclusions.reverse + end + + # @private + def self.with_frame(name, location) + current_stack = shared_example_group_inclusions + current_stack << new(name, location) + yield + ensure + current_stack.pop + end + + # @private + def self.shared_example_group_inclusions + RSpec::Support.thread_local_data[:shared_example_group_inclusions] ||= [] + end + end + end + + # @private + # + # Namespace for the example group subclasses generated by top-level + # `describe`. + module ExampleGroups + extend Support::RecursiveConstMethods + + def self.assign_const(group) + base_name = base_name_for(group) + const_scope = constant_scope_for(group) + name = disambiguate(base_name, const_scope) + + const_scope.const_set(name, group) + end + + def self.constant_scope_for(group) + const_scope = group.superclass + const_scope = self if const_scope == ::RSpec::Core::ExampleGroup + const_scope + end + + def self.base_name_for(group) + return "Anonymous" if group.description.empty? + + # Convert to CamelCase. + name = ' ' << group.description + name.gsub!(/[^0-9a-zA-Z]+([0-9a-zA-Z])/) do + match = ::Regexp.last_match[1] + match.upcase! + match + end + + name.lstrip! # Remove leading whitespace + name.gsub!(/\W/, ''.freeze) # JRuby, RBX and others don't like non-ascii in const names + + # Ruby requires first const letter to be A-Z. Use `Nested` + # as necessary to enforce that. + name.gsub!(/\A([^A-Z]|\z)/, 'Nested\1'.freeze) + + name + end + + if RUBY_VERSION == '1.9.2' + # :nocov: + class << self + alias _base_name_for base_name_for + def base_name_for(group) + _base_name_for(group) + '_' + end + end + private_class_method :_base_name_for + # :nocov: + end + + def self.disambiguate(name, const_scope) + return name unless const_defined_on?(const_scope, name) + + # Add a trailing number if needed to disambiguate from an existing + # constant. + name << "_2" + name.next! while const_defined_on?(const_scope, name) + name + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/example_status_persister.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/example_status_persister.rb new file mode 100644 index 0000000..0eb8a0a --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/example_status_persister.rb @@ -0,0 +1,235 @@ +RSpec::Support.require_rspec_support "directory_maker" + +module RSpec + module Core + # Persists example ids and their statuses so that we can filter + # to just the ones that failed the last time they ran. + # @private + class ExampleStatusPersister + def self.load_from(file_name) + return [] unless File.exist?(file_name) + ExampleStatusParser.parse(File.read(file_name)) + end + + def self.persist(examples, file_name) + new(examples, file_name).persist + end + + def initialize(examples, file_name) + @examples = examples + @file_name = file_name + end + + def persist + write dumped_statuses + end + + private + + def write(statuses) + RSpec::Support::DirectoryMaker.mkdir_p(File.dirname(@file_name)) + File.open(@file_name, "w") { |f| f.write(statuses) } + end + + def dumped_statuses + ExampleStatusDumper.dump(merged_statuses) + end + + def merged_statuses + ExampleStatusMerger.merge(statuses_from_this_run, statuses_from_previous_runs) + end + + def statuses_from_this_run + @examples.map do |ex| + result = ex.execution_result + + { + :example_id => ex.id, + :status => result.status ? result.status.to_s : Configuration::UNKNOWN_STATUS, + :run_time => result.run_time ? Formatters::Helpers.format_duration(result.run_time) : "" + } + end + end + + def statuses_from_previous_runs + self.class.load_from(@file_name) + end + end + + # Merges together a list of example statuses from this run + # and a list from previous runs (presumably loaded from disk). + # Each example status object is expected to be a hash with + # at least an `:example_id` and a `:status` key. Examples that + # were loaded but not executed (due to filtering, `--fail-fast` + # or whatever) should have a `:status` of `UNKNOWN_STATUS`. + # + # This willl produce a new list that: + # - Will be missing examples from previous runs that we know for sure + # no longer exist. + # - Will have the latest known status for any examples that either + # definitively do exist or may still exist. + # - Is sorted by file name and example definition order, so that + # the saved file is easily scannable if users want to inspect it. + # @private + class ExampleStatusMerger + def self.merge(this_run, from_previous_runs) + new(this_run, from_previous_runs).merge + end + + def initialize(this_run, from_previous_runs) + @this_run = hash_from(this_run) + @from_previous_runs = hash_from(from_previous_runs) + @file_exists_cache = Hash.new { |hash, file| hash[file] = File.exist?(file) } + end + + def merge + delete_previous_examples_that_no_longer_exist + + @this_run.merge(@from_previous_runs) do |_ex_id, new, old| + new.fetch(:status) == Configuration::UNKNOWN_STATUS ? old : new + end.values.sort_by(&method(:sort_value_from)) + end + + private + + def hash_from(example_list) + example_list.inject({}) do |hash, example| + hash[example.fetch(:example_id)] = example + hash + end + end + + def delete_previous_examples_that_no_longer_exist + @from_previous_runs.delete_if do |ex_id, _| + example_must_no_longer_exist?(ex_id) + end + end + + def example_must_no_longer_exist?(ex_id) + # Obviously, it exists if it was loaded for this spec run... + return false if @this_run.key?(ex_id) + + spec_file = spec_file_from(ex_id) + + # `this_run` includes examples that were loaded but not executed. + # Given that, if the spec file for this example was loaded, + # but the id does not still exist, it's safe to assume that + # the example must no longer exist. + return true if loaded_spec_files.include?(spec_file) + + # The example may still exist as long as the file exists... + !@file_exists_cache[spec_file] + end + + def loaded_spec_files + @loaded_spec_files ||= Set.new(@this_run.keys.map(&method(:spec_file_from))) + end + + def spec_file_from(ex_id) + ex_id.split("[").first + end + + def sort_value_from(example) + file, scoped_id = example.fetch(:example_id).split(Configuration::ON_SQUARE_BRACKETS) + [file, *scoped_id.split(":").map(&method(:Integer))] + end + end + + # Dumps a list of hashes in a pretty, human readable format + # for later parsing. The hashes are expected to have symbol + # keys and string values, and each hash should have the same + # set of keys. + # @private + class ExampleStatusDumper + def self.dump(examples) + new(examples).dump + end + + def initialize(examples) + @examples = examples + end + + def dump + return nil if @examples.empty? + (formatted_header_rows + formatted_value_rows).join("\n") << "\n" + end + + private + + def formatted_header_rows + @formatted_header_rows ||= begin + dividers = column_widths.map { |w| "-" * w } + [formatted_row_from(headers.map(&:to_s)), formatted_row_from(dividers)] + end + end + + def formatted_value_rows + @foramtted_value_rows ||= rows.map do |row| + formatted_row_from(row) + end + end + + def rows + @rows ||= @examples.map { |ex| ex.values_at(*headers) } + end + + def formatted_row_from(row_values) + padded_values = row_values.each_with_index.map do |value, index| + value.ljust(column_widths[index]) + end + + padded_values.join(" | ") << " |" + end + + def headers + @headers ||= @examples.first.keys + end + + def column_widths + @column_widths ||= begin + value_sets = rows.transpose + + headers.each_with_index.map do |header, index| + values = value_sets[index] << header.to_s + values.map(&:length).max + end + end + end + end + + # Parses a string that has been previously dumped by ExampleStatusDumper. + # Note that this parser is a bit naive in that it does a simple split on + # "\n" and " | ", with no concern for handling escaping. For now, that's + # OK because the values we plan to persist (example id, status, and perhaps + # example duration) are highly unlikely to contain "\n" or " | " -- after + # all, who puts those in file names? + # @private + class ExampleStatusParser + def self.parse(string) + new(string).parse + end + + def initialize(string) + @header_line, _, *@row_lines = string.lines.to_a + end + + def parse + @row_lines.map { |line| parse_row(line) } + end + + private + + def parse_row(line) + Hash[headers.zip(split_line(line))] + end + + def headers + @headers ||= split_line(@header_line).grep(/\S/).map(&:to_sym) + end + + def split_line(line) + line.split(/\s+\|\s+?/, -1) + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/filter_manager.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/filter_manager.rb new file mode 100644 index 0000000..e5e062a --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/filter_manager.rb @@ -0,0 +1,231 @@ +module RSpec + module Core + # @private + class FilterManager + attr_reader :exclusions, :inclusions + + def initialize + @exclusions, @inclusions = FilterRules.build + end + + # @api private + # + # @param file_path [String] + # @param line_numbers [Array] + def add_location(file_path, line_numbers) + # locations is a hash of expanded paths to arrays of line + # numbers to match against. e.g. + # { "path/to/file.rb" => [37, 42] } + add_path_to_arrays_filter(:locations, File.expand_path(file_path), line_numbers) + end + + def add_ids(rerun_path, scoped_ids) + # ids is a hash of relative paths to arrays of ids + # to match against. e.g. + # { "./path/to/file.rb" => ["1:1", "2:4"] } + rerun_path = Metadata.relative_path(File.expand_path rerun_path) + add_path_to_arrays_filter(:ids, rerun_path, scoped_ids) + end + + def empty? + inclusions.empty? && exclusions.empty? + end + + def prune(examples) + # Semantically, this is unnecessary (the filtering below will return the empty + # array unmodified), but for perf reasons it's worth exiting early here. Users + # commonly have top-level examples groups that do not have any direct examples + # and instead have nested groups with examples. In that kind of situation, + # `examples` will be empty. + return examples if examples.empty? + + examples = prune_conditionally_filtered_examples(examples) + + if inclusions.standalone? + examples.select { |e| inclusions.include_example?(e) } + else + locations, ids, non_scoped_inclusions = inclusions.split_file_scoped_rules + + examples.select do |ex| + file_scoped_include?(ex.metadata, ids, locations) do + !exclusions.include_example?(ex) && non_scoped_inclusions.include_example?(ex) + end + end + end + end + + def exclude(*args) + exclusions.add(args.last) + end + + def exclude_only(*args) + exclusions.use_only(args.last) + end + + def exclude_with_low_priority(*args) + exclusions.add_with_low_priority(args.last) + end + + def include(*args) + inclusions.add(args.last) + end + + def include_only(*args) + inclusions.use_only(args.last) + end + + def include_with_low_priority(*args) + inclusions.add_with_low_priority(args.last) + end + + private + + def add_path_to_arrays_filter(filter_key, path, values) + filter = inclusions.delete(filter_key) || Hash.new { |h, k| h[k] = [] } + filter[path].concat(values) + inclusions.add(filter_key => filter) + end + + def prune_conditionally_filtered_examples(examples) + examples.reject do |ex| + meta = ex.metadata + !meta.fetch(:if, true) || meta[:unless] + end + end + + # When a user specifies a particular spec location, that takes priority + # over any exclusion filters (such as if the spec is tagged with `:slow` + # and there is a `:slow => true` exclusion filter), but only for specs + # defined in the same file as the location filters. Excluded specs in + # other files should still be excluded. + def file_scoped_include?(ex_metadata, ids, locations) + no_id_filters = ids[ex_metadata[:rerun_file_path]].empty? + no_location_filters = locations[ + File.expand_path(ex_metadata[:rerun_file_path]) + ].empty? + + return yield if no_location_filters && no_id_filters + + MetadataFilter.filter_applies?(:ids, ids, ex_metadata) || + MetadataFilter.filter_applies?(:locations, locations, ex_metadata) + end + end + + # @private + class FilterRules + PROC_HEX_NUMBER = /0x[0-9a-f]+@/ + PROJECT_DIR = File.expand_path('.') + + attr_accessor :opposite + attr_reader :rules + + def self.build + exclusions = ExclusionRules.new + inclusions = InclusionRules.new + exclusions.opposite = inclusions + inclusions.opposite = exclusions + [exclusions, inclusions] + end + + def initialize(rules={}) + @rules = rules + end + + def add(updated) + @rules.merge!(updated).each_key { |k| opposite.delete(k) } + end + + def add_with_low_priority(updated) + updated = updated.merge(@rules) + opposite.each_pair { |k, v| updated.delete(k) if updated[k] == v } + @rules.replace(updated) + end + + def use_only(updated) + updated.each_key { |k| opposite.delete(k) } + @rules.replace(updated) + end + + def clear + @rules.clear + end + + def delete(key) + @rules.delete(key) + end + + def fetch(*args, &block) + @rules.fetch(*args, &block) + end + + def [](key) + @rules[key] + end + + def empty? + rules.empty? + end + + def each_pair(&block) + @rules.each_pair(&block) + end + + def description + rules.inspect.gsub(PROC_HEX_NUMBER, '').gsub(PROJECT_DIR, '.').gsub(' (lambda)', '') + end + + def include_example?(example) + MetadataFilter.apply?(:any?, @rules, example.metadata) + end + end + + # @private + ExclusionRules = FilterRules + + # @private + class InclusionRules < FilterRules + def add(*args) + apply_standalone_filter(*args) || super + end + + def add_with_low_priority(*args) + apply_standalone_filter(*args) || super + end + + def include_example?(example) + @rules.empty? || super + end + + def standalone? + is_standalone_filter?(@rules) + end + + def split_file_scoped_rules + rules_dup = @rules.dup + locations = rules_dup.delete(:locations) { Hash.new([]) } + ids = rules_dup.delete(:ids) { Hash.new([]) } + + return locations, ids, self.class.new(rules_dup) + end + + private + + def apply_standalone_filter(updated) + return true if standalone? + return nil unless is_standalone_filter?(updated) + + replace_filters(updated) + true + end + + def replace_filters(new_rules) + @rules.replace(new_rules) + opposite.clear + end + + def is_standalone_filter?(rules) + rules.key?(:full_description) + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/flat_map.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/flat_map.rb new file mode 100644 index 0000000..0e30cce --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/flat_map.rb @@ -0,0 +1,20 @@ +module RSpec + module Core + # @private + module FlatMap + if [].respond_to?(:flat_map) + def flat_map(array, &block) + array.flat_map(&block) + end + else # for 1.8.7 + # :nocov: + def flat_map(array, &block) + array.map(&block).flatten(1) + end + # :nocov: + end + + module_function :flat_map + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters.rb new file mode 100644 index 0000000..401e2d8 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters.rb @@ -0,0 +1,254 @@ +RSpec::Support.require_rspec_support "directory_maker" +# ## Built-in Formatters +# +# * progress (default) - Prints dots for passing examples, `F` for failures, `*` +# for pending. +# * documentation - Prints the docstrings passed to `describe` and `it` methods +# (and their aliases). +# * html +# * json - Useful for archiving data for subsequent analysis. +# +# The progress formatter is the default, but you can choose any one or more of +# the other formatters by passing with the `--format` (or `-f` for short) +# command-line option, e.g. +# +# rspec --format documentation +# +# You can also send the output of multiple formatters to different streams, e.g. +# +# rspec --format documentation --format html --out results.html +# +# This example sends the output of the documentation formatter to `$stdout`, and +# the output of the html formatter to results.html. +# +# ## Custom Formatters +# +# You can tell RSpec to use a custom formatter by passing its path and name to +# the `rspec` commmand. For example, if you define MyCustomFormatter in +# path/to/my_custom_formatter.rb, you would type this command: +# +# rspec --require path/to/my_custom_formatter.rb --format MyCustomFormatter +# +# The reporter calls every formatter with this protocol: +# +# * To start +# * `start(StartNotification)` +# * Once per example group +# * `example_group_started(GroupNotification)` +# * Once per example +# * `example_started(ExampleNotification)` +# * One of these per example, depending on outcome +# * `example_passed(ExampleNotification)` +# * `example_failed(FailedExampleNotification)` +# * `example_pending(ExampleNotification)` +# * Optionally at any time +# * `message(MessageNotification)` +# * At the end of the suite +# * `stop(ExamplesNotification)` +# * `start_dump(NullNotification)` +# * `dump_pending(ExamplesNotification)` +# * `dump_failures(ExamplesNotification)` +# * `dump_summary(SummaryNotification)` +# * `seed(SeedNotification)` +# * `close(NullNotification)` +# +# Only the notifications to which you subscribe your formatter will be called +# on your formatter. To subscribe your formatter use: +# `RSpec::Core::Formatters#register` e.g. +# +# `RSpec::Core::Formatters.register FormatterClassName, :example_passed, :example_failed` +# +# We recommend you implement the methods yourself; for simplicity we provide the +# default formatter output via our notification objects but if you prefer you +# can subclass `RSpec::Core::Formatters::BaseTextFormatter` and override the +# methods you wish to enhance. +# +# @see RSpec::Core::Formatters::BaseTextFormatter +# @see RSpec::Core::Reporter +module RSpec::Core::Formatters + autoload :DocumentationFormatter, 'rspec/core/formatters/documentation_formatter' + autoload :HtmlFormatter, 'rspec/core/formatters/html_formatter' + autoload :FallbackMessageFormatter, 'rspec/core/formatters/fallback_message_formatter' + autoload :ProgressFormatter, 'rspec/core/formatters/progress_formatter' + autoload :ProfileFormatter, 'rspec/core/formatters/profile_formatter' + autoload :JsonFormatter, 'rspec/core/formatters/json_formatter' + autoload :BisectFormatter, 'rspec/core/formatters/bisect_formatter' + + # Register the formatter class + # @param formatter_class [Class] formatter class to register + # @param notifications [Symbol, ...] one or more notifications to be + # registered to the specified formatter + # + # @see RSpec::Core::Formatters::BaseFormatter + def self.register(formatter_class, *notifications) + Loader.formatters[formatter_class] = notifications + end + + # @api private + # + # `RSpec::Core::Formatters::Loader` is an internal class for + # managing formatters used by a particular configuration. It is + # not expected to be used directly, but only through the configuration + # interface. + class Loader + # @api private + # + # Internal formatters are stored here when loaded. + def self.formatters + @formatters ||= {} + end + + # @api private + def initialize(reporter) + @formatters = [] + @reporter = reporter + self.default_formatter = 'progress' + end + + # @return [Array] the loaded formatters + attr_reader :formatters + + # @return [Reporter] the reporter + attr_reader :reporter + + # @return [String] the default formatter to setup, defaults to `progress` + attr_accessor :default_formatter + + # @private + def setup_default(output_stream, deprecation_stream) + add default_formatter, output_stream if @formatters.empty? + + unless @formatters.any? { |formatter| DeprecationFormatter === formatter } + add DeprecationFormatter, deprecation_stream, output_stream + end + + unless existing_formatter_implements?(:message) + add FallbackMessageFormatter, output_stream + end + + return unless RSpec.configuration.profile_examples? + + @reporter.setup_profiler + + return if existing_formatter_implements?(:dump_profile) + + add RSpec::Core::Formatters::ProfileFormatter, output_stream + end + + # @private + def add(formatter_to_use, *paths) + formatter_class = find_formatter(formatter_to_use) + + args = paths.map { |p| p.respond_to?(:puts) ? p : file_at(p) } + + if !Loader.formatters[formatter_class].nil? + formatter = formatter_class.new(*args) + register formatter, notifications_for(formatter_class) + elsif defined?(RSpec::LegacyFormatters) + formatter = RSpec::LegacyFormatters.load_formatter formatter_class, *args + register formatter, formatter.notifications + else + call_site = "Formatter added at: #{::RSpec::CallerFilter.first_non_rspec_line}" + + RSpec.warn_deprecation <<-WARNING.gsub(/\s*\|/, ' ') + |The #{formatter_class} formatter uses the deprecated formatter + |interface not supported directly by RSpec 3. + | + |To continue to use this formatter you must install the + |`rspec-legacy_formatters` gem, which provides support + |for legacy formatters or upgrade the formatter to a + |compatible version. + | + |#{call_site} + WARNING + end + end + + private + + def find_formatter(formatter_to_use) + built_in_formatter(formatter_to_use) || + custom_formatter(formatter_to_use) || + (raise ArgumentError, "Formatter '#{formatter_to_use}' unknown - " \ + "maybe you meant 'documentation' or 'progress'?.") + end + + def register(formatter, notifications) + return if duplicate_formatter_exists?(formatter) + @reporter.register_listener formatter, *notifications + @formatters << formatter + formatter + end + + def duplicate_formatter_exists?(new_formatter) + @formatters.any? do |formatter| + formatter.class == new_formatter.class && formatter.output == new_formatter.output + end + end + + def existing_formatter_implements?(notification) + @reporter.registered_listeners(notification).any? + end + + def built_in_formatter(key) + case key.to_s + when 'd', 'doc', 'documentation' + DocumentationFormatter + when 'h', 'html' + HtmlFormatter + when 'p', 'progress' + ProgressFormatter + when 'j', 'json' + JsonFormatter + when 'bisect' + BisectFormatter + end + end + + def notifications_for(formatter_class) + formatter_class.ancestors.inject(::RSpec::Core::Set.new) do |notifications, klass| + notifications.merge Loader.formatters.fetch(klass) { ::RSpec::Core::Set.new } + end + end + + def custom_formatter(formatter_ref) + if Class === formatter_ref + formatter_ref + elsif string_const?(formatter_ref) + begin + formatter_ref.gsub(/^::/, '').split('::').inject(Object) { |a, e| a.const_get e } + rescue NameError + require(path_for(formatter_ref)) ? retry : raise + end + end + end + + def string_const?(str) + str.is_a?(String) && /\A[A-Z][a-zA-Z0-9_:]*\z/ =~ str + end + + def path_for(const_ref) + underscore_with_fix_for_non_standard_rspec_naming(const_ref) + end + + def underscore_with_fix_for_non_standard_rspec_naming(string) + underscore(string).sub(%r{(^|/)r_spec($|/)}, '\\1rspec\\2') + end + + # activesupport/lib/active_support/inflector/methods.rb, line 48 + def underscore(camel_cased_word) + word = camel_cased_word.to_s.dup + word.gsub!(/::/, '/') + word.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2') + word.gsub!(/([a-z\d])([A-Z])/, '\1_\2') + word.tr!("-", "_") + word.downcase! + word + end + + def file_at(path) + RSpec::Support::DirectoryMaker.mkdir_p(File.dirname(path)) + File.new(path, 'w') + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/base_formatter.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/base_formatter.rb new file mode 100644 index 0000000..84248aa --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/base_formatter.rb @@ -0,0 +1,70 @@ +RSpec::Support.require_rspec_core "formatters/helpers" +require 'stringio' + +module RSpec + module Core + module Formatters + # RSpec's built-in formatters are all subclasses of + # RSpec::Core::Formatters::BaseTextFormatter. + # + # @see RSpec::Core::Formatters::BaseTextFormatter + # @see RSpec::Core::Reporter + # @see RSpec::Core::Formatters::Protocol + class BaseFormatter + # All formatters inheriting from this formatter will receive these + # notifications. + Formatters.register self, :start, :example_group_started, :close + attr_accessor :example_group + attr_reader :output + + # @api public + # @param output [IO] the formatter output + # @see RSpec::Core::Formatters::Protocol#initialize + def initialize(output) + @output = output || StringIO.new + @example_group = nil + end + + # @api public + # + # @param notification [StartNotification] + # @see RSpec::Core::Formatters::Protocol#start + def start(notification) + start_sync_output + @example_count = notification.count + end + + # @api public + # + # @param notification [GroupNotification] containing example_group + # subclass of `RSpec::Core::ExampleGroup` + # @see RSpec::Core::Formatters::Protocol#example_group_started + def example_group_started(notification) + @example_group = notification.group + end + + # @api public + # + # @param _notification [NullNotification] (Ignored) + # @see RSpec::Core::Formatters::Protocol#close + def close(_notification) + restore_sync_output + end + + private + + def start_sync_output + @old_sync, output.sync = output.sync, true if output_supports_sync + end + + def restore_sync_output + output.sync = @old_sync if output_supports_sync && !output.closed? + end + + def output_supports_sync + output.respond_to?(:sync=) + end + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/base_text_formatter.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/base_text_formatter.rb new file mode 100644 index 0000000..262a8d3 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/base_text_formatter.rb @@ -0,0 +1,77 @@ +RSpec::Support.require_rspec_core "formatters/base_formatter" +RSpec::Support.require_rspec_core "formatters/console_codes" + +module RSpec + module Core + module Formatters + # Base for all of RSpec's built-in formatters. See + # RSpec::Core::Formatters::BaseFormatter to learn more about all of the + # methods called by the reporter. + # + # @see RSpec::Core::Formatters::BaseFormatter + # @see RSpec::Core::Reporter + class BaseTextFormatter < BaseFormatter + Formatters.register self, + :message, :dump_summary, :dump_failures, :dump_pending, :seed + + # @api public + # + # Used by the reporter to send messages to the output stream. + # + # @param notification [MessageNotification] containing message + def message(notification) + output.puts notification.message + end + + # @api public + # + # Dumps detailed information about each example failure. + # + # @param notification [NullNotification] + def dump_failures(notification) + return if notification.failure_notifications.empty? + output.puts notification.fully_formatted_failed_examples + end + + # @api public + # + # This method is invoked after the dumping of examples and failures. + # Each parameter is assigned to a corresponding attribute. + # + # @param summary [SummaryNotification] containing duration, + # example_count, failure_count and pending_count + def dump_summary(summary) + output.puts summary.fully_formatted + end + + # @private + def dump_pending(notification) + return if notification.pending_examples.empty? + output.puts notification.fully_formatted_pending_examples + end + + # @private + def seed(notification) + return unless notification.seed_used? + output.puts notification.fully_formatted + end + + # @api public + # + # Invoked at the very end, `close` allows the formatter to clean + # up resources, e.g. open streams, etc. + # + # @param _notification [NullNotification] (Ignored) + def close(_notification) + return unless IO === output + return if output.closed? + + output.puts + + output.flush + output.close unless output == $stdout + end + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/bisect_formatter.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/bisect_formatter.rb new file mode 100644 index 0000000..60d8678 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/bisect_formatter.rb @@ -0,0 +1,68 @@ +require 'drb/drb' + +module RSpec + module Core + module Formatters + # Used by `--bisect`. When it shells out and runs a portion of the suite, it uses + # this formatter as a means to have the status reported back to it, via DRb. + # + # Note that since DRb calls carry considerable overhead compared to normal + # method calls, we try to minimize the number of DRb calls for perf reasons, + # opting to communicate only at the start and the end of the run, rather than + # after each example. + # @private + class BisectFormatter + Formatters.register self, :start, :start_dump, :example_started, + :example_failed, :example_passed, :example_pending + + def initialize(_output) + port = RSpec.configuration.drb_port + drb_uri = "druby://localhost:#{port}" + @all_example_ids = [] + @failed_example_ids = [] + @bisect_server = DRbObject.new_with_uri(drb_uri) + @remaining_failures = [] + end + + def start(_notification) + @remaining_failures = Set.new(@bisect_server.expected_failures) + end + + def example_started(notification) + @all_example_ids << notification.example.id + end + + def example_failed(notification) + @failed_example_ids << notification.example.id + example_finished(notification, :failed) + end + + def example_passed(notification) + example_finished(notification, :passed) + end + + def example_pending(notification) + example_finished(notification, :pending) + end + + def start_dump(_notification) + @bisect_server.latest_run_results = RunResults.new( + @all_example_ids, @failed_example_ids + ) + end + + RunResults = Struct.new(:all_example_ids, :failed_example_ids) + + private + + def example_finished(notification, status) + return unless @remaining_failures.include?(notification.example.id) + @remaining_failures.delete(notification.example.id) + + return if status == :failed && !@remaining_failures.empty? + RSpec.world.wants_to_quit = true + end + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/bisect_progress_formatter.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/bisect_progress_formatter.rb new file mode 100644 index 0000000..3b12c21 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/bisect_progress_formatter.rb @@ -0,0 +1,115 @@ +RSpec::Support.require_rspec_core "formatters/base_text_formatter" + +module RSpec + module Core + module Formatters + # @private + # Produces progress output while bisecting. + class BisectProgressFormatter < BaseTextFormatter + # We've named all events with a `bisect_` prefix to prevent naming collisions. + Formatters.register self, :bisect_starting, :bisect_original_run_complete, + :bisect_round_started, :bisect_individual_run_complete, + :bisect_round_finished, :bisect_complete, :bisect_repro_command, + :bisect_failed, :bisect_aborted + + def bisect_starting(notification) + options = notification.original_cli_args.join(' ') + output.puts "Bisect started using options: #{options.inspect}" + output.print "Running suite to find failures..." + end + + def bisect_original_run_complete(notification) + failures = Helpers.pluralize(notification.failed_example_ids.size, "failing example") + non_failures = Helpers.pluralize(notification.non_failing_example_ids.size, "non-failing example") + + output.puts " (#{Helpers.format_duration(notification.duration)})" + output.puts "Starting bisect with #{failures} and #{non_failures}." + end + + def bisect_round_started(notification, include_trailing_space=true) + search_desc = Helpers.pluralize( + notification.subset_size, "non-failing example" + ) + + output.print "\nRound #{notification.round}: searching for #{search_desc}" \ + " (of #{notification.remaining_count}) to ignore:" + output.print " " if include_trailing_space + end + + def bisect_round_finished(notification) + output.print " (#{Helpers.format_duration(notification.duration)})" + end + + def bisect_individual_run_complete(_) + output.print '.' + end + + def bisect_complete(notification) + output.puts "\nBisect complete! Reduced necessary non-failing examples " \ + "from #{notification.original_non_failing_count} to " \ + "#{notification.remaining_count} in " \ + "#{Helpers.format_duration(notification.duration)}." + end + + def bisect_repro_command(notification) + output.puts "\nThe minimal reproduction command is:\n #{notification.repro}" + end + + def bisect_failed(notification) + output.puts "\nBisect failed! #{notification.failure_explanation}" + end + + def bisect_aborted(notification) + output.puts "\n\nBisect aborted!" + output.puts "\nThe most minimal reproduction command discovered so far is:\n #{notification.repro}" + end + end + + # @private + # Produces detailed debug output while bisecting. Used when + # bisect is performed while the `DEBUG_RSPEC_BISECT` ENV var is used. + # Designed to provide details for us when we need to troubleshoot bisect bugs. + class BisectDebugFormatter < BisectProgressFormatter + Formatters.register self, :bisect_original_run_complete, :bisect_individual_run_start, + :bisect_individual_run_complete, :bisect_round_finished, :bisect_ignoring_ids + + def bisect_original_run_complete(notification) + output.puts " (#{Helpers.format_duration(notification.duration)})" + + output.puts " - #{describe_ids 'Failing examples', notification.failed_example_ids}" + output.puts " - #{describe_ids 'Non-failing examples', notification.non_failing_example_ids}" + end + + def bisect_individual_run_start(notification) + output.print "\n - Running: #{notification.command}" + end + + def bisect_individual_run_complete(notification) + output.print " (#{Helpers.format_duration(notification.duration)})" + end + + def bisect_round_started(notification) + super(notification, false) + end + + def bisect_round_finished(notification) + output.print "\n - Round finished" + super + end + + def bisect_ignoring_ids(notification) + output.print "\n - #{describe_ids 'Examples we can safely ignore', notification.ids_to_ignore}" + output.print "\n - #{describe_ids 'Remaining non-failing examples', notification.remaining_ids}" + end + + private + + def describe_ids(description, ids) + organized_ids = Formatters::Helpers.organize_ids(ids) + formatted_ids = organized_ids.map { |id| " - #{id}" }.join("\n") + "#{description} (#{ids.size}):\n#{formatted_ids}" + end + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/console_codes.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/console_codes.rb new file mode 100644 index 0000000..1419dbc --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/console_codes.rb @@ -0,0 +1,65 @@ +module RSpec + module Core + module Formatters + # ConsoleCodes provides helpers for formatting console output + # with ANSI codes, e.g. color's and bold. + module ConsoleCodes + # @private + VT100_CODES = + { + :black => 30, + :red => 31, + :green => 32, + :yellow => 33, + :blue => 34, + :magenta => 35, + :cyan => 36, + :white => 37, + :bold => 1, + } + # @private + VT100_CODE_VALUES = VT100_CODES.invert + + module_function + + # @private + CONFIG_COLORS_TO_METHODS = Configuration.instance_methods.grep(/_color\z/).inject({}) do |hash, method| + hash[method.to_s.sub(/_color\z/, '').to_sym] = method + hash + end + + # Fetches the correct code for the supplied symbol, or checks + # that a code is valid. Defaults to white (37). + # + # @param code_or_symbol [Symbol, Fixnum] Symbol or code to check + # @return [Fixnum] a console code + def console_code_for(code_or_symbol) + if (config_method = CONFIG_COLORS_TO_METHODS[code_or_symbol]) + console_code_for RSpec.configuration.__send__(config_method) + elsif VT100_CODE_VALUES.key?(code_or_symbol) + code_or_symbol + else + VT100_CODES.fetch(code_or_symbol) do + console_code_for(:white) + end + end + end + + # Wraps a piece of text in ANSI codes with the supplied code. Will + # only apply the control code if `RSpec.configuration.color_enabled?` + # returns true. + # + # @param text [String] the text to wrap + # @param code_or_symbol [Symbol, Fixnum] the desired control code + # @return [String] the wrapped text + def wrap(text, code_or_symbol) + if RSpec.configuration.color_enabled? + "\e[#{console_code_for(code_or_symbol)}m#{text}\e[0m" + else + text + end + end + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/deprecation_formatter.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/deprecation_formatter.rb new file mode 100644 index 0000000..ab90962 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/deprecation_formatter.rb @@ -0,0 +1,223 @@ +RSpec::Support.require_rspec_core "formatters/helpers" + +module RSpec + module Core + module Formatters + # @private + class DeprecationFormatter + Formatters.register self, :deprecation, :deprecation_summary + + attr_reader :count, :deprecation_stream, :summary_stream + + def initialize(deprecation_stream, summary_stream) + @deprecation_stream = deprecation_stream + @summary_stream = summary_stream + @seen_deprecations = Set.new + @count = 0 + end + alias :output :deprecation_stream + + def printer + @printer ||= case deprecation_stream + when File + ImmediatePrinter.new(FileStream.new(deprecation_stream), + summary_stream, self) + when RaiseErrorStream + ImmediatePrinter.new(deprecation_stream, summary_stream, self) + else + DelayedPrinter.new(deprecation_stream, summary_stream, self) + end + end + + def deprecation(notification) + return if @seen_deprecations.include? notification + + @count += 1 + printer.print_deprecation_message notification + @seen_deprecations << notification + end + + def deprecation_summary(_notification) + printer.deprecation_summary + end + + def deprecation_message_for(data) + if data.message + SpecifiedDeprecationMessage.new(data) + else + GeneratedDeprecationMessage.new(data) + end + end + + RAISE_ERROR_CONFIG_NOTICE = <<-EOS.gsub(/^\s+\|/, '') + | + |If you need more of the backtrace for any of these deprecations to + |identify where to make the necessary changes, you can configure + |`config.raise_errors_for_deprecations!`, and it will turn the + |deprecation warnings into errors, giving you the full backtrace. + EOS + + DEPRECATION_STREAM_NOTICE = "Pass `--deprecation-out` or set " \ + "`config.deprecation_stream` to a file for full output." + + SpecifiedDeprecationMessage = Struct.new(:type) do + def initialize(data) + @message = data.message + super deprecation_type_for(data) + end + + def to_s + output_formatted @message + end + + def too_many_warnings_message + msg = "Too many similar deprecation messages reported, disregarding further reports. " + msg << DEPRECATION_STREAM_NOTICE + msg + end + + private + + def output_formatted(str) + return str unless str.lines.count > 1 + separator = "#{'-' * 80}" + "#{separator}\n#{str.chomp}\n#{separator}" + end + + def deprecation_type_for(data) + data.message.gsub(/(\w+\/)+\w+\.rb:\d+/, '') + end + end + + GeneratedDeprecationMessage = Struct.new(:type) do + def initialize(data) + @data = data + super data.deprecated + end + + def to_s + msg = "#{@data.deprecated} is deprecated." + msg << " Use #{@data.replacement} instead." if @data.replacement + msg << " Called from #{@data.call_site}." if @data.call_site + msg + end + + def too_many_warnings_message + msg = "Too many uses of deprecated '#{type}'. " + msg << DEPRECATION_STREAM_NOTICE + msg + end + end + + # @private + class ImmediatePrinter + attr_reader :deprecation_stream, :summary_stream, :deprecation_formatter + + def initialize(deprecation_stream, summary_stream, deprecation_formatter) + @deprecation_stream = deprecation_stream + + @summary_stream = summary_stream + @deprecation_formatter = deprecation_formatter + end + + def print_deprecation_message(data) + deprecation_message = deprecation_formatter.deprecation_message_for(data) + deprecation_stream.puts deprecation_message.to_s + end + + def deprecation_summary + return if deprecation_formatter.count.zero? + deprecation_stream.summarize(summary_stream, deprecation_formatter.count) + end + end + + # @private + class DelayedPrinter + TOO_MANY_USES_LIMIT = 4 + + attr_reader :deprecation_stream, :summary_stream, :deprecation_formatter + + def initialize(deprecation_stream, summary_stream, deprecation_formatter) + @deprecation_stream = deprecation_stream + @summary_stream = summary_stream + @deprecation_formatter = deprecation_formatter + @seen_deprecations = Hash.new { 0 } + @deprecation_messages = Hash.new { |h, k| h[k] = [] } + end + + def print_deprecation_message(data) + deprecation_message = deprecation_formatter.deprecation_message_for(data) + @seen_deprecations[deprecation_message] += 1 + + stash_deprecation_message(deprecation_message) + end + + def stash_deprecation_message(deprecation_message) + if @seen_deprecations[deprecation_message] < TOO_MANY_USES_LIMIT + @deprecation_messages[deprecation_message] << deprecation_message.to_s + elsif @seen_deprecations[deprecation_message] == TOO_MANY_USES_LIMIT + @deprecation_messages[deprecation_message] << deprecation_message.too_many_warnings_message + end + end + + def deprecation_summary + return unless @deprecation_messages.any? + + print_deferred_deprecation_warnings + deprecation_stream.puts RAISE_ERROR_CONFIG_NOTICE + + summary_stream.puts "\n#{Helpers.pluralize(deprecation_formatter.count, 'deprecation warning')} total" + end + + def print_deferred_deprecation_warnings + deprecation_stream.puts "\nDeprecation Warnings:\n\n" + @deprecation_messages.keys.sort_by(&:type).each do |deprecation| + messages = @deprecation_messages[deprecation] + messages.each { |msg| deprecation_stream.puts msg } + deprecation_stream.puts + end + end + end + + # @private + # Not really a stream, but is usable in place of one. + class RaiseErrorStream + def puts(message) + raise DeprecationError, message + end + + def summarize(summary_stream, deprecation_count) + summary_stream.puts "\n#{Helpers.pluralize(deprecation_count, 'deprecation')} found." + end + end + + # @private + # Wraps a File object and provides file-specific operations. + class FileStream + def initialize(file) + @file = file + + # In one of my test suites, I got lots of duplicate output in the + # deprecation file (e.g. 200 of the same deprecation, even though + # the `puts` below was only called 6 times). Setting `sync = true` + # fixes this (but we really have no idea why!). + @file.sync = true + end + + def puts(*args) + @file.puts(*args) + end + + def summarize(summary_stream, deprecation_count) + path = @file.respond_to?(:path) ? @file.path : @file.inspect + summary_stream.puts "\n#{Helpers.pluralize(deprecation_count, 'deprecation')} logged to #{path}" + puts RAISE_ERROR_CONFIG_NOTICE + end + end + end + end + + # Deprecation Error. + DeprecationError = Class.new(StandardError) + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/documentation_formatter.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/documentation_formatter.rb new file mode 100644 index 0000000..fd50c87 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/documentation_formatter.rb @@ -0,0 +1,70 @@ +RSpec::Support.require_rspec_core "formatters/base_text_formatter" + +module RSpec + module Core + module Formatters + # @private + class DocumentationFormatter < BaseTextFormatter + Formatters.register self, :example_group_started, :example_group_finished, + :example_passed, :example_pending, :example_failed + + def initialize(output) + super + @group_level = 0 + end + + def example_group_started(notification) + output.puts if @group_level == 0 + output.puts "#{current_indentation}#{notification.group.description.strip}" + + @group_level += 1 + end + + def example_group_finished(_notification) + @group_level -= 1 + end + + def example_passed(passed) + output.puts passed_output(passed.example) + end + + def example_pending(pending) + output.puts pending_output(pending.example, + pending.example.execution_result.pending_message) + end + + def example_failed(failure) + output.puts failure_output(failure.example, + failure.example.execution_result.exception) + end + + private + + def passed_output(example) + ConsoleCodes.wrap("#{current_indentation}#{example.description.strip}", :success) + end + + def pending_output(example, message) + ConsoleCodes.wrap("#{current_indentation}#{example.description.strip} " \ + "(PENDING: #{message})", + :pending) + end + + def failure_output(example, _exception) + ConsoleCodes.wrap("#{current_indentation}#{example.description.strip} " \ + "(FAILED - #{next_failure_index})", + :failure) + end + + def next_failure_index + @next_failure_index ||= 0 + @next_failure_index += 1 + end + + def current_indentation + ' ' * @group_level + end + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/exception_presenter.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/exception_presenter.rb new file mode 100644 index 0000000..3afa7c5 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/exception_presenter.rb @@ -0,0 +1,393 @@ +module RSpec + module Core + module Formatters + # @private + class ExceptionPresenter + attr_reader :exception, :example, :description, :message_color, + :detail_formatter, :extra_detail_formatter, :backtrace_formatter + private :message_color, :detail_formatter, :extra_detail_formatter, :backtrace_formatter + + def initialize(exception, example, options={}) + @exception = exception + @example = example + @message_color = options.fetch(:message_color) { RSpec.configuration.failure_color } + @description = options.fetch(:description_formatter) { Proc.new { example.full_description } }.call(self) + @detail_formatter = options.fetch(:detail_formatter) { Proc.new {} } + @extra_detail_formatter = options.fetch(:extra_detail_formatter) { Proc.new {} } + @backtrace_formatter = options.fetch(:backtrace_formatter) { RSpec.configuration.backtrace_formatter } + @indentation = options.fetch(:indentation, 2) + @skip_shared_group_trace = options.fetch(:skip_shared_group_trace, false) + @failure_lines = options[:failure_lines] + end + + def message_lines + add_shared_group_lines(failure_lines, Notifications::NullColorizer) + end + + def colorized_message_lines(colorizer=::RSpec::Core::Formatters::ConsoleCodes) + add_shared_group_lines(failure_lines, colorizer).map do |line| + colorizer.wrap line, message_color + end + end + + def formatted_backtrace + backtrace_formatter.format_backtrace(exception_backtrace, example.metadata) + end + + def colorized_formatted_backtrace(colorizer=::RSpec::Core::Formatters::ConsoleCodes) + formatted_backtrace.map do |backtrace_info| + colorizer.wrap "# #{backtrace_info}", RSpec.configuration.detail_color + end + end + + def fully_formatted(failure_number, colorizer=::RSpec::Core::Formatters::ConsoleCodes) + alignment_basis = "#{' ' * @indentation}#{failure_number}) " + indentation = ' ' * alignment_basis.length + + "\n#{alignment_basis}#{description_and_detail(colorizer, indentation)}" \ + "\n#{formatted_message_and_backtrace(colorizer, indentation)}" \ + "#{extra_detail_formatter.call(failure_number, colorizer, indentation)}" + end + + def failure_slash_error_line + @failure_slash_error_line ||= "Failure/Error: #{read_failed_line.strip}" + end + + private + + def description_and_detail(colorizer, indentation) + detail = detail_formatter.call(example, colorizer, indentation) + return (description || detail) unless description && detail + "#{description}\n#{indentation}#{detail}" + end + + if String.method_defined?(:encoding) + def encoding_of(string) + string.encoding + end + + def encoded_string(string) + RSpec::Support::EncodedString.new(string, Encoding.default_external) + end + else # for 1.8.7 + # :nocov: + def encoding_of(_string) + end + + def encoded_string(string) + RSpec::Support::EncodedString.new(string) + end + # :nocov: + end + + def exception_class_name + name = exception.class.name.to_s + name = "(anonymous error class)" if name == '' + name + end + + def failure_lines + @failure_lines ||= + begin + lines = [] + lines << failure_slash_error_line unless (description == failure_slash_error_line) + lines << "#{exception_class_name}:" unless exception_class_name =~ /RSpec/ + encoded_string(exception.message.to_s).split("\n").each do |line| + lines << " #{line}" + end + lines + end + end + + def add_shared_group_lines(lines, colorizer) + return lines if @skip_shared_group_trace + + example.metadata[:shared_group_inclusion_backtrace].each do |frame| + lines << colorizer.wrap(frame.description, RSpec.configuration.default_color) + end + + lines + end + + def read_failed_line + matching_line = find_failed_line + unless matching_line + return "Unable to find matching line from backtrace" + end + + file_path, line_number = matching_line.match(/(.+?):(\d+)(|:\d+)/)[1..2] + + if File.exist?(file_path) + File.readlines(file_path)[line_number.to_i - 1] || + "Unable to find matching line in #{file_path}" + else + "Unable to find #{file_path} to read failed line" + end + rescue SecurityError + "Unable to read failed line" + end + + def find_failed_line + example_path = example.metadata[:absolute_file_path].downcase + exception_backtrace.find do |line| + next unless (line_path = line[/(.+?):(\d+)(|:\d+)/, 1]) + File.expand_path(line_path).downcase == example_path + end + end + + def formatted_message_and_backtrace(colorizer, indentation) + lines = colorized_message_lines(colorizer) + colorized_formatted_backtrace(colorizer) + + formatted = "" + + lines.each do |line| + formatted << RSpec::Support::EncodedString.new("#{indentation}#{line}\n", encoding_of(formatted)) + end + + formatted + end + + def exception_backtrace + exception.backtrace || [] + end + + # @private + # Configuring the `ExceptionPresenter` with the right set of options to handle + # pending vs failed vs skipped and aggregated (or not) failures is not simple. + # This class takes care of building an appropriate `ExceptionPresenter` for the + # provided example. + class Factory + def build + ExceptionPresenter.new(@exception, @example, options) + end + + private + + def initialize(example) + @example = example + @execution_result = example.execution_result + @exception = if @execution_result.status == :pending + @execution_result.pending_exception + else + @execution_result.exception + end + end + + def options + with_multiple_error_options_as_needed(@exception, pending_options || {}) + end + + def pending_options + if @execution_result.pending_fixed? + { + :description_formatter => Proc.new { "#{@example.full_description} FIXED" }, + :message_color => RSpec.configuration.fixed_color, + :failure_lines => [ + "Expected pending '#{@execution_result.pending_message}' to fail. No Error was raised." + ] + } + elsif @execution_result.status == :pending + { + :message_color => RSpec.configuration.pending_color, + :detail_formatter => PENDING_DETAIL_FORMATTER + } + end + end + + def with_multiple_error_options_as_needed(exception, options) + return options unless multiple_exceptions_error?(exception) + + options = options.merge( + :failure_lines => [], + :extra_detail_formatter => sub_failure_list_formatter(exception, options[:message_color]), + :detail_formatter => multiple_exception_summarizer(exception, + options[:detail_formatter], + options[:message_color]) + ) + + options[:description_formatter] &&= Proc.new {} + + return options unless exception.aggregation_metadata[:hide_backtrace] + options[:backtrace_formatter] = EmptyBacktraceFormatter + options + end + + def multiple_exceptions_error?(exception) + MultipleExceptionError::InterfaceTag === exception + end + + def multiple_exception_summarizer(exception, prior_detail_formatter, color) + lambda do |example, colorizer, indentation| + summary = if exception.aggregation_metadata[:hide_backtrace] + # Since the backtrace is hidden, the subfailures will come + # immediately after this, and using `:` will read well. + "Got #{exception.exception_count_description}:" + else + # The backtrace comes after this, so using a `:` doesn't make sense + # since the failures may be many lines below. + "#{exception.summary}." + end + + summary = colorizer.wrap(summary, color || RSpec.configuration.failure_color) + return summary unless prior_detail_formatter + "#{prior_detail_formatter.call(example, colorizer, indentation)}\n#{indentation}#{summary}" + end + end + + def sub_failure_list_formatter(exception, message_color) + common_backtrace_truncater = CommonBacktraceTruncater.new(exception) + + lambda do |failure_number, colorizer, indentation| + exception.all_exceptions.each_with_index.map do |failure, index| + options = with_multiple_error_options_as_needed( + failure, + :description_formatter => :failure_slash_error_line.to_proc, + :indentation => indentation.length, + :message_color => message_color || RSpec.configuration.failure_color, + :skip_shared_group_trace => true + ) + + failure = common_backtrace_truncater.with_truncated_backtrace(failure) + presenter = ExceptionPresenter.new(failure, @example, options) + presenter.fully_formatted("#{failure_number}.#{index + 1}", colorizer) + end.join + end + end + + # @private + # Used to prevent a confusing backtrace from showing up from the `aggregate_failures` + # block declared for `:aggregate_failures` metadata. + module EmptyBacktraceFormatter + def self.format_backtrace(*) + [] + end + end + + # @private + class CommonBacktraceTruncater + def initialize(parent) + @parent = parent + end + + def with_truncated_backtrace(child) + child_bt = child.backtrace + parent_bt = @parent.backtrace + return child if child_bt.nil? || child_bt.empty? || parent_bt.nil? + + index_before_first_common_frame = -1.downto(-child_bt.size).find do |index| + parent_bt[index] != child_bt[index] + end + + return child if index_before_first_common_frame == -1 + + child = child.dup + child.set_backtrace(child_bt[0..index_before_first_common_frame]) + child + end + end + end + + # @private + PENDING_DETAIL_FORMATTER = Proc.new do |example, colorizer| + colorizer.wrap("# #{example.execution_result.pending_message}", :detail) + end + end + end + + # Provides a single exception instance that provides access to + # multiple sub-exceptions. This is used in situations where a single + # individual spec has multiple exceptions, such as one in the `it` block + # and one in an `after` block. + class MultipleExceptionError < StandardError + # @private + # Used so there is a common module in the ancestor chain of this class + # and `RSpec::Expectations::MultipleExpectationsNotMetError`, which allows + # code to detect exceptions that are instances of either, without first + # checking to see if rspec-expectations is loaded. + module InterfaceTag + # Appends the provided exception to the list. + # @param exception [Exception] Exception to append to the list. + # @private + def add(exception) + # `PendingExampleFixedError` can be assigned to an example that initially has no + # failures, but when the `aggregate_failures` around hook completes, it notifies of + # a failure. If we do not ignore `PendingExampleFixedError` it would be surfaced to + # the user as part of a multiple exception error, which is undesirable. While it's + # pretty weird we handle this here, it's the best solution I've been able to come + # up with, and `PendingExampleFixedError` always represents the _lack_ of any exception + # so clearly when we are transitioning to a `MultipleExceptionError`, it makes sense to + # ignore it. + return if Pending::PendingExampleFixedError === exception + + all_exceptions << exception + + if exception.class.name =~ /RSpec/ + failures << exception + else + other_errors << exception + end + end + + # Provides a way to force `ex` to be something that satisfies the multiple + # exception error interface. If it already satisfies it, it will be returned; + # otherwise it will wrap it in a `MultipleExceptionError`. + # @private + def self.for(ex) + return ex if self === ex + MultipleExceptionError.new(ex) + end + end + + include InterfaceTag + + # @return [Array] The list of failures. + attr_reader :failures + + # @return [Array] The list of other errors. + attr_reader :other_errors + + # @return [Array] The list of failures and other exceptions, combined. + attr_reader :all_exceptions + + # @return [Hash] Metadata used by RSpec for formatting purposes. + attr_reader :aggregation_metadata + + # @return [nil] Provided only for interface compatibility with + # `RSpec::Expectations::MultipleExpectationsNotMetError`. + attr_reader :aggregation_block_label + + # @param exceptions [Array] The initial list of exceptions. + def initialize(*exceptions) + super() + + @failures = [] + @other_errors = [] + @all_exceptions = [] + @aggregation_metadata = { :hide_backtrace => true } + @aggregation_block_label = nil + + exceptions.each { |e| add e } + end + + # @return [String] Combines all the exception messages into a single string. + # @note RSpec does not actually use this -- instead it formats each exception + # individually. + def message + all_exceptions.map(&:message).join("\n\n") + end + + # @return [String] A summary of the failure, including the block label and a count of failures. + def summary + "Got #{exception_count_description}" + end + + # return [String] A description of the failure/error counts. + def exception_count_description + failure_count = Formatters::Helpers.pluralize(failures.size, "failure") + return failure_count if other_errors.empty? + error_count = Formatters::Helpers.pluralize(other_errors.size, "other error") + "#{failure_count} and #{error_count}" + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/fallback_message_formatter.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/fallback_message_formatter.rb new file mode 100644 index 0000000..db4423f --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/fallback_message_formatter.rb @@ -0,0 +1,28 @@ +module RSpec + module Core + module Formatters + # @api private + # Formatter for providing message output as a fallback when no other + # profiler implements #message + class FallbackMessageFormatter + Formatters.register self, :message + + def initialize(output) + @output = output + end + + # @private + attr_reader :output + + # @api public + # + # Used by the reporter to send messages to the output stream. + # + # @param notification [MessageNotification] containing message + def message(notification) + output.puts notification.message + end + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/helpers.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/helpers.rb new file mode 100644 index 0000000..3d3b0f5 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/helpers.rb @@ -0,0 +1,109 @@ +RSpec::Support.require_rspec_core "shell_escape" + +module RSpec + module Core + module Formatters + # Formatters helpers. + module Helpers + # @private + SUB_SECOND_PRECISION = 5 + + # @private + DEFAULT_PRECISION = 2 + + # @api private + # + # Formats seconds into a human-readable string. + # + # @param duration [Float, Fixnum] in seconds + # @return [String] human-readable time + # + # @example + # format_duration(1) #=> "1 minute 1 second" + # format_duration(135.14) #=> "2 minutes 15.14 seconds" + def self.format_duration(duration) + precision = case + when duration < 1 then SUB_SECOND_PRECISION + when duration < 120 then DEFAULT_PRECISION + when duration < 300 then 1 + else 0 + end + + if duration > 60 + minutes = (duration.to_i / 60).to_i + seconds = duration - minutes * 60 + + "#{pluralize(minutes, 'minute')} #{pluralize(format_seconds(seconds, precision), 'second')}" + else + pluralize(format_seconds(duration, precision), 'second') + end + end + + # @api private + # + # Formats seconds to have 5 digits of precision with trailing zeros + # removed if the number is less than 1 or with 2 digits of precision if + # the number is greater than zero. + # + # @param float [Float] + # @return [String] formatted float + # + # @example + # format_seconds(0.000006) #=> "0.00001" + # format_seconds(0.020000) #=> "0.02" + # format_seconds(1.00000000001) #=> "1" + # + # The precision used is set in {Helpers::SUB_SECOND_PRECISION} and + # {Helpers::DEFAULT_PRECISION}. + # + # @see #strip_trailing_zeroes + def self.format_seconds(float, precision=nil) + precision ||= (float < 1) ? SUB_SECOND_PRECISION : DEFAULT_PRECISION + formatted = "%.#{precision}f" % float + strip_trailing_zeroes(formatted) + end + + # @api private + # + # Remove trailing zeros from a string. + # + # Only remove trailing zeros after a decimal place. + # see: http://rubular.com/r/ojtTydOgpn + # + # @param string [String] string with trailing zeros + # @return [String] string with trailing zeros removed + def self.strip_trailing_zeroes(string) + string.sub(/(?:(\..*[^0])0+|\.0+)$/, '\1') + end + private_class_method :strip_trailing_zeroes + + # @api private + # + # Pluralize a word based on a count. + # + # @param count [Fixnum] number of objects + # @param string [String] word to be pluralized + # @return [String] pluralized word + def self.pluralize(count, string) + "#{count} #{string}#{'s' unless count.to_f == 1}" + end + + # @api private + # Given a list of example ids, organizes them into a compact, ordered list. + def self.organize_ids(ids) + grouped = ids.inject(Hash.new { |h, k| h[k] = [] }) do |hash, id| + file, id = id.split(Configuration::ON_SQUARE_BRACKETS) + hash[file] << id + hash + end + + grouped.sort_by(&:first).map do |file, grouped_ids| + grouped_ids = grouped_ids.sort_by { |id| id.split(':').map(&:to_i) } + id = Metadata.id_from(:rerun_file_path => file, :scoped_id => grouped_ids.join(',')) + ShellEscape.conditionally_quote(id) + end + end + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/html_formatter.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/html_formatter.rb new file mode 100644 index 0000000..4644c01 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/html_formatter.rb @@ -0,0 +1,151 @@ +RSpec::Support.require_rspec_core "formatters/base_text_formatter" +RSpec::Support.require_rspec_core "formatters/html_printer" + +module RSpec + module Core + module Formatters + # @private + class HtmlFormatter < BaseFormatter + Formatters.register self, :start, :example_group_started, :start_dump, + :example_started, :example_passed, :example_failed, + :example_pending, :dump_summary + + def initialize(output) + super(output) + @failed_examples = [] + @example_group_number = 0 + @example_number = 0 + @header_red = nil + @printer = HtmlPrinter.new(output) + end + + def start(notification) + super + @printer.print_html_start + @printer.flush + end + + def example_group_started(notification) + super + @example_group_red = false + @example_group_number += 1 + + @printer.print_example_group_end unless example_group_number == 1 + @printer.print_example_group_start(example_group_number, + notification.group.description, + notification.group.parent_groups.size) + @printer.flush + end + + def start_dump(_notification) + @printer.print_example_group_end + @printer.flush + end + + def example_started(_notification) + @example_number += 1 + end + + def example_passed(passed) + @printer.move_progress(percent_done) + @printer.print_example_passed(passed.example.description, passed.example.execution_result.run_time) + @printer.flush + end + + def example_failed(failure) + @failed_examples << failure.example + unless @header_red + @header_red = true + @printer.make_header_red + end + + unless @example_group_red + @example_group_red = true + @printer.make_example_group_header_red(example_group_number) + end + + @printer.move_progress(percent_done) + + example = failure.example + + exception = failure.exception + exception_details = if exception + { + :message => exception.message, + :backtrace => failure.formatted_backtrace.join("\n") + } + end + extra = extra_failure_content(failure) + + @printer.print_example_failed( + example.execution_result.pending_fixed, + example.description, + example.execution_result.run_time, + @failed_examples.size, + exception_details, + (extra == "") ? false : extra + ) + @printer.flush + end + + def example_pending(pending) + example = pending.example + + @printer.make_header_yellow unless @header_red + @printer.make_example_group_header_yellow(example_group_number) unless @example_group_red + @printer.move_progress(percent_done) + @printer.print_example_pending(example.description, example.execution_result.pending_message) + @printer.flush + end + + def dump_summary(summary) + @printer.print_summary( + summary.duration, + summary.example_count, + summary.failure_count, + summary.pending_count + ) + @printer.flush + end + + private + + # If these methods are declared with attr_reader Ruby will issue a + # warning because they are private. + # rubocop:disable Style/TrivialAccessors + + # The number of the currently running example_group. + def example_group_number + @example_group_number + end + + # The number of the currently running example (a global counter). + def example_number + @example_number + end + # rubocop:enable Style/TrivialAccessors + + def percent_done + result = 100.0 + if @example_count > 0 + result = (((example_number).to_f / @example_count.to_f * 1000).to_i / 10.0).to_f + end + result + end + + # Override this method if you wish to output extra HTML for a failed + # spec. For example, you could output links to images or other files + # produced during the specs. + def extra_failure_content(failure) + RSpec::Support.require_rspec_core "formatters/snippet_extractor" + backtrace = (failure.exception.backtrace || []).map do |line| + RSpec.configuration.backtrace_formatter.backtrace_line(line) + end + backtrace.compact! + @snippet_extractor ||= SnippetExtractor.new + "
#{@snippet_extractor.snippet(backtrace)}
" + end + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/html_printer.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/html_printer.rb new file mode 100644 index 0000000..dfb68a9 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/html_printer.rb @@ -0,0 +1,415 @@ +require 'erb' + +module RSpec + module Core + module Formatters + # @private + class HtmlPrinter + include ERB::Util # For the #h method. + def initialize(output) + @output = output + end + + def print_html_start + @output.puts HTML_HEADER + @output.puts REPORT_HEADER + end + + def print_example_group_end + @output.puts " " + @output.puts "
" + end + + def print_example_group_start(group_id, description, number_of_parents) + @output.puts "
" + @output.puts "
" + @output.puts "
#{h(description)}
" + end + + def print_example_passed(description, run_time) + formatted_run_time = "%.5f" % run_time + @output.puts "
" \ + "#{h(description)}" \ + "#{formatted_run_time}s
" + end + + # rubocop:disable Style/ParameterLists + def print_example_failed(pending_fixed, description, run_time, failure_id, + exception, extra_content) + # rubocop:enable Style/ParameterLists + formatted_run_time = "%.5f" % run_time + + @output.puts "
" + @output.puts " #{h(description)}" + @output.puts " #{formatted_run_time}s" + @output.puts "
" + if exception + @output.puts "
#{h(exception[:message])}
" + @output.puts "
#{h exception[:backtrace]}
" + end + @output.puts extra_content if extra_content + @output.puts "
" + @output.puts "
" + end + + def print_example_pending(description, pending_message) + @output.puts "
" \ + "#{h(description)} " \ + "(PENDING: #{h(pending_message)})
" + end + + def print_summary(duration, example_count, failure_count, pending_count) + totals = "#{example_count} example#{'s' unless example_count == 1}, " + totals << "#{failure_count} failure#{'s' unless failure_count == 1}" + totals << ", #{pending_count} pending" if pending_count > 0 + + formatted_duration = "%.5f" % duration + + @output.puts "" + @output.puts "" + @output.puts "
" + @output.puts "" + @output.puts "" + @output.puts "" + end + + def flush + @output.flush + end + + def move_progress(percent_done) + @output.puts " " + @output.flush + end + + def make_header_red + @output.puts " " + end + + def make_header_yellow + @output.puts " " + end + + def make_example_group_header_red(group_id) + @output.puts " " + @output.puts " " + end + + def make_example_group_header_yellow(group_id) + @output.puts " " + @output.puts " " + end + + private + + def indentation_style(number_of_parents) + "style=\"margin-left: #{(number_of_parents - 1) * 15}px;\"" + end + + # rubocop:disable LineLength + REPORT_HEADER = <<-EOF +
+ +
+
+

RSpec Code Examples

+
+ +
+ + + +
+ +
+

 

+

 

+
+
+ + +
+EOF + # rubocop:enable LineLength + + # rubocop:disable LineLength + GLOBAL_SCRIPTS = <<-EOF + +function addClass(element_id, classname) { + document.getElementById(element_id).className += (" " + classname); +} + +function removeClass(element_id, classname) { + var elem = document.getElementById(element_id); + var classlist = elem.className.replace(classname,''); + elem.className = classlist; +} + +function moveProgressBar(percentDone) { + document.getElementById("rspec-header").style.width = percentDone +"%"; +} + +function makeRed(element_id) { + removeClass(element_id, 'passed'); + removeClass(element_id, 'not_implemented'); + addClass(element_id,'failed'); +} + +function makeYellow(element_id) { + var elem = document.getElementById(element_id); + if (elem.className.indexOf("failed") == -1) { // class doesn't includes failed + if (elem.className.indexOf("not_implemented") == -1) { // class doesn't include not_implemented + removeClass(element_id, 'passed'); + addClass(element_id,'not_implemented'); + } + } +} + +function apply_filters() { + var passed_filter = document.getElementById('passed_checkbox').checked; + var failed_filter = document.getElementById('failed_checkbox').checked; + var pending_filter = document.getElementById('pending_checkbox').checked; + + assign_display_style("example passed", passed_filter); + assign_display_style("example failed", failed_filter); + assign_display_style("example not_implemented", pending_filter); + + assign_display_style_for_group("example_group passed", passed_filter); + assign_display_style_for_group("example_group not_implemented", pending_filter, pending_filter || passed_filter); + assign_display_style_for_group("example_group failed", failed_filter, failed_filter || pending_filter || passed_filter); +} + +function get_display_style(display_flag) { + var style_mode = 'none'; + if (display_flag == true) { + style_mode = 'block'; + } + return style_mode; +} + +function assign_display_style(classname, display_flag) { + var style_mode = get_display_style(display_flag); + var elems = document.getElementsByClassName(classname) + for (var i=0; i + + + RSpec results + + + + + + + + +EOF + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/json_formatter.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/json_formatter.rb new file mode 100644 index 0000000..510a80c --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/json_formatter.rb @@ -0,0 +1,96 @@ +RSpec::Support.require_rspec_core "formatters/base_formatter" +require 'json' + +module RSpec + module Core + module Formatters + # @private + class JsonFormatter < BaseFormatter + Formatters.register self, :message, :dump_summary, :dump_profile, :stop, :close + + attr_reader :output_hash + + def initialize(output) + super + @output_hash = { + :version => RSpec::Core::Version::STRING + } + end + + def message(notification) + (@output_hash[:messages] ||= []) << notification.message + end + + def dump_summary(summary) + @output_hash[:summary] = { + :duration => summary.duration, + :example_count => summary.example_count, + :failure_count => summary.failure_count, + :pending_count => summary.pending_count + } + @output_hash[:summary_line] = summary.totals_line + end + + def stop(notification) + @output_hash[:examples] = notification.examples.map do |example| + format_example(example).tap do |hash| + e = example.exception + if e + hash[:exception] = { + :class => e.class.name, + :message => e.message, + :backtrace => e.backtrace, + } + end + end + end + end + + def close(_notification) + output.write @output_hash.to_json + output.close if IO === output && output != $stdout + end + + def dump_profile(profile) + @output_hash[:profile] = {} + dump_profile_slowest_examples(profile) + dump_profile_slowest_example_groups(profile) + end + + # @api private + def dump_profile_slowest_examples(profile) + @output_hash[:profile] = {} + @output_hash[:profile][:examples] = profile.slowest_examples.map do |example| + format_example(example).tap do |hash| + hash[:run_time] = example.execution_result.run_time + end + end + @output_hash[:profile][:slowest] = profile.slow_duration + @output_hash[:profile][:total] = profile.duration + end + + # @api private + def dump_profile_slowest_example_groups(profile) + @output_hash[:profile] ||= {} + @output_hash[:profile][:groups] = profile.slowest_groups.map do |loc, hash| + hash.update(:location => loc) + end + end + + private + + def format_example(example) + { + :description => example.description, + :full_description => example.full_description, + :status => example.execution_result.status.to_s, + :file_path => example.metadata[:file_path], + :line_number => example.metadata[:line_number], + :run_time => example.execution_result.run_time, + :pending_message => example.execution_result.pending_message, + } + end + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/profile_formatter.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/profile_formatter.rb new file mode 100644 index 0000000..4b95d93 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/profile_formatter.rb @@ -0,0 +1,68 @@ +RSpec::Support.require_rspec_core "formatters/console_codes" + +module RSpec + module Core + module Formatters + # @api private + # Formatter for providing profile output. + class ProfileFormatter + Formatters.register self, :dump_profile + + def initialize(output) + @output = output + end + + # @private + attr_reader :output + + # @api public + # + # This method is invoked after the dumping the summary if profiling is + # enabled. + # + # @param profile [ProfileNotification] containing duration, + # slowest_examples and slowest_example_groups + def dump_profile(profile) + dump_profile_slowest_examples(profile) + dump_profile_slowest_example_groups(profile) + end + + private + + def dump_profile_slowest_examples(profile) + @output.puts "\nTop #{profile.slowest_examples.size} slowest " \ + "examples (#{Helpers.format_seconds(profile.slow_duration)} " \ + "seconds, #{profile.percentage}% of total time):\n" + + profile.slowest_examples.each do |example| + @output.puts " #{example.full_description}" + @output.puts " #{bold(Helpers.format_seconds(example.execution_result.run_time))} " \ + "#{bold("seconds")} #{format_caller(example.location)}" + end + end + + def dump_profile_slowest_example_groups(profile) + return if profile.slowest_groups.empty? + + @output.puts "\nTop #{profile.slowest_groups.size} slowest example groups:" + profile.slowest_groups.each do |loc, hash| + average = "#{bold(Helpers.format_seconds(hash[:average]))} #{bold("seconds")} average" + total = "#{Helpers.format_seconds(hash[:total_time])} seconds" + count = Helpers.pluralize(hash[:count], "example") + @output.puts " #{hash[:description]}" + @output.puts " #{average} (#{total} / #{count}) #{loc}" + end + end + + def format_caller(caller_info) + RSpec.configuration.backtrace_formatter.backtrace_line( + caller_info.to_s.split(':in `block').first) + end + + def bold(text) + ConsoleCodes.wrap(text, :bold) + end + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/progress_formatter.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/progress_formatter.rb new file mode 100644 index 0000000..f0978bc --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/progress_formatter.rb @@ -0,0 +1,28 @@ +RSpec::Support.require_rspec_core "formatters/base_text_formatter" + +module RSpec + module Core + module Formatters + # @private + class ProgressFormatter < BaseTextFormatter + Formatters.register self, :example_passed, :example_pending, :example_failed, :start_dump + + def example_passed(_notification) + output.print ConsoleCodes.wrap('.', :success) + end + + def example_pending(_notification) + output.print ConsoleCodes.wrap('*', :pending) + end + + def example_failed(_notification) + output.print ConsoleCodes.wrap('F', :failure) + end + + def start_dump(_notification) + output.puts + end + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/protocol.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/protocol.rb new file mode 100644 index 0000000..f9e2ae5 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/protocol.rb @@ -0,0 +1,172 @@ +module RSpec + module Core + module Formatters + # This class isn't loaded at runtime but serves to document all of the + # notifications implemented as part of the standard interface. The + # reporter will issue these during a normal test suite run, but a + # formatter will only receive those notifications it has registered + # itself to receive. To register a formatter call: + # + # `::RSpec::Core::Formatters.register class, :list, :of, :notifications` + # + # e.g. + # + # `::RSpec::Core::Formatters.register self, :start, :example_started` + # + # @see RSpec::Core::Formatters::BaseFormatter + # @see RSpec::Core::Formatters::BaseTextFormatter + # @see RSpec::Core::Reporter + class Protocol + # @method initialize + # @api public + # + # @param output [IO] the formatter output + + # @method start + # @api public + # @group Suite Notifications + # + # This method is invoked before any examples are run, right after + # they have all been collected. This can be useful for special + # formatters that need to provide progress on feedback (graphical ones). + # + # This will only be invoked once, and the next one to be invoked + # is {#example_group_started}. + # + # @param notification [StartNotification] + + # @method example_group_started + # @api public + # @group Group Notifications + # + # This method is invoked at the beginning of the execution of each + # example group. + # + # The next method to be invoked after this is {#example_passed}, + # {#example_pending}, or {#example_group_finished}. + # + # @param notification [GroupNotification] containing example_group + # subclass of `RSpec::Core::ExampleGroup` + + # @method example_group_finished + # @api public + # @group Group Notifications + # + # Invoked at the end of the execution of each example group. + # + # @param notification [GroupNotification] containing example_group + # subclass of `RSpec::Core::ExampleGroup` + + # @method example_started + # @api public + # @group Example Notifications + # + # Invoked at the beginning of the execution of each example. + # + # @param notification [ExampleNotification] containing example subclass + # of `RSpec::Core::Example` + + # @method example_passed + # @api public + # @group Example Notifications + # + # Invoked when an example passes. + # + # @param notification [ExampleNotification] containing example subclass + # of `RSpec::Core::Example` + + # @method example_pending + # @api public + # @group Example Notifications + # + # Invoked when an example is pending. + # + # @param notification [ExampleNotification] containing example subclass + # of `RSpec::Core::Example` + + # @method example_failed + # @api public + # @group Example Notifications + # + # Invoked when an example fails. + # + # @param notification [ExampleNotification] containing example subclass + # of `RSpec::Core::Example` + + # @method message + # @api public + # @group Suite Notifications + # + # Used by the reporter to send messages to the output stream. + # + # @param notification [MessageNotification] containing message + + # @method stop + # @api public + # @group Suite Notifications + # + # Invoked after all examples have executed, before dumping post-run + # reports. + # + # @param notification [NullNotification] + + # @method start_dump + # @api public + # @group Suite Notifications + # + # This method is invoked after all of the examples have executed. The + # next method to be invoked after this one is {#dump_failures} + # (BaseTextFormatter then calls {#dump_failures} once for each failed + # example). + # + # @param notification [NullNotification] + + # @method dump_failures + # @api public + # @group Suite Notifications + # + # Dumps detailed information about each example failure. + # + # @param notification [NullNotification] + + # @method dump_summary + # @api public + # @group Suite Notifications + # + # This method is invoked after the dumping of examples and failures. + # Each parameter is assigned to a corresponding attribute. + # + # @param summary [SummaryNotification] containing duration, + # example_count, failure_count and pending_count + + # @method dump_profile + # @api public + # @group Suite Notifications + # + # This method is invoked after the dumping the summary if profiling is + # enabled. + # + # @param profile [ProfileNotification] containing duration, + # slowest_examples and slowest_example_groups + + # @method dump_pending + # @api public + # @group Suite Notifications + # + # Outputs a report of pending examples. This gets invoked + # after the summary if option is set to do so. + # + # @param notification [NullNotification] + + # @method close + # @api public + # @group Suite Notifications + # + # Invoked at the very end, `close` allows the formatter to clean + # up resources, e.g. open streams, etc. + # + # @param notification [NullNotification] + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/snippet_extractor.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/snippet_extractor.rb new file mode 100644 index 0000000..bae3132 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/formatters/snippet_extractor.rb @@ -0,0 +1,116 @@ +module RSpec + module Core + module Formatters + # @api private + # + # Extracts code snippets by looking at the backtrace of the passed error + # and applies synax highlighting and line numbers using html. + class SnippetExtractor + # @private + module NullConverter + def self.convert(code) + %Q(#{code}\n# Install the coderay gem to get syntax highlighting) + end + end + + # @private + module CoderayConverter + def self.convert(code) + CodeRay.scan(code, :ruby).html(:line_numbers => false) + end + end + + # rubocop:disable Style/ClassVars + @@converter = NullConverter + begin + require 'coderay' + @@converter = CoderayConverter + # rubocop:disable Lint/HandleExceptions + rescue LoadError + # it'll fall back to the NullConverter assigned above + # rubocop:enable Lint/HandleExceptions + end + + # rubocop:enable Style/ClassVars + + # @api private + # + # Extract lines of code corresponding to a backtrace. + # + # @param backtrace [String] the backtrace from a test failure + # @return [String] highlighted code snippet indicating where the test + # failure occured + # + # @see #post_process + def snippet(backtrace) + raw_code, line = snippet_for(backtrace[0]) + highlighted = @@converter.convert(raw_code) + post_process(highlighted, line) + end + # rubocop:enable Style/ClassVars + + # @api private + # + # Create a snippet from a line of code. + # + # @param error_line [String] file name with line number (i.e. + # 'foo_spec.rb:12') + # @return [String] lines around the target line within the file + # + # @see #lines_around + def snippet_for(error_line) + if error_line =~ /(.*):(\d+)/ + file = Regexp.last_match[1] + line = Regexp.last_match[2].to_i + [lines_around(file, line), line] + else + ["# Couldn't get snippet for #{error_line}", 1] + end + end + + # @api private + # + # Extract lines of code centered around a particular line within a + # source file. + # + # @param file [String] filename + # @param line [Fixnum] line number + # @return [String] lines around the target line within the file (2 above + # and 1 below). + def lines_around(file, line) + if File.file?(file) + lines = File.read(file).split("\n") + min = [0, line - 3].max + max = [line + 1, lines.length - 1].min + selected_lines = [] + selected_lines.join("\n") + lines[min..max].join("\n") + else + "# Couldn't get snippet for #{file}" + end + rescue SecurityError + "# Couldn't get snippet for #{file}" + end + + # @api private + # + # Adds line numbers to all lines and highlights the line where the + # failure occurred using html `span` tags. + # + # @param highlighted [String] syntax-highlighted snippet surrounding the + # offending line of code + # @param offending_line [Fixnum] line where failure occured + # @return [String] completed snippet + def post_process(highlighted, offending_line) + new_lines = [] + highlighted.split("\n").each_with_index do |line, i| + new_line = "#{offending_line + i - 2}#{line}" + new_line = "#{new_line}" if i == 2 + new_lines << new_line + end + new_lines.join("\n") + end + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/hooks.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/hooks.rb new file mode 100644 index 0000000..3d020b0 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/hooks.rb @@ -0,0 +1,638 @@ +module RSpec + module Core + # Provides `before`, `after` and `around` hooks as a means of + # supporting common setup and teardown. This module is extended + # onto {ExampleGroup}, making the methods available from any `describe` + # or `context` block and included in {Configuration}, making them + # available off of the configuration object to define global setup + # or teardown logic. + module Hooks + # @api public + # + # @overload before(&block) + # @overload before(scope, &block) + # @param scope [Symbol] `:example`, `:context`, or `:suite` + # (defaults to `:example`) + # @overload before(scope, conditions, &block) + # @param scope [Symbol] `:example`, `:context`, or `:suite` + # (defaults to `:example`) + # @param conditions [Hash] + # constrains this hook to examples matching these conditions e.g. + # `before(:example, :ui => true) { ... }` will only run with examples + # or groups declared with `:ui => true`. + # @overload before(conditions, &block) + # @param conditions [Hash] + # constrains this hook to examples matching these conditions e.g. + # `before(:example, :ui => true) { ... }` will only run with examples + # or groups declared with `:ui => true`. + # + # @see #after + # @see #around + # @see ExampleGroup + # @see SharedContext + # @see SharedExampleGroup + # @see Configuration + # + # Declare a block of code to be run before each example (using `:example`) + # or once before any example (using `:context`). These are usually + # declared directly in the {ExampleGroup} to which they apply, but they + # can also be shared across multiple groups. + # + # You can also use `before(:suite)` to run a block of code before any + # example groups are run. This should be declared in {RSpec.configure}. + # + # Instance variables declared in `before(:example)` or `before(:context)` + # are accessible within each example. + # + # ### Order + # + # `before` hooks are stored in three scopes, which are run in order: + # `:suite`, `:context`, and `:example`. They can also be declared in + # several different places: `RSpec.configure`, a parent group, the current + # group. They are run in the following order: + # + # before(:suite) # Declared in RSpec.configure. + # before(:context) # Declared in RSpec.configure. + # before(:context) # Declared in a parent group. + # before(:context) # Declared in the current group. + # before(:example) # Declared in RSpec.configure. + # before(:example) # Declared in a parent group. + # before(:example) # Declared in the current group. + # + # If more than one `before` is declared within any one scope, they are run + # in the order in which they are declared. + # + # ### Conditions + # + # When you add a conditions hash to `before(:example)` or + # `before(:context)`, RSpec will only apply that hook to groups or + # examples that match the conditions. e.g. + # + # RSpec.configure do |config| + # config.before(:example, :authorized => true) do + # log_in_as :authorized_user + # end + # end + # + # describe Something, :authorized => true do + # # The before hook will run in before each example in this group. + # end + # + # describe SomethingElse do + # it "does something", :authorized => true do + # # The before hook will run before this example. + # end + # + # it "does something else" do + # # The hook will not run before this example. + # end + # end + # + # Note that filtered config `:context` hooks can still be applied + # to individual examples that have matching metadata. Just like + # Ruby's object model is that every object has a singleton class + # which has only a single instance, RSpec's model is that every + # example has a singleton example group containing just the one + # example. + # + # ### Warning: `before(:suite, :with => :conditions)` + # + # The conditions hash is used to match against specific examples. Since + # `before(:suite)` is not run in relation to any specific example or + # group, conditions passed along with `:suite` are effectively ignored. + # + # ### Exceptions + # + # When an exception is raised in a `before` block, RSpec skips any + # subsequent `before` blocks and the example, but runs all of the + # `after(:example)` and `after(:context)` hooks. + # + # ### Warning: implicit before blocks + # + # `before` hooks can also be declared in shared contexts which get + # included implicitly either by you or by extension libraries. Since + # RSpec runs these in the order in which they are declared within each + # scope, load order matters, and can lead to confusing results when one + # before block depends on state that is prepared in another before block + # that gets run later. + # + # ### Warning: `before(:context)` + # + # It is very tempting to use `before(:context)` to speed things up, but we + # recommend that you avoid this as there are a number of gotchas, as well + # as things that simply don't work. + # + # #### Context + # + # `before(:context)` is run in an example that is generated to provide + # group context for the block. + # + # #### Instance variables + # + # Instance variables declared in `before(:context)` are shared across all + # the examples in the group. This means that each example can change the + # state of a shared object, resulting in an ordering dependency that can + # make it difficult to reason about failures. + # + # #### Unsupported RSpec constructs + # + # RSpec has several constructs that reset state between each example + # automatically. These are not intended for use from within + # `before(:context)`: + # + # * `let` declarations + # * `subject` declarations + # * Any mocking, stubbing or test double declaration + # + # ### other frameworks + # + # Mock object frameworks and database transaction managers (like + # ActiveRecord) are typically designed around the idea of setting up + # before an example, running that one example, and then tearing down. This + # means that mocks and stubs can (sometimes) be declared in + # `before(:context)`, but get torn down before the first real example is + # ever run. + # + # You _can_ create database-backed model objects in a `before(:context)` + # in rspec-rails, but it will not be wrapped in a transaction for you, so + # you are on your own to clean up in an `after(:context)` block. + # + # @example before(:example) declared in an {ExampleGroup} + # + # describe Thing do + # before(:example) do + # @thing = Thing.new + # end + # + # it "does something" do + # # Here you can access @thing. + # end + # end + # + # @example before(:context) declared in an {ExampleGroup} + # + # describe Parser do + # before(:context) do + # File.open(file_to_parse, 'w') do |f| + # f.write <<-CONTENT + # stuff in the file + # CONTENT + # end + # end + # + # it "parses the file" do + # Parser.parse(file_to_parse) + # end + # + # after(:context) do + # File.delete(file_to_parse) + # end + # end + # + # @note The `:example` and `:context` scopes are also available as + # `:each` and `:all`, respectively. Use whichever you prefer. + # @note The `:scope` alias is only supported for hooks registered on + # `RSpec.configuration` since they exist independently of any + # example or example group. + def before(*args, &block) + hooks.register :append, :before, *args, &block + end + + alias_method :append_before, :before + + # Adds `block` to the front of the list of `before` blocks in the same + # scope (`:example`, `:context`, or `:suite`). + # + # See {#before} for scoping semantics. + def prepend_before(*args, &block) + hooks.register :prepend, :before, *args, &block + end + + # @api public + # @overload after(&block) + # @overload after(scope, &block) + # @param scope [Symbol] `:example`, `:context`, or `:suite` (defaults to + # `:example`) + # @overload after(scope, conditions, &block) + # @param scope [Symbol] `:example`, `:context`, or `:suite` (defaults to + # `:example`) + # @param conditions [Hash] + # constrains this hook to examples matching these conditions e.g. + # `after(:example, :ui => true) { ... }` will only run with examples + # or groups declared with `:ui => true`. + # @overload after(conditions, &block) + # @param conditions [Hash] + # constrains this hook to examples matching these conditions e.g. + # `after(:example, :ui => true) { ... }` will only run with examples + # or groups declared with `:ui => true`. + # + # @see #before + # @see #around + # @see ExampleGroup + # @see SharedContext + # @see SharedExampleGroup + # @see Configuration + # + # Declare a block of code to be run after each example (using `:example`) + # or once after all examples n the context (using `:context`). See + # {#before} for more information about ordering. + # + # ### Exceptions + # + # `after` hooks are guaranteed to run even when there are exceptions in + # `before` hooks or examples. When an exception is raised in an after + # block, the exception is captured for later reporting, and subsequent + # `after` blocks are run. + # + # ### Order + # + # `after` hooks are stored in three scopes, which are run in order: + # `:example`, `:context`, and `:suite`. They can also be declared in + # several different places: `RSpec.configure`, a parent group, the current + # group. They are run in the following order: + # + # after(:example) # Declared in the current group. + # after(:example) # Declared in a parent group. + # after(:example) # Declared in RSpec.configure. + # after(:context) # Declared in the current group. + # after(:context) # Declared in a parent group. + # after(:context) # Declared in RSpec.configure. + # after(:suite) # Declared in RSpec.configure. + # + # This is the reverse of the order in which `before` hooks are run. + # Similarly, if more than one `after` is declared within any one scope, + # they are run in reverse order of that in which they are declared. + # + # @note The `:example` and `:context` scopes are also available as + # `:each` and `:all`, respectively. Use whichever you prefer. + # @note The `:scope` alias is only supported for hooks registered on + # `RSpec.configuration` since they exist independently of any + # example or example group. + def after(*args, &block) + hooks.register :prepend, :after, *args, &block + end + + alias_method :prepend_after, :after + + # Adds `block` to the back of the list of `after` blocks in the same + # scope (`:example`, `:context`, or `:suite`). + # + # See {#after} for scoping semantics. + def append_after(*args, &block) + hooks.register :append, :after, *args, &block + end + + # @api public + # @overload around(&block) + # @overload around(scope, &block) + # @param scope [Symbol] `:example` (defaults to `:example`) + # present for syntax parity with `before` and `after`, but + # `:example`/`:each` is the only supported value. + # @overload around(scope, conditions, &block) + # @param scope [Symbol] `:example` (defaults to `:example`) + # present for syntax parity with `before` and `after`, but + # `:example`/`:each` is the only supported value. + # @param conditions [Hash] constrains this hook to examples matching + # these conditions e.g. `around(:example, :ui => true) { ... }` will + # only run with examples or groups declared with `:ui => true`. + # @overload around(conditions, &block) + # @param conditions [Hash] constrains this hook to examples matching + # these conditions e.g. `around(:example, :ui => true) { ... }` will + # only run with examples or groups declared with `:ui => true`. + # + # @yield [Example] the example to run + # + # @note the syntax of `around` is similar to that of `before` and `after` + # but the semantics are quite different. `before` and `after` hooks are + # run in the context of of the examples with which they are associated, + # whereas `around` hooks are actually responsible for running the + # examples. Consequently, `around` hooks do not have direct access to + # resources that are made available within the examples and their + # associated `before` and `after` hooks. + # + # @note `:example`/`:each` is the only supported scope. + # + # Declare a block of code, parts of which will be run before and parts + # after the example. It is your responsibility to run the example: + # + # around(:example) do |ex| + # # Do some stuff before. + # ex.run + # # Do some stuff after. + # end + # + # The yielded example aliases `run` with `call`, which lets you treat it + # like a `Proc`. This is especially handy when working with libaries + # that manage their own setup and teardown using a block or proc syntax, + # e.g. + # + # around(:example) {|ex| Database.transaction(&ex)} + # around(:example) {|ex| FakeFS(&ex)} + # + def around(*args, &block) + hooks.register :prepend, :around, *args, &block + end + + # @private + # Holds the various registered hooks. + def hooks + @hooks ||= HookCollections.new(self, FilterableItemRepository::UpdateOptimized) + end + + private + + # @private + class Hook + attr_reader :block, :options + + def initialize(block, options) + @block = block + @options = options + end + end + + # @private + class BeforeHook < Hook + def run(example) + example.instance_exec(example, &block) + end + end + + # @private + class AfterHook < Hook + def run(example) + example.instance_exec(example, &block) + rescue Exception => ex + example.set_exception(ex) + end + end + + # @private + class AfterContextHook < Hook + def run(example) + example.instance_exec(example, &block) + rescue Exception => e + # TODO: Come up with a better solution for this. + RSpec.configuration.reporter.message <<-EOS + +An error occurred in an `after(:context)` hook. + #{e.class}: #{e.message} + occurred at #{e.backtrace.first} + +EOS + end + end + + # @private + class AroundHook < Hook + def execute_with(example, procsy) + example.instance_exec(procsy, &block) + return if procsy.executed? + Pending.mark_skipped!(example, + "#{hook_description} did not execute the example") + end + + if Proc.method_defined?(:source_location) + def hook_description + "around hook at #{Metadata.relative_path(block.source_location.join(':'))}" + end + else # for 1.8.7 + # :nocov: + def hook_description + "around hook" + end + # :nocov: + end + end + + # @private + # + # This provides the primary API used by other parts of rspec-core. By hiding all + # implementation details behind this facade, it's allowed us to heavily optimize + # this, so that, for example, hook collection objects are only instantiated when + # a hook is added. This allows us to avoid many object allocations for the common + # case of a group having no hooks. + # + # This is only possible because this interface provides a "tell, don't ask"-style + # API, so that callers _tell_ this class what to do with the hooks, rather than + # asking this class for a list of hooks, and then doing something with them. + class HookCollections + def initialize(owner, filterable_item_repo_class) + @owner = owner + @filterable_item_repo_class = filterable_item_repo_class + @before_example_hooks = nil + @after_example_hooks = nil + @before_context_hooks = nil + @after_context_hooks = nil + @around_example_hooks = nil + end + + def register_globals(host, globals) + parent_groups = host.parent_groups + + process(host, parent_groups, globals, :before, :example, &:options) + process(host, parent_groups, globals, :after, :example, &:options) + process(host, parent_groups, globals, :around, :example, &:options) + + process(host, parent_groups, globals, :before, :context, &:options) + process(host, parent_groups, globals, :after, :context, &:options) + end + + def register_global_singleton_context_hooks(example, globals) + parent_groups = example.example_group.parent_groups + + process(example, parent_groups, globals, :before, :context) { {} } + process(example, parent_groups, globals, :after, :context) { {} } + end + + def register(prepend_or_append, position, *args, &block) + scope, options = scope_and_options_from(*args) + + if scope == :suite + # TODO: consider making this an error in RSpec 4. For SemVer reasons, + # we are only warning in RSpec 3. + RSpec.warn_with "WARNING: `#{position}(:suite)` hooks are only supported on " \ + "the RSpec configuration object. This " \ + "`#{position}(:suite)` hook, registered on an example " \ + "group, will be ignored." + return + end + + hook = HOOK_TYPES[position][scope].new(block, options) + ensure_hooks_initialized_for(position, scope).__send__(prepend_or_append, hook, options) + end + + # @private + # + # Runs all of the blocks stored with the hook in the context of the + # example. If no example is provided, just calls the hook directly. + def run(position, scope, example_or_group) + return if RSpec.configuration.dry_run? + + if scope == :context + run_owned_hooks_for(position, :context, example_or_group) + else + case position + when :before then run_example_hooks_for(example_or_group, :before, :reverse_each) + when :after then run_example_hooks_for(example_or_group, :after, :each) + when :around then run_around_example_hooks_for(example_or_group) { yield } + end + end + end + + SCOPES = [:example, :context] + + SCOPE_ALIASES = { :each => :example, :all => :context } + + HOOK_TYPES = { + :before => Hash.new { BeforeHook }, + :after => Hash.new { AfterHook }, + :around => Hash.new { AroundHook } + } + + HOOK_TYPES[:after][:context] = AfterContextHook + + protected + + EMPTY_HOOK_ARRAY = [].freeze + + def matching_hooks_for(position, scope, example_or_group) + repository = hooks_for(position, scope) { return EMPTY_HOOK_ARRAY } + + # It would be nice to not have to switch on type here, but + # we don't want to define `ExampleGroup#metadata` because then + # `metadata` from within an individual example would return the + # group's metadata but the user would probably expect it to be + # the example's metadata. + metadata = case example_or_group + when ExampleGroup then example_or_group.class.metadata + else example_or_group.metadata + end + + repository.items_for(metadata) + end + + def all_hooks_for(position, scope) + hooks_for(position, scope) { return EMPTY_HOOK_ARRAY }.items_and_filters.map(&:first) + end + + def run_owned_hooks_for(position, scope, example_or_group) + matching_hooks_for(position, scope, example_or_group).each do |hook| + hook.run(example_or_group) + end + end + + def processable_hooks_for(position, scope, host) + if scope == :example + all_hooks_for(position, scope) + else + matching_hooks_for(position, scope, host) + end + end + + private + + def hooks_for(position, scope) + if position == :before + scope == :example ? @before_example_hooks : @before_context_hooks + elsif position == :after + scope == :example ? @after_example_hooks : @after_context_hooks + else # around + @around_example_hooks + end || yield + end + + def ensure_hooks_initialized_for(position, scope) + if position == :before + if scope == :example + @before_example_hooks ||= @filterable_item_repo_class.new(:all?) + else + @before_context_hooks ||= @filterable_item_repo_class.new(:all?) + end + elsif position == :after + if scope == :example + @after_example_hooks ||= @filterable_item_repo_class.new(:all?) + else + @after_context_hooks ||= @filterable_item_repo_class.new(:all?) + end + else # around + @around_example_hooks ||= @filterable_item_repo_class.new(:all?) + end + end + + def process(host, parent_groups, globals, position, scope) + hooks_to_process = globals.processable_hooks_for(position, scope, host) + return if hooks_to_process.empty? + + hooks_to_process -= FlatMap.flat_map(parent_groups) do |group| + group.hooks.all_hooks_for(position, scope) + end + return if hooks_to_process.empty? + + repository = ensure_hooks_initialized_for(position, scope) + hooks_to_process.each { |hook| repository.append hook, (yield hook) } + end + + def scope_and_options_from(*args) + return :suite if args.first == :suite + scope = extract_scope_from(args) + meta = Metadata.build_hash_from(args, :warn_about_example_group_filtering) + return scope, meta + end + + def extract_scope_from(args) + if known_scope?(args.first) + normalized_scope_for(args.shift) + elsif args.any? { |a| a.is_a?(Symbol) } + error_message = "You must explicitly give a scope " \ + "(#{SCOPES.join(", ")}) or scope alias " \ + "(#{SCOPE_ALIASES.keys.join(", ")}) when using symbols as " \ + "metadata for a hook." + raise ArgumentError.new error_message + else + :example + end + end + + def known_scope?(scope) + SCOPES.include?(scope) || SCOPE_ALIASES.keys.include?(scope) + end + + def normalized_scope_for(scope) + SCOPE_ALIASES[scope] || scope + end + + def run_example_hooks_for(example, position, each_method) + owner_parent_groups.__send__(each_method) do |group| + group.hooks.run_owned_hooks_for(position, :example, example) + end + end + + def run_around_example_hooks_for(example) + hooks = FlatMap.flat_map(owner_parent_groups) do |group| + group.hooks.matching_hooks_for(:around, :example, example) + end + + return yield if hooks.empty? # exit early to avoid the extra allocation cost of `Example::Procsy` + + initial_procsy = Example::Procsy.new(example) { yield } + hooks.inject(initial_procsy) do |procsy, around_hook| + procsy.wrap { around_hook.execute_with(example, procsy) } + end.call + end + + if respond_to?(:singleton_class) && singleton_class.ancestors.include?(singleton_class) + def owner_parent_groups + @owner.parent_groups + end + else # Ruby < 2.1 (see https://bugs.ruby-lang.org/issues/8035) + # :nocov: + def owner_parent_groups + @owner_parent_groups ||= [@owner] + @owner.parent_groups + end + # :nocov: + end + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/memoized_helpers.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/memoized_helpers.rb new file mode 100644 index 0000000..f7d904f --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/memoized_helpers.rb @@ -0,0 +1,532 @@ +require 'rspec/core/reentrant_mutex' + +module RSpec + module Core + # This module is included in {ExampleGroup}, making the methods + # available to be called from within example blocks. + # + # @see ClassMethods + module MemoizedHelpers + # @note `subject` was contributed by Joe Ferris to support the one-liner + # syntax embraced by shoulda matchers: + # + # describe Widget do + # it { is_expected.to validate_presence_of(:name) } + # # or + # it { should validate_presence_of(:name) } + # end + # + # While the examples below demonstrate how to use `subject` + # explicitly in examples, we recommend that you define a method with + # an intention revealing name instead. + # + # @example + # + # # Explicit declaration of subject. + # describe Person do + # subject { Person.new(:birthdate => 19.years.ago) } + # it "should be eligible to vote" do + # subject.should be_eligible_to_vote + # # ^ ^ explicit reference to subject not recommended + # end + # end + # + # # Implicit subject => { Person.new }. + # describe Person do + # it "should be eligible to vote" do + # subject.should be_eligible_to_vote + # # ^ ^ explicit reference to subject not recommended + # end + # end + # + # # One-liner syntax - expectation is set on the subject. + # describe Person do + # it { is_expected.to be_eligible_to_vote } + # # or + # it { should be_eligible_to_vote } + # end + # + # @note Because `subject` is designed to create state that is reset + # between each example, and `before(:context)` is designed to setup + # state that is shared across _all_ examples in an example group, + # `subject` is _not_ intended to be used in a `before(:context)` hook. + # + # @see #should + # @see #should_not + # @see #is_expected + def subject + __memoized.fetch_or_store(:subject) do + described = described_class || self.class.metadata.fetch(:description_args).first + Class === described ? described.new : described + end + end + + # When `should` is called with no explicit receiver, the call is + # delegated to the object returned by `subject`. Combined with an + # implicit subject this supports very concise expressions. + # + # @example + # + # describe Person do + # it { should be_eligible_to_vote } + # end + # + # @see #subject + # @see #is_expected + # + # @note This only works if you are using rspec-expectations. + # @note If you are using RSpec's newer expect-based syntax you may + # want to use `is_expected.to` instead of `should`. + def should(matcher=nil, message=nil) + RSpec::Expectations::PositiveExpectationHandler.handle_matcher(subject, matcher, message) + end + + # Just like `should`, `should_not` delegates to the subject (implicit or + # explicit) of the example group. + # + # @example + # + # describe Person do + # it { should_not be_eligible_to_vote } + # end + # + # @see #subject + # @see #is_expected + # + # @note This only works if you are using rspec-expectations. + # @note If you are using RSpec's newer expect-based syntax you may + # want to use `is_expected.to_not` instead of `should_not`. + def should_not(matcher=nil, message=nil) + RSpec::Expectations::NegativeExpectationHandler.handle_matcher(subject, matcher, message) + end + + # Wraps the `subject` in `expect` to make it the target of an expectation. + # Designed to read nicely for one-liners. + # + # @example + # + # describe [1, 2, 3] do + # it { is_expected.to be_an Array } + # it { is_expected.not_to include 4 } + # end + # + # @see #subject + # @see #should + # @see #should_not + # + # @note This only works if you are using rspec-expectations. + def is_expected + expect(subject) + end + + # @private + # should just be placed in private section, + # but Ruby issues warnings on private attributes. + # and expanding it to the equivalent method upsets Rubocop, + # b/c it should obviously be a reader + attr_reader :__memoized + private :__memoized + + private + + # @private + def initialize(*) + __init_memoized + super + end + + # @private + def __init_memoized + @__memoized = if RSpec.configuration.threadsafe? + ThreadsafeMemoized.new + else + NonThreadSafeMemoized.new + end + end + + # @private + class ThreadsafeMemoized + def initialize + @memoized = {} + @mutex = ReentrantMutex.new + end + + def fetch_or_store(key) + @memoized.fetch(key) do # only first access pays for synchronization + @mutex.synchronize do + @memoized.fetch(key) { @memoized[key] = yield } + end + end + end + end + + # @private + class NonThreadSafeMemoized + def initialize + @memoized = {} + end + + def fetch_or_store(key) + @memoized.fetch(key) { @memoized[key] = yield } + end + end + + # Used internally to customize the behavior of the + # memoized hash when used in a `before(:context)` hook. + # + # @private + class ContextHookMemoized + def self.isolate_for_context_hook(example_group_instance) + exploding_memoized = self + + example_group_instance.instance_exec do + @__memoized = exploding_memoized + + begin + yield + ensure + # This is doing a reset instead of just isolating for context hook. + # Really, this should set the old @__memoized back into place. + # + # Caller is the before and after context hooks + # which are both called from self.run + # I didn't look at why it made tests fail, maybe an object was getting reused in RSpec tests, + # if so, then that probably already works, and its the tests that are wrong. + __init_memoized + end + end + end + + def self.fetch_or_store(key, &_block) + description = if key == :subject + "subject" + else + "let declaration `#{key}`" + end + + raise <<-EOS +#{description} accessed in #{article} #{hook_expression} hook at: + #{CallerFilter.first_non_rspec_line} + +`let` and `subject` declarations are not intended to be called +in #{article} #{hook_expression} hook, as they exist to define state that +is reset between each example, while #{hook_expression} exists to +#{hook_intention}. +EOS + end + + # @private + class Before < self + def self.hook_expression + "`before(:context)`" + end + + def self.article + "a" + end + + def self.hook_intention + "define state that is shared across examples in an example group" + end + end + + # @private + class After < self + def self.hook_expression + "`after(:context)`" + end + + def self.article + "an" + end + + def self.hook_intention + "cleanup state that is shared across examples in an example group" + end + end + end + + # This module is extended onto {ExampleGroup}, making the methods + # available to be called from within example group blocks. + # You can think of them as being analagous to class macros. + module ClassMethods + # Generates a method whose return value is memoized after the first + # call. Useful for reducing duplication between examples that assign + # values to the same local variable. + # + # @note `let` _can_ enhance readability when used sparingly (1,2, or + # maybe 3 declarations) in any given example group, but that can + # quickly degrade with overuse. YMMV. + # + # @note `let` can be configured to be threadsafe or not. + # If it is threadsafe, it will take longer to access the value. + # If it is not threadsafe, it may behave in surprising ways in examples + # that spawn separate threads. Specify this on `RSpec.configure` + # + # @note Because `let` is designed to create state that is reset between + # each example, and `before(:context)` is designed to setup state that + # is shared across _all_ examples in an example group, `let` is _not_ + # intended to be used in a `before(:context)` hook. + # + # @example + # + # describe Thing do + # let(:thing) { Thing.new } + # + # it "does something" do + # # First invocation, executes block, memoizes and returns result. + # thing.do_something + # + # # Second invocation, returns the memoized value. + # thing.should be_something + # end + # end + def let(name, &block) + # We have to pass the block directly to `define_method` to + # allow it to use method constructs like `super` and `return`. + raise "#let or #subject called without a block" if block.nil? + MemoizedHelpers.module_for(self).__send__(:define_method, name, &block) + + # Apply the memoization. The method has been defined in an ancestor + # module so we can use `super` here to get the value. + if block.arity == 1 + define_method(name) { __memoized.fetch_or_store(name) { super(RSpec.current_example, &nil) } } + else + define_method(name) { __memoized.fetch_or_store(name) { super(&nil) } } + end + end + + # Just like `let`, except the block is invoked by an implicit `before` + # hook. This serves a dual purpose of setting up state and providing a + # memoized reference to that state. + # + # @example + # + # class Thing + # def self.count + # @count ||= 0 + # end + # + # def self.count=(val) + # @count += val + # end + # + # def self.reset_count + # @count = 0 + # end + # + # def initialize + # self.class.count += 1 + # end + # end + # + # describe Thing do + # after(:example) { Thing.reset_count } + # + # context "using let" do + # let(:thing) { Thing.new } + # + # it "is not invoked implicitly" do + # Thing.count.should eq(0) + # end + # + # it "can be invoked explicitly" do + # thing + # Thing.count.should eq(1) + # end + # end + # + # context "using let!" do + # let!(:thing) { Thing.new } + # + # it "is invoked implicitly" do + # Thing.count.should eq(1) + # end + # + # it "returns memoized version on first invocation" do + # thing + # Thing.count.should eq(1) + # end + # end + # end + def let!(name, &block) + let(name, &block) + before { __send__(name) } + end + + # Declares a `subject` for an example group which can then be wrapped + # with `expect` using `is_expected` to make it the target of an + # expectation in a concise, one-line example. + # + # Given a `name`, defines a method with that name which returns the + # `subject`. This lets you declare the subject once and access it + # implicitly in one-liners and explicitly using an intention revealing + # name. + # + # When given a `name`, calling `super` in the block is not supported. + # + # @note `subject` can be configured to be threadsafe or not. + # If it is threadsafe, it will take longer to access the value. + # If it is not threadsafe, it may behave in surprising ways in examples + # that spawn separate threads. Specify this on `RSpec.configure` + # + # @param name [String,Symbol] used to define an accessor with an + # intention revealing name + # @param block defines the value to be returned by `subject` in examples + # + # @example + # + # describe CheckingAccount, "with $50" do + # subject { CheckingAccount.new(Money.new(50, :USD)) } + # it { is_expected.to have_a_balance_of(Money.new(50, :USD)) } + # it { is_expected.not_to be_overdrawn } + # end + # + # describe CheckingAccount, "with a non-zero starting balance" do + # subject(:account) { CheckingAccount.new(Money.new(50, :USD)) } + # it { is_expected.not_to be_overdrawn } + # it "has a balance equal to the starting balance" do + # account.balance.should eq(Money.new(50, :USD)) + # end + # end + # + # @see MemoizedHelpers#should + # @see MemoizedHelpers#should_not + # @see MemoizedHelpers#is_expected + def subject(name=nil, &block) + if name + let(name, &block) + alias_method :subject, name + + self::NamedSubjectPreventSuper.__send__(:define_method, name) do + raise NotImplementedError, "`super` in named subjects is not supported" + end + else + let(:subject, &block) + end + end + + # Just like `subject`, except the block is invoked by an implicit + # `before` hook. This serves a dual purpose of setting up state and + # providing a memoized reference to that state. + # + # @example + # + # class Thing + # def self.count + # @count ||= 0 + # end + # + # def self.count=(val) + # @count += val + # end + # + # def self.reset_count + # @count = 0 + # end + # + # def initialize + # self.class.count += 1 + # end + # end + # + # describe Thing do + # after(:example) { Thing.reset_count } + # + # context "using subject" do + # subject { Thing.new } + # + # it "is not invoked implicitly" do + # Thing.count.should eq(0) + # end + # + # it "can be invoked explicitly" do + # subject + # Thing.count.should eq(1) + # end + # end + # + # context "using subject!" do + # subject!(:thing) { Thing.new } + # + # it "is invoked implicitly" do + # Thing.count.should eq(1) + # end + # + # it "returns memoized version on first invocation" do + # subject + # Thing.count.should eq(1) + # end + # end + # end + def subject!(name=nil, &block) + subject(name, &block) + before { subject } + end + end + + # @private + # + # Gets the LetDefinitions module. The module is mixed into + # the example group and is used to hold all let definitions. + # This is done so that the block passed to `let` can be + # forwarded directly on to `define_method`, so that all method + # constructs (including `super` and `return`) can be used in + # a `let` block. + # + # The memoization is provided by a method definition on the + # example group that supers to the LetDefinitions definition + # in order to get the value to memoize. + def self.module_for(example_group) + get_constant_or_yield(example_group, :LetDefinitions) do + mod = Module.new do + include Module.new { + example_group.const_set(:NamedSubjectPreventSuper, self) + } + end + + example_group.const_set(:LetDefinitions, mod) + mod + end + end + + # @private + def self.define_helpers_on(example_group) + example_group.__send__(:include, module_for(example_group)) + end + + if Module.method(:const_defined?).arity == 1 # for 1.8 + # @private + # + # Gets the named constant or yields. + # On 1.8, const_defined? / const_get do not take into + # account the inheritance hierarchy. + # :nocov: + def self.get_constant_or_yield(example_group, name) + if example_group.const_defined?(name) + example_group.const_get(name) + else + yield + end + end + # :nocov: + else + # @private + # + # Gets the named constant or yields. + # On 1.9, const_defined? / const_get take into account the + # the inheritance by default, and accept an argument to + # disable this behavior. It's important that we don't + # consider inheritance here; each example group level that + # uses a `let` should get its own `LetDefinitions` module. + def self.get_constant_or_yield(example_group, name) + if example_group.const_defined?(name, (check_ancestors = false)) + example_group.const_get(name, check_ancestors) + else + yield + end + end + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/metadata.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/metadata.rb new file mode 100644 index 0000000..2c02034 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/metadata.rb @@ -0,0 +1,490 @@ +module RSpec + module Core + # Each ExampleGroup class and Example instance owns an instance of + # Metadata, which is Hash extended to support lazy evaluation of values + # associated with keys that may or may not be used by any example or group. + # + # In addition to metadata that is used internally, this also stores + # user-supplied metadata, e.g. + # + # describe Something, :type => :ui do + # it "does something", :slow => true do + # # ... + # end + # end + # + # `:type => :ui` is stored in the Metadata owned by the example group, and + # `:slow => true` is stored in the Metadata owned by the example. These can + # then be used to select which examples are run using the `--tag` option on + # the command line, or several methods on `Configuration` used to filter a + # run (e.g. `filter_run_including`, `filter_run_excluding`, etc). + # + # @see Example#metadata + # @see ExampleGroup.metadata + # @see FilterManager + # @see Configuration#filter_run_including + # @see Configuration#filter_run_excluding + module Metadata + # Matches strings either at the beginning of the input or prefixed with a + # whitespace, containing the current path, either postfixed with the + # separator, or at the end of the string. Match groups are the character + # before and the character after the string if any. + # + # http://rubular.com/r/fT0gmX6VJX + # http://rubular.com/r/duOrD4i3wb + # http://rubular.com/r/sbAMHFrOx1 + def self.relative_path_regex + @relative_path_regex ||= /(\A|\s)#{File.expand_path('.')}(#{File::SEPARATOR}|\s|\Z)/ + end + + # @api private + # + # @param line [String] current code line + # @return [String] relative path to line + def self.relative_path(line) + line = line.sub(relative_path_regex, "\\1.\\2".freeze) + line = line.sub(/\A([^:]+:\d+)$/, '\\1'.freeze) + return nil if line == '-e:1'.freeze + line + rescue SecurityError + nil + end + + # @private + # Iteratively walks up from the given metadata through all + # example group ancestors, yielding each metadata hash along the way. + def self.ascending(metadata) + yield metadata + return unless (group_metadata = metadata.fetch(:example_group) { metadata[:parent_example_group] }) + + loop do + yield group_metadata + break unless (group_metadata = group_metadata[:parent_example_group]) + end + end + + # @private + # Returns an enumerator that iteratively walks up the given metadata through all + # example group ancestors, yielding each metadata hash along the way. + def self.ascend(metadata) + enum_for(:ascending, metadata) + end + + # @private + # Used internally to build a hash from an args array. + # Symbols are converted into hash keys with a value of `true`. + # This is done to support simple tagging using a symbol, rather + # than needing to do `:symbol => true`. + def self.build_hash_from(args, warn_about_example_group_filtering=false) + hash = args.last.is_a?(Hash) ? args.pop : {} + + hash[args.pop] = true while args.last.is_a?(Symbol) + + if warn_about_example_group_filtering && hash.key?(:example_group) + RSpec.deprecate("Filtering by an `:example_group` subhash", + :replacement => "the subhash to filter directly") + end + + hash + end + + # @private + def self.deep_hash_dup(object) + return object.dup if Array === object + return object unless Hash === object + + object.inject(object.dup) do |duplicate, (key, value)| + duplicate[key] = deep_hash_dup(value) + duplicate + end + end + + # @private + def self.id_from(metadata) + "#{metadata[:rerun_file_path]}[#{metadata[:scoped_id]}]" + end + + # @private + # Used internally to populate metadata hashes with computed keys + # managed by RSpec. + class HashPopulator + attr_reader :metadata, :user_metadata, :description_args, :block + + def initialize(metadata, user_metadata, index_provider, description_args, block) + @metadata = metadata + @user_metadata = user_metadata + @index_provider = index_provider + @description_args = description_args + @block = block + end + + def populate + ensure_valid_user_keys + + metadata[:execution_result] = Example::ExecutionResult.new + metadata[:block] = block + metadata[:description_args] = description_args + metadata[:description] = build_description_from(*metadata[:description_args]) + metadata[:full_description] = full_description + metadata[:described_class] = described_class + + populate_location_attributes + metadata.update(user_metadata) + RSpec.configuration.apply_derived_metadata_to(metadata) + end + + private + + def populate_location_attributes + backtrace = user_metadata.delete(:caller) + + file_path, line_number = if backtrace + file_path_and_line_number_from(backtrace) + elsif block.respond_to?(:source_location) + block.source_location + else + file_path_and_line_number_from(caller) + end + + relative_file_path = Metadata.relative_path(file_path) + metadata[:file_path] = relative_file_path + metadata[:line_number] = line_number.to_i + metadata[:location] = "#{relative_file_path}:#{line_number}" + metadata[:absolute_file_path] = File.expand_path(relative_file_path) + metadata[:rerun_file_path] ||= relative_file_path + metadata[:scoped_id] = build_scoped_id_for(relative_file_path) + end + + def file_path_and_line_number_from(backtrace) + first_caller_from_outside_rspec = backtrace.find { |l| l !~ CallerFilter::LIB_REGEX } + first_caller_from_outside_rspec ||= backtrace.first + /(.+?):(\d+)(?:|:\d+)/.match(first_caller_from_outside_rspec).captures + end + + def description_separator(parent_part, child_part) + if parent_part.is_a?(Module) && child_part =~ /^(#|::|\.)/ + ''.freeze + else + ' '.freeze + end + end + + def build_description_from(parent_description=nil, my_description=nil) + return parent_description.to_s unless my_description + separator = description_separator(parent_description, my_description) + (parent_description.to_s + separator) << my_description.to_s + end + + def build_scoped_id_for(file_path) + index = @index_provider.call(file_path).to_s + parent_scoped_id = metadata.fetch(:scoped_id) { return index } + "#{parent_scoped_id}:#{index}" + end + + def ensure_valid_user_keys + RESERVED_KEYS.each do |key| + next unless user_metadata.key?(key) + raise <<-EOM.gsub(/^\s+\|/, '') + |#{"*" * 50} + |:#{key} is not allowed + | + |RSpec reserves some hash keys for its own internal use, + |including :#{key}, which is used on: + | + | #{CallerFilter.first_non_rspec_line}. + | + |Here are all of RSpec's reserved hash keys: + | + | #{RESERVED_KEYS.join("\n ")} + |#{"*" * 50} + EOM + end + end + end + + # @private + class ExampleHash < HashPopulator + def self.create(group_metadata, user_metadata, index_provider, description, block) + example_metadata = group_metadata.dup + group_metadata = Hash.new(&ExampleGroupHash.backwards_compatibility_default_proc do |hash| + hash[:parent_example_group] + end) + group_metadata.update(example_metadata) + + example_metadata[:example_group] = group_metadata + example_metadata[:shared_group_inclusion_backtrace] = SharedExampleGroupInclusionStackFrame.current_backtrace + example_metadata.delete(:parent_example_group) + + description_args = description.nil? ? [] : [description] + hash = new(example_metadata, user_metadata, index_provider, description_args, block) + hash.populate + hash.metadata + end + + private + + def described_class + metadata[:example_group][:described_class] + end + + def full_description + build_description_from( + metadata[:example_group][:full_description], + metadata[:description] + ) + end + end + + # @private + class ExampleGroupHash < HashPopulator + def self.create(parent_group_metadata, user_metadata, example_group_index, *args, &block) + group_metadata = hash_with_backwards_compatibility_default_proc + + if parent_group_metadata + group_metadata.update(parent_group_metadata) + group_metadata[:parent_example_group] = parent_group_metadata + end + + hash = new(group_metadata, user_metadata, example_group_index, args, block) + hash.populate + hash.metadata + end + + def self.hash_with_backwards_compatibility_default_proc + Hash.new(&backwards_compatibility_default_proc { |hash| hash }) + end + + def self.backwards_compatibility_default_proc(&example_group_selector) + Proc.new do |hash, key| + case key + when :example_group + # We commonly get here when rspec-core is applying a previously + # configured filter rule, such as when a gem configures: + # + # RSpec.configure do |c| + # c.include MyGemHelpers, :example_group => { :file_path => /spec\/my_gem_specs/ } + # end + # + # It's confusing for a user to get a deprecation at this point in + # the code, so instead we issue a deprecation from the config APIs + # that take a metadata hash, and MetadataFilter sets this thread + # local to silence the warning here since it would be so + # confusing. + unless RSpec::Support.thread_local_data[:silence_metadata_example_group_deprecations] + RSpec.deprecate("The `:example_group` key in an example group's metadata hash", + :replacement => "the example group's hash directly for the " \ + "computed keys and `:parent_example_group` to access the parent " \ + "example group metadata") + end + + group_hash = example_group_selector.call(hash) + LegacyExampleGroupHash.new(group_hash) if group_hash + when :example_group_block + RSpec.deprecate("`metadata[:example_group_block]`", + :replacement => "`metadata[:block]`") + hash[:block] + when :describes + RSpec.deprecate("`metadata[:describes]`", + :replacement => "`metadata[:described_class]`") + hash[:described_class] + end + end + end + + private + + def described_class + candidate = metadata[:description_args].first + return candidate unless NilClass === candidate || String === candidate + parent_group = metadata[:parent_example_group] + parent_group && parent_group[:described_class] + end + + def full_description + description = metadata[:description] + parent_example_group = metadata[:parent_example_group] + return description unless parent_example_group + + parent_description = parent_example_group[:full_description] + separator = description_separator(parent_example_group[:description_args].last, + metadata[:description_args].first) + + parent_description + separator + description + end + end + + # @private + RESERVED_KEYS = [ + :description, + :description_args, + :described_class, + :example_group, + :parent_example_group, + :execution_result, + :last_run_status, + :file_path, + :absolute_file_path, + :rerun_file_path, + :full_description, + :line_number, + :location, + :scoped_id, + :block, + :shared_group_inclusion_backtrace + ] + end + + # Mixin that makes the including class imitate a hash for backwards + # compatibility. The including class should use `attr_accessor` to + # declare attributes. + # @private + module HashImitatable + def self.included(klass) + klass.extend ClassMethods + end + + def to_h + hash = extra_hash_attributes.dup + + self.class.hash_attribute_names.each do |name| + hash[name] = __send__(name) + end + + hash + end + + (Hash.public_instance_methods - Object.public_instance_methods).each do |method_name| + next if [:[], :[]=, :to_h].include?(method_name.to_sym) + + define_method(method_name) do |*args, &block| + issue_deprecation(method_name, *args) + + hash = hash_for_delegation + self.class.hash_attribute_names.each do |name| + hash.delete(name) unless instance_variable_defined?(:"@#{name}") + end + + hash.__send__(method_name, *args, &block).tap do + # apply mutations back to the object + hash.each do |name, value| + if directly_supports_attribute?(name) + set_value(name, value) + else + extra_hash_attributes[name] = value + end + end + end + end + end + + def [](key) + issue_deprecation(:[], key) + + if directly_supports_attribute?(key) + get_value(key) + else + extra_hash_attributes[key] + end + end + + def []=(key, value) + issue_deprecation(:[]=, key, value) + + if directly_supports_attribute?(key) + set_value(key, value) + else + extra_hash_attributes[key] = value + end + end + + private + + def extra_hash_attributes + @extra_hash_attributes ||= {} + end + + def directly_supports_attribute?(name) + self.class.hash_attribute_names.include?(name) + end + + def get_value(name) + __send__(name) + end + + def set_value(name, value) + __send__(:"#{name}=", value) + end + + def hash_for_delegation + to_h + end + + def issue_deprecation(_method_name, *_args) + # no-op by default: subclasses can override + end + + # @private + module ClassMethods + def hash_attribute_names + @hash_attribute_names ||= [] + end + + def attr_accessor(*names) + hash_attribute_names.concat(names) + super + end + end + end + + # @private + # Together with the example group metadata hash default block, + # provides backwards compatibility for the old `:example_group` + # key. In RSpec 2.x, the computed keys of a group's metadata + # were exposed from a nested subhash keyed by `[:example_group]`, and + # then the parent group's metadata was exposed by sub-subhash + # keyed by `[:example_group][:example_group]`. + # + # In RSpec 3, we reorganized this to that the computed keys are + # exposed directly of the group metadata hash (no nesting), and + # `:parent_example_group` returns the parent group's metadata. + # + # Maintaining backwards compatibility was difficult: we wanted + # `:example_group` to return an object that: + # + # * Exposes the top-level metadata keys that used to be nested + # under `:example_group`. + # * Supports mutation (rspec-rails, for example, assigns + # `metadata[:example_group][:described_class]` when you use + # anonymous controller specs) such that changes are written + # back to the top-level metadata hash. + # * Exposes the parent group metadata as + # `[:example_group][:example_group]`. + class LegacyExampleGroupHash + include HashImitatable + + def initialize(metadata) + @metadata = metadata + parent_group_metadata = metadata.fetch(:parent_example_group) { {} }[:example_group] + self[:example_group] = parent_group_metadata if parent_group_metadata + end + + def to_h + super.merge(@metadata) + end + + private + + def directly_supports_attribute?(name) + name != :example_group + end + + def get_value(name) + @metadata[name] + end + + def set_value(name, value) + @metadata[name] = value + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/metadata_filter.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/metadata_filter.rb new file mode 100644 index 0000000..d544931 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/metadata_filter.rb @@ -0,0 +1,235 @@ +module RSpec + module Core + # Contains metadata filtering logic. This has been extracted from + # the metadata classes because it operates ON a metadata hash but + # does not manage any of the state in the hash. We're moving towards + # having metadata be a raw hash (not a custom subclass), so externalizing + # this filtering logic helps us move in that direction. + module MetadataFilter + class << self + # @private + def apply?(predicate, filters, metadata) + filters.__send__(predicate) { |k, v| filter_applies?(k, v, metadata) } + end + + # @private + def filter_applies?(key, value, metadata) + silence_metadata_example_group_deprecations do + return filter_applies_to_any_value?(key, value, metadata) if Array === metadata[key] && !(Proc === value) + return location_filter_applies?(value, metadata) if key == :locations + return id_filter_applies?(value, metadata) if key == :ids + return filters_apply?(key, value, metadata) if Hash === value + + return false unless metadata.key?(key) + + case value + when Regexp + metadata[key] =~ value + when Proc + case value.arity + when 0 then value.call + when 2 then value.call(metadata[key], metadata) + else value.call(metadata[key]) + end + else + metadata[key].to_s == value.to_s + end + end + end + + private + + def filter_applies_to_any_value?(key, value, metadata) + metadata[key].any? { |v| filter_applies?(key, v, key => value) } + end + + def id_filter_applies?(rerun_paths_to_scoped_ids, metadata) + scoped_ids = rerun_paths_to_scoped_ids.fetch(metadata[:rerun_file_path]) { return false } + + Metadata.ascend(metadata).any? do |meta| + scoped_ids.include?(meta[:scoped_id]) + end + end + + def location_filter_applies?(locations, metadata) + line_numbers = example_group_declaration_lines(locations, metadata) + line_number_filter_applies?(line_numbers, metadata) + end + + def line_number_filter_applies?(line_numbers, metadata) + preceding_declaration_lines = line_numbers.map { |n| RSpec.world.preceding_declaration_line(n) } + !(relevant_line_numbers(metadata) & preceding_declaration_lines).empty? + end + + def relevant_line_numbers(metadata) + Metadata.ascend(metadata).map { |meta| meta[:line_number] } + end + + def example_group_declaration_lines(locations, metadata) + FlatMap.flat_map(Metadata.ascend(metadata)) do |meta| + locations[meta[:absolute_file_path]] + end.uniq + end + + def filters_apply?(key, value, metadata) + subhash = metadata[key] + return false unless Hash === subhash || HashImitatable === subhash + value.all? { |k, v| filter_applies?(k, v, subhash) } + end + + def silence_metadata_example_group_deprecations + RSpec::Support.thread_local_data[:silence_metadata_example_group_deprecations] = true + yield + ensure + RSpec::Support.thread_local_data.delete(:silence_metadata_example_group_deprecations) + end + end + end + + # Tracks a collection of filterable items (e.g. modules, hooks, etc) + # and provides an optimized API to get the applicable items for the + # metadata of an example or example group. + # + # There are two implementations, optimized for different uses. + # @private + module FilterableItemRepository + # This implementation is simple, and is optimized for frequent + # updates but rare queries. `append` and `prepend` do no extra + # processing, and no internal memoization is done, since this + # is not optimized for queries. + # + # This is ideal for use by a example or example group, which may + # be updated multiple times with globally configured hooks, etc, + # but will not be queried frequently by other examples or examle + # groups. + # @private + class UpdateOptimized + attr_reader :items_and_filters + + def initialize(applies_predicate) + @applies_predicate = applies_predicate + @items_and_filters = [] + end + + def append(item, metadata) + @items_and_filters << [item, metadata] + end + + def prepend(item, metadata) + @items_and_filters.unshift [item, metadata] + end + + def items_for(request_meta) + @items_and_filters.each_with_object([]) do |(item, item_meta), to_return| + to_return << item if item_meta.empty? || + MetadataFilter.apply?(@applies_predicate, item_meta, request_meta) + end + end + + unless [].respond_to?(:each_with_object) # For 1.8.7 + # :nocov: + undef items_for + def items_for(request_meta) + @items_and_filters.inject([]) do |to_return, (item, item_meta)| + to_return << item if item_meta.empty? || + MetadataFilter.apply?(@applies_predicate, item_meta, request_meta) + to_return + end + end + # :nocov: + end + end + + # This implementation is much more complex, and is optimized for + # rare (or hopefully no) updates once the queries start. Updates + # incur a cost as it has to clear the memoization and keep track + # of applicable keys. Queries will be O(N) the first time an item + # is provided with a given set of applicable metadata; subsequent + # queries with items with the same set of applicable metadata will + # be O(1) due to internal memoization. + # + # This is ideal for use by config, where filterable items (e.g. hooks) + # are typically added at the start of the process (e.g. in `spec_helper`) + # and then repeatedly queried as example groups and examples are defined. + # @private + class QueryOptimized < UpdateOptimized + alias find_items_for items_for + private :find_items_for + + def initialize(applies_predicate) + super + @applicable_keys = Set.new + @proc_keys = Set.new + @memoized_lookups = Hash.new do |hash, applicable_metadata| + hash[applicable_metadata] = find_items_for(applicable_metadata) + end + end + + def append(item, metadata) + super + handle_mutation(metadata) + end + + def prepend(item, metadata) + super + handle_mutation(metadata) + end + + def items_for(metadata) + # The filtering of `metadata` to `applicable_metadata` is the key thing + # that makes the memoization actually useful in practice, since each + # example and example group have different metadata (e.g. location and + # description). By filtering to the metadata keys our items care about, + # we can ignore extra metadata keys that differ for each example/group. + # For example, given `config.include DBHelpers, :db`, example groups + # can be split into these two sets: those that are tagged with `:db` and those + # that are not. For each set, this method for the first group in the set is + # still an `O(N)` calculation, but all subsequent groups in the set will be + # constant time lookups when they call this method. + applicable_metadata = applicable_metadata_from(metadata) + + if applicable_metadata.any? { |k, _| @proc_keys.include?(k) } + # It's unsafe to memoize lookups involving procs (since they can + # be non-deterministic), so we skip the memoization in this case. + find_items_for(applicable_metadata) + else + @memoized_lookups[applicable_metadata] + end + end + + private + + def handle_mutation(metadata) + @applicable_keys.merge(metadata.keys) + @proc_keys.merge(proc_keys_from metadata) + @memoized_lookups.clear + end + + def applicable_metadata_from(metadata) + @applicable_keys.inject({}) do |hash, key| + hash[key] = metadata[key] if metadata.key?(key) + hash + end + end + + def proc_keys_from(metadata) + metadata.each_with_object([]) do |(key, value), to_return| + to_return << key if Proc === value + end + end + + unless [].respond_to?(:each_with_object) # For 1.8.7 + # :nocov: + undef proc_keys_from + def proc_keys_from(metadata) + metadata.inject([]) do |to_return, (key, value)| + to_return << key if Proc === value + to_return + end + end + # :nocov: + end + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/minitest_assertions_adapter.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/minitest_assertions_adapter.rb new file mode 100644 index 0000000..25db751 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/minitest_assertions_adapter.rb @@ -0,0 +1,31 @@ +begin + # Only the minitest 5.x gem includes the minitest.rb and assertions.rb files. + require 'minitest' + require 'minitest/assertions' +rescue LoadError + # We must be using Ruby Core's MiniTest or the Minitest gem 4.x. + require 'minitest/unit' + Minitest = MiniTest +end + +module RSpec + module Core + # @private + module MinitestAssertionsAdapter + include ::Minitest::Assertions + # Need to forcefully include Pending after Minitest::Assertions + # to make sure our own #skip method beats Minitest's. + include ::RSpec::Core::Pending + + # Minitest 5.x requires this accessor to be available. See + # https://github.com/seattlerb/minitest/blob/38f0a5fcbd9c37c3f80a3eaad4ba84d3fc9947a0/lib/minitest/assertions.rb#L8 + # + # It is not required for other extension libraries, and RSpec does not + # report or make this information available to formatters. + attr_writer :assertions + def assertions + @assertions ||= 0 + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/mocking_adapters/flexmock.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/mocking_adapters/flexmock.rb new file mode 100644 index 0000000..91475ae --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/mocking_adapters/flexmock.rb @@ -0,0 +1,31 @@ +# Created by Jim Weirich on 2007-04-10. +# Copyright (c) 2007. All rights reserved. + +require 'flexmock/rspec' + +module RSpec + module Core + module MockingAdapters + # @private + module Flexmock + include ::FlexMock::MockContainer + + def self.framework_name + :flexmock + end + + def setup_mocks_for_rspec + # No setup required. + end + + def verify_mocks_for_rspec + flexmock_verify + end + + def teardown_mocks_for_rspec + flexmock_close + end + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/mocking_adapters/mocha.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/mocking_adapters/mocha.rb new file mode 100644 index 0000000..8caf7b6 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/mocking_adapters/mocha.rb @@ -0,0 +1,57 @@ +# In order to support all versions of mocha, we have to jump through some +# hoops here. +# +# mocha >= '0.13.0': +# require 'mocha/api' is required. +# require 'mocha/object' raises a LoadError b/c the file no longer exists. +# mocha < '0.13.0', >= '0.9.7' +# require 'mocha/api' is required. +# require 'mocha/object' is required. +# mocha < '0.9.7': +# require 'mocha/api' raises a LoadError b/c the file does not yet exist. +# require 'mocha/standalone' is required. +# require 'mocha/object' is required. +begin + require 'mocha/api' + + begin + require 'mocha/object' + rescue LoadError + # Mocha >= 0.13.0 no longer contains this file nor needs it to be loaded. + end +rescue LoadError + require 'mocha/standalone' + require 'mocha/object' +end + +module RSpec + module Core + module MockingAdapters + # @private + module Mocha + def self.framework_name + :mocha + end + + # Mocha::Standalone was deprecated as of Mocha 0.9.7. + begin + include ::Mocha::API + rescue NameError + include ::Mocha::Standalone + end + + def setup_mocks_for_rspec + mocha_setup + end + + def verify_mocks_for_rspec + mocha_verify + end + + def teardown_mocks_for_rspec + mocha_teardown + end + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/mocking_adapters/null.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/mocking_adapters/null.rb new file mode 100644 index 0000000..442de9a --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/mocking_adapters/null.rb @@ -0,0 +1,14 @@ +module RSpec + module Core + module MockingAdapters + # @private + module Null + def setup_mocks_for_rspec; end + + def verify_mocks_for_rspec; end + + def teardown_mocks_for_rspec; end + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/mocking_adapters/rr.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/mocking_adapters/rr.rb new file mode 100644 index 0000000..d72651a --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/mocking_adapters/rr.rb @@ -0,0 +1,31 @@ +require 'rr' + +RSpec.configuration.backtrace_exclusion_patterns.push(RR::Errors::BACKTRACE_IDENTIFIER) + +module RSpec + module Core + # @private + module MockingAdapters + # @private + module RR + def self.framework_name + :rr + end + + include ::RR::Extensions::InstanceMethods + + def setup_mocks_for_rspec + ::RR::Space.instance.reset + end + + def verify_mocks_for_rspec + ::RR::Space.instance.verify_doubles + end + + def teardown_mocks_for_rspec + ::RR::Space.instance.reset + end + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/mocking_adapters/rspec.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/mocking_adapters/rspec.rb new file mode 100644 index 0000000..bb3f0ae --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/mocking_adapters/rspec.rb @@ -0,0 +1,32 @@ +require 'rspec/mocks' + +module RSpec + module Core + module MockingAdapters + # @private + module RSpec + include ::RSpec::Mocks::ExampleMethods + + def self.framework_name + :rspec + end + + def self.configuration + ::RSpec::Mocks.configuration + end + + def setup_mocks_for_rspec + ::RSpec::Mocks.setup + end + + def verify_mocks_for_rspec + ::RSpec::Mocks.verify + end + + def teardown_mocks_for_rspec + ::RSpec::Mocks.teardown + end + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/mutex.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/mutex.rb new file mode 100644 index 0000000..57945ee --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/mutex.rb @@ -0,0 +1,63 @@ +module RSpec + module Core + # On 1.8.7, it's in the stdlib. + # We don't want to load the stdlib, b/c this is a test tool, and can affect the test environment, + # causing tests to pass where they should fail. + # + # So we're transcribing/modifying it from https://github.com/ruby/ruby/blob/v1_8_7_374/lib/thread.rb#L56 + # Some methods we don't need are deleted. + # Anything I don't understand (there's quite a bit, actually) is left in. + # Some formating changes are made to appease the robot overlord: + # https://travis-ci.org/rspec/rspec-core/jobs/54410874 + # @private + class Mutex + def initialize + @waiting = [] + @locked = false + @waiting.taint + taint + end + + # @private + def lock + while Thread.critical = true && @locked + @waiting.push Thread.current + Thread.stop + end + @locked = true + Thread.critical = false + self + end + + # @private + def unlock + return unless @locked + Thread.critical = true + @locked = false + begin + t = @waiting.shift + t.wakeup if t + rescue ThreadError + retry + end + Thread.critical = false + begin + t.run if t + rescue ThreadError + :noop + end + self + end + + # @private + def synchronize + lock + begin + yield + ensure + unlock + end + end + end unless defined?(::RSpec::Core::Mutex) # Avoid warnings for library wide checks spec + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/notifications.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/notifications.rb new file mode 100644 index 0000000..25f0faa --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/notifications.rb @@ -0,0 +1,498 @@ +RSpec::Support.require_rspec_core "formatters/exception_presenter" +RSpec::Support.require_rspec_core "formatters/helpers" +RSpec::Support.require_rspec_core "shell_escape" +RSpec::Support.require_rspec_support "encoded_string" + +module RSpec::Core + # Notifications are value objects passed to formatters to provide them + # with information about a particular event of interest. + module Notifications + # @private + module NullColorizer + module_function + def wrap(line, _code_or_symbol) + line + end + end + + # The `StartNotification` represents a notification sent by the reporter + # when the suite is started. It contains the expected amount of examples + # to be executed, and the load time of RSpec. + # + # @attr count [Fixnum] the number counted + # @attr load_time [Float] the number of seconds taken to boot RSpec + # and load the spec files + StartNotification = Struct.new(:count, :load_time) + + # The `ExampleNotification` represents notifications sent by the reporter + # which contain information about the current (or soon to be) example. + # It is used by formatters to access information about that example. + # + # @example + # def example_started(notification) + # puts "Hey I started #{notification.example.description}" + # end + # + # @attr example [RSpec::Core::Example] the current example + ExampleNotification = Struct.new(:example) + class ExampleNotification + # @private + def self.for(example) + execution_result = example.execution_result + + return SkippedExampleNotification.new(example) if execution_result.example_skipped? + return new(example) unless execution_result.status == :pending || execution_result.status == :failed + + klass = if execution_result.pending_fixed? + PendingExampleFixedNotification + elsif execution_result.status == :pending + PendingExampleFailedAsExpectedNotification + else + FailedExampleNotification + end + + exception_presenter = Formatters::ExceptionPresenter::Factory.new(example).build + klass.new(example, exception_presenter) + end + + private_class_method :new + end + + # The `ExamplesNotification` represents notifications sent by the reporter + # which contain information about the suites examples. + # + # @example + # def stop(notification) + # puts "Hey I ran #{notification.examples.size}" + # end + # + class ExamplesNotification + def initialize(reporter) + @reporter = reporter + end + + # @return [Array] list of examples + def examples + @reporter.examples + end + + # @return [Array] list of failed examples + def failed_examples + @reporter.failed_examples + end + + # @return [Array] list of pending examples + def pending_examples + @reporter.pending_examples + end + + # @return [Array] + # returns examples as notifications + def notifications + @notifications ||= format_examples(examples) + end + + # @return [Array] + # returns failed examples as notifications + def failure_notifications + @failed_notifications ||= format_examples(failed_examples) + end + + # @return [Array] + # returns pending examples as notifications + def pending_notifications + @pending_notifications ||= format_examples(pending_examples) + end + + # @return [String] The list of failed examples, fully formatted in the way + # that RSpec's built-in formatters emit. + def fully_formatted_failed_examples(colorizer=::RSpec::Core::Formatters::ConsoleCodes) + formatted = "\nFailures:\n" + + failure_notifications.each_with_index do |failure, index| + formatted << failure.fully_formatted(index.next, colorizer) + end + + formatted + end + + # @return [String] The list of pending examples, fully formatted in the + # way that RSpec's built-in formatters emit. + def fully_formatted_pending_examples(colorizer=::RSpec::Core::Formatters::ConsoleCodes) + formatted = "\nPending: (Failures listed here are expected and do not affect your suite's status)\n" + + pending_notifications.each_with_index do |notification, index| + formatted << notification.fully_formatted(index.next, colorizer) + end + + formatted + end + + private + + def format_examples(examples) + examples.map do |example| + ExampleNotification.for(example) + end + end + end + + # The `FailedExampleNotification` extends `ExampleNotification` with + # things useful for examples that have failure info -- typically a + # failed or pending spec. + # + # @example + # def example_failed(notification) + # puts "Hey I failed :(" + # puts "Here's my stack trace" + # puts notification.exception.backtrace.join("\n") + # end + # + # @attr [RSpec::Core::Example] example the current example + # @see ExampleNotification + class FailedExampleNotification < ExampleNotification + public_class_method :new + + # @return [Exception] The example failure + def exception + @exception_presenter.exception + end + + # @return [String] The example description + def description + @exception_presenter.description + end + + # Returns the message generated for this failure line by line. + # + # @return [Array] The example failure message + def message_lines + @exception_presenter.message_lines + end + + # Returns the message generated for this failure colorized line by line. + # + # @param colorizer [#wrap] An object to colorize the message_lines by + # @return [Array] The example failure message colorized + def colorized_message_lines(colorizer=::RSpec::Core::Formatters::ConsoleCodes) + @exception_presenter.colorized_message_lines(colorizer) + end + + # Returns the failures formatted backtrace. + # + # @return [Array] the examples backtrace lines + def formatted_backtrace + @exception_presenter.formatted_backtrace + end + + # Returns the failures colorized formatted backtrace. + # + # @param colorizer [#wrap] An object to colorize the message_lines by + # @return [Array] the examples colorized backtrace lines + def colorized_formatted_backtrace(colorizer=::RSpec::Core::Formatters::ConsoleCodes) + @exception_presenter.colorized_formatted_backtrace(colorizer) + end + + # @return [String] The failure information fully formatted in the way that + # RSpec's built-in formatters emit. + def fully_formatted(failure_number, colorizer=::RSpec::Core::Formatters::ConsoleCodes) + @exception_presenter.fully_formatted(failure_number, colorizer) + end + + private + + def initialize(example, exception_presenter=Formatters::ExceptionPresenter.new(example.execution_result.exception, example)) + @exception_presenter = exception_presenter + super(example) + end + end + + # @deprecated Use {FailedExampleNotification} instead. + class PendingExampleFixedNotification < FailedExampleNotification; end + + # @deprecated Use {FailedExampleNotification} instead. + class PendingExampleFailedAsExpectedNotification < FailedExampleNotification; end + + # The `SkippedExampleNotification` extends `ExampleNotification` with + # things useful for specs that are skipped. + # + # @attr [RSpec::Core::Example] example the current example + # @see ExampleNotification + class SkippedExampleNotification < ExampleNotification + public_class_method :new + + # @return [String] The pending detail fully formatted in the way that + # RSpec's built-in formatters emit. + def fully_formatted(pending_number, colorizer=::RSpec::Core::Formatters::ConsoleCodes) + formatted_caller = RSpec.configuration.backtrace_formatter.backtrace_line(example.location) + colorizer.wrap("\n #{pending_number}) #{example.full_description}", :pending) << "\n " << + Formatters::ExceptionPresenter::PENDING_DETAIL_FORMATTER.call(example, colorizer) << + "\n" << colorizer.wrap(" # #{formatted_caller}\n", :detail) + end + end + + # The `GroupNotification` represents notifications sent by the reporter + # which contain information about the currently running (or soon to be) + # example group. It is used by formatters to access information about that + # group. + # + # @example + # def example_group_started(notification) + # puts "Hey I started #{notification.group.description}" + # end + # @attr group [RSpec::Core::ExampleGroup] the current group + GroupNotification = Struct.new(:group) + + # The `MessageNotification` encapsulates generic messages that the reporter + # sends to formatters. + # + # @attr message [String] the message + MessageNotification = Struct.new(:message) + + # The `SeedNotification` holds the seed used to randomize examples and + # whether that seed has been used or not. + # + # @attr seed [Fixnum] the seed used to randomize ordering + # @attr used [Boolean] whether the seed has been used or not + SeedNotification = Struct.new(:seed, :used) + class SeedNotification + # @api + # @return [Boolean] has the seed been used? + def seed_used? + !!used + end + private :used + + # @return [String] The seed information fully formatted in the way that + # RSpec's built-in formatters emit. + def fully_formatted + "\nRandomized with seed #{seed}\n" + end + end + + # The `SummaryNotification` holds information about the results of running + # a test suite. It is used by formatters to provide information at the end + # of the test run. + # + # @attr duration [Float] the time taken (in seconds) to run the suite + # @attr examples [Array] the examples run + # @attr failed_examples [Array] the failed examples + # @attr pending_examples [Array] the pending examples + # @attr load_time [Float] the number of seconds taken to boot RSpec + # and load the spec files + SummaryNotification = Struct.new(:duration, :examples, :failed_examples, :pending_examples, :load_time) + class SummaryNotification + # @api + # @return [Fixnum] the number of examples run + def example_count + @example_count ||= examples.size + end + + # @api + # @return [Fixnum] the number of failed examples + def failure_count + @failure_count ||= failed_examples.size + end + + # @api + # @return [Fixnum] the number of pending examples + def pending_count + @pending_count ||= pending_examples.size + end + + # @api + # @return [String] A line summarising the result totals of the spec run. + def totals_line + summary = Formatters::Helpers.pluralize(example_count, "example") + summary << ", " << Formatters::Helpers.pluralize(failure_count, "failure") + summary << ", #{pending_count} pending" if pending_count > 0 + summary + end + + # @api public + # + # Wraps the results line with colors based on the configured + # colors for failure, pending, and success. Defaults to red, + # yellow, green accordingly. + # + # @param colorizer [#wrap] An object which supports wrapping text with + # specific colors. + # @return [String] A colorized results line. + def colorized_totals_line(colorizer=::RSpec::Core::Formatters::ConsoleCodes) + if failure_count > 0 + colorizer.wrap(totals_line, RSpec.configuration.failure_color) + elsif pending_count > 0 + colorizer.wrap(totals_line, RSpec.configuration.pending_color) + else + colorizer.wrap(totals_line, RSpec.configuration.success_color) + end + end + + # @api public + # + # Formats failures into a rerunable command format. + # + # @param colorizer [#wrap] An object which supports wrapping text with + # specific colors. + # @return [String] A colorized summary line. + def colorized_rerun_commands(colorizer=::RSpec::Core::Formatters::ConsoleCodes) + "\nFailed examples:\n\n" + + failed_examples.map do |example| + colorizer.wrap("rspec #{rerun_argument_for(example)}", RSpec.configuration.failure_color) + " " + + colorizer.wrap("# #{example.full_description}", RSpec.configuration.detail_color) + end.join("\n") + end + + # @return [String] a formatted version of the time it took to run the + # suite + def formatted_duration + Formatters::Helpers.format_duration(duration) + end + + # @return [String] a formatted version of the time it took to boot RSpec + # and load the spec files + def formatted_load_time + Formatters::Helpers.format_duration(load_time) + end + + # @return [String] The summary information fully formatted in the way that + # RSpec's built-in formatters emit. + def fully_formatted(colorizer=::RSpec::Core::Formatters::ConsoleCodes) + formatted = "\nFinished in #{formatted_duration} " \ + "(files took #{formatted_load_time} to load)\n" \ + "#{colorized_totals_line(colorizer)}\n" + + unless failed_examples.empty? + formatted << colorized_rerun_commands(colorizer) << "\n" + end + + formatted + end + + private + + include RSpec::Core::ShellEscape + + def rerun_argument_for(example) + location = example.location_rerun_argument + return location unless duplicate_rerun_locations.include?(location) + conditionally_quote(example.id) + end + + def duplicate_rerun_locations + @duplicate_rerun_locations ||= begin + locations = RSpec.world.all_examples.map(&:location_rerun_argument) + + Set.new.tap do |s| + locations.group_by { |l| l }.each do |l, ls| + s << l if ls.count > 1 + end + end + end + end + end + + # The `ProfileNotification` holds information about the results of running a + # test suite when profiling is enabled. It is used by formatters to provide + # information at the end of the test run for profiling information. + # + # @attr duration [Float] the time taken (in seconds) to run the suite + # @attr examples [Array] the examples run + # @attr number_of_examples [Fixnum] the number of examples to profile + # @attr example_groups [Array] example groups run + class ProfileNotification + def initialize(duration, examples, number_of_examples, example_groups) + @duration = duration + @examples = examples + @number_of_examples = number_of_examples + @example_groups = example_groups + end + attr_reader :duration, :examples, :number_of_examples + + # @return [Array] the slowest examples + def slowest_examples + @slowest_examples ||= + examples.sort_by do |example| + -example.execution_result.run_time + end.first(number_of_examples) + end + + # @return [Float] the time taken (in seconds) to run the slowest examples + def slow_duration + @slow_duration ||= + slowest_examples.inject(0.0) do |i, e| + i + e.execution_result.run_time + end + end + + # @return [String] the percentage of total time taken + def percentage + @percentage ||= + begin + time_taken = slow_duration / duration + '%.1f' % ((time_taken.nan? ? 0.0 : time_taken) * 100) + end + end + + # @return [Array] the slowest example groups + def slowest_groups + @slowest_groups ||= calculate_slowest_groups + end + + private + + def calculate_slowest_groups + # stop if we've only one example group + return {} if @example_groups.keys.length <= 1 + + @example_groups.each_value do |hash| + hash[:average] = hash[:total_time].to_f / hash[:count] + end + + groups = @example_groups.sort_by { |_, hash| -hash[:average] }.first(number_of_examples) + groups.map { |group, data| [group.location, data] } + end + end + + # The `DeprecationNotification` is issued by the reporter when a deprecated + # part of RSpec is encountered. It represents information about the + # deprecated call site. + # + # @attr message [String] A custom message about the deprecation + # @attr deprecated [String] A custom message about the deprecation (alias of + # message) + # @attr replacement [String] An optional replacement for the deprecation + # @attr call_site [String] An optional call site from which the deprecation + # was issued + DeprecationNotification = Struct.new(:deprecated, :message, :replacement, :call_site) + class DeprecationNotification + private_class_method :new + + # @api + # Convenience way to initialize the notification + def self.from_hash(data) + new data[:deprecated], data[:message], data[:replacement], data[:call_site] + end + end + + # `NullNotification` represents a placeholder value for notifications that + # currently require no information, but we may wish to extend in future. + class NullNotification + end + + # `CustomNotification` is used when sending custom events to formatters / + # other registered listeners, it creates attributes based on supplied hash + # of options. + class CustomNotification < Struct + # @param options [Hash] A hash of method / value pairs to create on this notification + # @return [CustomNotification] + # + # Build a custom notification based on the supplied option key / values. + def self.for(options={}) + return NullNotification if options.keys.empty? + new(*options.keys).new(*options.values) + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/option_parser.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/option_parser.rb new file mode 100644 index 0000000..e9e278f --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/option_parser.rb @@ -0,0 +1,301 @@ +# http://www.ruby-doc.org/stdlib/libdoc/optparse/rdoc/classes/OptionParser.html +require 'optparse' + +module RSpec::Core + # @private + class Parser + def self.parse(args, source=nil) + new(args).parse(source) + end + + attr_reader :original_args + + def initialize(original_args) + @original_args = original_args + end + + def parse(source=nil) + return { :files_or_directories_to_run => [] } if original_args.empty? + args = original_args.dup + + options = args.delete('--tty') ? { :tty => true } : {} + begin + parser(options).parse!(args) + rescue OptionParser::InvalidOption => e + failure = e.message + failure << " (defined in #{source})" if source + abort "#{failure}\n\nPlease use --help for a listing of valid options" + end + + options[:files_or_directories_to_run] = args + options + end + + private + + # rubocop:disable MethodLength + def parser(options) + OptionParser.new do |parser| + parser.banner = "Usage: rspec [options] [files or directories]\n\n" + + parser.on('-I PATH', 'Specify PATH to add to $LOAD_PATH (may be used more than once).') do |dirs| + options[:libs] ||= [] + options[:libs].concat(dirs.split(File::PATH_SEPARATOR)) + end + + parser.on('-r', '--require PATH', 'Require a file.') do |path| + options[:requires] ||= [] + options[:requires] << path + end + + parser.on('-O', '--options PATH', 'Specify the path to a custom options file.') do |path| + options[:custom_options_file] = path + end + + parser.on('--order TYPE[:SEED]', 'Run examples by the specified order type.', + ' [defined] examples and groups are run in the order they are defined', + ' [rand] randomize the order of groups and examples', + ' [random] alias for rand', + ' [random:SEED] e.g. --order random:123') do |o| + options[:order] = o + end + + parser.on('--seed SEED', Integer, 'Equivalent of --order rand:SEED.') do |seed| + options[:order] = "rand:#{seed}" + end + + parser.on('--bisect[=verbose]', 'Repeatedly runs the suite in order to isolate the failures to the ', + ' smallest reproducible case.') do |argument| + bisect_and_exit(argument) + end + + parser.on('--[no-]fail-fast', 'Abort the run on first failure.') do |value| + set_fail_fast(options, value) + end + + parser.on('--failure-exit-code CODE', Integer, + 'Override the exit code used when there are failing specs.') do |code| + options[:failure_exit_code] = code + end + + parser.on('--dry-run', 'Print the formatter output of your suite without', + ' running any examples or hooks') do |_o| + options[:dry_run] = true + end + + parser.on('-X', '--[no-]drb', 'Run examples via DRb.') do |o| + options[:drb] = o + end + + parser.on('--drb-port PORT', 'Port to connect to the DRb server.') do |o| + options[:drb_port] = o.to_i + end + + parser.on('--init', 'Initialize your project with RSpec.') do |_cmd| + initialize_project_and_exit + end + + parser.separator("\n **** Output ****\n\n") + + parser.on('-f', '--format FORMATTER', 'Choose a formatter.', + ' [p]rogress (default - dots)', + ' [d]ocumentation (group and example names)', + ' [h]tml', + ' [j]son', + ' custom formatter class name') do |o| + options[:formatters] ||= [] + options[:formatters] << [o] + end + + parser.on('-o', '--out FILE', + 'Write output to a file instead of $stdout. This option applies', + ' to the previously specified --format, or the default format', + ' if no format is specified.' + ) do |o| + options[:formatters] ||= [['progress']] + options[:formatters].last << o + end + + parser.on('--deprecation-out FILE', 'Write deprecation warnings to a file instead of $stderr.') do |file| + options[:deprecation_stream] = file + end + + parser.on('-b', '--backtrace', 'Enable full backtrace.') do |_o| + options[:full_backtrace] = true + end + + parser.on('-c', '--[no-]color', '--[no-]colour', 'Enable color in the output.') do |o| + options[:color] = o + end + + parser.on('-p', '--[no-]profile [COUNT]', + 'Enable profiling of examples and list the slowest examples (default: 10).') do |argument| + options[:profile_examples] = if argument.nil? + true + elsif argument == false + false + else + begin + Integer(argument) + rescue ArgumentError + RSpec.warning "Non integer specified as profile count, seperate " \ + "your path from options with -- e.g. " \ + "`rspec --profile -- #{argument}`", + :call_site => nil + true + end + end + end + + parser.on('-w', '--warnings', 'Enable ruby warnings') do + $VERBOSE = true + end + + parser.separator <<-FILTERING + + **** Filtering/tags **** + + In addition to the following options for selecting specific files, groups, or + examples, you can select individual examples by appending the line number(s) to + the filename: + + rspec path/to/a_spec.rb:37:87 + + You can also pass example ids enclosed in square brackets: + + rspec path/to/a_spec.rb[1:5,1:6] # run the 5th and 6th examples/groups defined in the 1st group + +FILTERING + + parser.on('--only-failures', "Filter to just the examples that failed the last time they ran.") do + configure_only_failures(options) + end + + parser.on("--next-failure", "Apply `--only-failures` and abort after one failure.", + " (Equivalent to `--only-failures --fail-fast --order defined`)") do + configure_only_failures(options) + set_fail_fast(options, true) + options[:order] ||= 'defined' + end + + parser.on('-P', '--pattern PATTERN', 'Load files matching pattern (default: "spec/**/*_spec.rb").') do |o| + options[:pattern] = o + end + + parser.on('--exclude-pattern PATTERN', + 'Load files except those matching pattern. Opposite effect of --pattern.') do |o| + options[:exclude_pattern] = o + end + + parser.on('-e', '--example STRING', "Run examples whose full nested names include STRING (may be", + " used more than once)") do |o| + (options[:full_description] ||= []) << Regexp.compile(Regexp.escape(o)) + end + + parser.on('-t', '--tag TAG[:VALUE]', + 'Run examples with the specified tag, or exclude examples', + 'by adding ~ before the tag.', + ' - e.g. ~slow', + ' - TAG is always converted to a symbol') do |tag| + filter_type = tag =~ /^~/ ? :exclusion_filter : :inclusion_filter + + name, value = tag.gsub(/^(~@|~|@)/, '').split(':', 2) + name = name.to_sym + + parsed_value = case value + when nil then true # The default value for tags is true + when 'true' then true + when 'false' then false + when 'nil' then nil + when /^:/ then value[1..-1].to_sym + when /^\d+$/ then Integer(value) + when /^\d+.\d+$/ then Float(value) + else + value + end + + add_tag_filter(options, filter_type, name, parsed_value) + end + + parser.on('--default-path PATH', 'Set the default path where RSpec looks for examples (can', + ' be a path to a file or a directory).') do |path| + options[:default_path] = path + end + + parser.separator("\n **** Utility ****\n\n") + + parser.on('-v', '--version', 'Display the version.') do + print_version_and_exit + end + + # These options would otherwise be confusing to users, so we forcibly + # prevent them from executing. + # + # * --I is too similar to -I. + # * -d was a shorthand for --debugger, which is removed, but now would + # trigger --default-path. + invalid_options = %w[-d --I] + + parser.on_tail('-h', '--help', "You're looking at it.") do + print_help_and_exit(parser, invalid_options) + end + + # This prevents usage of the invalid_options. + invalid_options.each do |option| + parser.on(option) do + raise OptionParser::InvalidOption.new + end + end + + end + end + # rubocop:enable MethodLength + + def add_tag_filter(options, filter_type, tag_name, value=true) + (options[filter_type] ||= {})[tag_name] = value + end + + def set_fail_fast(options, value) + options[:fail_fast] = value + end + + def configure_only_failures(options) + options[:only_failures] = true + add_tag_filter(options, :inclusion_filter, :last_run_status, 'failed') + end + + def initialize_project_and_exit + RSpec::Support.require_rspec_core "project_initializer" + ProjectInitializer.new.run + exit + end + + def bisect_and_exit(argument) + RSpec::Support.require_rspec_core "bisect/coordinator" + + success = Bisect::Coordinator.bisect_with( + original_args, + RSpec.configuration, + bisect_formatter_for(argument) + ) + + exit(success ? 0 : 1) + end + + def bisect_formatter_for(argument) + return Formatters::BisectDebugFormatter if argument == "verbose" + Formatters::BisectProgressFormatter + end + + def print_version_and_exit + puts RSpec::Core::Version::STRING + exit + end + + def print_help_and_exit(parser, invalid_options) + # Removing the blank invalid options from the output. + puts parser.to_s.gsub(/^\s+(#{invalid_options.join('|')})\s*$\n/, '') + exit + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/ordering.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/ordering.rb new file mode 100644 index 0000000..f2284fb --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/ordering.rb @@ -0,0 +1,158 @@ +module RSpec + module Core + # @private + module Ordering + # @private + # The default global ordering (defined order). + class Identity + def order(items) + items + end + end + + # @private + # Orders items randomly. + class Random + def initialize(configuration) + @configuration = configuration + @used = false + end + + def used? + @used + end + + def order(items) + @used = true + + seed = @configuration.seed.to_s + items.sort_by { |item| jenkins_hash_digest(seed + item.id) } + end + + private + + # http://en.wikipedia.org/wiki/Jenkins_hash_function + # Jenkins provides a good distribution and is simpler than MD5. + # It's a bit slower than MD5 (primarily because `Digest::MD5` is + # implemented in C) but has the advantage of not requiring us + # to load another part of stdlib, which we try to minimize. + def jenkins_hash_digest(string) + hash = 0 + + string.each_byte do |byte| + hash += byte + hash &= MAX_32_BIT + hash += ((hash << 10) & MAX_32_BIT) + hash &= MAX_32_BIT + hash ^= hash >> 6 + end + + hash += ((hash << 3) & MAX_32_BIT) + hash &= MAX_32_BIT + hash ^= hash >> 11 + hash += ((hash << 15) & MAX_32_BIT) + hash &= MAX_32_BIT + hash + end + + MAX_32_BIT = 4_294_967_295 + end + + # @private + # Orders items based on a custom block. + class Custom + def initialize(callable) + @callable = callable + end + + def order(list) + @callable.call(list) + end + end + + # @private + # Stores the different ordering strategies. + class Registry + def initialize(configuration) + @configuration = configuration + @strategies = {} + + register(:random, Random.new(configuration)) + + identity = Identity.new + register(:defined, identity) + + # The default global ordering is --defined. + register(:global, identity) + end + + def fetch(name, &fallback) + @strategies.fetch(name, &fallback) + end + + def register(sym, strategy) + @strategies[sym] = strategy + end + + def used_random_seed? + @strategies[:random].used? + end + end + + # @private + # Manages ordering configuration. + # + # @note This is not intended to be used externally. Use + # the APIs provided by `RSpec::Core::Configuration` instead. + class ConfigurationManager + attr_reader :seed, :ordering_registry + + def initialize + @ordering_registry = Registry.new(self) + @seed = rand(0xFFFF) + @seed_forced = false + @order_forced = false + end + + def seed_used? + ordering_registry.used_random_seed? + end + + def seed=(seed) + return if @seed_forced + register_ordering(:global, ordering_registry.fetch(:random)) + @seed = seed.to_i + end + + def order=(type) + order, seed = type.to_s.split(':') + @seed = seed.to_i if seed + + ordering_name = if order.include?('rand') + :random + elsif order == 'defined' + :defined + end + + register_ordering(:global, ordering_registry.fetch(ordering_name)) if ordering_name + end + + def force(hash) + if hash.key?(:seed) + self.seed = hash[:seed] + @seed_forced = true + @order_forced = true + elsif hash.key?(:order) + self.order = hash[:order] + @order_forced = true + end + end + + def register_ordering(name, strategy=Custom.new(Proc.new { |l| yield l })) + return if @order_forced && name == :global + ordering_registry.register(name, strategy) + end + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/pending.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/pending.rb new file mode 100644 index 0000000..f04e3be --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/pending.rb @@ -0,0 +1,165 @@ +module RSpec + module Core + # Provides methods to mark examples as pending. These methods are available + # to be called from within any example or hook. + module Pending + # Raised in the middle of an example to indicate that it should be marked + # as skipped. + class SkipDeclaredInExample < StandardError + attr_reader :argument + + def initialize(argument) + @argument = argument + end + end + + # If Test::Unit is loaded, we'll use its error as baseclass, so that + # Test::Unit will report unmet RSpec expectations as failures rather than + # errors. + begin + class PendingExampleFixedError < Test::Unit::AssertionFailedError; end + rescue + class PendingExampleFixedError < StandardError; end + end + + # @private + NO_REASON_GIVEN = 'No reason given' + + # @private + NOT_YET_IMPLEMENTED = 'Not yet implemented' + + # @overload pending() + # @overload pending(message) + # + # Marks an example as pending. The rest of the example will still be + # executed, and if it passes the example will fail to indicate that the + # pending can be removed. + # + # @param message [String] optional message to add to the summary report. + # + # @example + # describe "an example" do + # # reported as "Pending: no reason given" + # it "is pending with no message" do + # pending + # raise "broken" + # end + # + # # reported as "Pending: something else getting finished" + # it "is pending with a custom message" do + # pending("something else getting finished") + # raise "broken" + # end + # end + # + # @note `before(:example)` hooks are eval'd when you use the `pending` + # method within an example. If you want to declare an example `pending` + # and bypass the `before` hooks as well, you can pass `:pending => true` + # to the `it` method: + # + # it "does something", :pending => true do + # # ... + # end + # + # or pass `:pending => "something else getting finished"` to add a + # message to the summary report: + # + # it "does something", :pending => "something else getting finished" do + # # ... + # end + def pending(message=nil) + current_example = RSpec.current_example + + if block_given? + raise ArgumentError, <<-EOS.gsub(/^\s+\|/, '') + |The semantics of `RSpec::Core::Pending#pending` have changed in + |RSpec 3. In RSpec 2.x, it caused the example to be skipped. In + |RSpec 3, the rest of the example is still run but is expected to + |fail, and will be marked as a failure (rather than as pending) if + |the example passes. + | + |Passing a block within an example is now deprecated. Marking the + |example as pending provides the same behavior in RSpec 3 which was + |provided only by the block in RSpec 2.x. + | + |Move the code in the block provided to `pending` into the rest of + |the example body. + | + |Called from #{CallerFilter.first_non_rspec_line}. + | + EOS + elsif current_example + Pending.mark_pending! current_example, message + else + raise "`pending` may not be used outside of examples, such as in " \ + "before(:context). Maybe you want `skip`?" + end + end + + # @overload skip() + # @overload skip(message) + # + # Marks an example as pending and skips execution. + # + # @param message [String] optional message to add to the summary report. + # + # @example + # describe "an example" do + # # reported as "Pending: no reason given" + # it "is skipped with no message" do + # skip + # end + # + # # reported as "Pending: something else getting finished" + # it "is skipped with a custom message" do + # skip "something else getting finished" + # end + # end + def skip(message=nil) + current_example = RSpec.current_example + + Pending.mark_skipped!(current_example, message) if current_example + + raise SkipDeclaredInExample.new(message) + end + + # @private + # + # Mark example as skipped. + # + # @param example [RSpec::Core::Example] the example to mark as skipped + # @param message_or_bool [Boolean, String] the message to use, or true + def self.mark_skipped!(example, message_or_bool) + Pending.mark_pending! example, message_or_bool + example.metadata[:skip] = true + end + + # @private + # + # Mark example as pending. + # + # @param example [RSpec::Core::Example] the example to mark as pending + # @param message_or_bool [Boolean, String] the message to use, or true + def self.mark_pending!(example, message_or_bool) + message = if !message_or_bool || !(String === message_or_bool) + NO_REASON_GIVEN + else + message_or_bool + end + + example.metadata[:pending] = true + example.execution_result.pending_message = message + example.execution_result.pending_fixed = false + end + + # @private + # + # Mark example as fixed. + # + # @param example [RSpec::Core::Example] the example to mark as fixed + def self.mark_fixed!(example) + example.execution_result.pending_fixed = true + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/profiler.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/profiler.rb new file mode 100644 index 0000000..afe7731 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/profiler.rb @@ -0,0 +1,32 @@ +module RSpec + module Core + # @private + class Profiler + NOTIFICATIONS = [:example_group_started, :example_group_finished, :example_started] + + def initialize + @example_groups = Hash.new { |h, k| h[k] = { :count => 0 } } + end + + attr_reader :example_groups + + def example_group_started(notification) + return unless notification.group.top_level? + + @example_groups[notification.group][:start] = Time.now + @example_groups[notification.group][:description] = notification.group.top_level_description + end + + def example_group_finished(notification) + return unless notification.group.top_level? + + @example_groups[notification.group][:total_time] = Time.now - @example_groups[notification.group][:start] + end + + def example_started(notification) + group = notification.example.example_group.parent_groups.last + @example_groups[group][:count] += 1 + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/project_initializer.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/project_initializer.rb new file mode 100644 index 0000000..ca707e0 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/project_initializer.rb @@ -0,0 +1,48 @@ +RSpec::Support.require_rspec_support "directory_maker" + +module RSpec + module Core + # @private + # Generates conventional files for an RSpec project. + class ProjectInitializer + attr_reader :destination, :stream, :template_path + + DOT_RSPEC_FILE = '.rspec' + SPEC_HELPER_FILE = 'spec/spec_helper.rb' + + def initialize(opts={}) + @destination = opts.fetch(:destination, Dir.getwd) + @stream = opts.fetch(:report_stream, $stdout) + @template_path = opts.fetch(:template_path) do + File.expand_path("../project_initializer", __FILE__) + end + end + + def run + copy_template DOT_RSPEC_FILE + copy_template SPEC_HELPER_FILE + end + + private + + def copy_template(file) + destination_file = File.join(destination, file) + return report_exists(file) if File.exist?(destination_file) + + report_creating(file) + RSpec::Support::DirectoryMaker.mkdir_p(File.dirname(destination_file)) + File.open(destination_file, 'w') do |f| + f.write File.read(File.join(template_path, file)) + end + end + + def report_exists(file) + stream.puts " exist #{file}" + end + + def report_creating(file) + stream.puts " create #{file}" + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/project_initializer/.rspec b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/project_initializer/.rspec new file mode 100644 index 0000000..83e16f8 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/project_initializer/.rspec @@ -0,0 +1,2 @@ +--color +--require spec_helper diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/project_initializer/spec/spec_helper.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/project_initializer/spec/spec_helper.rb new file mode 100644 index 0000000..6839d5f --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/project_initializer/spec/spec_helper.rb @@ -0,0 +1,96 @@ +# This file was generated by the `rspec --init` command. Conventionally, all +# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. +# The generated `.rspec` file contains `--require spec_helper` which will cause +# this file to always be loaded, without a need to explicitly require it in any +# files. +# +# Given that it is always loaded, you are encouraged to keep this file as +# light-weight as possible. Requiring heavyweight dependencies from this file +# will add to the boot time of your test suite on EVERY test run, even for an +# individual file that may not need all of that loaded. Instead, consider making +# a separate helper file that requires the additional dependencies and performs +# the additional setup, and require it from the spec files that actually need +# it. +# +# The `.rspec` file also contains a few flags that are not defaults but that +# users commonly want. +# +# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration +RSpec.configure do |config| + # rspec-expectations config goes here. You can use an alternate + # assertion/expectation library such as wrong or the stdlib/minitest + # assertions if you prefer. + config.expect_with :rspec do |expectations| + # This option will default to `true` in RSpec 4. It makes the `description` + # and `failure_message` of custom matchers include text for helper methods + # defined using `chain`, e.g.: + # be_bigger_than(2).and_smaller_than(4).description + # # => "be bigger than 2 and smaller than 4" + # ...rather than: + # # => "be bigger than 2" + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + # rspec-mocks config goes here. You can use an alternate test double + # library (such as bogus or mocha) by changing the `mock_with` option here. + config.mock_with :rspec do |mocks| + # Prevents you from mocking or stubbing a method that does not exist on + # a real object. This is generally recommended, and will default to + # `true` in RSpec 4. + mocks.verify_partial_doubles = true + end + +# The settings below are suggested to provide a good initial experience +# with RSpec, but feel free to customize to your heart's content. +=begin + # These two settings work together to allow you to limit a spec run + # to individual examples or groups you care about by tagging them with + # `:focus` metadata. When nothing is tagged with `:focus`, all examples + # get run. + config.filter_run :focus + config.run_all_when_everything_filtered = true + + # Allows RSpec to persist some state between runs in order to support + # the `--only-failures` and `--next-failure` CLI options. We recommend + # you configure your source control system to ignore this file. + config.example_status_persistence_file_path = "spec/examples.txt" + + # Limits the available syntax to the non-monkey patched syntax that is + # recommended. For more details, see: + # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax + # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ + # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching + config.disable_monkey_patching! + + # This setting enables warnings. It's recommended, but in some cases may + # be too noisy due to issues in dependencies. + config.warnings = true + + # Many RSpec users commonly either run the entire suite or an individual + # file, and it's useful to allow more verbose output when running an + # individual spec file. + if config.files_to_run.one? + # Use the documentation formatter for detailed output, + # unless a formatter has already been configured + # (e.g. via a command-line flag). + config.default_formatter = 'doc' + end + + # Print the 10 slowest examples and example groups at the + # end of the spec run, to help surface which specs are running + # particularly slow. + config.profile_examples = 10 + + # Run specs in random order to surface order dependencies. If you find an + # order dependency and want to debug it, you can fix the order by providing + # the seed, which is printed after each run. + # --seed 1234 + config.order = :random + + # Seed global randomization in this process using the `--seed` CLI option. + # Setting this allows you to use `--seed` to deterministically reproduce + # test failures related to randomization by passing the same `--seed` value + # as the one that triggered the failure. + Kernel.srand config.seed +=end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/rake_task.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/rake_task.rb new file mode 100644 index 0000000..60308fd --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/rake_task.rb @@ -0,0 +1,158 @@ +require 'rake' +require 'rake/tasklib' +require 'rspec/support/ruby_features' +require 'rspec/core/shell_escape' + +module RSpec + module Core + # RSpec rake task + # + # @see Rakefile + class RakeTask < ::Rake::TaskLib + include ::Rake::DSL if defined?(::Rake::DSL) + include RSpec::Core::ShellEscape + + # Default path to the RSpec executable. + DEFAULT_RSPEC_PATH = File.expand_path('../../../../exe/rspec', __FILE__) + + # Default pattern for spec files. + DEFAULT_PATTERN = 'spec/**{,/*/**}/*_spec.rb' + + # Name of task. Defaults to `:spec`. + attr_accessor :name + + # Files matching this pattern will be loaded. + # Defaults to `'spec/**{,/*/**}/*_spec.rb'`. + attr_accessor :pattern + + # Files matching this pattern will be excluded. + # Defaults to `nil`. + attr_accessor :exclude_pattern + + # Whether or not to fail Rake when an error occurs (typically when + # examples fail). Defaults to `true`. + attr_accessor :fail_on_error + + # A message to print to stderr when there are failures. + attr_accessor :failure_message + + # Use verbose output. If this is set to true, the task will print the + # executed spec command to stdout. Defaults to `true`. + attr_accessor :verbose + + # Command line options to pass to ruby. Defaults to `nil`. + attr_accessor :ruby_opts + + # Path to RSpec. Defaults to the absolute path to the + # rspec binary from the loaded rspec-core gem. + attr_accessor :rspec_path + + # Command line options to pass to RSpec. Defaults to `nil`. + attr_accessor :rspec_opts + + def initialize(*args, &task_block) + @name = args.shift || :spec + @ruby_opts = nil + @rspec_opts = nil + @verbose = true + @fail_on_error = true + @rspec_path = DEFAULT_RSPEC_PATH + @pattern = DEFAULT_PATTERN + + define(args, &task_block) + end + + # @private + def run_task(verbose) + command = spec_command + puts command if verbose + + return if system(command) + puts failure_message if failure_message + + return unless fail_on_error + $stderr.puts "#{command} failed" if verbose + exit $?.exitstatus + end + + private + + # @private + def define(args, &task_block) + desc "Run RSpec code examples" unless ::Rake.application.last_comment + + task name, *args do |_, task_args| + RakeFileUtils.__send__(:verbose, verbose) do + task_block.call(*[self, task_args].slice(0, task_block.arity)) if task_block + run_task verbose + end + end + end + + def file_inclusion_specification + if ENV['SPEC'] + FileList[ ENV['SPEC']].sort + elsif String === pattern && !File.exist?(pattern) + "--pattern #{escape pattern}" + else + # Before RSpec 3.1, we used `FileList` to get the list of matched + # files, and then pass that along to the `rspec` command. Starting + # with 3.1, we prefer to pass along the pattern as-is to the `rspec` + # command, for 3 reasons: + # + # * It's *much* less verbose to pass one `--pattern` option than a + # long list of files. + # * It ensures `task.pattern` and `--pattern` have the same + # behavior. + # * It fixes a bug, where + # `task.pattern = pattern_that_matches_no_files` would run *all* + # files because it would cause no pattern or file args to get + # passed to `rspec`, which causes all files to get run. + # + # However, `FileList` is *far* more flexible than the `--pattern` + # option. Specifically, it supports individual files and directories, + # as well as arrays of files, directories and globs, as well as other + # `FileList` objects. + # + # For backwards compatibility, we have to fall back to using FileList + # if the user has passed a `pattern` option that will not work with + # `--pattern`. + # + # TODO: consider deprecating support for this and removing it in + # RSpec 4. + FileList[pattern].sort.map { |file| escape file } + end + end + + def file_exclusion_specification + " --exclude-pattern #{escape exclude_pattern}" if exclude_pattern + end + + def spec_command + cmd_parts = [] + cmd_parts << RUBY + cmd_parts << ruby_opts + cmd_parts << rspec_load_path + cmd_parts << escape(rspec_path) + cmd_parts << file_inclusion_specification + cmd_parts << file_exclusion_specification + cmd_parts << rspec_opts + cmd_parts.flatten.reject(&blank).join(" ") + end + + def blank + lambda { |s| s.nil? || s == "" } + end + + def rspec_load_path + @rspec_load_path ||= begin + core_and_support = $LOAD_PATH.grep( + /#{File::SEPARATOR}rspec-(core|support)[^#{File::SEPARATOR}]*#{File::SEPARATOR}lib/ + ).uniq + + "-I#{core_and_support.map { |file| escape file }.join(File::PATH_SEPARATOR)}" + end + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/reentrant_mutex.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/reentrant_mutex.rb new file mode 100644 index 0000000..c3065ec --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/reentrant_mutex.rb @@ -0,0 +1,52 @@ +module RSpec + module Core + # Allows a thread to lock out other threads from a critical section of code, + # while allowing the thread with the lock to reenter that section. + # + # Based on Monitor as of 2.2 - https://github.com/ruby/ruby/blob/eb7ddaa3a47bf48045d26c72eb0f263a53524ebc/lib/monitor.rb#L9 + # + # Depends on Mutex, but Mutex is only available as part of core since 1.9.1: + # exists - http://ruby-doc.org/core-1.9.1/Mutex.html + # dne - http://ruby-doc.org/core-1.9.0/Mutex.html + # + # @private + class ReentrantMutex + def initialize + @owner = nil + @count = 0 + @mutex = Mutex.new + end + + def synchronize + enter + yield + ensure + exit + end + + private + + def enter + @mutex.lock if @owner != Thread.current + @owner = Thread.current + @count += 1 + end + + def exit + @count -= 1 + return unless @count == 0 + @owner = nil + @mutex.unlock + end + end + + if defined? ::Mutex + # On 1.9 and up, this is in core, so we just use the real one + Mutex = ::Mutex + else # For 1.8.7 + # :nocov: + RSpec::Support.require_rspec_core "mutex" + # :nocov: + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/reporter.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/reporter.rb new file mode 100644 index 0000000..b396261 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/reporter.rb @@ -0,0 +1,220 @@ +module RSpec::Core + # A reporter will send notifications to listeners, usually formatters for the + # spec suite run. + class Reporter + # @private + RSPEC_NOTIFICATIONS = Set.new( + [ + :close, :deprecation, :deprecation_summary, :dump_failures, :dump_pending, + :dump_profile, :dump_summary, :example_failed, :example_group_finished, + :example_group_started, :example_passed, :example_pending, :example_started, + :message, :seed, :start, :start_dump, :stop + ]) + + def initialize(configuration) + @configuration = configuration + @listeners = Hash.new { |h, k| h[k] = Set.new } + @examples = [] + @failed_examples = [] + @pending_examples = [] + @duration = @start = @load_time = nil + end + + # @private + attr_reader :examples, :failed_examples, :pending_examples + + # @private + def reset + @examples = [] + @failed_examples = [] + @pending_examples = [] + @profiler = Profiler.new if defined?(@profiler) + end + + # @private + def setup_profiler + @profiler = Profiler.new + register_listener @profiler, *Profiler::NOTIFICATIONS + end + + # Registers a listener to a list of notifications. The reporter will send + # notification of events to all registered listeners. + # + # @param listener [Object] An obect that wishes to be notified of reporter + # events + # @param notifications [Array] Array of symbols represents the events a + # listener wishes to subscribe too + def register_listener(listener, *notifications) + notifications.each do |notification| + @listeners[notification.to_sym] << listener + end + true + end + + # @private + def registered_listeners(notification) + @listeners[notification].to_a + end + + # @overload report(count, &block) + # @overload report(count, &block) + # @param expected_example_count [Integer] the number of examples being run + # @yield [Block] block yields itself for further reporting. + # + # Initializes the report run and yields itself for further reporting. The + # block is required, so that the reporter can manage cleaning up after the + # run. + # + # @example + # + # reporter.report(group.examples.size) do |r| + # example_groups.map {|g| g.run(r) } + # end + # + def report(expected_example_count) + start(expected_example_count) + begin + yield self + ensure + finish + end + end + + # @private + def start(expected_example_count, time=RSpec::Core::Time.now) + @start = time + @load_time = (@start - @configuration.start_time).to_f + notify :seed, Notifications::SeedNotification.new(@configuration.seed, seed_used?) + notify :start, Notifications::StartNotification.new(expected_example_count, @load_time) + end + + # @param message [#to_s] A message object to send to formatters + # + # Send a custom message to supporting formatters. + def message(message) + notify :message, Notifications::MessageNotification.new(message) + end + + # @param event [Symbol] Name of the custom event to trigger on formatters + # @param options [Hash] Hash of arguments to provide via `CustomNotification` + # + # Publish a custom event to supporting registered formatters. + # @see RSpec::Core::Notifications::CustomNotification + def publish(event, options={}) + if RSPEC_NOTIFICATIONS.include? event + raise "RSpec::Core::Reporter#publish is intended for sending custom " \ + "events not internal RSpec ones, please rename your custom event." + end + notify event, Notifications::CustomNotification.for(options) + end + + # @private + def example_group_started(group) + notify :example_group_started, Notifications::GroupNotification.new(group) unless group.descendant_filtered_examples.empty? + end + + # @private + def example_group_finished(group) + notify :example_group_finished, Notifications::GroupNotification.new(group) unless group.descendant_filtered_examples.empty? + end + + # @private + def example_started(example) + @examples << example + notify :example_started, Notifications::ExampleNotification.for(example) + end + + # @private + def example_passed(example) + notify :example_passed, Notifications::ExampleNotification.for(example) + end + + # @private + def example_failed(example) + @failed_examples << example + notify :example_failed, Notifications::ExampleNotification.for(example) + end + + # @private + def example_pending(example) + @pending_examples << example + notify :example_pending, Notifications::ExampleNotification.for(example) + end + + # @private + def deprecation(hash) + notify :deprecation, Notifications::DeprecationNotification.from_hash(hash) + end + + # @private + def finish + close_after do + stop + notify :start_dump, Notifications::NullNotification + notify :dump_pending, Notifications::ExamplesNotification.new(self) + notify :dump_failures, Notifications::ExamplesNotification.new(self) + notify :deprecation_summary, Notifications::NullNotification + unless mute_profile_output? + notify :dump_profile, Notifications::ProfileNotification.new(@duration, @examples, + @configuration.profile_examples, + @profiler.example_groups) + end + notify :dump_summary, Notifications::SummaryNotification.new(@duration, @examples, @failed_examples, + @pending_examples, @load_time) + notify :seed, Notifications::SeedNotification.new(@configuration.seed, seed_used?) + end + end + + # @private + def close_after + yield + ensure + close + end + + # @private + def stop + @duration = (RSpec::Core::Time.now - @start).to_f if @start + notify :stop, Notifications::ExamplesNotification.new(self) + end + + # @private + def notify(event, notification) + registered_listeners(event).each do |formatter| + formatter.__send__(event, notification) + end + end + + # @private + def abort_with(msg, exit_status) + message(msg) + close + exit!(exit_status) + end + + private + + def close + notify :close, Notifications::NullNotification + end + + def mute_profile_output? + # Don't print out profiled info if there are failures and `--fail-fast` is + # used, it just clutters the output. + !@configuration.profile_examples? || (@configuration.fail_fast? && @failed_examples.size > 0) + end + + def seed_used? + @configuration.seed && @configuration.seed_used? + end + end + + # @private + # # Used in place of a {Reporter} for situations where we don't want reporting output. + class NullReporter + def self.method_missing(*) + # ignore + end + private_class_method :method_missing + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/ruby_project.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/ruby_project.rb new file mode 100644 index 0000000..10c89f9 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/ruby_project.rb @@ -0,0 +1,53 @@ +# This is borrowed (slightly modified) from Scott Taylor's +# project_path project: +# http://github.com/smtlaissezfaire/project_path +module RSpec + module Core + # @private + module RubyProject + def add_to_load_path(*dirs) + dirs.map { |dir| add_dir_to_load_path(File.join(root, dir)) } + end + + def add_dir_to_load_path(dir) + $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir) + end + + def root + @project_root ||= determine_root + end + + def determine_root + find_first_parent_containing('spec') || '.' + end + + def find_first_parent_containing(dir) + ascend_until { |path| File.exist?(File.join(path, dir)) } + end + + def ascend_until + fs = File::SEPARATOR + escaped_slash = "\\#{fs}" + special = "_RSPEC_ESCAPED_SLASH_" + project_path = File.expand_path(".") + parts = project_path.gsub(escaped_slash, special).squeeze(fs).split(fs).map do |x| + x.gsub(special, escaped_slash) + end + + until parts.empty? + path = parts.join(fs) + path = fs if path == "" + return path if yield(path) + parts.pop + end + end + + module_function :add_to_load_path + module_function :add_dir_to_load_path + module_function :root + module_function :determine_root + module_function :find_first_parent_containing + module_function :ascend_until + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/runner.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/runner.rb new file mode 100644 index 0000000..18dbc11 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/runner.rb @@ -0,0 +1,179 @@ +module RSpec + module Core + # Provides the main entry point to run a suite of RSpec examples. + class Runner + # Register an `at_exit` hook that runs the suite when the process exits. + # + # @note This is not generally needed. The `rspec` command takes care + # of running examples for you without involving an `at_exit` + # hook. This is only needed if you are running specs using + # the `ruby` command, and even then, the normal way to invoke + # this is by requiring `rspec/autorun`. + def self.autorun + if autorun_disabled? + RSpec.deprecate("Requiring `rspec/autorun` when running RSpec via the `rspec` command") + return + elsif installed_at_exit? || running_in_drb? + return + end + + at_exit { perform_at_exit } + @installed_at_exit = true + end + + # @private + def self.perform_at_exit + # Don't bother running any specs and just let the program terminate + # if we got here due to an unrescued exception (anything other than + # SystemExit, which is raised when somebody calls Kernel#exit). + return unless $!.nil? || $!.is_a?(SystemExit) + + # We got here because either the end of the program was reached or + # somebody called Kernel#exit. Run the specs and then override any + # existing exit status with RSpec's exit status if any specs failed. + invoke + end + + # Runs the suite of specs and exits the process with an appropriate exit + # code. + def self.invoke + disable_autorun! + status = run(ARGV, $stderr, $stdout).to_i + exit(status) if status != 0 + end + + # Run a suite of RSpec examples. Does not exit. + # + # This is used internally by RSpec to run a suite, but is available + # for use by any other automation tool. + # + # If you want to run this multiple times in the same process, and you + # want files like `spec_helper.rb` to be reloaded, be sure to load `load` + # instead of `require`. + # + # @param args [Array] command-line-supported arguments + # @param err [IO] error stream + # @param out [IO] output stream + # @return [Fixnum] exit status code. 0 if all specs passed, + # or the configured failure exit code (1 by default) if specs + # failed. + def self.run(args, err=$stderr, out=$stdout) + trap_interrupt + options = ConfigurationOptions.new(args) + + if options.options[:drb] + require 'rspec/core/drb' + begin + DRbRunner.new(options).run(err, out) + rescue DRb::DRbConnError + err.puts "No DRb server is running. Running in local process instead ..." + new(options).run(err, out) + end + else + new(options).run(err, out) + end + end + + def initialize(options, configuration=RSpec.configuration, world=RSpec.world) + @options = options + @configuration = configuration + @world = world + end + + # Configures and runs a spec suite. + # + # @param err [IO] error stream + # @param out [IO] output stream + def run(err, out) + setup(err, out) + run_specs(@world.ordered_example_groups).tap do + persist_example_statuses + end + end + + # Wires together the various configuration objects and state holders. + # + # @param err [IO] error stream + # @param out [IO] output stream + def setup(err, out) + @configuration.error_stream = err + @configuration.output_stream = out if @configuration.output_stream == $stdout + @options.configure(@configuration) + @configuration.load_spec_files + @world.announce_filters + end + + # Runs the provided example groups. + # + # @param example_groups [Array] groups to run + # @return [Fixnum] exit status code. 0 if all specs passed, + # or the configured failure exit code (1 by default) if specs + # failed. + def run_specs(example_groups) + @configuration.reporter.report(@world.example_count(example_groups)) do |reporter| + @configuration.with_suite_hooks do + example_groups.map { |g| g.run(reporter) }.all? ? 0 : @configuration.failure_exit_code + end + end + end + + private + + def persist_example_statuses + return unless (path = @configuration.example_status_persistence_file_path) + + ExampleStatusPersister.persist(@world.all_examples, path) + rescue SystemCallError => e + RSpec.warning "Could not write example statuses to #{path} (configured as " \ + "`config.example_status_persistence_file_path`) due to a " \ + "system error: #{e.inspect}. Please check that the config " \ + "option is set to an accessible, valid file path", :call_site => nil + end + + # @private + def self.disable_autorun! + @autorun_disabled = true + end + + # @private + def self.autorun_disabled? + @autorun_disabled ||= false + end + + # @private + def self.installed_at_exit? + @installed_at_exit ||= false + end + + # @private + # rubocop:disable Lint/EnsureReturn + def self.running_in_drb? + if defined?(DRb) && DRb.current_server + require 'socket' + require 'uri' + local_ipv4 = IPSocket.getaddress(Socket.gethostname) + local_drb = ["127.0.0.1", "localhost", local_ipv4].any? { |addr| addr == URI(DRb.current_server.uri).host } + end + rescue DRb::DRbServerNotFound + ensure + return local_drb || false + end + # rubocop:enable Lint/EnsureReturn + + # @private + def self.trap_interrupt + trap('INT') { handle_interrupt } + end + + # @private + def self.handle_interrupt + if RSpec.world.wants_to_quit + exit!(1) + else + RSpec.world.wants_to_quit = true + STDERR.puts "\nRSpec is shutting down and will print the summary report... Interrupt again to force quit." + end + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/sandbox.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/sandbox.rb new file mode 100644 index 0000000..e7d518c --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/sandbox.rb @@ -0,0 +1,37 @@ +module RSpec + module Core + # A sandbox isolates the enclosed code into an environment that looks 'new' + # meaning globally accessed objects are reset for the duration of the + # sandbox. + # + # @note This module is not normally available. You must require + # `rspec/core/sandbox` to load it. + module Sandbox + # Execute a provided block with RSpec global objects (configuration, + # world) reset. This is used to test RSpec with RSpec. + # + # When calling this the configuration is passed into the provided block. + # Use this to set custom configs for your sandboxed examples. + # + # ``` + # Sandbox.sandboxed do |config| + # config.before(:context) { RSpec.current_example = nil } + # end + # ``` + def self.sandboxed + orig_config = RSpec.configuration + orig_world = RSpec.world + orig_example = RSpec.current_example + + RSpec.configuration = RSpec::Core::Configuration.new + RSpec.world = RSpec::Core::World.new(RSpec.configuration) + + yield RSpec.configuration + ensure + RSpec.configuration = orig_config + RSpec.world = orig_world + RSpec.current_example = orig_example + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/set.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/set.rb new file mode 100644 index 0000000..359199a --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/set.rb @@ -0,0 +1,49 @@ +module RSpec + module Core + # @private + # + # We use this to replace `::Set` so we can have the advantage of + # constant time key lookups for unique arrays but without the + # potential to pollute a developers environment with an extra + # piece of the stdlib. This helps to prevent false positive + # builds. + # + class Set + include Enumerable + + def initialize(array=[]) + @values = {} + merge(array) + end + + def empty? + @values.empty? + end + + def <<(key) + @values[key] = true + self + end + + def delete(key) + @values.delete(key) + end + + def each(&block) + @values.keys.each(&block) + self + end + + def include?(key) + @values.key?(key) + end + + def merge(values) + values.each do |key| + @values[key] = true + end + self + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/shared_context.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/shared_context.rb new file mode 100644 index 0000000..6de7f64 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/shared_context.rb @@ -0,0 +1,55 @@ +module RSpec + module Core + # Exposes {ExampleGroup}-level methods to a module, so you can include that + # module in an {ExampleGroup}. + # + # @example + # + # module LoggedInAsAdmin + # extend RSpec::Core::SharedContext + # before(:example) do + # log_in_as :admin + # end + # end + # + # describe "admin section" do + # include LoggedInAsAdmin + # # ... + # end + module SharedContext + # @private + def included(group) + __shared_context_recordings.each do |recording| + recording.playback_onto(group) + end + end + + # @private + def __shared_context_recordings + @__shared_context_recordings ||= [] + end + + # @private + Recording = Struct.new(:method_name, :args, :block) do + def playback_onto(group) + group.__send__(method_name, *args, &block) + end + end + + # @private + def self.record(methods) + methods.each do |meth| + define_method(meth) do |*args, &block| + __shared_context_recordings << Recording.new(meth, args, block) + end + end + end + + # @private + record [:describe, :context] + Hooks.instance_methods(false) + + MemoizedHelpers::ClassMethods.instance_methods(false) + end + end + # @private + SharedContext = Core::SharedContext +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/shared_example_group.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/shared_example_group.rb new file mode 100644 index 0000000..e1b7b86 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/shared_example_group.rb @@ -0,0 +1,210 @@ +module RSpec + module Core + # Represents some functionality that is shared with multiple example groups. + # The functionality is defined by the provided block, which is lazily + # eval'd when the `SharedExampleGroupModule` instance is included in an example + # group. + class SharedExampleGroupModule < Module + def initialize(description, definition) + @description = description + @definition = definition + end + + # Provides a human-readable representation of this module. + def inspect + "#<#{self.class.name} #{@description.inspect}>" + end + alias to_s inspect + + # Ruby callback for when a module is included in another module is class. + # Our definition evaluates the shared group block in the context of the + # including example group. + def included(klass) + inclusion_line = klass.metadata[:location] + SharedExampleGroupInclusionStackFrame.with_frame(@description, inclusion_line) do + klass.class_exec(&@definition) + end + end + end + + # Shared example groups let you define common context and/or common + # examples that you wish to use in multiple example groups. + # + # When defined, the shared group block is stored for later evaluation. + # It can later be included in an example group either explicitly + # (using `include_examples`, `include_context` or `it_behaves_like`) + # or implicitly (via matching metadata). + # + # Named shared example groups are scoped based on where they are + # defined. Shared groups defined in an example group are available + # for inclusion in that example group or any child example groups, + # but not in any parent or sibling example groups. Shared example + # groups defined at the top level can be included from any example group. + module SharedExampleGroup + # @overload shared_examples(name, &block) + # @param name [String, Symbol, Module] identifer to use when looking up + # this shared group + # @param block The block to be eval'd + # @overload shared_examples(name, metadata, &block) + # @param name [String, Symbol, Module] identifer to use when looking up + # this shared group + # @param metadata [Array, Hash] metadata to attach to this + # group; any example group or example with matching metadata will + # automatically include this shared example group. + # @param block The block to be eval'd + # @overload shared_examples(metadata, &block) + # @param metadata [Array, Hash] metadata to attach to this + # group; any example group or example with matching metadata will + # automatically include this shared example group. + # @param block The block to be eval'd + # + # Stores the block for later use. The block will be evaluated + # in the context of an example group via `include_examples`, + # `include_context`, or `it_behaves_like`. + # + # @example + # shared_examples "auditable" do + # it "stores an audit record on save!" do + # expect { auditable.save! }.to change(Audit, :count).by(1) + # end + # end + # + # describe Account do + # it_behaves_like "auditable" do + # let(:auditable) { Account.new } + # end + # end + # + # @see ExampleGroup.it_behaves_like + # @see ExampleGroup.include_examples + # @see ExampleGroup.include_context + def shared_examples(name, *args, &block) + top_level = self == ExampleGroup + if top_level && RSpec::Support.thread_local_data[:in_example_group] + raise "Creating isolated shared examples from within a context is " \ + "not allowed. Remove `RSpec.` prefix or move this to a " \ + "top-level scope." + end + + RSpec.world.shared_example_group_registry.add(self, name, *args, &block) + end + alias shared_context shared_examples + alias shared_examples_for shared_examples + + # @api private + # + # Shared examples top level DSL. + module TopLevelDSL + # @private + def self.definitions + proc do + def shared_examples(name, *args, &block) + RSpec.world.shared_example_group_registry.add(:main, name, *args, &block) + end + alias shared_context shared_examples + alias shared_examples_for shared_examples + end + end + + # @private + def self.exposed_globally? + @exposed_globally ||= false + end + + # @api private + # + # Adds the top level DSL methods to Module and the top level binding. + def self.expose_globally! + return if exposed_globally? + Core::DSL.change_global_dsl(&definitions) + @exposed_globally = true + end + + # @api private + # + # Removes the top level DSL methods to Module and the top level binding. + def self.remove_globally! + return unless exposed_globally? + + Core::DSL.change_global_dsl do + undef shared_examples + undef shared_context + undef shared_examples_for + end + + @exposed_globally = false + end + end + + # @private + class Registry + def add(context, name, *metadata_args, &block) + ensure_block_has_source_location(block) { CallerFilter.first_non_rspec_line } + + if valid_name?(name) + warn_if_key_taken context, name, block + shared_example_groups[context][name] = block + else + metadata_args.unshift name + end + + return if metadata_args.empty? + RSpec.configuration.include SharedExampleGroupModule.new(name, block), *metadata_args + end + + def find(lookup_contexts, name) + lookup_contexts.each do |context| + found = shared_example_groups[context][name] + return found if found + end + + shared_example_groups[:main][name] + end + + private + + def shared_example_groups + @shared_example_groups ||= Hash.new { |hash, context| hash[context] = {} } + end + + def valid_name?(candidate) + case candidate + when String, Symbol, Module then true + else false + end + end + + def warn_if_key_taken(context, key, new_block) + existing_block = shared_example_groups[context][key] + + return unless existing_block + + RSpec.warn_with <<-WARNING.gsub(/^ +\|/, ''), :call_site => nil + |WARNING: Shared example group '#{key}' has been previously defined at: + | #{formatted_location existing_block} + |...and you are now defining it at: + | #{formatted_location new_block} + |The new definition will overwrite the original one. + WARNING + end + + def formatted_location(block) + block.source_location.join ":" + end + + if Proc.method_defined?(:source_location) + def ensure_block_has_source_location(_block); end + else # for 1.8.7 + # :nocov: + def ensure_block_has_source_location(block) + source_location = yield.split(':') + block.extend Module.new { define_method(:source_location) { source_location } } + end + # :nocov: + end + end + end + end + + instance_exec(&Core::SharedExampleGroup::TopLevelDSL.definitions) +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/shell_escape.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/shell_escape.rb new file mode 100644 index 0000000..46950cc --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/shell_escape.rb @@ -0,0 +1,49 @@ +module RSpec + module Core + # @private + # Deals with the fact that `shellwords` only works on POSIX systems. + module ShellEscape + module_function + + def quote(argument) + "'#{argument.gsub("'", "\\\\'")}'" + end + + if RSpec::Support::OS.windows? + # :nocov: + alias escape quote + # :nocov: + else + require 'shellwords' + + def escape(shell_command) + shell_command.shellescape + end + end + + # Known shells that require quoting: zsh, csh, tcsh. + # + # Feel free to add other shells to this list that are known to + # allow `rspec ./some_spec.rb[1:1]` syntax without quoting the id. + # + # @private + SHELLS_ALLOWING_UNQUOTED_IDS = %w[ bash ksh fish ] + + def conditionally_quote(id) + return id if shell_allows_unquoted_ids? + quote(id) + end + + def shell_allows_unquoted_ids? + # Note: ENV['SHELL'] isn't necessarily the shell the user is currently running. + # According to http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html: + # "This variable shall represent a pathname of the user's preferred command language interpreter." + # + # It's the best we can easily do, though. We err on the side of safety (quoting + # the id when not actually needed) so it's not a big deal if the user is actually + # using a different shell. + SHELLS_ALLOWING_UNQUOTED_IDS.include?(ENV['SHELL'].to_s.split('/').last) + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/test_unit_assertions_adapter.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/test_unit_assertions_adapter.rb new file mode 100644 index 0000000..d84ecb1 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/test_unit_assertions_adapter.rb @@ -0,0 +1,30 @@ +require 'test/unit/assertions' + +module RSpec + module Core + # @private + module TestUnitAssertionsAdapter + include ::Test::Unit::Assertions + + # If using test/unit from Ruby core with Ruby 1.9+, it includes + # MiniTest::Assertions by default. Note the upcasing of 'Test'. + # + # If the test/unit gem is being loaded, it will not include any minitest + # assertions. + # + # Only if Minitest 5.x is included / loaded do we need to worry about + # adding a shim for the new updates. Thus instead of checking on the + # RUBY_VERSION we need to check ancestors. + begin + # MiniTest is 4.x. + # Minitest is 5.x. + if ancestors.include?(::Minitest::Assertions) + require 'rspec/core/minitest_assertions_adapter' + include ::RSpec::Core::MinitestAssertionsAdapter + end + rescue NameError + # No-op. Minitest 5.x was not loaded. + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/version.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/version.rb new file mode 100644 index 0000000..a12db3b --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/version.rb @@ -0,0 +1,9 @@ +module RSpec + module Core + # Version information for RSpec Core. + module Version + # Current version of RSpec Core, in semantic versioning format. + STRING = '3.3.2' + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/warnings.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/warnings.rb new file mode 100644 index 0000000..b880059 --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/warnings.rb @@ -0,0 +1,40 @@ +require "rspec/support/warnings" + +module RSpec + module Core + # @private + module Warnings + # @private + # + # Used internally to print deprecation warnings. + def deprecate(deprecated, data={}) + RSpec.configuration.reporter.deprecation( + { + :deprecated => deprecated, + :call_site => CallerFilter.first_non_rspec_line + }.merge(data) + ) + end + + # @private + # + # Used internally to print deprecation warnings. + def warn_deprecation(message, opts={}) + RSpec.configuration.reporter.deprecation opts.merge(:message => message) + end + + # @private + def warn_with(message, options={}) + if options[:use_spec_location_as_call_site] + message += "." unless message.end_with?(".") + + if RSpec.current_example + message += " Warning generated from spec at `#{RSpec.current_example.location}`." + end + end + + super(message, options) + end + end + end +end diff --git a/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/world.rb b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/world.rb new file mode 100644 index 0000000..ed15daa --- /dev/null +++ b/.bundle/gems/rspec-core-3.3.2/lib/rspec/core/world.rb @@ -0,0 +1,178 @@ +module RSpec + module Core + # @api private + # + # Internal container for global non-configuration data. + class World + # @private + attr_reader :example_groups, :filtered_examples + + # Used internally to determine what to do when a SIGINT is received. + attr_accessor :wants_to_quit + + def initialize(configuration=RSpec.configuration) + @configuration = configuration + @example_groups = [] + @example_group_counts_by_spec_file = Hash.new(0) + @filtered_examples = Hash.new do |hash, group| + hash[group] = filter_manager.prune(group.examples) + end + end + + # @api private + # + # Apply ordering strategy from configuration to example groups. + def ordered_example_groups + ordering_strategy = @configuration.ordering_registry.fetch(:global) + ordering_strategy.order(@example_groups) + end + + # @api private + # + # Reset world to 'scratch' before running suite. + def reset + example_groups.clear + @shared_example_group_registry = nil + end + + # @private + def filter_manager + @configuration.filter_manager + end + + # @api private + # + # Register an example group. + def register(example_group) + example_groups << example_group + @example_group_counts_by_spec_file[example_group.metadata[:file_path]] += 1 + example_group + end + + # @private + def num_example_groups_defined_in(file) + @example_group_counts_by_spec_file[file] + end + + # @private + def shared_example_group_registry + @shared_example_group_registry ||= SharedExampleGroup::Registry.new + end + + # @private + def inclusion_filter + @configuration.inclusion_filter + end + + # @private + def exclusion_filter + @configuration.exclusion_filter + end + + # @api private + # + # Get count of examples to be run. + def example_count(groups=example_groups) + FlatMap.flat_map(groups) { |g| g.descendants }. + inject(0) { |a, e| a + e.filtered_examples.size } + end + + # @private + def all_example_groups + FlatMap.flat_map(example_groups) { |g| g.descendants } + end + + # @private + def all_examples + FlatMap.flat_map(all_example_groups) { |g| g.examples } + end + + # @api private + # + # Find line number of previous declaration. + def preceding_declaration_line(filter_line) + declaration_line_numbers.sort.inject(nil) do |highest_prior_declaration_line, line| + line <= filter_line ? line : highest_prior_declaration_line + end + end + + # @private + def reporter + @configuration.reporter + end + + # @api private + # + # Notify reporter of filters. + def announce_filters + fail_if_config_and_cli_options_invalid + filter_announcements = [] + + announce_inclusion_filter filter_announcements + announce_exclusion_filter filter_announcements + + unless filter_manager.empty? + if filter_announcements.length == 1 + reporter.message("Run options: #{filter_announcements[0]}") + else + reporter.message("Run options:\n #{filter_announcements.join("\n ")}") + end + end + + if @configuration.run_all_when_everything_filtered? && example_count.zero? && !@configuration.only_failures? + reporter.message("#{everything_filtered_message}; ignoring #{inclusion_filter.description}") + filtered_examples.clear + inclusion_filter.clear + end + + return unless example_count.zero? + + example_groups.clear + if filter_manager.empty? + reporter.message("No examples found.") + elsif exclusion_filter.empty? || inclusion_filter.empty? + reporter.message(everything_filtered_message) + end + end + + # @private + def everything_filtered_message + "\nAll examples were filtered out" + end + + # @api private + # + # Add inclusion filters to announcement message. + def announce_inclusion_filter(announcements) + return if inclusion_filter.empty? + + announcements << "include #{inclusion_filter.description}" + end + + # @api private + # + # Add exclusion filters to announcement message. + def announce_exclusion_filter(announcements) + return if exclusion_filter.empty? + + announcements << "exclude #{exclusion_filter.description}" + end + + private + + def declaration_line_numbers + @declaration_line_numbers ||= FlatMap.flat_map(example_groups, &:declaration_line_numbers) + end + + def fail_if_config_and_cli_options_invalid + return unless @configuration.only_failures_but_not_configured? + + reporter.abort_with( + "\nTo use `--only-failures`, you must first set " \ + "`config.example_status_persistence_file_path`.", + 1 # exit code + ) + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/.document b/.bundle/gems/rspec-expectations-3.3.1/.document new file mode 100644 index 0000000..050e204 --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/.document @@ -0,0 +1,5 @@ +lib/**/*.rb +- +README.md +License.txt +Changelog.md diff --git a/.bundle/gems/rspec-expectations-3.3.1/.yardopts b/.bundle/gems/rspec-expectations-3.3.1/.yardopts new file mode 100644 index 0000000..15f63ee --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/.yardopts @@ -0,0 +1,6 @@ +--exclude features +--no-private +--markup markdown +- +Changelog.md +License.txt diff --git a/.bundle/gems/rspec-expectations-3.3.1/Changelog.md b/.bundle/gems/rspec-expectations-3.3.1/Changelog.md new file mode 100644 index 0000000..db84bc4 --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/Changelog.md @@ -0,0 +1,953 @@ +### 3.3.1 / 2015-07-15 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.3.0...v3.3.1) + +Bug Fixes: + +* Fix `be >`, `be <`, etc so that it fails rather than allowing an + argument error to be raised when compared against an object of the + wrong type. This allows it to be used in composed matcher expressions + against heterogeneous objects. (Dennis Günnewig, #809) +* Fix `respond_to` to work properly on target objects + that redefine the `method` method. (unmanbearpig, #821) + +### 3.3.0 / 2015-06-12 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.2.1...v3.3.0) + +Enhancements: + +* Expose `RSpec::Matchers::EnglishPhrasing` to make it easier to write + nice failure messages in custom matchers. (Jared Beck, #736) +* Add `RSpec::Matchers::FailMatchers`, a mixin which provides + `fail`, `fail_with` and `fail_including` matchers for use in + specifying that an expectation fails for use by + extension/plugin authors. (Charlie Rudolph, #729) +* Avoid loading `tempfile` (and its dependencies) unless + it is absolutely needed. (Myron Marston, #735) +* Improve failure output when attempting to use `be_true` or `be_false`. + (Tim Wade, #744) +* Define `RSpec::Matchers#respond_to_missing?` so that + `RSpec::Matchers#respond_to?` and `RSpec::Matchers#method` handle + dynamic predicate matchers. (Andrei Botalov, #751) +* Use custom Time/DateTime/BigDecimal formatting for all matchers + so they are consistently represented in failure messages. + (Gavin Miller, #740) +* Add configuration to turn off warnings about matcher combinations that + may cause false positives. (Jon Rowe, #768) +* Warn when using a bare `raise_error` matcher that you may be subject to + false positives. (Jon Rowe, #768) +* Warn rather than raise when using the`raise_error` matcher in negative + expectations that may be subject to false positives. (Jon Rowe, #775) +* Improve failure message for `include(a, b, c)` so that if `a` and `b` + are included the failure message only mentions `c`. (Chris Arcand, #780) +* Allow `satisfy` matcher to take an optional description argument + that will be used in the `description`, `failure_message` and + `failure_message_when_negated` in place of the undescriptive + "sastify block". (Chris Arcand, #783) +* Add new `aggregate_failures` API that allows multiple independent + expectations to all fail and be listed in the failure output, rather + than the example aborting on the first failure. (Myron Marston, #776) +* Improve `raise_error` matcher so that it can accept a matcher as a single argument + that matches the message. (Time Wade, #782) + +Bug Fixes: + +* Make `contain_exactly` / `match_array` work with strict test doubles + that have not defined `<=>`. (Myron Marston, #758) +* Fix `include` matcher so that it omits the diff when it would + confusingly highlight items that are actually included but are not + an exact match in a line-by-line diff. (Tim Wade, #763) +* Fix `match` matcher so that it does not blow up when matching a string + or regex against another matcher (rather than a string or regex). + (Myron Marston, #772) +* Silence whitespace-only diffs. (Myron Marston, #801) + +### 3.2.1 / 2015-04-06 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.2.0...v3.2.1) + +Bug Fixes: + +* Prevent `Range`s from being enumerated when generating matcher + descriptions. (Jon Rowe, #755) +* Ensure exception messages are compared as strings in the `raise_error` + matcher. (Jon Rowe, #755) + +### 3.2.0 / 2015-02-03 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.1.2...v3.2.0) + +Enhancements: + +* Add `block_arg` method to custom matcher API, which allows you to + access the block passed to a custom matcher, if there is one. + (Mike Dalton, #645) +* Provide more detail in failure message of `yield_control` matcher. + (Jon Rowe, #650) +* Add a shorthand syntax for `chain` in the matcher DSL which assigns values + for use elsewhere, for example `chain :and_smaller_than, :small_value` + creates an `attr_reader` for `small_value` (Tom Stuart, #644) +* Provide a more helpful deprecation message when using the `should` syntax. + (Elia Schito, #663) +* Provide more detail in the `have_attributes` matcher failure message. + (Jon Rowe, #668) +* Make the `have_attributes` matcher diffable. + (Jon Rowe, Alexey Fedorov, #668) +* Add `output(...).to_std(out|err)_from_any_process` as alternatives + to `output(...).to_std(out|err)`. The latter doesn't work when a sub + process writes to the named stream but is much faster. + (Alex Genco, #700) +* Improve compound matchers (created by `and` and `or`) so that diffs + are included in failures when one or more of their matchers + are diffable. (Alexey Fedorov, #713) + +Bug Fixes: + +* Avoid calling `private_methods` from the `be` predicate matcher on + the target object if the object publicly responds to the predicate + method. This avoids a possible error that can occur if the object + raises errors from `private_methods` (which can happen with celluloid + objects). (@chapmajs, #670) +* Make `yield_control` (with no modifier) default to + `at_least(:once)` rather than raising a confusing error + when multiple yields are encountered. + (Myron Marston, #675) +* Fix "instance variable @color not initialized" warning when using + rspec-expectations outside of an rspec-core context. (Myron Marston, #689) +* Fix `start_with` and `end_with` to work properly when checking a + string against an array of strings. (Myron Marston, #690) +* Don't use internally delegated matchers when generating descriptions + for examples without doc strings. (Myron Marston, #692) + +### 3.1.2 / 2014-09-26 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.1.1...v3.1.2) + +Bug Fixes: + +* Fix `define_negated_matcher` so that matchers that support fluent + interfaces continue to be negated after you use the chained method. + (Myron Marston, #656) +* Fix `define_negated_matcher` so that the matchers fail with an + appropriate failure message. (Myron Marston, #659) + +### 3.1.1 / 2014-09-15 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.1.0...v3.1.1) + +Bug Fixes: + +* Fix regression in `all` matcher in 3.1.0 that prevented it from + working on objects that are not `Enumerable` but do implement + `each_with_index` (such as an ActiveRecord proxy). (Jori Hardman, #647) + +### 3.1.0 / 2014-09-04 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.0.4...v3.1.0) + +Enhancements: + +* Add `have_attributes` matcher, that passes if actual's attribute + values match the expected attributes hash: + `Person = Struct.new(:name, :age)` + `person = Person.new("Bob", 32)` + `expect(person).to have_attributes(:name => "Bob", :age => 32)`. + (Adam Farhi, #571) +* Extended compound matcher support to block matchers, for cases like: + `expect { ... }.to change { x }.to(3).and change { y }.to(4)`. (Myron + Marston, #567) +* Include chained methods in custom matcher description and failure message + when new `include_chain_clauses_in_custom_matcher_descriptions` config + option is enabled. (Dan Oved, #600) +* Add `thrice` modifier to `yield_control` matcher as a synonym for + `exactly(3).times`. (Dennis Taylor, #615) +* Add `RSpec::Matchers.define_negated_matcher`, which defines a negated + version of the named matcher. (Adam Farhi, Myron Marston, #618) +* Document and support negation of `contain_exactly`/`match_array`. + (Jon Rowe, #626). + +Bug Fixes: + +* Rename private `LegacyMacherAdapter` constant to `LegacyMatcherAdapter` + to fix typo. (Abdelkader Boudih, #563) +* Fix `all` matcher so that it fails properly (rather than raising a + `NoMethodError`) when matched against a non-enumerable. (Hao Su, #622) + +### 3.0.4 / 2014-08-14 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.0.3...v3.0.4) + +Bug Fixes: + +* Fix `start_with` and `end_with` so that they work properly with + structs. (Myron Marston, #620) +* Fix failure message generation so that structs are printed properly + in failures. Previously failure messages would represent them as + an array. (Myron Marston, #620) +* Fix composable matcher support so that it does not wrongly treat + structs as arrays. (Myron Marston, #620) + +### 3.0.3 / 2014-07-21 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.0.2...v3.0.3) + +Bug Fixes: + +* Fix issue with detection of generic operator matchers so they work + correctly when undefined. (Myron Marston, #597) +* Don't inadvertently define `BasicObject` in 1.8.7. (Chris Griego, #603) +* Fix `include` matcher so that it fails gracefully when matched against + an object that does not respond to `include?`. (Myron Marston, #607) + +### 3.0.2 / 2014-06-19 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.0.1...v3.0.2) + +Bug Fixes: + +* Fix regression in `contain_exactly` (AKA `match_array`) that caused it + to wrongly pass when the expected array was empty. (Myron Marston, #581) +* Provide a better error message when you use the `change(obj, :msg)` + form of the change matcher but forget the message argument. (Alex + Sunderland, #585) +* Make the `contain_exactly` matcher work with arrays that contain hashes in + arbitrary ordering. (Sam Phippen, #578) + +### 3.0.1 / 2014-06-12 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.0.0...v3.0.1) + +Bug Fixes: + +* Add a missing `require` that would cause the `respond_to` matcher to + fail when used in a project where the rest of RSpec (e.g. core and + expecatations) weren't being used. (Myron Marston, #566) +* Structs are no longer treated as arrays when diffed. (Jon Rowe, #576) + +### 3.0.0 / 2014-06-01 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.0.0.rc1...v3.0.0) + +No code changes. Just taking it out of pre-release. + +### 3.0.0.rc1 / 2014-05-18 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.0.0.beta2...v3.0.0.rc1) + +Breaking Changes for 3.0.0: + +* Remove `matcher_execution_context` attribute from DSL-defined + custom matchers. (Myron Marston) +* Remove `RSpec::Matchers::Pretty#_pretty_print`. (Myron Marston) +* Remove `RSpec::Matchers::Pretty#expected_to_sentence`. (Myron Marston) +* Rename `RSpec::Matchers::Configuration` constant to + `RSpec::Expectations::Configuration`. (Myron Marston) +* Prevent `have_xyz` predicate matchers using private methods. + (Adrian Gonzalez) +* Block matchers must now implement `supports_block_expectations?`. + (Myron Marston) +* Stop supporting `require 'rspec-expectations'`. + Use `require 'rspec/expectations'` instead. (Myron Marston) + +Bug Fixes: + +* Fix `NoMethodError` triggered by beta2 when `YARD` was loaded in + the test environment. (Myron Marston) +* Fix `be_xyz` matcher to accept a `do...end` block. (Myron Marston) +* Fix composable matcher failure message generation logic + so that it does not blow up when given `$stdout` or `$stderr`. + (Myron Marston) +* Fix `change` matcher to work properly with `IO` objects. + (Myron Marston) +* Fix `exist` matcher so that it can be used in composed matcher + expressions involving objects that do not implement `exist?` or + `exists?`. (Daniel Fone) +* Fix composable matcher match logic so that it clones matchers + before using them in order to work properly with matchers + that use internal memoization based on a given `actual` value. + (Myron Marston) +* Fix `be_xyz` and `has_xyz` predicate matchers so that they can + be used in composed matcher expressions involving objects that + do not implement the predicate method. (Daniel Fone) + +Enhancements: + +* Document the remaining public APIs. rspec-expectations now has 100% of + the public API documented and will remain that way (as new undocumented + methods will fail the build). (Myron Marston) +* Improve the formatting of BigDecimal objects in `eq` matcher failure + messages. (Daniel Fone) +* Improve the failure message for `be_xyz` predicate matchers so + that it includes the `inspect` output of the receiver. + (Erik Michaels-Ober, Sam Phippen) +* Add `all` matcher, to allow you to specify that a given matcher + matches all elements in a collection: + `expect([1, 3, 5]).to all( be_odd )`. (Adam Farhi) +* Add boolean aliases (`&`/`|`) for compound operators (`and`/`or`). (Adam Farhi) +* Give users a clear error when they wrongly use a value matcher + in a block expectation expression (e.g. `expect { 3 }.to eq(3)`) + or vice versa. (Myron Marston) + +### 3.0.0.beta2 / 2014-02-17 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.0.0.beta1...v3.0.0.beta2) + +Breaking Changes for 3.0.0: + +* Remove deprecated support for accessing the `RSpec` constant using + `Rspec` or `Spec`. (Myron Marston) +* Remove deprecated `RSpec::Expectations.differ=`. (Myron Marston) +* Remove support for deprecated `expect(...).should`. (Myron Marston) +* Explicitly disallow `expect { }.not_to change { }` with `by`, + `by_at_least`, `by_at_most` or `to`. These have never been supported + but did not raise explicit errors. (Myron Marston) +* Provide `===` rather than `==` as an alias of `matches?` for + all matchers. The semantics of `===` are closer to an RSpec + matcher than `==`. (Myron Marston) +* Remove deprecated `RSpec::Matchers::OperatorMatcher` constant. + (Myron Marston) +* Make `RSpec::Expectations::ExpectationNotMetError` subclass + `Exception` rather than `StandardError` so they can bypass + a bare `rescue` in end-user code (e.g. when an expectation is + set from within a rspec-mocks stub implementation). (Myron Marston) +* Remove Test::Unit and Minitest 4.x integration. (Myron Marston) + +Enhancements: + +* Simplify the failure message of the `be` matcher when matching against: + `true`, `false` and `nil`. (Sam Phippen) +* Update matcher protocol and custom matcher DSL to better align + with the newer `expect` syntax. If you want your matchers to + maintain compatibility with multiple versions of RSpec, you can + alias the new names to the old. (Myron Marston) + * `failure_message_for_should` => `failure_message` + * `failure_message_for_should_not` => `failure_message_when_negated` + * `match_for_should` => `match` + * `match_for_should_not` => `match_when_negated` +* Improve generated descriptions from `change` matcher. (Myron Marston) +* Add support for compound matcher expressions using `and` and `or`. + Simply chain them off of any existing matcher to create an expression + like `expect(alphabet).to start_with("a").and end_with("z")`. + (Eloy Espinaco) +* Add `contain_exactly` as a less ambiguous version of `match_array`. + Note that it expects the expected array to be splatted as + individual args: `expect(array).to contain_exactly(1, 2)` is + the same as `expect(array).to match_array([1, 2])`. (Myron Marston) +* Update `contain_exactly`/`match_array` so that it can match against + other non-array collections (such as a `Set`). (Myron Marston) +* Update built-in matchers so that they can accept matchers as arguments + to allow you to compose matchers in arbitrary ways. (Myron Marston) +* Add `RSpec::Matchers::Composable` mixin that can be used to make + a custom matcher composable as well. Note that custom matchers + defined via `RSpec::Matchers.define` already have this. (Myron + Marston) +* Define noun-phrase aliases for built-in matchers, which can be + used when creating composed matcher expressions that read better + and provide better failure messages. (Myron Marston) +* Add `RSpec::Matchers.alias_matcher` so users can define their own + matcher aliases. The `description` of the matcher will reflect the + alternate matcher name. (Myron Marston) +* Add explicit `be_between` matcher. `be_between` has worked for a + long time as a dynamic predicate matcher, but the failure message + was suboptimal. The new matcher provides a much better failure + message. (Erik Michaels-Ober) +* Enhance the `be_between` matcher to allow for `inclusive` or `exclusive` + comparison (e.g. inclusive of min/max or exclusive of min/max). + (Pedro Gimenez) +* Make failure message for `not_to be #{operator}` less confusing by + only saying it's confusing when comparison operators are used. + (Prathamesh Sonpatki) +* Improve failure message of `eq` matcher when `Time` or `DateTime` + objects are used so that the full sub-second precision is included. + (Thomas Holmes, Jeff Wallace) +* Add `output` matcher for expecting that a block outputs `to_stdout` + or `to_stderr`. (Luca Pette, Matthias Günther) +* Forward a provided block on to the `has_xyz?` method call when + the `have_xyz` matcher is used. (Damian Galarza) +* Provide integration with Minitest 5.x. Require + `rspec/expectations/minitest_integration` after loading minitest + to use rspec-expectations with minitest. (Myron Marston) + +Bug Fixes: + +* Fix wrong matcher descriptions with falsey expected value (yujinakayama) +* Fix `expect { }.not_to change { }.from(x)` so that the matcher only + passes if the starting value is `x`. (Tyler Rick, Myron Marston) +* Fix hash diffing, so that it colorizes properly and doesn't consider trailing + commas when performing the diff. (Jared Norman) +* Fix built-in matchers to fail normally rather than raising + `ArgumentError` when given an object of the wrong type to match + against, so that they work well in composite matcher expressions like + `expect([1.51, "foo"]).to include(a_string_matching(/foo/), a_value_within(0.1).of(1.5))`. + (Myron Marston) + +Deprecations: + +* Retain support for RSpec 2 matcher protocol (e.g. for matchers + in 3rd party extension gems like `shoulda`), but it will print + a deprecation warning. (Myron Marston) + +### 3.0.0.beta1 / 2013-11-07 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.99.2...v3.0.0.beta1) + +Breaking Changes for 3.0.0: + +* Remove explicit support for 1.8.6. (Jon Rowe) +* Remove the deprecated `be_close` matcher, preferring `be_within` instead. + (Sam Phippen) +* Remove the deprecated `have`, `have_at_least` and `have_at_most` matchers. + You can continue using those matchers through https://github.com/rspec/rspec-collection_matchers, + or you can rewrite your expectations with something like + `expect(your_object.size).to eq(num)`. (Hugo Baraúna) +* Rename `be_true` and `be_false` to `be_truthy` and `be_falsey`. (Sam Phippen) +* Make `expect { }.to_not raise_error(SomeSpecificClass, message)`, + `expect { }.to_not raise_error(SomeSpecificClass)` and + `expect { }.to_not raise_error(message)` invalid, since they are prone + to hiding failures. Instead, use `expect { }.to_not raise_error` (with no + args). (Sam Phippen) +* Within `RSpec::Matchers.define` blocks, helper methods made available + either via `def self.helper` or `extend HelperModule` are no longer + available to the `match` block (or any of the others). Instead + `include` your helper module and define the helper method as an + instance method. (Myron Marston) +* Force upgrading Diff::LCS for encoding compatability with diffs. (Jon Rowe) + +Enhancements: + +* Support `do..end` style block with `raise_error` matcher. (Yuji Nakayama) +* Rewrote custom matcher DSL to simplify its implementation and solve a + few issues. (Myron Marston) +* Allow early `return` from within custom matcher DSL blocks. (Myron + Marston) +* The custom matcher DSL's `chain` can now accept a block. (Myron + Marston) +* Support setting an expectation on a `raise_error` matcher via a chained + `with_message` method call. (Sam Phippen) + +Bug Fixes: + +* Allow `include` and `match` matchers to be used from within a + DSL-defined custom matcher's `match` block. (Myron Marston) +* Correct encoding error message on diff failure (Jon Rowe) + +Deprecations: + + * Using the old `:should` syntax without explicitly configuring it is deprecated. + It will continue to work but will emit a deprecation warning in RSpec 3 if + you do not explicitly enable it. (Sam Phippen) + +### 2.99.2 / 2014-07-21 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.99.1...v2.99.2) + +Bug Fixes: + +* Fix regression in `Expectations#method_handle_for` where proxy objects + with method delegated would wrongly not return a method handle. + (Jon Rowe, #594) +* Fix issue with detection of generic operator matchers so they work + correctly when undefined. (Myron Marston, #597) + +### 2.99.1 / 2014-06-19 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.99.0...v2.99.1) + +Bug Fixes: + +* Fix typo in custom matcher `expected` deprecation warning -- it's + `expected_as_array`, not `expected_array`. (Frederick Cheung, #562) + +### 2.99.0 / 2014-06-01 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.99.0.rc1...v2.99.0) + +Enhancements: + +* Special case deprecation message for `errors_on` with `rspec-rails` to be more useful. + (Aaron Kromer) + +### 2.99.0.rc1 / 2014-05-18 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.99.0.beta2...2.99.0.rc1) + +Deprecations: + +* Deprecate `matcher_execution_context` attribute on DSL-defined + custom matchers. (Myron Marston) +* Deprecate `RSpec::Matchers::Pretty#_pretty_print`. (Myron Marston) +* Deprecate `RSpec::Matchers::Pretty#expected_to_sentence`. (Myron Marston) +* Deprecate `RSpec::Matchers::Configuration` in favor of + `RSpec::Expectations::Configuration`. (Myron Marston) +* Deprecate `be_xyz` predicate matcher on an object that doesn't respond to + `xyz?` or `xyzs?`. (Daniel Fone) +* Deprecate `have_xyz` matcher on an object that doesn't respond to `has_xyz?`. + (Daniel Fone) +* Deprecate `have_xyz` matcher on an object that has a private method `has_xyz?`. + (Jon Rowe) +* Issue a deprecation warning when a block expectation expression is + used with a matcher that doesn't explicitly support block expectations + via `supports_block_expectations?`. (Myron Marston) +* Deprecate `require 'rspec-expectations'`. Use + `require 'rspec/expectations'` instead. (Myron Marston) + +### 2.99.0.beta2 / 2014-02-17 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.99.0.beta1...v2.99.0.beta2) + +Deprecations: + +* Deprecate chaining `by`, `by_at_least`, `by_at_most` or `to` off of + `expect { }.not_to change { }`. The docs have always said these are + not supported for the negative form but now they explicitly raise + errors in RSpec 3. (Myron Marston) +* Change the semantics of `expect { }.not_to change { x }.from(y)`. + In RSpec 2.x, this expectation would only fail if `x` started with + the value of `y` and changed. If it started with a different value + and changed, it would pass. In RSpec 3, it will pass only if the + value starts at `y` and it does not change. (Myron Marston) +* Deprecate `matcher == value` as an alias for `matcher.matches?(value)`, + in favor of `matcher === value`. (Myron Marston) +* Deprecate `RSpec::Matchers::OperatorMatcher` in favor of + `RSpec::Matchers::BuiltIn::OperatorMatcher`. (Myron Marston) +* Deprecate auto-integration with Test::Unit and minitest. + Instead, include `RSpec::Matchers` in the appropriate test case + base class yourself. (Myron Marston) +* Deprecate treating `#expected` on a DSL-generated custom matcher + as an array when only 1 argument is passed to the matcher method. + In RSpec 3 it will be the single value in order to make diffs + work properly. (Jon Rowe) + +### 2.99.0.beta1 / 2013-11-07 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.14.4...v2.99.0.beta1) + +Deprecations + +* Deprecate `have`, `have_at_least` and `have_at_most`. You can continue using those + matchers through https://github.com/rspec/rspec-collection_matchers, or + you can rewrite your expectations with something like + `expect(your_object.size).to eq(num)`. (Hugo Baraúna) +* Deprecate `be_xyz` predicate matcher when `xyz?` is a private method. + (Jon Rowe) +* Deprecate `be_true`/`be_false` in favour of `be_truthy`/`be_falsey` + (for Ruby's conditional semantics) or `be true`/`be false` + (for exact equality). (Sam Phippen) +* Deprecate calling helper methods from a custom matcher with the wrong + scope. (Myron Marston) + * `def self.foo` / `extend Helper` can be used to add macro methods + (e.g. methods that call the custom matcher DSL methods), but should + not be used to define helper methods called from within the DSL + blocks. + * `def foo` / `include Helper` is the opposite: it's for helper methods + callable from within a DSL block, but not for defining macros. + * RSpec 2.x allowed helper methods defined either way to be used for + either purpose, but RSpec 3.0 will not. + +### 2.14.5 / 2014-02-01 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.14.4...v2.14.5) + +Bug fixes + +* Fix wrong matcher descriptions with falsey expected value + (yujinakayama) + +### 2.14.4 / 2013-11-06 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.14.3...v2.14.4) + +Bug fixes + +* Make the `match` matcher produce a diff output. (Jon Rowe, Ben Moss) +* Choose encoding for diff's more intelligently, and when all else fails fall + back to default internal encoding with replacing characters. (Jon Rowe) + +### 2.14.3 / 2013-09-22 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.14.2...v2.14.3) + +Bug fixes + +* Fix operator matchers (`should` syntax) when `method` is redefined on target. + (Brandon Turner) +* Fix diffing of hashes with object based keys. (Jon Rowe) +* Fix operator matchers (`should` syntax) when operator is defined via + `method_missing` (Jon Rowe) + +### 2.14.2 / 2013-08-14 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.14.1...v2.14.2) + +Bug fixes + +* Fix `be_` matcher to not support operator chaining like the + `be` matcher does (e.g. `be == 5`). This led to some odd behaviors + since `be_ == anything` returned a `BeComparedTo` matcher + and was thus always truthy. This was a consequence of the implementation + (e.g. subclassing the basic `Be` matcher) and was not intended behavior. + (Myron Marston). +* Fix `change` matcher to compare using `==` in addition to `===`. This + is important for an expression like: + `expect {}.to change { a.class }.from(ClassA).to(ClassB)` because + `SomeClass === SomeClass` returns false. (Myron Marston) + +### 2.14.1 / 2013-08-08 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.14.0...2.14.1) + +Bug fixes + +* Ensure diff output uses the same encoding as the encoding of + the string being diff'd to prevent `Encoding::UndefinedConversionError` + errors (Jon Rowe). + +### 2.14.0 / 2013-07-06 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.14.0.rc1...v2.14.0) + +Bug fixes + +* Values that are not matchers use `#inspect`, rather than `#description` for + documentation output (Andy Lindeman, Sam Phippen). +* Make `expect(a).to be_within(x).percent_of(y)` work with negative y + (Katsuhiko Nishimra). +* Make the `be_predicate` matcher work as expected used with `expect{...}.to + change...` (Sam Phippen). + +### 2.14.0.rc1 / 2013-05-27 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.13.0...v2.14.0.rc1) + +Enhancements + +* Enhance `yield_control` so that you can specify an exact or relative + number of times: `expect { }.to yield_control.exactly(3).times`, + `expect { }.to yield_control.at_least(2).times`, etc (Bartek + Borkowski). +* Make the differ that is used when an expectation fails better handle arrays + by splitting each element of the array onto its own line. (Sam Phippen) +* Accept duck-typed strings that respond to `:to_str` as expectation messages. + (Toby Ovod-Everett) + +Bug fixes + +* Fix differ to not raise errors when dealing with differently-encoded + strings (Jon Rowe). +* Fix `expect(something).to be_within(x).percent_of(y)` where x and y are both + integers (Sam Phippen). +* Fix `have` matcher to handle the fact that on ruby 2.0, + `Enumerator#size` may return nil (Kenta Murata). +* Fix `expect { raise s }.to raise_error(s)` where s is an error instance + on ruby 2.0 (Sam Phippen). +* Fix `expect(object).to raise_error` passing. This now warns the user and + fails the spec (tomykaira). + +Deprecations + +* Deprecate `expect { }.not_to raise_error(SpecificErrorClass)` or + `expect { }.not_to raise_error("some specific message")`. Using + these was prone to hiding failures as they would allow _any other + error_ to pass. (Sam Phippen and David Chelimsky) + +### 2.13.0 / 2013-02-23 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.12.1...v2.13.0) + +Enhancements + +* Add support for percent deltas to `be_within` matcher: + `expect(value).to be_within(10).percent_of(expected)` + (Myron Marston). +* Add support to `include` matcher to allow it to be given a list + of matchers as the expecteds to match against (Luke Redpath). + +Bug fixes + +* Fix `change` matcher so that it dups strings in order to handle + mutated strings (Myron Marston). +* Fix `should be =~ /some regex/` / `expect(...).to be =~ /some regex/`. + Previously, these either failed with a confusing `undefined method + matches?' for false:FalseClass` error or were no-ops that didn't + actually verify anything (Myron Marston). +* Add compatibility for diff-lcs 1.2 and relax the version + constraint (Peter Goldstein). +* Fix DSL-generated matchers to allow multiple instances of the + same matcher in the same example to have different description + and failure messages based on the expected value (Myron Marston). +* Prevent `undefined method #split for Array` error when dumping + the diff of an array of multiline strings (Myron Marston). +* Don't blow up when comparing strings that are in an encoding + that is not ASCII compatible (Myron Marston). +* Remove confusing "Check the implementation of #==" message + printed for empty diffs (Myron Marston). + +### 2.12.1 / 2012-12-15 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.12.0...v2.12.1) + +Bug fixes + +* Improve the failure message for an expression like + `{}.should =~ {}`. (Myron Marston and Andy Lindeman) +* Provide a `match_regex` alias so that custom matchers + built using the matcher DSL can use it (since `match` + is a different method in that context). + (Steven Harman) + +### 2.12.0 / 2012-11-12 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.11.3...v2.12.0) + +Enhancements + +* Colorize diffs if the `--color` option is configured. (Alex Coplan) +* Include backtraces in unexpected errors handled by `raise_error` + matcher (Myron Marston) +* Print a warning when users accidentally pass a non-string argument + as an expectation message (Sam Phippen) +* `=~` and `match_array` matchers output a more useful error message when + the actual value is not an array (or an object that responds to `#to_ary`) + (Sam Phippen) + +Bug fixes + +* Fix `include` matcher so that `expect({}).to include(:a => nil)` + fails as it should (Sam Phippen). +* Fix `be_an_instance_of` matcher so that `Class#to_s` is used in the + description rather than `Class#inspect`, since some classes (like + `ActiveRecord::Base`) define a long, verbose `#inspect`. + (Tom Stuart) + +### 2.11.3 / 2012-09-04 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.11.2...v2.11.3) + +Bug fixes + +* Fix (and deprecate) `expect { }.should` syntax so that it works even + though it was never a documented or intended syntax. It worked as a + consequence of the implementation of `expect` in RSpec 2.10 and + earlier. (Myron Marston) +* Ensure #== is defined on built in matchers so that they can be composed. + For example: + + expect { + user.emailed! + }.to change { user.last_emailed_at }.to be_within(1.second).of(Time.zone.now) + +### 2.11.2 / 2012-07-25 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.11.1...v2.11.2) + +Bug fixes + +* Define `should` and `should_not` on `Object` rather than `BasicObject` + on MacRuby. On MacRuby, `BasicObject` is defined but is not the root + of the object hierarchy. (Gabriel Gilder) + +### 2.11.1 / 2012-07-08 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.11.0...v2.11.1) + +Bug fixes + +* Constrain `actual` in `be_within` matcher to values that respond to `-` instead + of requiring a specific type. + * `Time`, for example, is a legit alternative. + +### 2.11.0 / 2012-07-07 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.10.0...v2.11.0) + +Enhancements + +* Expand `expect` syntax so that it supports expections on bare values + in addition to blocks (Myron Marston). +* Add configuration options to control available expectation syntaxes + (Myron Marston): + * `RSpec.configuration.expect_with(:rspec) { |c| c.syntax = :expect }` + * `RSpec.configuration.expect_with(:rspec) { |c| c.syntax = :should }` + * `RSpec.configuration.expect_with(:rspec) { |c| c.syntax = [:should, :expect] }` + * `RSpec.configuration.add_should_and_should_not_to Delegator` + +Bug fixes + +* Allow only `Numeric` values to be the "actual" in the `be_within` matcher. + This prevents confusing error messages. (Su Zhang @zhangsu) +* Define `should` and `should_not` on `BasicObject` rather than `Kernel` + on 1.9. This makes `should` and `should_not` work properly with + `BasicObject`-subclassed proxy objects like `Delegator`. (Myron + Marston) + +### 2.10.0 / 2012-05-03 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.9.1...v2.10.0) + +Enhancements + +* Add new `start_with` and `end_with` matchers (Jeremy Wadsack) +* Add new matchers for specifying yields (Myron Marston): + * `expect {...}.to yield_control` + * `expect {...}.to yield_with_args(1, 2, 3)` + * `expect {...}.to yield_with_no_args` + * `expect {...}.to yield_successive_args(1, 2, 3)` +* `match_unless_raises` takes multiple exception args + +Bug fixes + +* Fix `be_within` matcher to be inclusive of delta. +* Fix message-specific specs to pass on Rubinius (John Firebaugh) + +### 2.9.1 / 2012-04-03 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.9.0...v2.9.1) + +Bug fixes + +* Provide a helpful message if the diff between two objects is empty. +* Fix bug diffing single strings with multiline strings. +* Fix for error with using custom matchers inside other custom matchers + (mirasrael) +* Fix using execution context methods in nested DSL matchers (mirasrael) + +### 2.9.0 / 2012-03-17 +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.8.0...v2.9.0) + +Enhancements + +* Move built-in matcher classes to RSpec::Matchers::BuiltIn to reduce pollution + of RSpec::Matchers (which is included in every example). +* Autoload files with matcher classes to improve load time. + +Bug fixes + +* Align `respond_to?` and `method_missing` in DSL-defined matchers. +* Clear out user-defined instance variables between invocations of DSL-defined + matchers. +* Dup the instance of a DSL generated matcher so its state is not changed by + subsequent invocations. +* Treat expected args consistently across positive and negative expectations + (thanks to Ralf Kistner for the heads up) + +### 2.8.0 / 2012-01-04 + +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.8.0.rc2...v2.8.0) + +Enhancements + +* Better diff output for Hash (Philippe Creux) +* Eliminate Ruby warnings (Olek Janiszewski) + +### 2.8.0.rc2 / 2011-12-19 + +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.8.0.rc1...v2.8.0.rc2) + +No changes for this release. Just releasing with the other rspec gems. + +### 2.8.0.rc1 / 2011-11-06 + +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.7.0...v2.8.0.rc1) + +Enhancements + +* Use classes for the built-in matchers (they're faster). +* Eliminate Ruby warnings (Matijs van Zuijlen) + +### 2.7.0 / 2011-10-16 + +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.6.0...v2.7.0) + +Enhancements + +* `HaveMatcher` converts argument using `to_i` (Alex Bepple & Pat Maddox) +* Improved failure message for the `have_xxx` matcher (Myron Marston) +* `HaveMatcher` supports `count` (Matthew Bellantoni) +* Change matcher dups `Enumerable` before the action, supporting custom + `Enumerable` types like `CollectionProxy` in Rails (David Chelimsky) + +Bug fixes + +* Fix typo in `have(n).xyz` documentation (Jean Boussier) +* fix `safe_sort` for ruby 1.9.2 (`Kernel` now defines `<=>` for Object) (Peter + van Hardenberg) + +### 2.6.0 / 2011-05-12 + +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.5.0...v2.6.0) + +Enhancements + +* `change` matcher accepts regexps (Robert Davis) +* better descriptions for `have_xxx` matchers (Magnus Bergmark) +* `range.should cover(*values)` (Anders Furseth) + +Bug fixes + +* Removed non-ascii characters that were choking rcov (Geoffrey Byers) +* change matcher dups arrays and hashes so their before/after states can be + compared correctly. +* Fix the order of inclusion of RSpec::Matchers in Test::Unit::TestCase and + MiniTest::Unit::TestCase to prevent a SystemStackError (Myron Marston) + +### 2.5.0 / 2011-02-05 + +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.4.0...v2.5.0) + +Enhancements + +* `should exist` works with `exist?` or `exists?` (Myron Marston) +* `expect { ... }.not_to do_something` (in addition to `to_not`) + +Documentation + +* improved docs for raise_error matcher (James Almond) + +### 2.4.0 / 2011-01-02 + +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.3.0...v2.4.0) + +No functional changes in this release, which was made to align with the +rspec-core-2.4.0 release. + +Enhancements + +* improved RDoc for change matcher (Jo Liss) + +### 2.3.0 / 2010-12-12 + +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.2.1...v2.3.0) + +Enhancements + +* diff strings when include matcher fails (Mike Sassak) + +### 2.2.0 / 2010-11-28 + +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.1.0...v2.2.0) + +### 2.1.0 / 2010-11-07 + +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.0.1...v2.1.0) + +Enhancements + +* `be_within(delta).of(expected)` matcher (Myron Marston) +* Lots of new Cucumber features (Myron Marston) +* Raise error if you try `should != expected` on Ruby-1.9 (Myron Marston) +* Improved failure messages from `throw_symbol` (Myron Marston) + +Bug fixes + +* Eliminate hard dependency on `RSpec::Core` (Myron Marston) +* `have_matcher` - use pluralize only when ActiveSupport inflections are indeed + defined (Josep M Bach) +* throw_symbol matcher no longer swallows exceptions (Myron Marston) +* fix matcher chaining to avoid name collisions (Myron Marston) + +### 2.0.0 / 2010-10-10 + +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.0.0.rc...v2.0.0) + +Enhancements + +* Add match_for_should_not method to matcher DSL (Myron Marston) + +Bug fixes + +* `respond_to` matcher works correctly with `should_not` with multiple methods + (Myron Marston) +* `include` matcher works correctly with `should_not` with multiple values + (Myron Marston) + +### 2.0.0.rc / 2010-10-05 + +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.0.0.beta.22...v2.0.0.rc) + +Enhancements + +* `require 'rspec/expectations'` in a T::U or MiniUnit suite (Josep M. Bach) + +Bug fixes + +* change by 0 passes/fails correctly (Len Smith) +* Add description to satisfy matcher + +### 2.0.0.beta.22 / 2010-09-12 + +[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.0.0.beta.20...v2.0.0.beta.22) + +Enhancements + +* diffing improvements + * diff multiline strings + * don't diff single line strings + * don't diff numbers (silly) + * diff regexp + multiline string + +Bug fixes + * `should[_not]` change now handles boolean values correctly diff --git a/.bundle/gems/rspec-expectations-3.3.1/License.txt b/.bundle/gems/rspec-expectations-3.3.1/License.txt new file mode 100644 index 0000000..91cfc94 --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/License.txt @@ -0,0 +1,24 @@ +(The MIT License) + +Copyright (c) 2012 David Chelimsky, Myron Marston +Copyright (c) 2006 David Chelimsky, The RSpec Development Team +Copyright (c) 2005 Steven Baker + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/.bundle/gems/rspec-expectations-3.3.1/README.md b/.bundle/gems/rspec-expectations-3.3.1/README.md new file mode 100644 index 0000000..d6744ef --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/README.md @@ -0,0 +1,289 @@ +# RSpec Expectations [![Build Status](https://secure.travis-ci.org/rspec/rspec-expectations.svg?branch=master)](http://travis-ci.org/rspec/rspec-expectations) [![Code Climate](https://codeclimate.com/github/rspec/rspec-expectations.svg)](https://codeclimate.com/github/rspec/rspec-expectations) + +RSpec::Expectations lets you express expected outcomes on an object in an +example. + + expect(account.balance).to eq(Money.new(37.42, :USD)) + +## Install + +If you want to use rspec-expectations with rspec, just install the rspec gem +and RubyGems will also install rspec-expectations for you (along with +rspec-core and rspec-mocks): + + gem install rspec + +Want to run against the `master` branch? You'll need to include the dependent +RSpec repos as well. Add the following to your `Gemfile`: + +```ruby +%w[rspec-core rspec-expectations rspec-mocks rspec-support].each do |lib| + gem lib, :git => "git://github.com/rspec/#{lib}.git", :branch => 'master' +end +``` + +If you want to use rspec-expectations with another tool, like Test::Unit, +Minitest, or Cucumber, you can install it directly: + + gem install rspec-expectations + +## Basic usage + +Here's an example using rspec-core: + +```ruby +RSpec.describe Order do + it "sums the prices of the items in its line items" do + order = Order.new + order.add_entry(LineItem.new(:item => Item.new( + :price => Money.new(1.11, :USD) + ))) + order.add_entry(LineItem.new(:item => Item.new( + :price => Money.new(2.22, :USD), + :quantity => 2 + ))) + expect(order.total).to eq(Money.new(5.55, :USD)) + end +end +``` + +The `describe` and `it` methods come from rspec-core. The `Order`, `LineItem`, `Item` and `Money` classes would be from _your_ code. The last line of the example +expresses an expected outcome. If `order.total == Money.new(5.55, :USD)`, then +the example passes. If not, it fails with a message like: + + expected: # + got: # + +## Built-in matchers + +### Equivalence + +```ruby +expect(actual).to eq(expected) # passes if actual == expected +expect(actual).to eql(expected) # passes if actual.eql?(expected) +expect(actual).not_to eql(not_expected) # passes if not(actual.eql?(expected)) +``` + +Note: The new `expect` syntax no longer supports the `==` matcher. + +### Identity + +```ruby +expect(actual).to be(expected) # passes if actual.equal?(expected) +expect(actual).to equal(expected) # passes if actual.equal?(expected) +``` + +### Comparisons + +```ruby +expect(actual).to be > expected +expect(actual).to be >= expected +expect(actual).to be <= expected +expect(actual).to be < expected +expect(actual).to be_within(delta).of(expected) +``` + +### Regular expressions + +```ruby +expect(actual).to match(/expression/) +``` + +Note: The new `expect` syntax no longer supports the `=~` matcher. + +### Types/classes + +```ruby +expect(actual).to be_an_instance_of(expected) # passes if actual.class == expected +expect(actual).to be_a(expected) # passes if actual.kind_of?(expected) +expect(actual).to be_an(expected) # an alias for be_a +expect(actual).to be_a_kind_of(expected) # another alias +``` + +### Truthiness + +```ruby +expect(actual).to be_truthy # passes if actual is truthy (not nil or false) +expect(actual).to be true # passes if actual == true +expect(actual).to be_falsy # passes if actual is falsy (nil or false) +expect(actual).to be false # passes if actual == false +expect(actual).to be_nil # passes if actual is nil +expect(actual).to_not be_nil # passes if actual is not nil +``` + +### Expecting errors + +```ruby +expect { ... }.to raise_error +expect { ... }.to raise_error(ErrorClass) +expect { ... }.to raise_error("message") +expect { ... }.to raise_error(ErrorClass, "message") +``` + +### Expecting throws + +```ruby +expect { ... }.to throw_symbol +expect { ... }.to throw_symbol(:symbol) +expect { ... }.to throw_symbol(:symbol, 'value') +``` + +### Yielding + +```ruby +expect { |b| 5.tap(&b) }.to yield_control # passes regardless of yielded args + +expect { |b| yield_if_true(true, &b) }.to yield_with_no_args # passes only if no args are yielded + +expect { |b| 5.tap(&b) }.to yield_with_args(5) +expect { |b| 5.tap(&b) }.to yield_with_args(Fixnum) +expect { |b| "a string".tap(&b) }.to yield_with_args(/str/) + +expect { |b| [1, 2, 3].each(&b) }.to yield_successive_args(1, 2, 3) +expect { |b| { :a => 1, :b => 2 }.each(&b) }.to yield_successive_args([:a, 1], [:b, 2]) +``` + +### Predicate matchers + +```ruby +expect(actual).to be_xxx # passes if actual.xxx? +expect(actual).to have_xxx(:arg) # passes if actual.has_xxx?(:arg) +``` + +### Ranges (Ruby >= 1.9 only) + +```ruby +expect(1..10).to cover(3) +``` + +### Collection membership + +```ruby +expect(actual).to include(expected) +expect(actual).to start_with(expected) +expect(actual).to end_with(expected) + +expect(actual).to contain_exactly(individual, items) +# ...which is the same as: +expect(actual).to match_array(expected_array) +``` + +#### Examples + +```ruby +expect([1, 2, 3]).to include(1) +expect([1, 2, 3]).to include(1, 2) +expect([1, 2, 3]).to start_with(1) +expect([1, 2, 3]).to start_with(1, 2) +expect([1, 2, 3]).to end_with(3) +expect([1, 2, 3]).to end_with(2, 3) +expect({:a => 'b'}).to include(:a => 'b') +expect("this string").to include("is str") +expect("this string").to start_with("this") +expect("this string").to end_with("ring") +expect([1, 2, 3]).to contain_exactly(2, 3, 1) +expect([1, 2, 3]).to match_array([3, 2, 1]) +``` + +## `should` syntax + +In addition to the `expect` syntax, rspec-expectations continues to support the +`should` syntax: + +```ruby +actual.should eq expected +actual.should be > 3 +[1, 2, 3].should_not include 4 +``` + +See [detailed information on the `should` syntax and its usage.](https://github.com/rspec/rspec-expectations/blob/master/Should.md) + +## Compound Matcher Expressions + +You can also create compound matcher expressions using `and` or `or`: + +``` ruby +expect(alphabet).to start_with("a").and end_with("z") +expect(stoplight.color).to eq("red").or eq("green").or eq("yellow") +``` + +## Composing Matchers + +Many of the built-in matchers are designed to take matchers as +arguments, to allow you to flexibly specify only the essential +aspects of an object or data structure. In addition, all of the +built-in matchers have one or more aliases that provide better +phrasing for when they are used as arguments to another matcher. + +### Examples + +```ruby +expect { k += 1.05 }.to change { k }.by( a_value_within(0.1).of(1.0) ) + +expect { s = "barn" }.to change { s } + .from( a_string_matching(/foo/) ) + .to( a_string_matching(/bar/) ) + +expect(["barn", 2.45]).to contain_exactly( + a_value_within(0.1).of(2.5), + a_string_starting_with("bar") +) + +expect(["barn", "food", 2.45]).to end_with( + a_string_matching("foo"), + a_value > 2 +) + +expect(["barn", 2.45]).to include( a_string_starting_with("bar") ) + +expect(:a => "food", :b => "good").to include(:a => a_string_matching(/foo/)) + +hash = { + :a => { + :b => ["foo", 5], + :c => { :d => 2.05 } + } +} + +expect(hash).to match( + :a => { + :b => a_collection_containing_exactly( + a_string_starting_with("f"), + an_instance_of(Fixnum) + ), + :c => { :d => (a_value < 3) } + } +) + +expect { |probe| + [1, 2, 3].each(&probe) +}.to yield_successive_args( a_value < 2, 2, a_value > 2 ) +``` + +## Usage outside rspec-core + +You always need to load `rspec/expectations` even if you only want to use one part of the library: + +```ruby +require 'rspec/expectations' +``` + +Then simply include `RSpec::Matchers` in any class: + +```ruby +class MyClass + include RSpec::Matchers + + def do_something(arg) + expect(arg).to be > 0 + # do other stuff + end +end +``` + +## Also see + +* [http://github.com/rspec/rspec](http://github.com/rspec/rspec) +* [http://github.com/rspec/rspec-core](http://github.com/rspec/rspec-core) +* [http://github.com/rspec/rspec-mocks](http://github.com/rspec/rspec-mocks) +* [http://github.com/rspec/rspec-collection_matchers](https://github.com/rspec/rspec-collection_matchers) diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations.rb new file mode 100644 index 0000000..a54f5b4 --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations.rb @@ -0,0 +1,81 @@ +require 'rspec/support' +RSpec::Support.require_rspec_support "caller_filter" +RSpec::Support.require_rspec_support "warnings" +RSpec::Support.require_rspec_support "object_formatter" + +require 'rspec/matchers' + +RSpec::Support.define_optimized_require_for_rspec(:expectations) { |f| require_relative(f) } + +%w[ + expectation_target + configuration + fail_with + handler + version +].each { |file| RSpec::Support.require_rspec_expectations(file) } + +module RSpec + # RSpec::Expectations provides a simple, readable API to express + # the expected outcomes in a code example. To express an expected + # outcome, wrap an object or block in `expect`, call `to` or `to_not` + # (aliased as `not_to`) and pass it a matcher object: + # + # expect(order.total).to eq(Money.new(5.55, :USD)) + # expect(list).to include(user) + # expect(message).not_to match(/foo/) + # expect { do_something }.to raise_error + # + # The last form (the block form) is needed to match against ruby constructs + # that are not objects, but can only be observed when executing a block + # of code. This includes raising errors, throwing symbols, yielding, + # and changing values. + # + # When `expect(...).to` is invoked with a matcher, it turns around + # and calls `matcher.matches?()`. For example, + # in the expression: + # + # expect(order.total).to eq(Money.new(5.55, :USD)) + # + # ...`eq(Money.new(5.55, :USD))` returns a matcher object, and it results + # in the equivalent of `eq.matches?(order.total)`. If `matches?` returns + # `true`, the expectation is met and execution continues. If `false`, then + # the spec fails with the message returned by `eq.failure_message`. + # + # Given the expression: + # + # expect(order.entries).not_to include(entry) + # + # ...the `not_to` method (also available as `to_not`) invokes the equivalent of + # `include.matches?(order.entries)`, but it interprets `false` as success, and + # `true` as a failure, using the message generated by + # `include.failure_message_when_negated`. + # + # rspec-expectations ships with a standard set of useful matchers, and writing + # your own matchers is quite simple. + # + # See [RSpec::Matchers](../RSpec/Matchers) for more information about the + # built-in matchers that ship with rspec-expectations, and how to write your + # own custom matchers. + module Expectations + # Exception raised when an expectation fails. + # + # @note We subclass Exception so that in a stub implementation if + # the user sets an expectation, it can't be caught in their + # code by a bare `rescue`. + # @api public + class ExpectationNotMetError < Exception + end + + # Exception raised from `aggregate_failures` when multiple expectations fail. + # + # @note The constant is defined here but the extensive logic of this class + # is lazily defined when `FailureAggregator` is autoloaded, since we do + # not need to waste time defining that functionality unless + # `aggregate_failures` is used. + class MultipleExpectationsNotMetError < ExpectationNotMetError + end + + autoload :FailureAggregator, "rspec/expectations/failure_aggregator" + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/configuration.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/configuration.rb new file mode 100644 index 0000000..f0f0636 --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/configuration.rb @@ -0,0 +1,164 @@ +RSpec::Support.require_rspec_expectations "syntax" + +module RSpec + module Expectations + # Provides configuration options for rspec-expectations. + # If you are using rspec-core, you can access this via a + # block passed to `RSpec::Core::Configuration#expect_with`. + # Otherwise, you can access it via RSpec::Expectations.configuration. + # + # @example + # RSpec.configure do |rspec| + # rspec.expect_with :rspec do |c| + # # c is the config object + # end + # end + # + # # or + # + # RSpec::Expectations.configuration + class Configuration + def initialize + @warn_about_potential_false_positives = true + end + + # Configures the supported syntax. + # @param [Array, Symbol] values the syntaxes to enable + # @example + # RSpec.configure do |rspec| + # rspec.expect_with :rspec do |c| + # c.syntax = :should + # # or + # c.syntax = :expect + # # or + # c.syntax = [:should, :expect] + # end + # end + def syntax=(values) + if Array(values).include?(:expect) + Expectations::Syntax.enable_expect + else + Expectations::Syntax.disable_expect + end + + if Array(values).include?(:should) + Expectations::Syntax.enable_should + else + Expectations::Syntax.disable_should + end + end + + # The list of configured syntaxes. + # @return [Array] the list of configured syntaxes. + # @example + # unless RSpec::Matchers.configuration.syntax.include?(:expect) + # raise "this RSpec extension gem requires the rspec-expectations `:expect` syntax" + # end + def syntax + syntaxes = [] + syntaxes << :should if Expectations::Syntax.should_enabled? + syntaxes << :expect if Expectations::Syntax.expect_enabled? + syntaxes + end + + if ::RSpec.respond_to?(:configuration) + def color? + ::RSpec.configuration.color_enabled? + end + else + # Indicates whether or not diffs should be colored. + # Delegates to rspec-core's color option if rspec-core + # is loaded; otherwise you can set it here. + attr_writer :color + + # Indicates whether or not diffs should be colored. + # Delegates to rspec-core's color option if rspec-core + # is loaded; otherwise you can set it here. + def color? + defined?(@color) && @color + end + end + + # Adds `should` and `should_not` to the given classes + # or modules. This can be used to ensure `should` works + # properly on things like proxy objects (particular + # `Delegator`-subclassed objects on 1.8). + # + # @param [Array] modules the list of classes or modules + # to add `should` and `should_not` to. + def add_should_and_should_not_to(*modules) + modules.each do |mod| + Expectations::Syntax.enable_should(mod) + end + end + + # Sets or gets the backtrace formatter. The backtrace formatter should + # implement `#format_backtrace(Array)`. This is used + # to format backtraces of errors handled by the `raise_error` + # matcher. + # + # If you are using rspec-core, rspec-core's backtrace formatting + # will be used (including respecting the presence or absence of + # the `--backtrace` option). + # + # @!attribute [rw] backtrace_formatter + attr_writer :backtrace_formatter + def backtrace_formatter + @backtrace_formatter ||= if defined?(::RSpec.configuration.backtrace_formatter) + ::RSpec.configuration.backtrace_formatter + else + NullBacktraceFormatter + end + end + + # Sets if custom matcher descriptions and failure messages + # should include clauses from methods defined using `chain`. + # @param value [Boolean] + attr_writer :include_chain_clauses_in_custom_matcher_descriptions + + # Indicates whether or not custom matcher descriptions and failure messages + # should include clauses from methods defined using `chain`. It is + # false by default for backwards compatibility. + def include_chain_clauses_in_custom_matcher_descriptions? + @include_chain_clauses_in_custom_matcher_descriptions ||= false + end + + # @private + def reset_syntaxes_to_default + self.syntax = [:should, :expect] + RSpec::Expectations::Syntax.warn_about_should! + end + + # @api private + # Null implementation of a backtrace formatter used by default + # when rspec-core is not loaded. Does no filtering. + NullBacktraceFormatter = Module.new do + def self.format_backtrace(backtrace) + backtrace + end + end + + # Configures whether RSpec will warn about matcher use which will + # potentially cause false positives in tests. + # + # @param value [Boolean] + attr_writer :warn_about_potential_false_positives + + # Indicates whether RSpec will warn about matcher use which will + # potentially cause false positives in tests, generally you want to + # avoid such scenarios so this defaults to `true`. + def warn_about_potential_false_positives? + @warn_about_potential_false_positives + end + end + + # The configuration object. + # @return [RSpec::Expectations::Configuration] the configuration object + def self.configuration + @configuration ||= Configuration.new + end + + # set default syntax + configuration.reset_syntaxes_to_default + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/expectation_target.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/expectation_target.rb new file mode 100644 index 0000000..8851224 --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/expectation_target.rb @@ -0,0 +1,113 @@ +module RSpec + module Expectations + # Wraps the target of an expectation. + # + # @example + # expect(something) # => ExpectationTarget wrapping something + # expect { do_something } # => ExpectationTarget wrapping the block + # + # # used with `to` + # expect(actual).to eq(3) + # + # # with `not_to` + # expect(actual).not_to eq(3) + # + # @note `ExpectationTarget` is not intended to be instantiated + # directly by users. Use `expect` instead. + class ExpectationTarget + # @private + # Used as a sentinel value to be able to tell when the user + # did not pass an argument. We can't use `nil` for that because + # `nil` is a valid value to pass. + UndefinedValue = Module.new + + # @api private + def initialize(value) + @target = value + end + + # @private + def self.for(value, block) + if UndefinedValue.equal?(value) + unless block + raise ArgumentError, "You must pass either an argument or a block to `expect`." + end + BlockExpectationTarget.new(block) + elsif block + raise ArgumentError, "You cannot pass both an argument and a block to `expect`." + else + new(value) + end + end + + # Runs the given expectation, passing if `matcher` returns true. + # @example + # expect(value).to eq(5) + # expect { perform }.to raise_error + # @param [Matcher] + # matcher + # @param [String or Proc] message optional message to display when the expectation fails + # @return [Boolean] true if the expectation succeeds (else raises) + # @see RSpec::Matchers + def to(matcher=nil, message=nil, &block) + prevent_operator_matchers(:to) unless matcher + RSpec::Expectations::PositiveExpectationHandler.handle_matcher(@target, matcher, message, &block) + end + + # Runs the given expectation, passing if `matcher` returns false. + # @example + # expect(value).not_to eq(5) + # @param [Matcher] + # matcher + # @param [String or Proc] message optional message to display when the expectation fails + # @return [Boolean] false if the negative expectation succeeds (else raises) + # @see RSpec::Matchers + def not_to(matcher=nil, message=nil, &block) + prevent_operator_matchers(:not_to) unless matcher + RSpec::Expectations::NegativeExpectationHandler.handle_matcher(@target, matcher, message, &block) + end + alias to_not not_to + + private + + def prevent_operator_matchers(verb) + raise ArgumentError, "The expect syntax does not support operator matchers, " \ + "so you must pass a matcher to `##{verb}`." + end + end + + # @private + # Validates the provided matcher to ensure it supports block + # expectations, in order to avoid user confusion when they + # use a block thinking the expectation will be on the return + # value of the block rather than the block itself. + class BlockExpectationTarget < ExpectationTarget + def to(matcher, message=nil, &block) + enforce_block_expectation(matcher) + super + end + + def not_to(matcher, message=nil, &block) + enforce_block_expectation(matcher) + super + end + alias to_not not_to + + private + + def enforce_block_expectation(matcher) + return if supports_block_expectations?(matcher) + + raise ExpectationNotMetError, "You must pass an argument rather than a block to use the provided " \ + "matcher (#{RSpec::Support::ObjectFormatter.format(matcher)}), or the matcher must implement " \ + "`supports_block_expectations?`." + end + + def supports_block_expectations?(matcher) + matcher.supports_block_expectations? + rescue NoMethodError + false + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/fail_with.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/fail_with.rb new file mode 100644 index 0000000..cae52ea --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/fail_with.rb @@ -0,0 +1,31 @@ +module RSpec + module Expectations + class << self + # @private + def differ + RSpec::Support::Differ.new( + :object_preparer => lambda { |object| RSpec::Matchers::Composable.surface_descriptions_in(object) }, + :color => RSpec::Matchers.configuration.color? + ) + end + + # Raises an RSpec::Expectations::ExpectationNotMetError with message. + # @param [String] message + # @param [Object] expected + # @param [Object] actual + # + # Adds a diff to the failure message when `expected` and `actual` are + # both present. + def fail_with(message, expected=nil, actual=nil) + unless message + raise ArgumentError, "Failure message is nil. Does your matcher define the " \ + "appropriate failure_message[_when_negated] method to return a string?" + end + + message = ::RSpec::Matchers::ExpectedsForMultipleDiffs.from(expected).message_with_diff(message, differ, actual) + + RSpec::Support.notify_failure(RSpec::Expectations::ExpectationNotMetError.new message) + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/failure_aggregator.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/failure_aggregator.rb new file mode 100644 index 0000000..28d3936 --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/failure_aggregator.rb @@ -0,0 +1,194 @@ +module RSpec + module Expectations + # @private + class FailureAggregator + attr_reader :block_label, :metadata + + def aggregate + RSpec::Support.with_failure_notifier(self) do + begin + yield + rescue ExpectationNotMetError => e + # Normally, expectation failures will be notified via the `call` method, below, + # but since the failure notifier uses a thread local variable, failing expectations + # in another thread will still raise. We handle that here and categorize it as part + # of `failures` rather than letting it fall through and be categorized as part of + # `other_errors`. + failures << e + rescue Exception => e + # While it is normally a bad practice to rescue `Exception`, it's important we do + # so here. It's low risk (`notify_aggregated_failures` below will re-raise the exception, + # or raise a `MultipleExpectationsNotMetError` that includes the exception), and it's + # essential that the user is notified of expectation failures that may have already + # occurred in the `aggregate_failures` block. Those expectation failures may provide + # important diagnostics for understanding why this exception occurred, and if we simply + # allowed this exception to be raised as-is, it would (wrongly) suggest to the user + # that the expectation passed when it did not, which would be quite confusing. + other_errors << e + end + end + + notify_aggregated_failures + end + + def failures + @failures ||= [] + end + + def other_errors + @other_errors ||= [] + end + + # This method is defined to satisfy the callable interface + # expected by `RSpec::Support.with_failure_notifier`. + def call(failure, options) + source_id = options[:source_id] + return if source_id && @seen_source_ids.key?(source_id) + + @seen_source_ids[source_id] = true + assign_backtrace(failure) unless failure.backtrace + failures << failure + end + + private + + if RSpec::Support::Ruby.jruby? + # On JRuby, `caller` and `raise` produce different backtraces with regards to `.java` + # stack frames. It's important that we use `raise` for JRuby to produce a backtrace + # that has a continuous common section with the raised `MultipleExpectationsNotMetError`, + # so that rspec-core's truncation logic can work properly on it to list the backtrace + # relative to the `aggregate_failures` block. + def assign_backtrace(failure) + raise failure + rescue failure.class => e + failure.set_backtrace(e.backtrace) + end + else + # Using `caller` performs better (and is simpler) than `raise` on most Rubies. + def assign_backtrace(failure) + failure.set_backtrace(caller) + end + end + + def initialize(block_label, metadata) + @block_label = block_label + @metadata = metadata + @seen_source_ids = {} # don't want to load stdlib set + end + + def notify_aggregated_failures + all_errors = failures + other_errors + + case all_errors.size + when 0 then return nil + when 1 then RSpec::Support.notify_failure all_errors.first + else RSpec::Support.notify_failure MultipleExpectationsNotMetError.new(self) + end + end + end + + # Exception raised from `aggregate_failures` when multiple expectations fail. + class MultipleExpectationsNotMetError + # @return [String] The fully formatted exception message. + def message + @message ||= (["#{summary}:"] + enumerated_failures + enumerated_errors).join("\n\n") + end + + # @return [Array] The list of expectation failures. + def failures + @failure_aggregator.failures + end + + # @return [Array] The list of other exceptions. + def other_errors + @failure_aggregator.other_errors + end + + # @return [Array] The list of expectation failures and other exceptions, combined. + attr_reader :all_exceptions + + # @return [String] The user-assigned label for the aggregation block. + def aggregation_block_label + @failure_aggregator.block_label + end + + # @return [Hash] The metadata hash passed to `aggregate_failures`. + def aggregation_metadata + @failure_aggregator.metadata + end + + # @return [String] A summary of the failure, including the block label and a count of failures. + def summary + "Got #{exception_count_description} from failure aggregation " \ + "block#{block_description}" + end + + # return [String] A description of the failure/error counts. + def exception_count_description + failure_count = pluralize("failure", failures.size) + return failure_count if other_errors.empty? + error_count = pluralize("other error", other_errors.size) + "#{failure_count} and #{error_count}" + end + + private + + def initialize(failure_aggregator) + @failure_aggregator = failure_aggregator + @all_exceptions = failures + other_errors + end + + def block_description + return "" unless aggregation_block_label + " #{aggregation_block_label.inspect}" + end + + def pluralize(noun, count) + "#{count} #{noun}#{'s' unless count == 1}" + end + + def enumerated(exceptions, index_offset) + exceptions.each_with_index.map do |exception, index| + index += index_offset + formatted_message = yield exception + "#{index_label index}#{indented formatted_message, index}" + end + end + + def enumerated_failures + enumerated(failures, 0, &:message) + end + + def enumerated_errors + enumerated(other_errors, failures.size) do |error| + "#{error.class}: #{error.message}" + end + end + + def indented(failure_message, index) + line_1, *rest = failure_message.strip.lines.to_a + first_line_indentation = ' ' * (longest_index_label_width - width_of_label(index)) + + first_line_indentation + line_1 + rest.map do |line| + line =~ /\S/ ? indentation + line : line + end.join + end + + def indentation + @indentation ||= ' ' * longest_index_label_width + end + + def longest_index_label_width + @longest_index_label_width ||= width_of_label(failures.size) + end + + def width_of_label(index) + index_label(index).chars.count + end + + def index_label(index) + " #{index + 1}) " + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/handler.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/handler.rb new file mode 100644 index 0000000..afb571a --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/handler.rb @@ -0,0 +1,170 @@ +module RSpec + module Expectations + # @private + module ExpectationHelper + def self.check_message(msg) + unless msg.nil? || msg.respond_to?(:to_str) || msg.respond_to?(:call) + ::Kernel.warn [ + "WARNING: ignoring the provided expectation message argument (", + msg.inspect, + ") since it is not a string or a proc." + ].join + end + end + + # Returns an RSpec-3+ compatible matcher, wrapping a legacy one + # in an adapter if necessary. + # + # @private + def self.modern_matcher_from(matcher) + LegacyMatcherAdapter::RSpec2.wrap(matcher) || + LegacyMatcherAdapter::RSpec1.wrap(matcher) || matcher + end + + def self.with_matcher(handler, matcher, message) + check_message(message) + matcher = modern_matcher_from(matcher) + yield matcher + ensure + ::RSpec::Matchers.last_expectation_handler = handler + ::RSpec::Matchers.last_matcher = matcher + end + + def self.handle_failure(matcher, message, failure_message_method) + message = message.call if message.respond_to?(:call) + message ||= matcher.__send__(failure_message_method) + + if matcher.respond_to?(:diffable?) && matcher.diffable? + ::RSpec::Expectations.fail_with message, matcher.expected, matcher.actual + else + ::RSpec::Expectations.fail_with message + end + end + end + + # @private + class PositiveExpectationHandler + def self.handle_matcher(actual, initial_matcher, message=nil, &block) + ExpectationHelper.with_matcher(self, initial_matcher, message) do |matcher| + return ::RSpec::Matchers::BuiltIn::PositiveOperatorMatcher.new(actual) unless initial_matcher + matcher.matches?(actual, &block) || ExpectationHelper.handle_failure(matcher, message, :failure_message) + end + end + + def self.verb + "should" + end + + def self.should_method + :should + end + + def self.opposite_should_method + :should_not + end + end + + # @private + class NegativeExpectationHandler + def self.handle_matcher(actual, initial_matcher, message=nil, &block) + ExpectationHelper.with_matcher(self, initial_matcher, message) do |matcher| + return ::RSpec::Matchers::BuiltIn::NegativeOperatorMatcher.new(actual) unless initial_matcher + !(does_not_match?(matcher, actual, &block) || ExpectationHelper.handle_failure(matcher, message, :failure_message_when_negated)) + end + end + + def self.does_not_match?(matcher, actual, &block) + if matcher.respond_to?(:does_not_match?) + matcher.does_not_match?(actual, &block) + else + !matcher.matches?(actual, &block) + end + end + + def self.verb + "should not" + end + + def self.should_method + :should_not + end + + def self.opposite_should_method + :should + end + end + + # Wraps a matcher written against one of the legacy protocols in + # order to present the current protocol. + # + # @private + class LegacyMatcherAdapter < Matchers::MatcherDelegator + def initialize(matcher) + super + ::RSpec.warn_deprecation(<<-EOS.gsub(/^\s+\|/, ''), :type => "legacy_matcher") + |#{matcher.class.name || matcher.inspect} implements a legacy RSpec matcher + |protocol. For the current protocol you should expose the failure messages + |via the `failure_message` and `failure_message_when_negated` methods. + |(Used from #{CallerFilter.first_non_rspec_line}) + EOS + end + + def self.wrap(matcher) + new(matcher) if interface_matches?(matcher) + end + + # Starting in RSpec 1.2 (and continuing through all 2.x releases), + # the failure message protocol was: + # * `failure_message_for_should` + # * `failure_message_for_should_not` + # @private + class RSpec2 < self + def failure_message + base_matcher.failure_message_for_should + end + + def failure_message_when_negated + base_matcher.failure_message_for_should_not + end + + def self.interface_matches?(matcher) + ( + !matcher.respond_to?(:failure_message) && + matcher.respond_to?(:failure_message_for_should) + ) || ( + !matcher.respond_to?(:failure_message_when_negated) && + matcher.respond_to?(:failure_message_for_should_not) + ) + end + end + + # Before RSpec 1.2, the failure message protocol was: + # * `failure_message` + # * `negative_failure_message` + # @private + class RSpec1 < self + def failure_message + base_matcher.failure_message + end + + def failure_message_when_negated + base_matcher.negative_failure_message + end + + # Note: `failure_message` is part of the RSpec 3 protocol + # (paired with `failure_message_when_negated`), so we don't check + # for `failure_message` here. + def self.interface_matches?(matcher) + !matcher.respond_to?(:failure_message_when_negated) && + matcher.respond_to?(:negative_failure_message) + end + end + end + + # RSpec 3.0 was released with the class name misspelled. For SemVer compatibility, + # we will provide this misspelled alias until 4.0. + # @deprecated Use LegacyMatcherAdapter instead. + # @private + LegacyMacherAdapter = LegacyMatcherAdapter + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/minitest_integration.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/minitest_integration.rb new file mode 100644 index 0000000..5dcadec --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/minitest_integration.rb @@ -0,0 +1,31 @@ +require 'rspec/expectations' + +Minitest::Test.class_eval do + include ::RSpec::Matchers + + def expect(*a, &b) + assert(true) # so each expectation gets counted in minitest's assertion stats + super + end + + # Convert a `MultipleExpectationsNotMetError` to a `Minitest::Assertion` error so + # it gets counted in minitest's summary stats as a failure rather than an error. + # It would be nice to make `MultipleExpectationsNotMetError` subclass + # `Minitest::Assertion`, but Minitest's implementation does not treat subclasses + # the same, so this is the best we can do. + def aggregate_failures(*args, &block) + super + rescue RSpec::Expectations::MultipleExpectationsNotMetError => e + assertion_failed = Minitest::Assertion.new(e.message) + assertion_failed.set_backtrace e.backtrace + raise assertion_failed + end +end + +module RSpec + module Expectations + remove_const :ExpectationNotMetError + # Exception raised when an expectation fails. + ExpectationNotMetError = ::Minitest::Assertion + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/syntax.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/syntax.rb new file mode 100644 index 0000000..f2fc442 --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/syntax.rb @@ -0,0 +1,132 @@ +module RSpec + module Expectations + # @api private + # Provides methods for enabling and disabling the available + # syntaxes provided by rspec-expectations. + module Syntax + module_function + + # @api private + # Determines where we add `should` and `should_not`. + def default_should_host + @default_should_host ||= ::Object.ancestors.last + end + + # @api private + # Instructs rspec-expectations to warn on first usage of `should` or `should_not`. + # Enabled by default. This is largely here to facilitate testing. + def warn_about_should! + @warn_about_should = true + end + + # @api private + # Generates a deprecation warning for the given method if no warning + # has already been issued. + def warn_about_should_unless_configured(method_name) + return unless @warn_about_should + + RSpec.deprecate( + "Using `#{method_name}` from rspec-expectations' old `:should` syntax without explicitly enabling the syntax", + :replacement => "the new `:expect` syntax or explicitly enable `:should` with `config.expect_with(:rspec) { |c| c.syntax = :should }`" + ) + + @warn_about_should = false + end + + # @api private + # Enables the `should` syntax. + def enable_should(syntax_host=default_should_host) + @warn_about_should = false if syntax_host == default_should_host + return if should_enabled?(syntax_host) + + syntax_host.module_exec do + def should(matcher=nil, message=nil, &block) + ::RSpec::Expectations::Syntax.warn_about_should_unless_configured(__method__) + ::RSpec::Expectations::PositiveExpectationHandler.handle_matcher(self, matcher, message, &block) + end + + def should_not(matcher=nil, message=nil, &block) + ::RSpec::Expectations::Syntax.warn_about_should_unless_configured(__method__) + ::RSpec::Expectations::NegativeExpectationHandler.handle_matcher(self, matcher, message, &block) + end + end + end + + # @api private + # Disables the `should` syntax. + def disable_should(syntax_host=default_should_host) + return unless should_enabled?(syntax_host) + + syntax_host.module_exec do + undef should + undef should_not + end + end + + # @api private + # Enables the `expect` syntax. + def enable_expect(syntax_host=::RSpec::Matchers) + return if expect_enabled?(syntax_host) + + syntax_host.module_exec do + def expect(value=::RSpec::Expectations::ExpectationTarget::UndefinedValue, &block) + ::RSpec::Expectations::ExpectationTarget.for(value, block) + end + end + end + + # @api private + # Disables the `expect` syntax. + def disable_expect(syntax_host=::RSpec::Matchers) + return unless expect_enabled?(syntax_host) + + syntax_host.module_exec do + undef expect + end + end + + # @api private + # Indicates whether or not the `should` syntax is enabled. + def should_enabled?(syntax_host=default_should_host) + syntax_host.method_defined?(:should) + end + + # @api private + # Indicates whether or not the `expect` syntax is enabled. + def expect_enabled?(syntax_host=::RSpec::Matchers) + syntax_host.method_defined?(:expect) + end + end + end +end + +if defined?(BasicObject) + # The legacy `:should` syntax adds the following methods directly to + # `BasicObject` so that they are available off of any object. Note, however, + # that this syntax does not always play nice with delegate/proxy objects. + # We recommend you use the non-monkeypatching `:expect` syntax instead. + class BasicObject + # @method should + # Passes if `matcher` returns true. Available on every `Object`. + # @example + # actual.should eq expected + # actual.should match /expression/ + # @param [Matcher] + # matcher + # @param [String] message optional message to display when the expectation fails + # @return [Boolean] true if the expectation succeeds (else raises) + # @note This is only available when you have enabled the `:should` syntax. + # @see RSpec::Matchers + + # @method should_not + # Passes if `matcher` returns false. Available on every `Object`. + # @example + # actual.should_not eq expected + # @param [Matcher] + # matcher + # @param [String] message optional message to display when the expectation fails + # @return [Boolean] false if the negative expectation succeeds (else raises) + # @note This is only available when you have enabled the `:should` syntax. + # @see RSpec::Matchers + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/version.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/version.rb new file mode 100644 index 0000000..a4f3edd --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/expectations/version.rb @@ -0,0 +1,8 @@ +module RSpec + module Expectations + # @private + module Version + STRING = '3.3.1' + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers.rb new file mode 100644 index 0000000..67f174a --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers.rb @@ -0,0 +1,1009 @@ +require 'rspec/support' +RSpec::Support.require_rspec_support 'matcher_definition' +RSpec::Support.define_optimized_require_for_rspec(:matchers) { |f| require_relative(f) } + +%w[ + english_phrasing + composable + built_in + generated_descriptions + dsl + matcher_delegator + aliased_matcher + expecteds_for_multiple_diffs +].each { |file| RSpec::Support.require_rspec_matchers(file) } + +# RSpec's top level namespace. All of rspec-expectations is contained +# in the `RSpec::Expectations` and `RSpec::Matchers` namespaces. +module RSpec + # RSpec::Matchers provides a number of useful matchers we use to define + # expectations. Any object that implements the [matcher protocol](Matchers/MatcherProtocol) + # can be used as a matcher. + # + # ## Predicates + # + # In addition to matchers that are defined explicitly, RSpec will create + # custom matchers on the fly for any arbitrary predicate, giving your specs a + # much more natural language feel. + # + # A Ruby predicate is a method that ends with a "?" and returns true or false. + # Common examples are `empty?`, `nil?`, and `instance_of?`. + # + # All you need to do is write `expect(..).to be_` followed by the predicate + # without the question mark, and RSpec will figure it out from there. + # For example: + # + # expect([]).to be_empty # => [].empty?() | passes + # expect([]).not_to be_empty # => [].empty?() | fails + # + # In addtion to prefixing the predicate matchers with "be_", you can also use "be_a_" + # and "be_an_", making your specs read much more naturally: + # + # expect("a string").to be_an_instance_of(String) # =>"a string".instance_of?(String) # passes + # + # expect(3).to be_a_kind_of(Fixnum) # => 3.kind_of?(Numeric) | passes + # expect(3).to be_a_kind_of(Numeric) # => 3.kind_of?(Numeric) | passes + # expect(3).to be_an_instance_of(Fixnum) # => 3.instance_of?(Fixnum) | passes + # expect(3).not_to be_an_instance_of(Numeric) # => 3.instance_of?(Numeric) | fails + # + # RSpec will also create custom matchers for predicates like `has_key?`. To + # use this feature, just state that the object should have_key(:key) and RSpec will + # call has_key?(:key) on the target. For example: + # + # expect(:a => "A").to have_key(:a) + # expect(:a => "A").to have_key(:b) # fails + # + # You can use this feature to invoke any predicate that begins with "has_", whether it is + # part of the Ruby libraries (like `Hash#has_key?`) or a method you wrote on your own class. + # + # Note that RSpec does not provide composable aliases for these dynamic predicate + # matchers. You can easily define your own aliases, though: + # + # RSpec::Matchers.alias_matcher :a_user_who_is_an_admin, :be_an_admin + # expect(user_list).to include(a_user_who_is_an_admin) + # + # ## Custom Matchers + # + # When you find that none of the stock matchers provide a natural feeling + # expectation, you can very easily write your own using RSpec's matcher DSL + # or writing one from scratch. + # + # ### Matcher DSL + # + # Imagine that you are writing a game in which players can be in various + # zones on a virtual board. To specify that bob should be in zone 4, you + # could say: + # + # expect(bob.current_zone).to eql(Zone.new("4")) + # + # But you might find it more expressive to say: + # + # expect(bob).to be_in_zone("4") + # + # and/or + # + # expect(bob).not_to be_in_zone("3") + # + # You can create such a matcher like so: + # + # RSpec::Matchers.define :be_in_zone do |zone| + # match do |player| + # player.in_zone?(zone) + # end + # end + # + # This will generate a be_in_zone method that returns a matcher + # with logical default messages for failures. You can override the failure + # messages and the generated description as follows: + # + # RSpec::Matchers.define :be_in_zone do |zone| + # match do |player| + # player.in_zone?(zone) + # end + # + # failure_message do |player| + # # generate and return the appropriate string. + # end + # + # failure_message_when_negated do |player| + # # generate and return the appropriate string. + # end + # + # description do + # # generate and return the appropriate string. + # end + # end + # + # Each of the message-generation methods has access to the block arguments + # passed to the create method (in this case, zone). The + # failure message methods (failure_message and + # failure_message_when_negated) are passed the actual value (the + # receiver of expect(..) or expect(..).not_to). + # + # ### Custom Matcher from scratch + # + # You could also write a custom matcher from scratch, as follows: + # + # class BeInZone + # def initialize(expected) + # @expected = expected + # end + # + # def matches?(target) + # @target = target + # @target.current_zone.eql?(Zone.new(@expected)) + # end + # + # def failure_message + # "expected #{@target.inspect} to be in Zone #{@expected}" + # end + # + # def failure_message_when_negated + # "expected #{@target.inspect} not to be in Zone #{@expected}" + # end + # end + # + # ... and a method like this: + # + # def be_in_zone(expected) + # BeInZone.new(expected) + # end + # + # And then expose the method to your specs. This is normally done + # by including the method and the class in a module, which is then + # included in your spec: + # + # module CustomGameMatchers + # class BeInZone + # # ... + # end + # + # def be_in_zone(expected) + # # ... + # end + # end + # + # describe "Player behaviour" do + # include CustomGameMatchers + # # ... + # end + # + # or you can include in globally in a spec_helper.rb file required + # from your spec file(s): + # + # RSpec::configure do |config| + # config.include(CustomGameMatchers) + # end + # + # ### Making custom matchers composable + # + # RSpec's built-in matchers are designed to be composed, in expressions like: + # + # expect(["barn", 2.45]).to contain_exactly( + # a_value_within(0.1).of(2.5), + # a_string_starting_with("bar") + # ) + # + # Custom matchers can easily participate in composed matcher expressions like these. + # Include {RSpec::Matchers::Composable} in your custom matcher to make it support + # being composed (matchers defined using the DSL have this included automatically). + # Within your matcher's `matches?` method (or the `match` block, if using the DSL), + # use `values_match?(expected, actual)` rather than `expected == actual`. + # Under the covers, `values_match?` is able to match arbitrary + # nested data structures containing a mix of both matchers and non-matcher objects. + # It uses `===` and `==` to perform the matching, considering the values to + # match if either returns `true`. The `Composable` mixin also provides some helper + # methods for surfacing the matcher descriptions within your matcher's description + # or failure messages. + # + # RSpec's built-in matchers each have a number of aliases that rephrase the matcher + # from a verb phrase (such as `be_within`) to a noun phrase (such as `a_value_within`), + # which reads better when the matcher is passed as an argument in a composed matcher + # expressions, and also uses the noun-phrase wording in the matcher's `description`, + # for readable failure messages. You can alias your custom matchers in similar fashion + # using {RSpec::Matchers.alias_matcher}. + module Matchers + # @method expect + # Supports `expect(actual).to matcher` syntax by wrapping `actual` in an + # `ExpectationTarget`. + # @example + # expect(actual).to eq(expected) + # expect(actual).not_to eq(expected) + # @return [ExpectationTarget] + # @see ExpectationTarget#to + # @see ExpectationTarget#not_to + + # Defines a matcher alias. The returned matcher's `description` will be overriden + # to reflect the phrasing of the new name, which will be used in failure messages + # when passed as an argument to another matcher in a composed matcher expression. + # + # @param new_name [Symbol] the new name for the matcher + # @param old_name [Symbol] the original name for the matcher + # @param options [Hash] options for the aliased matcher + # @option options [Class] :klass the ruby class to use as the decorator. (Not normally used). + # @yield [String] optional block that, when given, is used to define the overriden + # logic. The yielded arg is the original description or failure message. If no + # block is provided, a default override is used based on the old and new names. + # + # @example + # RSpec::Matchers.alias_matcher :a_list_that_sums_to, :sum_to + # sum_to(3).description # => "sum to 3" + # a_list_that_sums_to(3).description # => "a list that sums to 3" + # + # @example + # RSpec::Matchers.alias_matcher :a_list_sorted_by, :be_sorted_by do |description| + # description.sub("be sorted by", "a list sorted by") + # end + # + # be_sorted_by(:age).description # => "be sorted by age" + # a_list_sorted_by(:age).description # => "a list sorted by age" + # + # @!macro [attach] alias_matcher + # @!parse + # alias $1 $2 + def self.alias_matcher(new_name, old_name, options={}, &description_override) + description_override ||= lambda do |old_desc| + old_desc.gsub(EnglishPhrasing.split_words(old_name), EnglishPhrasing.split_words(new_name)) + end + klass = options.fetch(:klass) { AliasedMatcher } + + define_method(new_name) do |*args, &block| + matcher = __send__(old_name, *args, &block) + klass.new(matcher, description_override) + end + end + + # Defines a negated matcher. The returned matcher's `description` and `failure_message` + # will be overriden to reflect the phrasing of the new name, and the match logic will + # be based on the original matcher but negated. + # + # @param negated_name [Symbol] the name for the negated matcher + # @param base_name [Symbol] the name of the original matcher that will be negated + # @yield [String] optional block that, when given, is used to define the overriden + # logic. The yielded arg is the original description or failure message. If no + # block is provided, a default override is used based on the old and new names. + # + # @example + # RSpec::Matchers.define_negated_matcher :exclude, :include + # include(1, 2).description # => "include 1 and 2" + # exclude(1, 2).description # => "exclude 1 and 2" + # + # @note While the most obvious negated form may be to add a `not_` prefix, + # the failure messages you get with that form can be confusing (e.g. + # "expected [actual] to not [verb], but did not"). We've found it works + # best to find a more positive name for the negated form, such as + # `avoid_changing` rather than `not_change`. + def self.define_negated_matcher(negated_name, base_name, &description_override) + alias_matcher(negated_name, base_name, :klass => AliasedNegatedMatcher, &description_override) + end + + # Allows multiple expectations in the provided block to fail, and then + # aggregates them into a single exception, rather than aborting on the + # first expectation failure like normal. This allows you to see all + # failures from an entire set of expectations without splitting each + # off into its own example (which may slow things down if the example + # setup is expensive). + # + # @param label [String] label for this aggregation block, which will be + # included in the aggregated exception message. + # @param metadata [Hash] additional metadata about this failure aggregation + # block. If multiple expectations fail, it will be exposed from the + # {Expectations::MultipleExpectationsNotMetError} exception. Mostly + # intended for internal RSpec use but you can use it as well. + # @yield Block containing as many expectation as you want. The block is + # simply yielded to, so you can trust that anything that works outside + # the block should work within it. + # @raise [Expectations::MultipleExpectationsNotMetError] raised when + # multiple expectations fail. + # @raise [Expectations::ExpectationNotMetError] raised when a single + # expectation fails. + # @raise [Exception] other sorts of exceptions will be raised as normal. + # + # @example + # aggregate_failures("verifying response") do + # expect(response.status).to eq(200) + # expect(response.headers).to include("Content-Type" => "text/plain") + # expect(response.body).to include("Success") + # end + # + # @note The implementation of this feature uses a thread-local variable, + # which means that if you have an expectation failure in another thread, + # it'll abort like normal. + def aggregate_failures(label=nil, metadata={}, &block) + Expectations::FailureAggregator.new(label, metadata).aggregate(&block) + end + + # Passes if actual is truthy (anything but false or nil) + def be_truthy + BuiltIn::BeTruthy.new + end + alias_matcher :a_truthy_value, :be_truthy + + # Passes if actual is falsey (false or nil) + def be_falsey + BuiltIn::BeFalsey.new + end + alias_matcher :be_falsy, :be_falsey + alias_matcher :a_falsey_value, :be_falsey + alias_matcher :a_falsy_value, :be_falsey + + # Passes if actual is nil + def be_nil + BuiltIn::BeNil.new + end + alias_matcher :a_nil_value, :be_nil + + # @example + # expect(actual).to be_truthy + # expect(actual).to be_falsey + # expect(actual).to be_nil + # expect(actual).to be_[arbitrary_predicate](*args) + # expect(actual).not_to be_nil + # expect(actual).not_to be_[arbitrary_predicate](*args) + # + # Given true, false, or nil, will pass if actual value is true, false or + # nil (respectively). Given no args means the caller should satisfy an if + # condition (to be or not to be). + # + # Predicates are any Ruby method that ends in a "?" and returns true or + # false. Given be_ followed by arbitrary_predicate (without the "?"), + # RSpec will match convert that into a query against the target object. + # + # The arbitrary_predicate feature will handle any predicate prefixed with + # "be_an_" (e.g. be_an_instance_of), "be_a_" (e.g. be_a_kind_of) or "be_" + # (e.g. be_empty), letting you choose the prefix that best suits the + # predicate. + def be(*args) + args.empty? ? Matchers::BuiltIn::Be.new : equal(*args) + end + alias_matcher :a_value, :be, :klass => AliasedMatcherWithOperatorSupport + + # passes if target.kind_of?(klass) + def be_a(klass) + be_a_kind_of(klass) + end + alias_method :be_an, :be_a + + # Passes if actual.instance_of?(expected) + # + # @example + # expect(5).to be_an_instance_of(Fixnum) + # expect(5).not_to be_an_instance_of(Numeric) + # expect(5).not_to be_an_instance_of(Float) + def be_an_instance_of(expected) + BuiltIn::BeAnInstanceOf.new(expected) + end + alias_method :be_instance_of, :be_an_instance_of + alias_matcher :an_instance_of, :be_an_instance_of + + # Passes if actual.kind_of?(expected) + # + # @example + # expect(5).to be_a_kind_of(Fixnum) + # expect(5).to be_a_kind_of(Numeric) + # expect(5).not_to be_a_kind_of(Float) + def be_a_kind_of(expected) + BuiltIn::BeAKindOf.new(expected) + end + alias_method :be_kind_of, :be_a_kind_of + alias_matcher :a_kind_of, :be_a_kind_of + + # Passes if actual.between?(min, max). Works with any Comparable object, + # including String, Symbol, Time, or Numeric (Fixnum, Bignum, Integer, + # Float, Complex, and Rational). + # + # By default, `be_between` is inclusive (i.e. passes when given either the max or min value), + # but you can make it `exclusive` by chaining that off the matcher. + # + # @example + # expect(5).to be_between(1, 10) + # expect(11).not_to be_between(1, 10) + # expect(10).not_to be_between(1, 10).exclusive + def be_between(min, max) + BuiltIn::BeBetween.new(min, max) + end + alias_matcher :a_value_between, :be_between + + # Passes if actual == expected +/- delta + # + # @example + # expect(result).to be_within(0.5).of(3.0) + # expect(result).not_to be_within(0.5).of(3.0) + def be_within(delta) + BuiltIn::BeWithin.new(delta) + end + alias_matcher :a_value_within, :be_within + alias_matcher :within, :be_within + + # Applied to a proc, specifies that its execution will cause some value to + # change. + # + # @param [Object] receiver + # @param [Symbol] message the message to send the receiver + # + # You can either pass receiver and message, or a block, + # but not both. + # + # When passing a block, it must use the `{ ... }` format, not + # do/end, as `{ ... }` binds to the `change` method, whereas do/end + # would errantly bind to the `expect(..).to` or `expect(...).not_to` method. + # + # You can chain any of the following off of the end to specify details + # about the change: + # + # * `from` + # * `to` + # + # or any one of: + # + # * `by` + # * `by_at_least` + # * `by_at_most` + # + # @example + # expect { + # team.add_player(player) + # }.to change(roster, :count) + # + # expect { + # team.add_player(player) + # }.to change(roster, :count).by(1) + # + # expect { + # team.add_player(player) + # }.to change(roster, :count).by_at_least(1) + # + # expect { + # team.add_player(player) + # }.to change(roster, :count).by_at_most(1) + # + # string = "string" + # expect { + # string.reverse! + # }.to change { string }.from("string").to("gnirts") + # + # string = "string" + # expect { + # string + # }.not_to change { string }.from("string") + # + # expect { + # person.happy_birthday + # }.to change(person, :birthday).from(32).to(33) + # + # expect { + # employee.develop_great_new_social_networking_app + # }.to change(employee, :title).from("Mail Clerk").to("CEO") + # + # expect { + # doctor.leave_office + # }.to change(doctor, :sign).from(/is in/).to(/is out/) + # + # user = User.new(:type => "admin") + # expect { + # user.symbolize_type + # }.to change(user, :type).from(String).to(Symbol) + # + # == Notes + # + # Evaluates `receiver.message` or `block` before and after it + # evaluates the block passed to `expect`. + # + # `expect( ... ).not_to change` supports the form that specifies `from` + # (which specifies what you expect the starting, unchanged value to be) + # but does not support forms with subsequent calls to `by`, `by_at_least`, + # `by_at_most` or `to`. + def change(receiver=nil, message=nil, &block) + BuiltIn::Change.new(receiver, message, &block) + end + alias_matcher :a_block_changing, :change + alias_matcher :changing, :change + + # Passes if actual contains all of the expected regardless of order. + # This works for collections. Pass in multiple args and it will only + # pass if all args are found in collection. + # + # @note This is also available using the `=~` operator with `should`, + # but `=~` is not supported with `expect`. + # + # @example + # expect([1, 2, 3]).to contain_exactly(1, 2, 3) + # expect([1, 2, 3]).to contain_exactly(1, 3, 2) + # + # @see #match_array + def contain_exactly(*items) + BuiltIn::ContainExactly.new(items) + end + alias_matcher :a_collection_containing_exactly, :contain_exactly + alias_matcher :containing_exactly, :contain_exactly + + # Passes if actual covers expected. This works for + # Ranges. You can also pass in multiple args + # and it will only pass if all args are found in Range. + # + # @example + # expect(1..10).to cover(5) + # expect(1..10).to cover(4, 6) + # expect(1..10).to cover(4, 6, 11) # fails + # expect(1..10).not_to cover(11) + # expect(1..10).not_to cover(5) # fails + # + # ### Warning:: Ruby >= 1.9 only + def cover(*values) + BuiltIn::Cover.new(*values) + end + alias_matcher :a_range_covering, :cover + alias_matcher :covering, :cover + + # Matches if the actual value ends with the expected value(s). In the case + # of a string, matches against the last `expected.length` characters of the + # actual string. In the case of an array, matches against the last + # `expected.length` elements of the actual array. + # + # @example + # expect("this string").to end_with "string" + # expect([0, 1, 2, 3, 4]).to end_with 4 + # expect([0, 2, 3, 4, 4]).to end_with 3, 4 + def end_with(*expected) + BuiltIn::EndWith.new(*expected) + end + alias_matcher :a_collection_ending_with, :end_with + alias_matcher :a_string_ending_with, :end_with + alias_matcher :ending_with, :end_with + + # Passes if actual == expected. + # + # See http://www.ruby-doc.org/core/classes/Object.html#M001057 for more + # information about equality in Ruby. + # + # @example + # expect(5).to eq(5) + # expect(5).not_to eq(3) + def eq(expected) + BuiltIn::Eq.new(expected) + end + alias_matcher :an_object_eq_to, :eq + alias_matcher :eq_to, :eq + + # Passes if `actual.eql?(expected)` + # + # See http://www.ruby-doc.org/core/classes/Object.html#M001057 for more + # information about equality in Ruby. + # + # @example + # expect(5).to eql(5) + # expect(5).not_to eql(3) + def eql(expected) + BuiltIn::Eql.new(expected) + end + alias_matcher :an_object_eql_to, :eql + alias_matcher :eql_to, :eql + + # Passes if actual.equal?(expected) (object identity). + # + # See http://www.ruby-doc.org/core/classes/Object.html#M001057 for more + # information about equality in Ruby. + # + # @example + # expect(5).to equal(5) # Fixnums are equal + # expect("5").not_to equal("5") # Strings that look the same are not the same object + def equal(expected) + BuiltIn::Equal.new(expected) + end + alias_matcher :an_object_equal_to, :equal + alias_matcher :equal_to, :equal + + # Passes if `actual.exist?` or `actual.exists?` + # + # @example + # expect(File).to exist("path/to/file") + def exist(*args) + BuiltIn::Exist.new(*args) + end + alias_matcher :an_object_existing, :exist + alias_matcher :existing, :exist + + # Passes if actual's attribute values match the expected attributes hash. + # This works no matter how you define your attribute readers. + # + # @example + # Person = Struct.new(:name, :age) + # person = Person.new("Bob", 32) + # + # expect(person).to have_attributes(:name => "Bob", :age => 32) + # expect(person).to have_attributes(:name => a_string_starting_with("B"), :age => (a_value > 30) ) + # + # @note It will fail if actual doesn't respond to any of the expected attributes. + # + # @example + # expect(person).to have_attributes(:color => "red") + def have_attributes(expected) + BuiltIn::HaveAttributes.new(expected) + end + alias_matcher :an_object_having_attributes, :have_attributes + + # Passes if actual includes expected. This works for + # collections and Strings. You can also pass in multiple args + # and it will only pass if all args are found in collection. + # + # @example + # expect([1,2,3]).to include(3) + # expect([1,2,3]).to include(2,3) + # expect([1,2,3]).to include(2,3,4) # fails + # expect([1,2,3]).not_to include(4) + # expect("spread").to include("read") + # expect("spread").not_to include("red") + # expect(:a => 1, :b => 2).to include(:a) + # expect(:a => 1, :b => 2).to include(:a, :b) + # expect(:a => 1, :b => 2).to include(:a => 1) + # expect(:a => 1, :b => 2).to include(:b => 2, :a => 1) + # expect(:a => 1, :b => 2).to include(:c) # fails + # expect(:a => 1, :b => 2).not_to include(:a => 2) + def include(*expected) + BuiltIn::Include.new(*expected) + end + alias_matcher :a_collection_including, :include + alias_matcher :a_string_including, :include + alias_matcher :a_hash_including, :include + alias_matcher :including, :include + + # Passes if the provided matcher passes when checked against all + # elements of the collection. + # + # @example + # expect([1, 3, 5]).to all be_odd + # expect([1, 3, 6]).to all be_odd # fails + # + # @note The negative form `not_to all` is not supported. Instead + # use `not_to include` or pass a negative form of a matcher + # as the argument (e.g. `all exclude(:foo)`). + # + # @note You can also use this with compound matchers as well. + # + # @example + # expect([1, 3, 5]).to all( be_odd.and be_an(Integer) ) + def all(expected) + BuiltIn::All.new(expected) + end + + # Given a `Regexp` or `String`, passes if `actual.match(pattern)` + # Given an arbitrary nested data structure (e.g. arrays and hashes), + # matches if `expected === actual` || `actual == expected` for each + # pair of elements. + # + # @example + # expect(email).to match(/^([^\s]+)((?:[-a-z0-9]+\.)+[a-z]{2,})$/i) + # expect(email).to match("@example.com") + # + # @example + # hash = { + # :a => { + # :b => ["foo", 5], + # :c => { :d => 2.05 } + # } + # } + # + # expect(hash).to match( + # :a => { + # :b => a_collection_containing_exactly( + # a_string_starting_with("f"), + # an_instance_of(Fixnum) + # ), + # :c => { :d => (a_value < 3) } + # } + # ) + # + # @note The `match_regex` alias is deprecated and is not recommended for use. + # It was added in 2.12.1 to facilitate its use from within custom + # matchers (due to how the custom matcher DSL was evaluated in 2.x, + # `match` could not be used there), but is no longer needed in 3.x. + def match(expected) + BuiltIn::Match.new(expected) + end + alias_matcher :match_regex, :match + alias_matcher :an_object_matching, :match + alias_matcher :a_string_matching, :match + alias_matcher :matching, :match + + # An alternate form of `contain_exactly` that accepts + # the expected contents as a single array arg rather + # that splatted out as individual items. + # + # @example + # expect(results).to contain_exactly(1, 2) + # # is identical to: + # expect(results).to match_array([1, 2]) + # + # @see #contain_exactly + def match_array(items) + contain_exactly(*items) + end + + # With no arg, passes if the block outputs `to_stdout` or `to_stderr`. + # With a string, passes if the block outputs that specific string `to_stdout` or `to_stderr`. + # With a regexp or matcher, passes if the block outputs a string `to_stdout` or `to_stderr` that matches. + # + # To capture output from any spawned subprocess as well, use `to_stdout_from_any_process` or + # `to_stderr_from_any_process`. Output from any process that inherits the main process's corresponding + # standard stream will be captured. + # + # @example + # expect { print 'foo' }.to output.to_stdout + # expect { print 'foo' }.to output('foo').to_stdout + # expect { print 'foo' }.to output(/foo/).to_stdout + # + # expect { do_something }.to_not output.to_stdout + # + # expect { warn('foo') }.to output.to_stderr + # expect { warn('foo') }.to output('foo').to_stderr + # expect { warn('foo') }.to output(/foo/).to_stderr + # + # expect { do_something }.to_not output.to_stderr + # + # expect { system('echo foo') }.to output("foo\n").to_stdout_from_any_process + # expect { system('echo foo', out: :err) }.to output("foo\n").to_stderr_from_any_process + # + # @note `to_stdout` and `to_stderr` work by temporarily replacing `$stdout` or `$stderr`, + # so they're not able to intercept stream output that explicitly uses `STDOUT`/`STDERR` + # or that uses a reference to `$stdout`/`$stderr` that was stored before the + # matcher was used. + # @note `to_stdout_from_any_process` and `to_stderr_from_any_process` use Tempfiles, and + # are thus significantly (~30x) slower than `to_stdout` and `to_stderr`. + def output(expected=nil) + BuiltIn::Output.new(expected) + end + alias_matcher :a_block_outputting, :output + + # With no args, matches if any error is raised. + # With a named error, matches only if that specific error is raised. + # With a named error and messsage specified as a String, matches only if both match. + # With a named error and messsage specified as a Regexp, matches only if both match. + # Pass an optional block to perform extra verifications on the exception matched + # + # @example + # expect { do_something_risky }.to raise_error + # expect { do_something_risky }.to raise_error(PoorRiskDecisionError) + # expect { do_something_risky }.to raise_error(PoorRiskDecisionError) { |error| expect(error.data).to eq 42 } + # expect { do_something_risky }.to raise_error(PoorRiskDecisionError, "that was too risky") + # expect { do_something_risky }.to raise_error(PoorRiskDecisionError, /oo ri/) + # + # expect { do_something_risky }.not_to raise_error + def raise_error(error=nil, message=nil, &block) + BuiltIn::RaiseError.new(error, message, &block) + end + alias_method :raise_exception, :raise_error + + alias_matcher :a_block_raising, :raise_error do |desc| + desc.sub("raise", "a block raising") + end + + alias_matcher :raising, :raise_error do |desc| + desc.sub("raise", "raising") + end + + # Matches if the target object responds to all of the names + # provided. Names can be Strings or Symbols. + # + # @example + # expect("string").to respond_to(:length) + # + def respond_to(*names) + BuiltIn::RespondTo.new(*names) + end + alias_matcher :an_object_responding_to, :respond_to + alias_matcher :responding_to, :respond_to + + # Passes if the submitted block returns true. Yields target to the + # block. + # + # Generally speaking, this should be thought of as a last resort when + # you can't find any other way to specify the behaviour you wish to + # specify. + # + # If you do find yourself in such a situation, you could always write + # a custom matcher, which would likely make your specs more expressive. + # + # @param description [String] optional description to be used for this matcher. + # + # @example + # expect(5).to satisfy { |n| n > 3 } + # expect(5).to satisfy("be greater than 3") { |n| n > 3 } + def satisfy(description="satisfy block", &block) + BuiltIn::Satisfy.new(description, &block) + end + alias_matcher :an_object_satisfying, :satisfy + alias_matcher :satisfying, :satisfy + + # Matches if the actual value starts with the expected value(s). In the + # case of a string, matches against the first `expected.length` characters + # of the actual string. In the case of an array, matches against the first + # `expected.length` elements of the actual array. + # + # @example + # expect("this string").to start_with "this s" + # expect([0, 1, 2, 3, 4]).to start_with 0 + # expect([0, 2, 3, 4, 4]).to start_with 0, 1 + def start_with(*expected) + BuiltIn::StartWith.new(*expected) + end + alias_matcher :a_collection_starting_with, :start_with + alias_matcher :a_string_starting_with, :start_with + alias_matcher :starting_with, :start_with + + # Given no argument, matches if a proc throws any Symbol. + # + # Given a Symbol, matches if the given proc throws the specified Symbol. + # + # Given a Symbol and an arg, matches if the given proc throws the + # specified Symbol with the specified arg. + # + # @example + # expect { do_something_risky }.to throw_symbol + # expect { do_something_risky }.to throw_symbol(:that_was_risky) + # expect { do_something_risky }.to throw_symbol(:that_was_risky, 'culprit') + # + # expect { do_something_risky }.not_to throw_symbol + # expect { do_something_risky }.not_to throw_symbol(:that_was_risky) + # expect { do_something_risky }.not_to throw_symbol(:that_was_risky, 'culprit') + def throw_symbol(expected_symbol=nil, expected_arg=nil) + BuiltIn::ThrowSymbol.new(expected_symbol, expected_arg) + end + + alias_matcher :a_block_throwing, :throw_symbol do |desc| + desc.sub("throw", "a block throwing") + end + + alias_matcher :throwing, :throw_symbol do |desc| + desc.sub("throw", "throwing") + end + + # Passes if the method called in the expect block yields, regardless + # of whether or not arguments are yielded. + # + # @example + # expect { |b| 5.tap(&b) }.to yield_control + # expect { |b| "a".to_sym(&b) }.not_to yield_control + # + # @note Your expect block must accept a parameter and pass it on to + # the method-under-test as a block. + def yield_control + BuiltIn::YieldControl.new + end + alias_matcher :a_block_yielding_control, :yield_control + alias_matcher :yielding_control, :yield_control + + # Passes if the method called in the expect block yields with + # no arguments. Fails if it does not yield, or yields with arguments. + # + # @example + # expect { |b| User.transaction(&b) }.to yield_with_no_args + # expect { |b| 5.tap(&b) }.not_to yield_with_no_args # because it yields with `5` + # expect { |b| "a".to_sym(&b) }.not_to yield_with_no_args # because it does not yield + # + # @note Your expect block must accept a parameter and pass it on to + # the method-under-test as a block. + # @note This matcher is not designed for use with methods that yield + # multiple times. + def yield_with_no_args + BuiltIn::YieldWithNoArgs.new + end + alias_matcher :a_block_yielding_with_no_args, :yield_with_no_args + alias_matcher :yielding_with_no_args, :yield_with_no_args + + # Given no arguments, matches if the method called in the expect + # block yields with arguments (regardless of what they are or how + # many there are). + # + # Given arguments, matches if the method called in the expect block + # yields with arguments that match the given arguments. + # + # Argument matching is done using `===` (the case match operator) + # and `==`. If the expected and actual arguments match with either + # operator, the matcher will pass. + # + # @example + # expect { |b| 5.tap(&b) }.to yield_with_args # because #tap yields an arg + # expect { |b| 5.tap(&b) }.to yield_with_args(5) # because 5 == 5 + # expect { |b| 5.tap(&b) }.to yield_with_args(Fixnum) # because Fixnum === 5 + # expect { |b| File.open("f.txt", &b) }.to yield_with_args(/txt/) # because /txt/ === "f.txt" + # + # expect { |b| User.transaction(&b) }.not_to yield_with_args # because it yields no args + # expect { |b| 5.tap(&b) }.not_to yield_with_args(1, 2, 3) + # + # @note Your expect block must accept a parameter and pass it on to + # the method-under-test as a block. + # @note This matcher is not designed for use with methods that yield + # multiple times. + def yield_with_args(*args) + BuiltIn::YieldWithArgs.new(*args) + end + alias_matcher :a_block_yielding_with_args, :yield_with_args + alias_matcher :yielding_with_args, :yield_with_args + + # Designed for use with methods that repeatedly yield (such as + # iterators). Passes if the method called in the expect block yields + # multiple times with arguments matching those given. + # + # Argument matching is done using `===` (the case match operator) + # and `==`. If the expected and actual arguments match with either + # operator, the matcher will pass. + # + # @example + # expect { |b| [1, 2, 3].each(&b) }.to yield_successive_args(1, 2, 3) + # expect { |b| { :a => 1, :b => 2 }.each(&b) }.to yield_successive_args([:a, 1], [:b, 2]) + # expect { |b| [1, 2, 3].each(&b) }.not_to yield_successive_args(1, 2) + # + # @note Your expect block must accept a parameter and pass it on to + # the method-under-test as a block. + def yield_successive_args(*args) + BuiltIn::YieldSuccessiveArgs.new(*args) + end + alias_matcher :a_block_yielding_successive_args, :yield_successive_args + alias_matcher :yielding_successive_args, :yield_successive_args + + # Delegates to {RSpec::Expectations.configuration}. + # This is here because rspec-core's `expect_with` option + # looks for a `configuration` method on the mixin + # (`RSpec::Matchers`) to yield to a block. + # @return [RSpec::Expectations::Configuration] the configuration object + def self.configuration + Expectations.configuration + end + + private + + BE_PREDICATE_REGEX = /^(be_(?:an?_)?)(.*)/ + HAS_REGEX = /^(?:have_)(.*)/ + DYNAMIC_MATCHER_REGEX = Regexp.union(BE_PREDICATE_REGEX, HAS_REGEX) + + def method_missing(method, *args, &block) + case method.to_s + when BE_PREDICATE_REGEX + BuiltIn::BePredicate.new(method, *args, &block) + when HAS_REGEX + BuiltIn::Has.new(method, *args, &block) + else + super + end + end + + if RUBY_VERSION.to_f >= 1.9 + def respond_to_missing?(method, *) + method =~ DYNAMIC_MATCHER_REGEX || super + end + else # for 1.8.7 + # :nocov: + def respond_to?(method, *) + method = method.to_s + method =~ DYNAMIC_MATCHER_REGEX || super + end + public :respond_to? + # :nocov: + end + + # @api private + def self.is_a_matcher?(obj) + return true if ::RSpec::Matchers::BuiltIn::BaseMatcher === obj + begin + return false if obj.respond_to?(:i_respond_to_everything_so_im_not_really_a_matcher) + rescue NoMethodError + # Some objects, like BasicObject, don't implemented standard + # reflection methods. + return false + end + return false unless obj.respond_to?(:matches?) + + obj.respond_to?(:failure_message) || + obj.respond_to?(:failure_message_for_should) # support legacy matchers + end + + ::RSpec::Support.register_matcher_definition do |obj| + is_a_matcher?(obj) + end + + # @api private + def self.is_a_describable_matcher?(obj) + is_a_matcher?(obj) && obj.respond_to?(:description) + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/aliased_matcher.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/aliased_matcher.rb new file mode 100644 index 0000000..c384d2a --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/aliased_matcher.rb @@ -0,0 +1,116 @@ +module RSpec + module Matchers + # Decorator that wraps a matcher and overrides `description` + # using the provided block in order to support an alias + # of a matcher. This is intended for use when composing + # matchers, so that you can use an expression like + # `include( a_value_within(0.1).of(3) )` rather than + # `include( be_within(0.1).of(3) )`, and have the corresponding + # description read naturally. + # + # @api private + class AliasedMatcher < MatcherDelegator + def initialize(base_matcher, description_block) + @description_block = description_block + super(base_matcher) + end + + # Forward messages on to the wrapped matcher. + # Since many matchers provide a fluent interface + # (e.g. `a_value_within(0.1).of(3)`), we need to wrap + # the returned value if it responds to `description`, + # so that our override can be applied when it is eventually + # used. + def method_missing(*) + return_val = super + return return_val unless RSpec::Matchers.is_a_matcher?(return_val) + self.class.new(return_val, @description_block) + end + + # Provides the description of the aliased matcher. Aliased matchers + # are designed to behave identically to the original matcher except + # for the description and failure messages. The description is different + # to reflect the aliased name. + # + # @api private + def description + @description_block.call(super) + end + + # Provides the failure_message of the aliased matcher. Aliased matchers + # are designed to behave identically to the original matcher except + # for the description and failure messages. The failure_message is different + # to reflect the aliased name. + # + # @api private + def failure_message + @description_block.call(super) + end + + # Provides the failure_message_when_negated of the aliased matcher. Aliased matchers + # are designed to behave identically to the original matcher except + # for the description and failure messages. The failure_message_when_negated is different + # to reflect the aliased name. + # + # @api private + def failure_message_when_negated + @description_block.call(super) + end + end + + # Decorator used for matchers that have special implementations of + # operators like `==` and `===`. + # @private + class AliasedMatcherWithOperatorSupport < AliasedMatcher + # We undef these so that they get delegated via `method_missing`. + undef == + undef === + end + + # @private + class AliasedNegatedMatcher < AliasedMatcher + def matches?(*args, &block) + if @base_matcher.respond_to?(:does_not_match?) + @base_matcher.does_not_match?(*args, &block) + else + !super + end + end + + def does_not_match?(*args, &block) + @base_matcher.matches?(*args, &block) + end + + def failure_message + optimal_failure_message(__method__, :failure_message_when_negated) + end + + def failure_message_when_negated + optimal_failure_message(__method__, :failure_message) + end + + private + + DefaultFailureMessages = BuiltIn::BaseMatcher::DefaultFailureMessages + + # For a matcher that uses the default failure messages, we prefer to + # use the override provided by the `description_block`, because it + # includes the phrasing that the user has expressed a preference for + # by going through the effort of defining a negated matcher. + # + # However, if the override didn't actually change anything, then we + # should return the opposite failure message instead -- the overriden + # message is going to be confusing if we return it as-is, as it represents + # the non-negated failure message for a negated match (or vice versa). + def optimal_failure_message(same, inverted) + if DefaultFailureMessages.has_default_failure_messages?(@base_matcher) + base_message = @base_matcher.__send__(same) + overriden = @description_block.call(base_message) + return overriden if overriden != base_message + end + + @base_matcher.__send__(inverted) + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in.rb new file mode 100644 index 0000000..7f184a0 --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in.rb @@ -0,0 +1,52 @@ +RSpec::Support.require_rspec_matchers "built_in/base_matcher" + +module RSpec + module Matchers + # Container module for all built-in matchers. The matcher classes are here + # (rather than directly under `RSpec::Matchers`) in order to prevent name + # collisions, since `RSpec::Matchers` gets included into the user's namespace. + # + # Autoloading is used to delay when the matcher classes get loaded, allowing + # rspec-matchers to boot faster, and avoiding loading matchers the user is + # not using. + module BuiltIn + autoload :BeAKindOf, 'rspec/matchers/built_in/be_kind_of' + autoload :BeAnInstanceOf, 'rspec/matchers/built_in/be_instance_of' + autoload :BeBetween, 'rspec/matchers/built_in/be_between' + autoload :Be, 'rspec/matchers/built_in/be' + autoload :BeComparedTo, 'rspec/matchers/built_in/be' + autoload :BeFalsey, 'rspec/matchers/built_in/be' + autoload :BeNil, 'rspec/matchers/built_in/be' + autoload :BePredicate, 'rspec/matchers/built_in/be' + autoload :BeTruthy, 'rspec/matchers/built_in/be' + autoload :BeWithin, 'rspec/matchers/built_in/be_within' + autoload :Change, 'rspec/matchers/built_in/change' + autoload :Compound, 'rspec/matchers/built_in/compound' + autoload :ContainExactly, 'rspec/matchers/built_in/contain_exactly' + autoload :Cover, 'rspec/matchers/built_in/cover' + autoload :EndWith, 'rspec/matchers/built_in/start_or_end_with' + autoload :Eq, 'rspec/matchers/built_in/eq' + autoload :Eql, 'rspec/matchers/built_in/eql' + autoload :Equal, 'rspec/matchers/built_in/equal' + autoload :Exist, 'rspec/matchers/built_in/exist' + autoload :Has, 'rspec/matchers/built_in/has' + autoload :HaveAttributes, 'rspec/matchers/built_in/have_attributes' + autoload :Include, 'rspec/matchers/built_in/include' + autoload :All, 'rspec/matchers/built_in/all' + autoload :Match, 'rspec/matchers/built_in/match' + autoload :NegativeOperatorMatcher, 'rspec/matchers/built_in/operators' + autoload :OperatorMatcher, 'rspec/matchers/built_in/operators' + autoload :Output, 'rspec/matchers/built_in/output' + autoload :PositiveOperatorMatcher, 'rspec/matchers/built_in/operators' + autoload :RaiseError, 'rspec/matchers/built_in/raise_error' + autoload :RespondTo, 'rspec/matchers/built_in/respond_to' + autoload :Satisfy, 'rspec/matchers/built_in/satisfy' + autoload :StartWith, 'rspec/matchers/built_in/start_or_end_with' + autoload :ThrowSymbol, 'rspec/matchers/built_in/throw_symbol' + autoload :YieldControl, 'rspec/matchers/built_in/yield' + autoload :YieldSuccessiveArgs, 'rspec/matchers/built_in/yield' + autoload :YieldWithArgs, 'rspec/matchers/built_in/yield' + autoload :YieldWithNoArgs, 'rspec/matchers/built_in/yield' + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/all.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/all.rb new file mode 100644 index 0000000..0d8e360 --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/all.rb @@ -0,0 +1,85 @@ +module RSpec + module Matchers + module BuiltIn + # @api private + # Provides the implementation for `all`. + # Not intended to be instantiated directly. + class All < BaseMatcher + # @private + attr_reader :matcher, :failed_objects + + def initialize(matcher) + @matcher = matcher + @failed_objects = {} + end + + # @private + def does_not_match?(_actual) + raise NotImplementedError, '`expect().not_to all( matcher )` is not supported.' + end + + # @api private + # @return [String] + def failure_message + unless iterable? + return "#{improve_hash_formatting(super)}, but was not iterable" + end + + all_messages = [improve_hash_formatting(super)] + failed_objects.each do |index, matcher_failure_message| + all_messages << failure_message_for_item(index, matcher_failure_message) + end + all_messages.join("\n\n") + end + + # @api private + # @return [String] + def description + improve_hash_formatting "all #{description_of matcher}" + end + + private + + def match(_expected, _actual) + return false unless iterable? + + index_failed_objects + failed_objects.empty? + end + + def index_failed_objects + actual.each_with_index do |actual_item, index| + cloned_matcher = matcher.clone + matches = cloned_matcher.matches?(actual_item) + failed_objects[index] = cloned_matcher.failure_message unless matches + end + end + + def failure_message_for_item(index, failure_message) + failure_message = indent_multiline_message(add_new_line_if_needed(failure_message)) + indent_multiline_message("object at index #{index} failed to match:#{failure_message}") + end + + def add_new_line_if_needed(message) + message.start_with?("\n") ? message : "\n#{message}" + end + + def indent_multiline_message(message) + message = message.sub(/\n+\z/, '') + message.lines.map do |line| + line =~ /\S/ ? ' ' + line : line + end.join + end + + def initialize_copy(other) + @matcher = @matcher.clone + super + end + + def iterable? + @actual.respond_to?(:each_with_index) + end + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/base_matcher.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/base_matcher.rb new file mode 100644 index 0000000..e5acf56 --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/base_matcher.rb @@ -0,0 +1,181 @@ +module RSpec + module Matchers + module BuiltIn + # @api private + # + # Used _internally_ as a base class for matchers that ship with + # rspec-expectations and rspec-rails. + # + # ### Warning: + # + # This class is for internal use, and subject to change without notice. We + # strongly recommend that you do not base your custom matchers on this + # class. If/when this changes, we will announce it and remove this warning. + class BaseMatcher + include RSpec::Matchers::Composable + + # @api private + # Used to detect when no arg is passed to `initialize`. + # `nil` cannot be used because it's a valid value to pass. + UNDEFINED = Object.new.freeze + + # @private + attr_reader :actual, :expected, :rescued_exception + + def initialize(expected=UNDEFINED) + @expected = expected unless UNDEFINED.equal?(expected) + end + + # @api private + # Indicates if the match is successful. Delegates to `match`, which + # should be defined on a subclass. Takes care of consistently + # initializing the `actual` attribute. + def matches?(actual) + @actual = actual + match(expected, actual) + end + + # @api private + # Used to wrap a block of code that will indicate failure by + # raising one of the named exceptions. + # + # This is used by rspec-rails for some of its matchers that + # wrap rails' assertions. + def match_unless_raises(*exceptions) + exceptions.unshift Exception if exceptions.empty? + begin + yield + true + rescue *exceptions => @rescued_exception + false + end + end + + # @api private + # Generates a description using {EnglishPhrasing}. + # @return [String] + def description + desc = EnglishPhrasing.split_words(self.class.matcher_name) + desc << EnglishPhrasing.list(@expected) if defined?(@expected) + desc + end + + # @api private + # Matchers are not diffable by default. Override this to make your + # subclass diffable. + def diffable? + false + end + + # @api private + # Most matchers are value matchers (i.e. meant to work with `expect(value)`) + # rather than block matchers (i.e. meant to work with `expect { }`), so + # this defaults to false. Block matchers must override this to return true. + def supports_block_expectations? + false + end + + # @api private + def expects_call_stack_jump? + false + end + + # @private + def expected_formatted + RSpec::Support::ObjectFormatter.format(@expected) + end + + # @private + def actual_formatted + RSpec::Support::ObjectFormatter.format(@actual) + end + + # @private + def self.matcher_name + @matcher_name ||= underscore(name.split("::").last) + end + + # @private + # Borrowed from ActiveSupport. + def self.underscore(camel_cased_word) + word = camel_cased_word.to_s.dup + word.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2') + word.gsub!(/([a-z\d])([A-Z])/, '\1_\2') + word.tr!("-", "_") + word.downcase! + word + end + private_class_method :underscore + + private + + def assert_ivars(*expected_ivars) + return unless (expected_ivars - present_ivars).any? + ivar_list = EnglishPhrasing.list(expected_ivars) + raise "#{self.class.name} needs to supply#{ivar_list}" + end + + if RUBY_VERSION.to_f < 1.9 + # :nocov: + def present_ivars + instance_variables.map { |v| v.to_sym } + end + # :nocov: + else + alias present_ivars instance_variables + end + + # @private + module HashFormatting + # `{ :a => 5, :b => 2 }.inspect` produces: + # + # {:a=>5, :b=>2} + # + # ...but it looks much better as: + # + # {:a => 5, :b => 2} + # + # This is idempotent and safe to run on a string multiple times. + def improve_hash_formatting(inspect_string) + inspect_string.gsub(/(\S)=>(\S)/, '\1 => \2') + end + module_function :improve_hash_formatting + end + + include HashFormatting + + # @api private + # Provides default implementations of failure messages, based on the `description`. + module DefaultFailureMessages + # @api private + # Provides a good generic failure message. Based on `description`. + # When subclassing, if you are not satisfied with this failure message + # you often only need to override `description`. + # @return [String] + def failure_message + "expected #{description_of @actual} to #{description}" + end + + # @api private + # Provides a good generic negative failure message. Based on `description`. + # When subclassing, if you are not satisfied with this failure message + # you often only need to override `description`. + # @return [String] + def failure_message_when_negated + "expected #{description_of @actual} not to #{description}" + end + + # @private + def self.has_default_failure_messages?(matcher) + matcher.method(:failure_message).owner == self && + matcher.method(:failure_message_when_negated).owner == self + rescue NameError + false + end + end + + include DefaultFailureMessages + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/be.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/be.rb new file mode 100644 index 0000000..4d6a838 --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/be.rb @@ -0,0 +1,285 @@ +module RSpec + module Matchers + module BuiltIn + # @api private + # Provides the implementation for `be_truthy`. + # Not intended to be instantiated directly. + class BeTruthy < BaseMatcher + # @api private + # @return [String] + def failure_message + "expected: truthy value\n got: #{actual_formatted}" + end + + # @api private + # @return [String] + def failure_message_when_negated + "expected: falsey value\n got: #{actual_formatted}" + end + + private + + def match(_, actual) + !!actual + end + end + + # @api private + # Provides the implementation for `be_falsey`. + # Not intended to be instantiated directly. + class BeFalsey < BaseMatcher + # @api private + # @return [String] + def failure_message + "expected: falsey value\n got: #{actual_formatted}" + end + + # @api private + # @return [String] + def failure_message_when_negated + "expected: truthy value\n got: #{actual_formatted}" + end + + private + + def match(_, actual) + !actual + end + end + + # @api private + # Provides the implementation for `be_nil`. + # Not intended to be instantiated directly. + class BeNil < BaseMatcher + # @api private + # @return [String] + def failure_message + "expected: nil\n got: #{actual_formatted}" + end + + # @api private + # @return [String] + def failure_message_when_negated + "expected: not nil\n got: nil" + end + + private + + def match(_, actual) + actual.nil? + end + end + + # @private + module BeHelpers + private + + def args_to_s + @args.empty? ? "" : parenthesize(inspected_args.join(', ')) + end + + def parenthesize(string) + "(#{string})" + end + + def inspected_args + @args.map { |a| RSpec::Support::ObjectFormatter.format(a) } + end + + def expected_to_sentence + EnglishPhrasing.split_words(@expected) + end + + def args_to_sentence + EnglishPhrasing.list(@args) + end + end + + # @api private + # Provides the implementation for `be`. + # Not intended to be instantiated directly. + class Be < BaseMatcher + include BeHelpers + + def initialize(*args) + @args = args + end + + # @api private + # @return [String] + def failure_message + "expected #{actual_formatted} to evaluate to true" + end + + # @api private + # @return [String] + def failure_message_when_negated + "expected #{actual_formatted} to evaluate to false" + end + + [:==, :<, :<=, :>=, :>, :===, :=~].each do |operator| + define_method operator do |operand| + BeComparedTo.new(operand, operator) + end + end + + private + + def match(_, actual) + !!actual + end + end + + # @api private + # Provides the implementation of `be value`. + # Not intended to be instantiated directly. + class BeComparedTo < BaseMatcher + include BeHelpers + + def initialize(operand, operator) + @expected, @operator = operand, operator + @args = [] + end + + def matches?(actual) + @actual = actual + @actual.__send__ @operator, @expected + rescue ArgumentError + false + end + + # @api private + # @return [String] + def failure_message + "expected: #{@operator} #{expected_formatted}\n got: #{@operator.to_s.gsub(/./, ' ')} #{actual_formatted}" + end + + # @api private + # @return [String] + def failure_message_when_negated + message = "`expect(#{actual_formatted}).not_to be #{@operator} #{expected_formatted}`" + if [:<, :>, :<=, :>=].include?(@operator) + message + " not only FAILED, it is a bit confusing." + else + message + end + end + + # @api private + # @return [String] + def description + "be #{@operator} #{expected_to_sentence}#{args_to_sentence}" + end + end + + # @api private + # Provides the implementation of `be_`. + # Not intended to be instantiated directly. + class BePredicate < BaseMatcher + include BeHelpers + + def initialize(*args, &block) + @expected = parse_expected(args.shift) + @args = args + @block = block + end + + def matches?(actual, &block) + @actual = actual + @block ||= block + predicate_accessible? && predicate_matches? + end + + def does_not_match?(actual, &block) + @actual = actual + @block ||= block + predicate_accessible? && !predicate_matches? + end + + # @api private + # @return [String] + def failure_message + failure_message_expecting(true) + end + + # @api private + # @return [String] + def failure_message_when_negated + failure_message_expecting(false) + end + + # @api private + # @return [String] + def description + "#{prefix_to_sentence}#{expected_to_sentence}#{args_to_sentence}" + end + + private + + def predicate_accessible? + actual.respond_to?(predicate) || actual.respond_to?(present_tense_predicate) + end + + # support 1.8.7, evaluate once at load time for performance + if String === methods.first + # :nocov: + def private_predicate? + @actual.private_methods.include? predicate.to_s + end + # :nocov: + else + def private_predicate? + @actual.private_methods.include? predicate + end + end + + def predicate_matches? + method_name = actual.respond_to?(predicate) ? predicate : present_tense_predicate + @predicate_matches = actual.__send__(method_name, *@args, &@block) + end + + def predicate + :"#{@expected}?" + end + + def present_tense_predicate + :"#{@expected}s?" + end + + def parse_expected(expected) + @prefix, expected = prefix_and_expected(expected) + expected + end + + def prefix_and_expected(symbol) + Matchers::BE_PREDICATE_REGEX.match(symbol.to_s).captures.compact + end + + def prefix_to_sentence + EnglishPhrasing.split_words(@prefix) + end + + def failure_message_expecting(value) + validity_message || + "expected `#{actual_formatted}.#{predicate}#{args_to_s}` to return #{value}, got #{description_of @predicate_matches}" + end + + def validity_message + return nil if predicate_accessible? + + msg = "expected #{@actual} to respond to `#{predicate}`" + + if private_predicate? + msg << " but `#{predicate}` is a private method" + elsif predicate == :true? + msg << " or perhaps you meant `be true` or `be_truthy`" + elsif predicate == :false? + msg << " or perhaps you meant `be false` or `be_falsey`" + end + + msg + end + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/be_between.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/be_between.rb new file mode 100644 index 0000000..55f084e --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/be_between.rb @@ -0,0 +1,77 @@ +module RSpec + module Matchers + module BuiltIn + # @api private + # Provides the implementation for `be_between`. + # Not intended to be instantiated directly. + class BeBetween < BaseMatcher + def initialize(min, max) + @min, @max = min, max + inclusive + end + + # @api public + # Makes the between comparison inclusive. + # + # @example + # expect(3).to be_between(2, 3).inclusive + # + # @note The matcher is inclusive by default; this simply provides + # a way to be more explicit about it. + def inclusive + @less_than_operator = :<= + @greater_than_operator = :>= + @mode = :inclusive + self + end + + # @api public + # Makes the between comparison exclusive. + # + # @example + # expect(3).to be_between(2, 4).exclusive + def exclusive + @less_than_operator = :< + @greater_than_operator = :> + @mode = :exclusive + self + end + + # @api private + # @return [Boolean] + def matches?(actual) + @actual = actual + comparable? && compare + rescue ArgumentError + false + end + + # @api private + # @return [String] + def failure_message + "#{super}#{not_comparable_clause}" + end + + # @api private + # @return [String] + def description + "be between #{description_of @min} and #{description_of @max} (#{@mode})" + end + + private + + def comparable? + @actual.respond_to?(@less_than_operator) && @actual.respond_to?(@greater_than_operator) + end + + def not_comparable_clause + ", but it does not respond to `#{@less_than_operator}` and `#{@greater_than_operator}`" unless comparable? + end + + def compare + @actual.__send__(@greater_than_operator, @min) && @actual.__send__(@less_than_operator, @max) + end + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/be_instance_of.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/be_instance_of.rb new file mode 100644 index 0000000..c6968f1 --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/be_instance_of.rb @@ -0,0 +1,22 @@ +module RSpec + module Matchers + module BuiltIn + # @api private + # Provides the implementation for `be_an_instance_of`. + # Not intended to be instantiated directly. + class BeAnInstanceOf < BaseMatcher + # @api private + # @return [String] + def description + "be an instance of #{expected}" + end + + private + + def match(expected, actual) + actual.instance_of? expected + end + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/be_kind_of.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/be_kind_of.rb new file mode 100644 index 0000000..eae9b26 --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/be_kind_of.rb @@ -0,0 +1,16 @@ +module RSpec + module Matchers + module BuiltIn + # @api private + # Provides the implementation for `be_a_kind_of`. + # Not intended to be instantiated directly. + class BeAKindOf < BaseMatcher + private + + def match(expected, actual) + actual.kind_of? expected + end + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/be_within.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/be_within.rb new file mode 100644 index 0000000..27ec769 --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/be_within.rb @@ -0,0 +1,72 @@ +module RSpec + module Matchers + module BuiltIn + # @api private + # Provides the implementation for `be_within`. + # Not intended to be instantiated directly. + class BeWithin < BaseMatcher + def initialize(delta) + @delta = delta + end + + # @api public + # Sets the expected value. + def of(expected) + @expected = expected + @tolerance = @delta + @unit = '' + self + end + + # @api public + # Sets the expected value, and makes the matcher do + # a percent comparison. + def percent_of(expected) + @expected = expected + @tolerance = @delta * @expected.abs / 100.0 + @unit = '%' + self + end + + # @private + def matches?(actual) + @actual = actual + raise needs_expected unless defined? @expected + numeric? && (@actual - @expected).abs <= @tolerance + end + + # @api private + # @return [String] + def failure_message + "expected #{actual_formatted} to #{description}#{not_numeric_clause}" + end + + # @api private + # @return [String] + def failure_message_when_negated + "expected #{actual_formatted} not to #{description}" + end + + # @api private + # @return [String] + def description + "be within #{@delta}#{@unit} of #{@expected}" + end + + private + + def numeric? + @actual.respond_to?(:-) + end + + def needs_expected + ArgumentError.new "You must set an expected value using #of: be_within(#{@delta}).of(expected_value)" + end + + def not_numeric_clause + ", but it could not be treated as a numeric value" unless numeric? + end + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/change.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/change.rb new file mode 100644 index 0000000..7fff8a5 --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/change.rb @@ -0,0 +1,337 @@ +module RSpec + module Matchers + module BuiltIn + # @api private + # Provides the implementation for `change`. + # Not intended to be instantiated directly. + class Change < BaseMatcher + # @api public + # Specifies the delta of the expected change. + def by(expected_delta) + ChangeRelatively.new(@change_details, expected_delta, :by) do |actual_delta| + values_match?(expected_delta, actual_delta) + end + end + + # @api public + # Specifies a minimum delta of the expected change. + def by_at_least(minimum) + ChangeRelatively.new(@change_details, minimum, :by_at_least) do |actual_delta| + actual_delta >= minimum + end + end + + # @api public + # Specifies a maximum delta of the expected change. + def by_at_most(maximum) + ChangeRelatively.new(@change_details, maximum, :by_at_most) do |actual_delta| + actual_delta <= maximum + end + end + + # @api public + # Specifies the new value you expect. + def to(value) + ChangeToValue.new(@change_details, value) + end + + # @api public + # Specifies the original value. + def from(value) + ChangeFromValue.new(@change_details, value) + end + + # @private + def matches?(event_proc) + @event_proc = event_proc + return false unless Proc === event_proc + raise_block_syntax_error if block_given? + @change_details.perform_change(event_proc) + @change_details.changed? + end + + def does_not_match?(event_proc) + raise_block_syntax_error if block_given? + !matches?(event_proc) && Proc === event_proc + end + + # @api private + # @return [String] + def failure_message + "expected #{@change_details.message} to have changed, but #{positive_failure_reason}" + end + + # @api private + # @return [String] + def failure_message_when_negated + "expected #{@change_details.message} not to have changed, but #{negative_failure_reason}" + end + + # @api private + # @return [String] + def description + "change #{@change_details.message}" + end + + # @private + def supports_block_expectations? + true + end + + private + + def initialize(receiver=nil, message=nil, &block) + @change_details = ChangeDetails.new(receiver, message, &block) + end + + def raise_block_syntax_error + raise SyntaxError, "The block passed to the `change` matcher must " \ + "use `{ ... }` instead of do/end" + end + + def positive_failure_reason + return "was not given a block" unless Proc === @event_proc + "is still #{description_of @change_details.actual_before}" + end + + def negative_failure_reason + return "was not given a block" unless Proc === @event_proc + "did change from #{description_of @change_details.actual_before} to #{description_of @change_details.actual_after}" + end + end + + # Used to specify a relative change. + # @api private + class ChangeRelatively < BaseMatcher + def initialize(change_details, expected_delta, relativity, &comparer) + @change_details = change_details + @expected_delta = expected_delta + @relativity = relativity + @comparer = comparer + end + + # @private + def failure_message + "expected #{@change_details.message} to have changed #{@relativity.to_s.gsub("_", " ")} #{description_of @expected_delta}, but #{failure_reason}" + end + + # @private + def matches?(event_proc) + @event_proc = event_proc + return false unless Proc === event_proc + @change_details.perform_change(event_proc) + @comparer.call(@change_details.actual_delta) + end + + # @private + def does_not_match?(_event_proc) + raise NotImplementedError, "`expect { }.not_to change { }.#{@relativity}()` is not supported" + end + + # @private + def description + "change #{@change_details.message} #{@relativity.to_s.gsub("_", " ")} #{description_of @expected_delta}" + end + + # @private + def supports_block_expectations? + true + end + + private + + def failure_reason + return "was not given a block" unless Proc === @event_proc + "was changed by #{description_of @change_details.actual_delta}" + end + end + + # @api private + # Base class for specifying a change from and/or to specific values. + class SpecificValuesChange < BaseMatcher + # @private + MATCH_ANYTHING = ::Object.ancestors.last + + def initialize(change_details, from, to) + @change_details = change_details + @expected_before = from + @expected_after = to + end + + # @private + def matches?(event_proc) + @event_proc = event_proc + return false unless Proc === event_proc + @change_details.perform_change(event_proc) + @change_details.changed? && matches_before? && matches_after? + end + + # @private + def description + "change #{@change_details.message} #{change_description}" + end + + # @private + def failure_message + return not_given_a_block_failure unless Proc === @event_proc + return before_value_failure unless matches_before? + return did_not_change_failure unless @change_details.changed? + after_value_failure + end + + # @private + def supports_block_expectations? + true + end + + private + + def matches_before? + values_match?(@expected_before, @change_details.actual_before) + end + + def matches_after? + values_match?(@expected_after, @change_details.actual_after) + end + + def before_value_failure + "expected #{@change_details.message} to have initially been #{description_of @expected_before}, but was #{description_of @change_details.actual_before}" + end + + def after_value_failure + "expected #{@change_details.message} to have changed to #{description_of @expected_after}, but is now #{description_of @change_details.actual_after}" + end + + def did_not_change_failure + "expected #{@change_details.message} to have changed #{change_description}, but did not change" + end + + def did_change_failure + "expected #{@change_details.message} not to have changed, but did change from #{description_of @change_details.actual_before} to #{description_of @change_details.actual_after}" + end + + def not_given_a_block_failure + "expected #{@change_details.message} to have changed #{change_description}, but was not given a block" + end + end + + # @api private + # Used to specify a change from a specific value + # (and, optionally, to a specific value). + class ChangeFromValue < SpecificValuesChange + def initialize(change_details, expected_before) + @description_suffix = nil + super(change_details, expected_before, MATCH_ANYTHING) + end + + # @api public + # Specifies the new value you expect. + def to(value) + @expected_after = value + @description_suffix = " to #{description_of value}" + self + end + + # @private + def does_not_match?(event_proc) + if @description_suffix + raise NotImplementedError, "`expect { }.not_to change { }.to()` is not supported" + end + + @event_proc = event_proc + return false unless Proc === event_proc + @change_details.perform_change(event_proc) + !@change_details.changed? && matches_before? + end + + # @private + def failure_message_when_negated + return not_given_a_block_failure unless Proc === @event_proc + return before_value_failure unless matches_before? + did_change_failure + end + + private + + def change_description + "from #{description_of @expected_before}#{@description_suffix}" + end + end + + # @api private + # Used to specify a change to a specific value + # (and, optionally, from a specific value). + class ChangeToValue < SpecificValuesChange + def initialize(change_details, expected_after) + @description_suffix = nil + super(change_details, MATCH_ANYTHING, expected_after) + end + + # @api public + # Specifies the original value. + def from(value) + @expected_before = value + @description_suffix = " from #{description_of value}" + self + end + + # @private + def does_not_match?(_event_proc) + raise NotImplementedError, "`expect { }.not_to change { }.to()` is not supported" + end + + private + + def change_description + "to #{description_of @expected_after}#{@description_suffix}" + end + end + + # @private + # Encapsulates the details of the before/after values. + class ChangeDetails + attr_reader :message, :actual_before, :actual_after + + def initialize(receiver=nil, message=nil, &block) + if receiver && !message + raise( + ArgumentError, + "`change` requires either an object and message " \ + "(`change(obj, :msg)`) or a block (`change { }`). " \ + "You passed an object but no message." + ) + end + @message = message ? "##{message}" : "result" + @value_proc = block || lambda { receiver.__send__(message) } + end + + def perform_change(event_proc) + @actual_before = evaluate_value_proc + event_proc.call + @actual_after = evaluate_value_proc + end + + def changed? + @actual_before != @actual_after + end + + def actual_delta + @actual_after - @actual_before + end + + private + + def evaluate_value_proc + case val = @value_proc.call + when IO # enumerable, but we don't want to dup it. + val + when Enumerable, String + val.dup + else + val + end + end + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/compound.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/compound.rb new file mode 100644 index 0000000..2479864 --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/compound.rb @@ -0,0 +1,293 @@ +module RSpec + module Matchers + module BuiltIn + # @api private + # Base class for `and` and `or` compound matchers. + # rubocop:disable ClassLength + class Compound < BaseMatcher + # @private + attr_reader :matcher_1, :matcher_2, :evaluator + + def initialize(matcher_1, matcher_2) + @matcher_1 = matcher_1 + @matcher_2 = matcher_2 + end + + # @private + def does_not_match?(_actual) + raise NotImplementedError, "`expect(...).not_to matcher.#{conjunction} matcher` " \ + "is not supported, since it creates a bit of an ambiguity. Instead, define negated versions " \ + "of whatever matchers you wish to negate with `RSpec::Matchers.define_negated_matcher` and " \ + "use `expect(...).to matcher.#{conjunction} matcher`." + end + + # @api private + # @return [String] + def description + singleline_message(matcher_1.description, matcher_2.description) + end + + def supports_block_expectations? + matcher_supports_block_expectations?(matcher_1) && + matcher_supports_block_expectations?(matcher_2) + end + + def expects_call_stack_jump? + NestedEvaluator.matcher_expects_call_stack_jump?(matcher_1) || + NestedEvaluator.matcher_expects_call_stack_jump?(matcher_2) + end + + # @api private + # @return [Boolean] + def diffable? + matcher_is_diffable?(matcher_1) || matcher_is_diffable?(matcher_2) + end + + # @api private + # @return [RSpec::Matchers::ExpectedsForMultipleDiffs] + def expected + return nil unless evaluator + ::RSpec::Matchers::ExpectedsForMultipleDiffs.for_many_matchers(diffable_matcher_list) + end + + protected + + def diffable_matcher_list + list = [] + list.concat(diffable_matcher_list_for(matcher_1)) unless matcher_1_matches? + list.concat(diffable_matcher_list_for(matcher_2)) unless matcher_2_matches? + list + end + + private + + def initialize_copy(other) + @matcher_1 = @matcher_1.clone + @matcher_2 = @matcher_2.clone + super + end + + def match(_expected, actual) + evaluator_klass = if supports_block_expectations? && Proc === actual + NestedEvaluator + else + SequentialEvaluator + end + + @evaluator = evaluator_klass.new(actual, matcher_1, matcher_2) + end + + def indent_multiline_message(message) + message.lines.map do |line| + line =~ /\S/ ? ' ' + line : line + end.join + end + + def compound_failure_message + message_1 = matcher_1.failure_message + message_2 = matcher_2.failure_message + + if multiline?(message_1) || multiline?(message_2) + multiline_message(message_1, message_2) + else + singleline_message(message_1, message_2) + end + end + + def multiline_message(message_1, message_2) + [ + indent_multiline_message(message_1.sub(/\n+\z/, '')), + "...#{conjunction}:", + indent_multiline_message(message_2.sub(/\A\n+/, '')) + ].join("\n\n") + end + + def multiline?(message) + message.lines.count > 1 + end + + def singleline_message(message_1, message_2) + [message_1, conjunction, message_2].join(' ') + end + + def matcher_1_matches? + evaluator.matcher_matches?(matcher_1) + end + + def matcher_2_matches? + evaluator.matcher_matches?(matcher_2) + end + + def matcher_supports_block_expectations?(matcher) + matcher.supports_block_expectations? + rescue NoMethodError + false + end + + def matcher_is_diffable?(matcher) + matcher.diffable? + rescue NoMethodError + false + end + + def diffable_matcher_list_for(matcher) + return [] unless matcher_is_diffable?(matcher) + return matcher.diffable_matcher_list if Compound === matcher + [matcher] + end + + # For value expectations, we can evaluate the matchers sequentially. + class SequentialEvaluator + def initialize(actual, *) + @actual = actual + end + + def matcher_matches?(matcher) + matcher.matches?(@actual) + end + end + + # Normally, we evaluate the matching sequentially. For an expression like + # `expect(x).to foo.and bar`, this becomes: + # + # expect(x).to foo + # expect(x).to bar + # + # For block expectations, we need to nest them instead, so that + # `expect { x }.to foo.and bar` becomes: + # + # expect { + # expect { x }.to foo + # }.to bar + # + # This is necessary so that the `expect` block is only executed once. + class NestedEvaluator + def initialize(actual, matcher_1, matcher_2) + @actual = actual + @matcher_1 = matcher_1 + @matcher_2 = matcher_2 + @match_results = {} + + inner, outer = order_block_matchers + + @match_results[outer] = outer.matches?(Proc.new do |*args| + @match_results[inner] = inner.matches?(inner_matcher_block(args)) + end) + end + + def matcher_matches?(matcher) + @match_results.fetch(matcher) + end + + private + + # Some block matchers (such as `yield_xyz`) pass args to the `expect` block. + # When such a matcher is used as the outer matcher, we need to forward the + # the args on to the `expect` block. + def inner_matcher_block(outer_args) + return @actual if outer_args.empty? + + Proc.new do |*inner_args| + unless inner_args.empty? + raise ArgumentError, "(#{@matcher_1.description}) and " \ + "(#{@matcher_2.description}) cannot be combined in a compound expectation " \ + "since both matchers pass arguments to the block." + end + + @actual.call(*outer_args) + end + end + + # For a matcher like `raise_error` or `throw_symbol`, where the block will jump + # up the call stack, we need to order things so that it is the inner matcher. + # For example, we need it to be this: + # + # expect { + # expect { + # x += 1 + # raise "boom" + # }.to raise_error("boom") + # }.to change { x }.by(1) + # + # ...rather than: + # + # expect { + # expect { + # x += 1 + # raise "boom" + # }.to change { x }.by(1) + # }.to raise_error("boom") + # + # In the latter case, the after-block logic in the `change` matcher would never + # get executed because the `raise "boom"` line would jump to the `rescue` in the + # `raise_error` logic, so only the former case will work properly. + # + # This method figures out which matcher should be the inner matcher and which + # should be the outer matcher. + def order_block_matchers + return @matcher_1, @matcher_2 unless self.class.matcher_expects_call_stack_jump?(@matcher_2) + return @matcher_2, @matcher_1 unless self.class.matcher_expects_call_stack_jump?(@matcher_1) + + raise ArgumentError, "(#{@matcher_1.description}) and " \ + "(#{@matcher_2.description}) cannot be combined in a compound expectation " \ + "because they both expect a call stack jump." + end + + def self.matcher_expects_call_stack_jump?(matcher) + matcher.expects_call_stack_jump? + rescue NoMethodError + false + end + end + + # @api public + # Matcher used to represent a compound `and` expectation. + class And < self + # @api private + # @return [String] + def failure_message + if matcher_1_matches? + matcher_2.failure_message + elsif matcher_2_matches? + matcher_1.failure_message + else + compound_failure_message + end + end + + private + + def match(*) + super + matcher_1_matches? && matcher_2_matches? + end + + def conjunction + "and" + end + end + + # @api public + # Matcher used to represent a compound `or` expectation. + class Or < self + # @api private + # @return [String] + def failure_message + compound_failure_message + end + + private + + def match(*) + super + matcher_1_matches? || matcher_2_matches? + end + + def conjunction + "or" + end + end + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/contain_exactly.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/contain_exactly.rb new file mode 100644 index 0000000..30cbccd --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/contain_exactly.rb @@ -0,0 +1,253 @@ +module RSpec + module Matchers + module BuiltIn + # @api private + # Provides the implementation for `contain_exactly` and `match_array`. + # Not intended to be instantiated directly. + class ContainExactly < BaseMatcher + # @api private + # @return [String] + def failure_message + if Array === actual + message = "expected collection contained: #{description_of(safe_sort(surface_descriptions_in expected))}\n" + message += "actual collection contained: #{description_of(safe_sort(actual))}\n" + message += "the missing elements were: #{description_of(safe_sort(surface_descriptions_in missing_items))}\n" unless missing_items.empty? + message += "the extra elements were: #{description_of(safe_sort(extra_items))}\n" unless extra_items.empty? + message + else + "expected a collection that can be converted to an array with " \ + "`#to_ary` or `#to_a`, but got #{actual_formatted}" + end + end + + # @api private + # @return [String] + def failure_message_when_negated + list = EnglishPhrasing.list(surface_descriptions_in(expected)) + "expected #{actual_formatted} not to contain exactly#{list}" + end + + # @api private + # @return [String] + def description + list = EnglishPhrasing.list(surface_descriptions_in(expected)) + "contain exactly#{list}" + end + + private + + def match(_expected, _actual) + return false unless convert_actual_to_an_array + match_when_sorted? || (extra_items.empty? && missing_items.empty?) + end + + # This cannot always work (e.g. when dealing with unsortable items, + # or matchers as expected items), but it's practically free compared to + # the slowness of the full matching algorithm, and in common cases this + # works, so it's worth a try. + def match_when_sorted? + values_match?(safe_sort(expected), safe_sort(actual)) + end + + def convert_actual_to_an_array + if actual.respond_to?(:to_ary) + @actual = actual.to_ary + elsif should_enumerate?(actual) && actual.respond_to?(:to_a) + @actual = actual.to_a + else + return false + end + end + + def safe_sort(array) + array.sort + rescue Exception + array + end + + def missing_items + @missing_items ||= best_solution.unmatched_expected_indexes.map do |index| + expected[index] + end + end + + def extra_items + @extra_items ||= best_solution.unmatched_actual_indexes.map do |index| + actual[index] + end + end + + def best_solution + @best_solution ||= pairings_maximizer.find_best_solution + end + + def pairings_maximizer + @pairings_maximizer ||= begin + expected_matches = Hash[Array.new(expected.size) { |i| [i, []] }] + actual_matches = Hash[Array.new(actual.size) { |i| [i, []] }] + + expected.each_with_index do |e, ei| + actual.each_with_index do |a, ai| + next unless values_match?(e, a) + + expected_matches[ei] << ai + actual_matches[ai] << ei + end + end + + PairingsMaximizer.new(expected_matches, actual_matches) + end + end + + # Once we started supporting composing matchers, the algorithm for this matcher got + # much more complicated. Consider this expression: + # + # expect(["fool", "food"]).to contain_exactly(/foo/, /fool/) + # + # This should pass (because we can pair /fool/ with "fool" and /foo/ with "food"), but + # the original algorithm used by this matcher would pair the first elements it could + # (/foo/ with "fool"), which would leave /fool/ and "food" unmatched. When we have + # an expected element which is a matcher that matches a superset of actual items + # compared to another expected element matcher, we need to consider every possible pairing. + # + # This class is designed to maximize the number of actual/expected pairings -- or, + # conversely, to minimize the number of unpaired items. It's essentially a brute + # force solution, but with a few heuristics applied to reduce the size of the + # problem space: + # + # * Any items which match none of the items in the other list are immediately + # placed into the `unmatched_expected_indexes` or `unmatched_actual_indexes` array. + # The extra items and missing items in the matcher failure message are derived + # from these arrays. + # * Any items which reciprocally match only each other are paired up and not + # considered further. + # + # What's left is only the items which match multiple items from the other list + # (or vice versa). From here, it performs a brute-force depth-first search, + # looking for a solution which pairs all elements in both lists, or, barring that, + # that produces the fewest unmatched items. + # + # @private + class PairingsMaximizer + Solution = Struct.new(:unmatched_expected_indexes, :unmatched_actual_indexes, + :indeterminate_expected_indexes, :indeterminate_actual_indexes) do + def worse_than?(other) + unmatched_item_count > other.unmatched_item_count + end + + def candidate? + indeterminate_expected_indexes.empty? && + indeterminate_actual_indexes.empty? + end + + def ideal? + candidate? && ( + unmatched_expected_indexes.empty? || + unmatched_actual_indexes.empty? + ) + end + + def unmatched_item_count + unmatched_expected_indexes.count + unmatched_actual_indexes.count + end + + def +(derived_candidate_solution) + self.class.new( + unmatched_expected_indexes + derived_candidate_solution.unmatched_expected_indexes, + unmatched_actual_indexes + derived_candidate_solution.unmatched_actual_indexes, + # Ignore the indeterminate indexes: by the time we get here, + # we've dealt with all indeterminates. + [], [] + ) + end + end + + attr_reader :expected_to_actual_matched_indexes, :actual_to_expected_matched_indexes, :solution + + def initialize(expected_to_actual_matched_indexes, actual_to_expected_matched_indexes) + @expected_to_actual_matched_indexes = expected_to_actual_matched_indexes + @actual_to_expected_matched_indexes = actual_to_expected_matched_indexes + + unmatched_expected_indexes, indeterminate_expected_indexes = + categorize_indexes(expected_to_actual_matched_indexes, actual_to_expected_matched_indexes) + + unmatched_actual_indexes, indeterminate_actual_indexes = + categorize_indexes(actual_to_expected_matched_indexes, expected_to_actual_matched_indexes) + + @solution = Solution.new(unmatched_expected_indexes, unmatched_actual_indexes, + indeterminate_expected_indexes, indeterminate_actual_indexes) + end + + def find_best_solution + return solution if solution.candidate? + best_solution_so_far = NullSolution + + expected_index = solution.indeterminate_expected_indexes.first + actuals = expected_to_actual_matched_indexes[expected_index] + + actuals.each do |actual_index| + solution = best_solution_for_pairing(expected_index, actual_index) + return solution if solution.ideal? + best_solution_so_far = solution if best_solution_so_far.worse_than?(solution) + end + + best_solution_so_far + end + + private + + # @private + # Starting solution that is worse than any other real solution. + NullSolution = Class.new do + def self.worse_than?(_other) + true + end + end + + def categorize_indexes(indexes_to_categorize, other_indexes) + unmatched = [] + indeterminate = [] + + indexes_to_categorize.each_pair do |index, matches| + if matches.empty? + unmatched << index + elsif !reciprocal_single_match?(matches, index, other_indexes) + indeterminate << index + end + end + + return unmatched, indeterminate + end + + def reciprocal_single_match?(matches, index, other_list) + return false unless matches.one? + other_list[matches.first] == [index] + end + + def best_solution_for_pairing(expected_index, actual_index) + modified_expecteds = apply_pairing_to( + solution.indeterminate_expected_indexes, + expected_to_actual_matched_indexes, actual_index) + + modified_expecteds.delete(expected_index) + + modified_actuals = apply_pairing_to( + solution.indeterminate_actual_indexes, + actual_to_expected_matched_indexes, expected_index) + + modified_actuals.delete(actual_index) + + solution + self.class.new(modified_expecteds, modified_actuals).find_best_solution + end + + def apply_pairing_to(indeterminates, original_matches, other_list_index) + indeterminates.inject({}) do |accum, index| + accum[index] = original_matches[index] - [other_list_index] + accum + end + end + end + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/cover.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/cover.rb new file mode 100644 index 0000000..47474a2 --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/cover.rb @@ -0,0 +1,24 @@ +module RSpec + module Matchers + module BuiltIn + # @api private + # Provides the implementation for `cover`. + # Not intended to be instantiated directly. + class Cover < BaseMatcher + def initialize(*expected) + @expected = expected + end + + def matches?(range) + @actual = range + @expected.all? { |e| range.cover?(e) } + end + + def does_not_match?(range) + @actual = range + expected.none? { |e| range.cover?(e) } + end + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/eq.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/eq.rb new file mode 100644 index 0000000..f0c804a --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/eq.rb @@ -0,0 +1,40 @@ +module RSpec + module Matchers + module BuiltIn + # @api private + # Provides the implementation for `eq`. + # Not intended to be instantiated directly. + class Eq < BaseMatcher + # @api private + # @return [String] + def failure_message + "\nexpected: #{expected_formatted}\n got: #{actual_formatted}\n\n(compared using ==)\n" + end + + # @api private + # @return [String] + def failure_message_when_negated + "\nexpected: value != #{expected_formatted}\n got: #{actual_formatted}\n\n(compared using ==)\n" + end + + # @api private + # @return [String] + def description + "eq #{expected_formatted}" + end + + # @api private + # @return [Boolean] + def diffable? + true + end + + private + + def match(expected, actual) + actual == expected + end + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/eql.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/eql.rb new file mode 100644 index 0000000..b1ec6fc --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/eql.rb @@ -0,0 +1,34 @@ +module RSpec + module Matchers + module BuiltIn + # @api private + # Provides the implementation for `eql`. + # Not intended to be instantiated directly. + class Eql < BaseMatcher + # @api private + # @return [String] + def failure_message + "\nexpected: #{expected_formatted}\n got: #{actual_formatted}\n\n(compared using eql?)\n" + end + + # @api private + # @return [String] + def failure_message_when_negated + "\nexpected: value != #{expected_formatted}\n got: #{actual_formatted}\n\n(compared using eql?)\n" + end + + # @api private + # @return [Boolean] + def diffable? + true + end + + private + + def match(expected, actual) + actual.eql? expected + end + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/equal.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/equal.rb new file mode 100644 index 0000000..bbab3ed --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/equal.rb @@ -0,0 +1,81 @@ +module RSpec + module Matchers + module BuiltIn + # @api private + # Provides the implementation for `equal`. + # Not intended to be instantiated directly. + class Equal < BaseMatcher + # @api private + # @return [String] + def failure_message + if expected_is_a_literal_singleton? + simple_failure_message + else + detailed_failure_message + end + end + + # @api private + # @return [String] + def failure_message_when_negated + <<-MESSAGE + +expected not #{inspect_object(actual)} + got #{inspect_object(expected)} + +Compared using equal?, which compares object identity. + +MESSAGE + end + + # @api private + # @return [Boolean] + def diffable? + !expected_is_a_literal_singleton? + end + + private + + def match(expected, actual) + actual.equal? expected + end + + LITERAL_SINGLETONS = [true, false, nil] + + def expected_is_a_literal_singleton? + LITERAL_SINGLETONS.include?(expected) + end + + def actual_inspected + if LITERAL_SINGLETONS.include?(actual) + actual_formatted + else + inspect_object(actual) + end + end + + def simple_failure_message + "\nexpected #{expected_formatted}\n got #{actual_inspected}\n" + end + + def detailed_failure_message + <<-MESSAGE + +expected #{inspect_object(expected)} + got #{inspect_object(actual)} + +Compared using equal?, which compares object identity, +but expected and actual are not the same object. Use +`expect(actual).to eq(expected)` if you don't care about +object identity in this example. + +MESSAGE + end + + def inspect_object(o) + "#<#{o.class}:#{o.object_id}> => #{RSpec::Support::ObjectFormatter.format(o)}" + end + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/exist.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/exist.rb new file mode 100644 index 0000000..f995452 --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/exist.rb @@ -0,0 +1,86 @@ +module RSpec + module Matchers + module BuiltIn + # @api private + # Provides the implementation for `exist`. + # Not intended to be instantiated directly. + class Exist < BaseMatcher + def initialize(*expected) + @expected = expected + end + + # @api private + # @return [Boolean] + def matches?(actual) + @actual = actual + @test = ExistenceTest.new @actual, @expected + @test.valid_test? && @test.actual_exists? + end + + # @api private + # @return [Boolean] + def does_not_match?(actual) + @actual = actual + @test = ExistenceTest.new @actual, @expected + @test.valid_test? && !@test.actual_exists? + end + + # @api private + # @return [String] + def failure_message + "expected #{actual_formatted} to exist#{@test.validity_message}" + end + + # @api private + # @return [String] + def failure_message_when_negated + "expected #{actual_formatted} not to exist#{@test.validity_message}" + end + + # @api private + # Simple class for memoizing actual/expected for this matcher + # and examining the match + class ExistenceTest < Struct.new(:actual, :expected) + # @api private + # @return [Boolean] + def valid_test? + uniq_truthy_values.size == 1 + end + + # @api private + # @return [Boolean] + def actual_exists? + existence_values.first + end + + # @api private + # @return [String] + def validity_message + case uniq_truthy_values.size + when 0 + " but it does not respond to either `exist?` or `exists?`" + when 2 + " but `exist?` and `exists?` returned different values:\n\n"\ + " exist?: #{existence_values.first}\n"\ + "exists?: #{existence_values.last}" + end + end + + private + + def uniq_truthy_values + @uniq_truthy_values ||= existence_values.map { |v| !!v }.uniq + end + + def existence_values + @existence_values ||= predicates.map { |p| actual.__send__(p, *expected) } + end + + def predicates + @predicates ||= [:exist?, :exists?].select { |p| actual.respond_to?(p) } + end + end + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/has.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/has.rb new file mode 100644 index 0000000..d5ca30b --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/has.rb @@ -0,0 +1,103 @@ +module RSpec + module Matchers + module BuiltIn + # @api private + # Provides the implementation for `has_`. + # Not intended to be instantiated directly. + class Has < BaseMatcher + def initialize(method_name, *args, &block) + @method_name, @args, @block = method_name, args, block + end + + # @private + def matches?(actual, &block) + @actual = actual + @block ||= block + predicate_accessible? && predicate_matches? + end + + # @private + def does_not_match?(actual, &block) + @actual = actual + @block ||= block + predicate_accessible? && !predicate_matches? + end + + # @api private + # @return [String] + def failure_message + validity_message || "expected ##{predicate}#{failure_message_args_description} to return true, got false" + end + + # @api private + # @return [String] + def failure_message_when_negated + validity_message || "expected ##{predicate}#{failure_message_args_description} to return false, got true" + end + + # @api private + # @return [String] + def description + [method_description, args_description].compact.join(' ') + end + + private + + def predicate_accessible? + !private_predicate? && predicate_exists? + end + + # support 1.8.7, evaluate once at load time for performance + if String === methods.first + # :nocov: + def private_predicate? + @actual.private_methods.include? predicate.to_s + end + # :nocov: + else + def private_predicate? + @actual.private_methods.include? predicate + end + end + + def predicate_exists? + @actual.respond_to? predicate + end + + def predicate_matches? + @actual.__send__(predicate, *@args, &@block) + end + + def predicate + # On 1.9, there appears to be a bug where String#match can return `false` + # rather than the match data object. Changing to Regex#match appears to + # work around this bug. For an example of this bug, see: + # https://travis-ci.org/rspec/rspec-expectations/jobs/27549635 + @predicate ||= :"has_#{Matchers::HAS_REGEX.match(@method_name.to_s).captures.first}?" + end + + def method_description + @method_name.to_s.gsub('_', ' ') + end + + def args_description + return nil if @args.empty? + @args.map { |arg| RSpec::Support::ObjectFormatter.format(arg) }.join(', ') + end + + def failure_message_args_description + desc = args_description + "(#{desc})" if desc + end + + def validity_message + if private_predicate? + "expected #{@actual} to respond to `#{predicate}` but `#{predicate}` is a private method" + elsif !predicate_exists? + "expected #{@actual} to respond to `#{predicate}`" + end + end + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/have_attributes.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/have_attributes.rb new file mode 100644 index 0000000..222771c --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/have_attributes.rb @@ -0,0 +1,114 @@ +module RSpec + module Matchers + module BuiltIn + # @api private + # Provides the implementation for `have_attributes`. + # Not intended to be instantiated directly. + class HaveAttributes < BaseMatcher + # @private + attr_reader :respond_to_failed + + def initialize(expected) + @expected = expected + @values = {} + @respond_to_failed = false + @negated = false + end + + # @private + def actual + @values + end + + # @api private + # @return [Boolean] + def matches?(actual) + @actual = actual + @negated = false + return false unless respond_to_attributes? + perform_match(:all?) + end + + # @api private + # @return [Boolean] + def does_not_match?(actual) + @actual = actual + @negated = true + return false unless respond_to_attributes? + perform_match(:none?) + end + + # @api private + # @return [String] + def description + described_items = surface_descriptions_in(expected) + improve_hash_formatting "have attributes #{RSpec::Support::ObjectFormatter.format(described_items)}" + end + + # @api private + # @return [Boolean] + def diffable? + !@respond_to_failed && !@negated + end + + # @api private + # @return [String] + def failure_message + respond_to_failure_message_or do + "expected #{actual_formatted} to #{description} but had attributes #{ formatted_values }" + end + end + + # @api private + # @return [String] + def failure_message_when_negated + respond_to_failure_message_or { "expected #{actual_formatted} not to #{description}" } + end + + private + + def cache_all_values + @values = {} + expected.each do |attribute_key, _attribute_value| + actual_value = @actual.__send__(attribute_key) + @values[attribute_key] = actual_value + end + end + + def perform_match(predicate) + cache_all_values + expected.__send__(predicate) do |attribute_key, attribute_value| + actual_has_attribute?(attribute_key, attribute_value) + end + end + + def actual_has_attribute?(attribute_key, attribute_value) + values_match?(attribute_value, @values.fetch(attribute_key)) + end + + def respond_to_attributes? + matches = respond_to_matcher.matches?(@actual) + @respond_to_failed = !matches + matches + end + + def respond_to_matcher + @respond_to_matcher ||= RespondTo.new(*expected.keys).with(0).arguments + end + + def respond_to_failure_message_or + if respond_to_failed + respond_to_matcher.failure_message + else + improve_hash_formatting(yield) + end + end + + def formatted_values + values = RSpec::Support::ObjectFormatter.format(@values) + improve_hash_formatting(values) + end + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/include.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/include.rb new file mode 100644 index 0000000..7a65d10 --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/include.rb @@ -0,0 +1,130 @@ +module RSpec + module Matchers + module BuiltIn + # @api private + # Provides the implementation for `include`. + # Not intended to be instantiated directly. + class Include < BaseMatcher + def initialize(*expected) + @expected = expected + end + + # @api private + # @return [Boolean] + def matches?(actual) + perform_match(actual) { |v| v } + end + + # @api private + # @return [Boolean] + def does_not_match?(actual) + perform_match(actual) { |v| !v } + end + + # @api private + # @return [String] + def description + improve_hash_formatting("include#{readable_list_of(expected)}") + end + + # @api private + # @return [String] + def failure_message + format_failure_message("to") { super } + end + + # @api private + # @return [String] + def failure_message_when_negated + format_failure_message("not to") { super } + end + + # @api private + # @return [Boolean] + def diffable? + !diff_would_wrongly_highlight_matched_item? + end + + private + + def format_failure_message(preposition) + if actual.respond_to?(:include?) + improve_hash_formatting("expected #{description_of @actual} #{preposition} include#{readable_list_of @divergent_items}") + else + improve_hash_formatting(yield) + ", but it does not respond to `include?`" + end + end + + def readable_list_of(items) + described_items = surface_descriptions_in(items) + if described_items.all? { |item| item.is_a?(Hash) } + " #{described_items.inject(:merge).inspect}" + else + EnglishPhrasing.list(described_items) + end + end + + def perform_match(actual, &block) + @actual = actual + @divergent_items = excluded_from_actual(&block) + actual.respond_to?(:include?) && @divergent_items.empty? + end + + def excluded_from_actual + return [] unless @actual.respond_to?(:include?) + + expected.inject([]) do |memo, expected_item| + if comparing_hash_to_a_subset?(expected_item) + expected_item.each do |(key, value)| + memo << { key => value } unless yield actual_hash_includes?(key, value) + end + elsif comparing_hash_keys?(expected_item) + memo << expected_item unless yield actual_hash_has_key?(expected_item) + else + memo << expected_item unless yield actual_collection_includes?(expected_item) + end + memo + end + end + + def comparing_hash_to_a_subset?(expected_item) + actual.is_a?(Hash) && expected_item.is_a?(Hash) + end + + def actual_hash_includes?(expected_key, expected_value) + actual_value = actual.fetch(expected_key) { return false } + values_match?(expected_value, actual_value) + end + + def comparing_hash_keys?(expected_item) + actual.is_a?(Hash) && !expected_item.is_a?(Hash) + end + + def actual_hash_has_key?(expected_key) + # We check `key?` first for perf: + # `key?` is O(1), but `any?` is O(N). + actual.key?(expected_key) || + actual.keys.any? { |key| values_match?(expected_key, key) } + end + + def actual_collection_includes?(expected_item) + return true if actual.include?(expected_item) + + # String lacks an `any?` method... + return false unless actual.respond_to?(:any?) + + actual.any? { |value| values_match?(expected_item, value) } + end + + def diff_would_wrongly_highlight_matched_item? + return false unless actual.is_a?(String) && expected.is_a?(Array) + + lines = actual.split("\n") + expected.any? do |str| + actual.include?(str) && lines.none? { |line| line == str } + end + end + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/match.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/match.rb new file mode 100644 index 0000000..b8ad9f6 --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/match.rb @@ -0,0 +1,37 @@ +module RSpec + module Matchers + module BuiltIn + # @api private + # Provides the implementation for `match`. + # Not intended to be instantiated directly. + class Match < BaseMatcher + # @api private + # @return [String] + def description + "match #{surface_descriptions_in(expected).inspect}" + end + + # @api private + # @return [Boolean] + def diffable? + true + end + + private + + def match(expected, actual) + return true if values_match?(expected, actual) + return false unless can_safely_call_match?(expected, actual) + actual.match(expected) + end + + def can_safely_call_match?(expected, actual) + return false unless actual.respond_to?(:match) + + !(RSpec::Matchers.is_a_matcher?(expected) && + (String === actual || Regexp === actual)) + end + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/operators.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/operators.rb new file mode 100644 index 0000000..64f8f3b --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/operators.rb @@ -0,0 +1,128 @@ +require 'rspec/support' + +module RSpec + module Matchers + module BuiltIn + # @api private + # Provides the implementation for operator matchers. + # Not intended to be instantiated directly. + # Only available for use with `should`. + class OperatorMatcher + class << self + # @private + def registry + @registry ||= {} + end + + # @private + def register(klass, operator, matcher) + registry[klass] ||= {} + registry[klass][operator] = matcher + end + + # @private + def unregister(klass, operator) + registry[klass] && registry[klass].delete(operator) + end + + # @private + def get(klass, operator) + klass.ancestors.each do |ancestor| + matcher = registry[ancestor] && registry[ancestor][operator] + return matcher if matcher + end + + nil + end + end + + register Enumerable, '=~', BuiltIn::ContainExactly + + def initialize(actual) + @actual = actual + end + + # @private + def self.use_custom_matcher_or_delegate(operator) + define_method(operator) do |expected| + if !has_non_generic_implementation_of?(operator) && (matcher = OperatorMatcher.get(@actual.class, operator)) + @actual.__send__(::RSpec::Matchers.last_expectation_handler.should_method, matcher.new(expected)) + else + eval_match(@actual, operator, expected) + end + end + + negative_operator = operator.sub(/^=/, '!') + if negative_operator != operator && respond_to?(negative_operator) + define_method(negative_operator) do |_expected| + opposite_should = ::RSpec::Matchers.last_expectation_handler.opposite_should_method + raise "RSpec does not support `#{::RSpec::Matchers.last_expectation_handler.should_method} #{negative_operator} expected`. " \ + "Use `#{opposite_should} #{operator} expected` instead." + end + end + end + + ['==', '===', '=~', '>', '>=', '<', '<='].each do |operator| + use_custom_matcher_or_delegate operator + end + + # @private + def fail_with_message(message) + RSpec::Expectations.fail_with(message, @expected, @actual) + end + + # @api private + # @return [String] + def description + "#{@operator} #{RSpec::Support::ObjectFormatter.format(@expected)}" + end + + private + + def has_non_generic_implementation_of?(op) + Support.method_handle_for(@actual, op).owner != ::Kernel + rescue NameError + false + end + + def eval_match(actual, operator, expected) + ::RSpec::Matchers.last_matcher = self + @operator, @expected = operator, expected + __delegate_operator(actual, operator, expected) + end + end + + # @private + # Handles operator matcher for `should`. + class PositiveOperatorMatcher < OperatorMatcher + def __delegate_operator(actual, operator, expected) + if actual.__send__(operator, expected) + true + else + expected_formatted = RSpec::Support::ObjectFormatter.format(expected) + actual_formatted = RSpec::Support::ObjectFormatter.format(actual) + + if ['==', '===', '=~'].include?(operator) + fail_with_message("expected: #{expected_formatted}\n got: #{actual_formatted} (using #{operator})") + else + fail_with_message("expected: #{operator} #{expected_formatted}\n got: #{operator.gsub(/./, ' ')} #{actual_formatted}") + end + end + end + end + + # @private + # Handles operator matcher for `should_not`. + class NegativeOperatorMatcher < OperatorMatcher + def __delegate_operator(actual, operator, expected) + return false unless actual.__send__(operator, expected) + + expected_formatted = RSpec::Support::ObjectFormatter.format(expected) + actual_formatted = RSpec::Support::ObjectFormatter.format(actual) + + fail_with_message("expected not: #{operator} #{expected_formatted}\n got: #{operator.gsub(/./, ' ')} #{actual_formatted}") + end + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/output.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/output.rb new file mode 100644 index 0000000..be100a2 --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/output.rb @@ -0,0 +1,200 @@ +require 'stringio' + +module RSpec + module Matchers + module BuiltIn + # @api private + # Provides the implementation for `output`. + # Not intended to be instantiated directly. + class Output < BaseMatcher + def initialize(expected) + @expected = expected + @actual = "" + @block = nil + @stream_capturer = NullCapture + end + + def matches?(block) + @block = block + return false unless Proc === block + @actual = @stream_capturer.capture(block) + @expected ? values_match?(@expected, @actual) : captured? + end + + def does_not_match?(block) + !matches?(block) && Proc === block + end + + # @api public + # Tells the matcher to match against stdout. + # Works only when the main Ruby process prints to stdout + def to_stdout + @stream_capturer = CaptureStdout + self + end + + # @api public + # Tells the matcher to match against stderr. + # Works only when the main Ruby process prints to stderr + def to_stderr + @stream_capturer = CaptureStderr + self + end + + # @api public + # Tells the matcher to match against stdout. + # Works when subprocesses print to stdout as well. + # This is significantly (~30x) slower than `to_stdout` + def to_stdout_from_any_process + @stream_capturer = CaptureStreamToTempfile.new("stdout", $stdout) + self + end + + # @api public + # Tells the matcher to match against stderr. + # Works when subprocesses print to stderr as well. + # This is significantly (~30x) slower than `to_stderr` + def to_stderr_from_any_process + @stream_capturer = CaptureStreamToTempfile.new("stderr", $stderr) + self + end + + # @api private + # @return [String] + def failure_message + "expected block to #{description}, but #{positive_failure_reason}" + end + + # @api private + # @return [String] + def failure_message_when_negated + "expected block to not #{description}, but #{negative_failure_reason}" + end + + # @api private + # @return [String] + def description + if @expected + "output #{description_of @expected} to #{@stream_capturer.name}" + else + "output to #{@stream_capturer.name}" + end + end + + # @api private + # @return [Boolean] + def diffable? + true + end + + # @api private + # Indicates this matcher matches against a block. + # @return [True] + def supports_block_expectations? + true + end + + private + + def captured? + @actual.length > 0 + end + + def positive_failure_reason + return "was not a block" unless Proc === @block + return "output #{actual_output_description}" if @expected + "did not" + end + + def negative_failure_reason + return "was not a block" unless Proc === @block + "output #{actual_output_description}" + end + + def actual_output_description + return "nothing" unless captured? + actual_formatted + end + end + + # @private + module NullCapture + def self.name + "some stream" + end + + def self.capture(_block) + raise "You must chain `to_stdout` or `to_stderr` off of the `output(...)` matcher." + end + end + + # @private + module CaptureStdout + def self.name + 'stdout' + end + + def self.capture(block) + captured_stream = StringIO.new + + original_stream = $stdout + $stdout = captured_stream + + block.call + + captured_stream.string + ensure + $stdout = original_stream + end + end + + # @private + module CaptureStderr + def self.name + 'stderr' + end + + def self.capture(block) + captured_stream = StringIO.new + + original_stream = $stderr + $stderr = captured_stream + + block.call + + captured_stream.string + ensure + $stderr = original_stream + end + end + + # @private + class CaptureStreamToTempfile < Struct.new(:name, :stream) + def capture(block) + # We delay loading tempfile until it is actually needed because + # we want to minimize stdlibs loaded so that users who use a + # portion of the stdlib can't have passing specs while forgetting + # to load it themselves. `CaptureStreamToTempfile` is rarely used + # and `tempfile` pulls in a bunch of things (delegate, tmpdir, + # thread, fileutils, etc), so it's worth delaying it until this point. + require 'tempfile' + + original_stream = stream.clone + captured_stream = Tempfile.new(name) + + begin + captured_stream.sync = true + stream.reopen(captured_stream) + block.call + captured_stream.rewind + captured_stream.read + ensure + stream.reopen(original_stream) + captured_stream.close + captured_stream.unlink + end + end + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/raise_error.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/raise_error.rb new file mode 100644 index 0000000..2434c68 --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/raise_error.rb @@ -0,0 +1,216 @@ +module RSpec + module Matchers + module BuiltIn + # @api private + # Provides the implementation for `raise_error`. + # Not intended to be instantiated directly. + # rubocop:disable ClassLength + class RaiseError + include Composable + + def initialize(expected_error_or_message=nil, expected_message=nil, &block) + @block = block + @actual_error = nil + @warn_about_bare_error = warn_about_potential_false_positives? && expected_error_or_message.nil? + + case expected_error_or_message + when nil + @expected_error, @expected_message = Exception, expected_message + when String + @expected_error, @expected_message = Exception, expected_error_or_message + else + @expected_error, @expected_message = expected_error_or_message, expected_message + end + end + + # @api public + # Specifies the expected error message. + def with_message(expected_message) + raise_message_already_set if @expected_message + @warn_about_bare_error = false + @expected_message = expected_message + self + end + + # rubocop:disable MethodLength + # @private + def matches?(given_proc, negative_expectation=false, &block) + @given_proc = given_proc + @block ||= block + @raised_expected_error = false + @with_expected_message = false + @eval_block = false + @eval_block_passed = false + + warn_about_bare_error if warning_about_bare_error && !negative_expectation + return false unless Proc === given_proc + + begin + given_proc.call + rescue Exception => @actual_error + if values_match?(@expected_error, @actual_error) || + values_match?(@expected_error, @actual_error.message) + @raised_expected_error = true + @with_expected_message = verify_message + end + end + + eval_block if !negative_expectation && ready_to_eval_block? + + expectation_matched? + end + # rubocop:enable MethodLength + + # @private + def does_not_match?(given_proc) + warn_for_false_positives + !matches?(given_proc, :negative_expectation) && Proc === given_proc + end + + # @private + def supports_block_expectations? + true + end + + def expects_call_stack_jump? + true + end + + # @api private + # @return [String] + def failure_message + @eval_block ? @actual_error.message : "expected #{expected_error}#{given_error}" + end + + # @api private + # @return [String] + def failure_message_when_negated + "expected no #{expected_error}#{given_error}" + end + + # @api private + # @return [String] + def description + "raise #{expected_error}" + end + + private + + def expectation_matched? + error_and_message_match? && block_matches? + end + + def error_and_message_match? + @raised_expected_error && @with_expected_message + end + + def block_matches? + @eval_block ? @eval_block_passed : true + end + + def ready_to_eval_block? + @raised_expected_error && @with_expected_message && @block + end + + def eval_block + @eval_block = true + begin + @block[@actual_error] + @eval_block_passed = true + rescue Exception => err + @actual_error = err + end + end + + def verify_message + return true if @expected_message.nil? + values_match?(@expected_message, @actual_error.message.to_s) + end + + def warn_for_false_positives + return unless warn_about_potential_false_positives? + expression = if expecting_specific_exception? && @expected_message + "`expect { }.not_to raise_error(SpecificErrorClass, message)`" + elsif expecting_specific_exception? + "`expect { }.not_to raise_error(SpecificErrorClass)`" + elsif @expected_message + "`expect { }.not_to raise_error(message)`" + end + + return unless expression + + warn_about_negative_false_positive expression + end + + def warn_about_potential_false_positives? + RSpec::Expectations.configuration.warn_about_potential_false_positives? + end + + def warning_about_bare_error + @warn_about_bare_error && @block.nil? + end + + def warn_about_bare_error + RSpec.warning("Using the `raise_error` matcher without providing a specific " \ + "error or message risks false positives, since `raise_error` " \ + "will match when Ruby raises a `NoMethodError`, `NameError` or " \ + "`ArgumentError`, potentially allowing the expectation to pass " \ + "without even executing the method you are intending to call. " \ + "Instead consider providing a specific error class or message. " \ + "This message can be supressed by setting: " \ + "`RSpec::Expectations.configuration.warn_about_potential_false_positives = false`") + end + + def warn_about_negative_false_positive(expression) + RSpec.warning("Using #{expression} risks false positives, since literally " \ + "any other error would cause the expectation to pass, " \ + "including those raised by Ruby (e.g. NoMethodError, NameError " \ + "and ArgumentError), meaning the code you are intending to test " \ + "may not even get reached. Instead consider using " \ + "`expect {}.not_to raise_error`. This message can be supressed by setting: " \ + "`RSpec::Expectations.configuration.warn_about_potential_false_positives = false`") + end + + def expected_error + case @expected_message + when nil + if RSpec::Support.is_a_matcher?(@expected_error) + "Exception with #{description_of(@expected_error)}" + else + description_of(@expected_error) + end + when Regexp + "#{@expected_error} with message matching #{description_of(@expected_message)}" + else + "#{@expected_error} with #{description_of(@expected_message)}" + end + end + + def format_backtrace(backtrace) + formatter = Matchers.configuration.backtrace_formatter + formatter.format_backtrace(backtrace) + end + + def given_error + return " but was not given a block" unless Proc === @given_proc + return " but nothing was raised" unless @actual_error + + backtrace = format_backtrace(@actual_error.backtrace) + [ + ", got #{description_of(@actual_error)} with backtrace:", + *backtrace + ].join("\n # ") + end + + def expecting_specific_exception? + @expected_error != Exception + end + + def raise_message_already_set + raise "`expect { }.to raise_error(message).with_message(message)` is not valid. The matcher only allows the expected message to be specified once" + end + end + # rubocop:enable ClassLength + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/respond_to.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/respond_to.rb new file mode 100644 index 0000000..9341fad --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/respond_to.rb @@ -0,0 +1,90 @@ +RSpec::Support.require_rspec_support "method_signature_verifier" + +module RSpec + module Matchers + module BuiltIn + # @api private + # Provides the implementation for `respond_to`. + # Not intended to be instantiated directly. + class RespondTo < BaseMatcher + def initialize(*names) + @names = names + @expected_arity = nil + end + + # @api public + # Specifies the number of expected arguments. + # + # @example + # expect(obj).to respond_to(:message).with(3).arguments + def with(n) + @expected_arity = n + self + end + + # @api public + # No-op. Intended to be used as syntactic sugar when using `with`. + # + # @example + # expect(obj).to respond_to(:message).with(3).arguments + def argument + self + end + alias :arguments :argument + + # @private + def matches?(actual) + find_failing_method_names(actual, :reject).empty? + end + + # @private + def does_not_match?(actual) + find_failing_method_names(actual, :select).empty? + end + + # @api private + # @return [String] + def failure_message + "expected #{actual_formatted} to respond to #{@failing_method_names.map { |name| description_of(name) }.join(', ')}#{with_arity}" + end + + # @api private + # @return [String] + def failure_message_when_negated + failure_message.sub(/to respond to/, 'not to respond to') + end + + # @api private + # @return [String] + def description + "respond to #{pp_names}#{with_arity}" + end + + private + + def find_failing_method_names(actual, filter_method) + @actual = actual + @failing_method_names = @names.__send__(filter_method) do |name| + @actual.respond_to?(name) && matches_arity?(actual, name) + end + end + + def matches_arity?(actual, name) + return true unless @expected_arity + + signature = Support::MethodSignature.new(Support.method_handle_for(actual, name)) + Support::StrictSignatureVerifier.new(signature, Array.new(@expected_arity)).valid? + end + + def with_arity + return "" unless @expected_arity + " with #{@expected_arity} argument#{@expected_arity == 1 ? '' : 's'}" + end + + def pp_names + @names.length == 1 ? "##{@names.first}" : description_of(@names) + end + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/satisfy.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/satisfy.rb new file mode 100644 index 0000000..b1a0c70 --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/satisfy.rb @@ -0,0 +1,37 @@ +module RSpec + module Matchers + module BuiltIn + # @api private + # Provides the implementation for `satisfy`. + # Not intended to be instantiated directly. + class Satisfy < BaseMatcher + # @private + attr_reader :description + + def initialize(description="satisfy block", &block) + @description = description + @block = block + end + + # @private + def matches?(actual, &block) + @block = block if block + @actual = actual + @block.call(actual) + end + + # @api private + # @return [String] + def failure_message + "expected #{actual_formatted} to #{description}" + end + + # @api private + # @return [String] + def failure_message_when_negated + "expected #{actual_formatted} not to #{description}" + end + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/start_or_end_with.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/start_or_end_with.rb new file mode 100644 index 0000000..81f06c2 --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/start_or_end_with.rb @@ -0,0 +1,94 @@ +module RSpec + module Matchers + module BuiltIn + # @api private + # Base class for the `end_with` and `start_with` matchers. + # Not intended to be instantiated directly. + class StartOrEndWith < BaseMatcher + def initialize(*expected) + @actual_does_not_have_ordered_elements = false + @expected = expected.length == 1 ? expected.first : expected + end + + # @api private + # @return [String] + def failure_message + super.tap do |msg| + if @actual_does_not_have_ordered_elements + msg << ", but it does not have ordered elements" + elsif !actual.respond_to?(:[]) + msg << ", but it cannot be indexed using #[]" + end + end + end + + # @api private + # @return [String] + def description + return super unless Hash === expected + english_name = EnglishPhrasing.split_words(self.class.matcher_name) + description_of_expected = surface_descriptions_in(expected).inspect + "#{english_name} #{description_of_expected}" + end + + private + + def match(_expected, actual) + return false unless actual.respond_to?(:[]) + + begin + return true if subsets_comparable? && subset_matches? + element_matches? + rescue ArgumentError + @actual_does_not_have_ordered_elements = true + return false + end + end + + def subsets_comparable? + # Structs support the Enumerable interface but don't really have + # the semantics of a subset of a larger set... + return false if Struct === expected + + expected.respond_to?(:length) + end + end + + # For RSpec 3.1, the base class was named `StartAndEndWith`. For SemVer reasons, + # we still provide this constant until 4.0. + # @deprecated Use StartOrEndWith instead. + # @private + StartAndEndWith = StartOrEndWith + + # @api private + # Provides the implementation for `start_with`. + # Not intended to be instantiated directly. + class StartWith < StartOrEndWith + private + + def subset_matches? + values_match?(expected, actual[0, expected.length]) + end + + def element_matches? + values_match?(expected, actual[0]) + end + end + + # @api private + # Provides the implementation for `end_with`. + # Not intended to be instantiated directly. + class EndWith < StartOrEndWith + private + + def subset_matches? + values_match?(expected, actual[-expected.length, expected.length]) + end + + def element_matches? + values_match?(expected, actual[-1]) + end + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/throw_symbol.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/throw_symbol.rb new file mode 100644 index 0000000..1b6b8bc --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/throw_symbol.rb @@ -0,0 +1,132 @@ +module RSpec + module Matchers + module BuiltIn + # @api private + # Provides the implementation for `throw_symbol`. + # Not intended to be instantiated directly. + class ThrowSymbol + include Composable + + def initialize(expected_symbol=nil, expected_arg=nil) + @expected_symbol = expected_symbol + @expected_arg = expected_arg + @caught_symbol = @caught_arg = nil + end + + # rubocop:disable MethodLength + # @private + def matches?(given_proc) + @block = given_proc + return false unless Proc === given_proc + + begin + if @expected_symbol.nil? + given_proc.call + else + @caught_arg = catch :proc_did_not_throw_anything do + catch @expected_symbol do + given_proc.call + throw :proc_did_not_throw_anything, :nothing_thrown + end + end + + if @caught_arg == :nothing_thrown + @caught_arg = nil + else + @caught_symbol = @expected_symbol + end + end + + # Ruby 1.8 uses NameError with `symbol' + # Ruby 1.9 uses ArgumentError with :symbol + rescue NameError, ArgumentError => e + unless (match_data = e.message.match(/uncaught throw (`|\:)([a-zA-Z0-9_]*)(')?/)) + other_exception = e + raise + end + @caught_symbol = match_data.captures[1].to_sym + rescue => other_exception + raise + ensure + # rubocop:disable EnsureReturn + unless other_exception + if @expected_symbol.nil? + return !!@caught_symbol + else + if @expected_arg.nil? + return @caught_symbol == @expected_symbol + else + return (@caught_symbol == @expected_symbol) && values_match?(@expected_arg, @caught_arg) + end + end + end + # rubocop:enable EnsureReturn + end + end + # rubocop:enable MethodLength + + def does_not_match?(given_proc) + !matches?(given_proc) && Proc === given_proc + end + + # @api private + # @return [String] + def failure_message + "expected #{expected} to be thrown, #{actual_result}" + end + + # @api private + # @return [String] + def failure_message_when_negated + "expected #{expected('no Symbol')}#{' not' if @expected_symbol} to be thrown, #{actual_result}" + end + + # @api private + # @return [String] + def description + "throw #{expected}" + end + + # @api private + # Indicates this matcher matches against a block. + # @return [True] + def supports_block_expectations? + true + end + + def expects_call_stack_jump? + true + end + + private + + def actual_result + return "but was not a block" unless Proc === @block + "got #{caught}" + end + + def expected(symbol_desc='a Symbol') + throw_description(@expected_symbol || symbol_desc, @expected_arg) + end + + def caught + throw_description(@caught_symbol || 'nothing', @caught_arg) + end + + def throw_description(symbol, arg) + symbol_description = symbol.is_a?(String) ? symbol : description_of(symbol) + + arg_description = if arg + " with #{description_of arg}" + elsif @expected_arg && @caught_symbol == @expected_symbol + " with no argument" + else + "" + end + + symbol_description + arg_description + end + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/yield.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/yield.rb new file mode 100644 index 0000000..814172f --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/built_in/yield.rb @@ -0,0 +1,418 @@ +RSpec::Support.require_rspec_support "method_signature_verifier" + +module RSpec + module Matchers + module BuiltIn + # @private + # Object that is yielded to `expect` when one of the + # yield matchers is used. Provides information about + # the yield behavior of the object-under-test. + class YieldProbe + def self.probe(block) + probe = new(block) + return probe unless probe.has_block? + probe.assert_valid_expect_block! + block.call(probe) + probe.assert_used! + probe + end + + attr_accessor :num_yields, :yielded_args + + def initialize(block) + @block = block + @used = false + self.num_yields, self.yielded_args = 0, [] + end + + def has_block? + Proc === @block + end + + def to_proc + @used = true + + probe = self + Proc.new do |*args| + probe.num_yields += 1 + probe.yielded_args << args + nil # to indicate the block does not return a meaningful value + end + end + + def single_yield_args + yielded_args.first + end + + def yielded_once?(matcher_name) + case num_yields + when 1 then true + when 0 then false + else + raise "The #{matcher_name} matcher is not designed to be used with a " \ + "method that yields multiple times. Use the yield_successive_args " \ + "matcher for that case." + end + end + + def successive_yield_args + yielded_args.map do |arg_array| + arg_array.size == 1 ? arg_array.first : arg_array + end + end + + def assert_used! + return if @used + raise "You must pass the argument yielded to your expect block on " \ + "to the method-under-test as a block. It acts as a probe that " \ + "allows the matcher to detect whether or not the method-under-test " \ + "yields, and, if so, how many times, and what the yielded arguments " \ + "are." + end + + if RUBY_VERSION.to_f > 1.8 + def assert_valid_expect_block! + block_signature = RSpec::Support::BlockSignature.new(@block) + return if RSpec::Support::StrictSignatureVerifier.new(block_signature, [self]).valid? + raise "Your expect block must accept an argument to be used with this " \ + "matcher. Pass the argument as a block on to the method you are testing." + end + else + # :nocov: + # On 1.8.7, `lambda { }.arity` and `lambda { |*a| }.arity` both return -1, + # so we can't distinguish between accepting no args and an arg splat. + # It's OK to skip, this, though; it just provides a nice error message + # when the user forgets to accept an arg in their block. They'll still get + # the `assert_used!` error message from above, which is sufficient. + def assert_valid_expect_block! + # nothing to do + end + # :nocov: + end + end + + # @api private + # Provides the implementation for `yield_control`. + # Not intended to be instantiated directly. + class YieldControl < BaseMatcher + def initialize + at_least(:once) + end + + # @api public + # Specifies that the method is expected to yield once. + def once + exactly(1) + self + end + + # @api public + # Specifies that the method is expected to yield twice. + def twice + exactly(2) + self + end + + # @api public + # Specifies that the method is expected to yield thrice. + def thrice + exactly(3) + self + end + + # @api public + # Specifies that the method is expected to yield the given number of times. + def exactly(number) + set_expected_yields_count(:==, number) + self + end + + # @api public + # Specifies the maximum number of times the method is expected to yield + def at_most(number) + set_expected_yields_count(:<=, number) + self + end + + # @api public + # Specifies the minimum number of times the method is expected to yield + def at_least(number) + set_expected_yields_count(:>=, number) + self + end + + # @api public + # No-op. Provides syntactic sugar. + def times + self + end + + # @private + def matches?(block) + @probe = YieldProbe.probe(block) + return false unless @probe.has_block? + + @probe.num_yields.__send__(@expectation_type, @expected_yields_count) + end + + # @private + def does_not_match?(block) + !matches?(block) && @probe.has_block? + end + + # @api private + # @return [String] + def failure_message + 'expected given block to yield control' + failure_reason + end + + # @api private + # @return [String] + def failure_message_when_negated + 'expected given block not to yield control' + failure_reason + end + + # @private + def supports_block_expectations? + true + end + + private + + def set_expected_yields_count(relativity, n) + @expectation_type = relativity + @expected_yields_count = case n + when Numeric then n + when :once then 1 + when :twice then 2 + when :thrice then 3 + end + end + + def failure_reason + return " but was not a block" unless @probe.has_block? + return '' unless @expected_yields_count + " #{human_readable_expectation_type}#{human_readable_count(@expected_yields_count)}" \ + " but yielded #{human_readable_count(@probe.num_yields)}" + end + + def human_readable_expectation_type + case @expectation_type + when :<= then 'at most ' + when :>= then 'at least ' + else '' + end + end + + def human_readable_count(count) + case count + when 1 then "once" + when 2 then "twice" + else "#{count} times" + end + end + end + + # @api private + # Provides the implementation for `yield_with_no_args`. + # Not intended to be instantiated directly. + class YieldWithNoArgs < BaseMatcher + # @private + def matches?(block) + @probe = YieldProbe.probe(block) + return false unless @probe.has_block? + @probe.yielded_once?(:yield_with_no_args) && @probe.single_yield_args.empty? + end + + # @private + def does_not_match?(block) + !matches?(block) && @probe.has_block? + end + + # @private + def failure_message + "expected given block to yield with no arguments, but #{positive_failure_reason}" + end + + # @private + def failure_message_when_negated + "expected given block not to yield with no arguments, but #{negative_failure_reason}" + end + + # @private + def supports_block_expectations? + true + end + + private + + def positive_failure_reason + return "was not a block" unless @probe.has_block? + return "did not yield" if @probe.num_yields.zero? + "yielded with arguments: #{description_of @probe.single_yield_args}" + end + + def negative_failure_reason + return "was not a block" unless @probe.has_block? + "did" + end + end + + # @api private + # Provides the implementation for `yield_with_args`. + # Not intended to be instantiated directly. + class YieldWithArgs < BaseMatcher + def initialize(*args) + @expected = args + end + + # @private + def matches?(block) + @probe = YieldProbe.probe(block) + return false unless @probe.has_block? + @actual = @probe.single_yield_args + @probe.yielded_once?(:yield_with_args) && args_match? + end + + # @private + def does_not_match?(block) + !matches?(block) && @probe.has_block? + end + + # @private + def failure_message + "expected given block to yield with arguments, but #{positive_failure_reason}" + end + + # @private + def failure_message_when_negated + "expected given block not to yield with arguments, but #{negative_failure_reason}" + end + + # @private + def description + desc = "yield with args" + desc << "(#{expected_arg_description})" unless @expected.empty? + desc + end + + # @private + def supports_block_expectations? + true + end + + private + + def positive_failure_reason + return "was not a block" unless @probe.has_block? + return "did not yield" if @probe.num_yields.zero? + @positive_args_failure + end + + def expected_arg_description + @expected.map { |e| description_of e }.join(", ") + end + + def negative_failure_reason + if !@probe.has_block? + "was not a block" + elsif all_args_match? + "yielded with expected arguments" \ + "\nexpected not: #{surface_descriptions_in(@expected).inspect}" + + "\n got: #{actual_formatted}" + else + "did" + end + end + + def args_match? + if @expected.empty? # expect {...}.to yield_with_args + @positive_args_failure = "yielded with no arguments" if @actual.empty? + return !@actual.empty? + end + + unless (match = all_args_match?) + @positive_args_failure = "yielded with unexpected arguments" \ + "\nexpected: #{surface_descriptions_in(@expected).inspect}" + + "\n got: #{actual_formatted}" + end + + match + end + + def all_args_match? + values_match?(@expected, @actual) + end + end + + # @api private + # Provides the implementation for `yield_successive_args`. + # Not intended to be instantiated directly. + class YieldSuccessiveArgs < BaseMatcher + def initialize(*args) + @expected = args + end + + # @private + def matches?(block) + @probe = YieldProbe.probe(block) + return false unless @probe.has_block? + @actual = @probe.successive_yield_args + args_match? + end + + def does_not_match?(block) + !matches?(block) && @probe.has_block? + end + + # @private + def failure_message + "expected given block to yield successively with arguments, but #{positive_failure_reason}" + end + + # @private + def failure_message_when_negated + "expected given block not to yield successively with arguments, but #{negative_failure_reason}" + end + + # @private + def description + desc = "yield successive args" + desc << "(#{expected_arg_description})" + desc + end + + # @private + def supports_block_expectations? + true + end + + private + + def args_match? + values_match?(@expected, @actual) + end + + def expected_arg_description + @expected.map { |e| description_of e }.join(", ") + end + + def positive_failure_reason + return "was not a block" unless @probe.has_block? + + "yielded with unexpected arguments" \ + "\nexpected: #{surface_descriptions_in(@expected).inspect}" \ + "\n got: #{actual_formatted}" + end + + def negative_failure_reason + return "was not a block" unless @probe.has_block? + + "yielded with expected arguments" \ + "\nexpected not: #{surface_descriptions_in(@expected).inspect}" \ + "\n got: #{actual_formatted}" + end + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/composable.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/composable.rb new file mode 100644 index 0000000..61ec371 --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/composable.rb @@ -0,0 +1,184 @@ +RSpec::Support.require_rspec_support "fuzzy_matcher" + +module RSpec + module Matchers + # Mixin designed to support the composable matcher features + # of RSpec 3+. Mix it into your custom matcher classes to + # allow them to be used in a composable fashion. + # + # @api public + module Composable + # Creates a compound `and` expectation. The matcher will + # only pass if both sub-matchers pass. + # This can be chained together to form an arbitrarily long + # chain of matchers. + # + # @example + # expect(alphabet).to start_with("a").and end_with("z") + # expect(alphabet).to start_with("a") & end_with("z") + # + # @note The negative form (`expect(...).not_to matcher.and other`) + # is not supported at this time. + def and(matcher) + BuiltIn::Compound::And.new self, matcher + end + alias & and + + # Creates a compound `or` expectation. The matcher will + # pass if either sub-matcher passes. + # This can be chained together to form an arbitrarily long + # chain of matchers. + # + # @example + # expect(stoplight.color).to eq("red").or eq("green").or eq("yellow") + # expect(stoplight.color).to eq("red") | eq("green") | eq("yellow") + # + # @note The negative form (`expect(...).not_to matcher.or other`) + # is not supported at this time. + def or(matcher) + BuiltIn::Compound::Or.new self, matcher + end + alias | or + + # Delegates to `#matches?`. Allows matchers to be used in composable + # fashion and also supports using matchers in case statements. + def ===(value) + matches?(value) + end + + private + + # This provides a generic way to fuzzy-match an expected value against + # an actual value. It understands nested data structures (e.g. hashes + # and arrays) and is able to match against a matcher being used as + # the expected value or within the expected value at any level of + # nesting. + # + # Within a custom matcher you are encouraged to use this whenever your + # matcher needs to match two values, unless it needs more precise semantics. + # For example, the `eq` matcher _does not_ use this as it is meant to + # use `==` (and only `==`) for matching. + # + # @param expected [Object] what is expected + # @param actual [Object] the actual value + # + # @!visibility public + def values_match?(expected, actual) + expected = with_matchers_cloned(expected) + Support::FuzzyMatcher.values_match?(expected, actual) + end + + # Returns the description of the given object in a way that is + # aware of composed matchers. If the object is a matcher with + # a `description` method, returns the description; otherwise + # returns `object.inspect`. + # + # You are encouraged to use this in your custom matcher's + # `description`, `failure_message` or + # `failure_message_when_negated` implementation if you are + # supporting matcher arguments. + # + # @!visibility public + def description_of(object) + RSpec::Support::ObjectFormatter.format(object) + end + + # Transforms the given data structue (typically a hash or array) + # into a new data structure that, when `#inspect` is called on it, + # will provide descriptions of any contained matchers rather than + # the normal `#inspect` output. + # + # You are encouraged to use this in your custom matcher's + # `description`, `failure_message` or + # `failure_message_when_negated` implementation if you are + # supporting any arguments which may be a data structure + # containing matchers. + # + # @!visibility public + def surface_descriptions_in(item) + if Matchers.is_a_describable_matcher?(item) + DescribableItem.new(item) + elsif Hash === item + Hash[surface_descriptions_in(item.to_a)] + elsif Struct === item + RSpec::Support::ObjectFormatter.format(item) + elsif should_enumerate?(item) + begin + item.map { |subitem| surface_descriptions_in(subitem) } + rescue IOError # STDOUT is enumerable but `map` raises an error + RSpec::Support::ObjectFormatter.format(item) + end + else + item + end + end + + # @private + # Historically, a single matcher instance was only checked + # against a single value. Given that the matcher was only + # used once, it's been common to memoize some intermediate + # calculation that is derived from the `actual` value in + # order to reuse that intermediate result in the failure + # message. + # + # This can cause a problem when using such a matcher as an + # argument to another matcher in a composed matcher expression, + # since the matcher instance may be checked against multiple + # values and produce invalid results due to the memoization. + # + # To deal with this, we clone any matchers in `expected` via + # this method when using `values_match?`, so that any memoization + # does not "leak" between checks. + def with_matchers_cloned(object) + if Matchers.is_a_matcher?(object) + object.clone + elsif Hash === object + Hash[with_matchers_cloned(object.to_a)] + elsif Struct === object + object + elsif should_enumerate?(object) + begin + object.map { |subobject| with_matchers_cloned(subobject) } + rescue IOError # STDOUT is enumerable but `map` raises an error + object + end + else + object + end + end + + if String.ancestors.include?(Enumerable) # 1.8.7 + # :nocov: + # Strings are not enumerable on 1.9, and on 1.8 they are an infinitely + # nested enumerable: since ruby lacks a character class, it yields + # 1-character strings, which are themselves enumerable, composed of a + # a single 1-character string, which is an enumerable, etc. + # + # @api private + def should_enumerate?(item) + return false if String === item + Enumerable === item && !(Range === item) + end + # :nocov: + else + # @api private + def should_enumerate?(item) + Enumerable === item && !(Range === item) + end + end + module_function :surface_descriptions_in, :should_enumerate? + + # Wraps an item in order to surface its `description` via `inspect`. + # @api private + DescribableItem = Struct.new(:item) do + def inspect + "(#{item.description})" + end + + def pretty_print(pp) + pp.text "(#{item.description})" + end + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/dsl.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/dsl.rb new file mode 100644 index 0000000..4098d1e --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/dsl.rb @@ -0,0 +1,453 @@ +module RSpec + module Matchers + # Defines the custom matcher DSL. + module DSL + # Defines a custom matcher. + # @see RSpec::Matchers + def define(name, &declarations) + warn_about_block_args(name, declarations) + define_method name do |*expected, &block_arg| + RSpec::Matchers::DSL::Matcher.new(name, declarations, self, *expected, &block_arg) + end + end + alias_method :matcher, :define + + private + + if Proc.method_defined?(:parameters) + def warn_about_block_args(name, declarations) + declarations.parameters.each do |type, arg_name| + next unless type == :block + RSpec.warning("Your `#{name}` custom matcher receives a block argument (`#{arg_name}`), " \ + "but due to limitations in ruby, RSpec cannot provide the block. Instead, " \ + "use the `block_arg` method to access the block") + end + end + else + # :nocov: + def warn_about_block_args(*) + # There's no way to detect block params on 1.8 since the method reflection APIs don't expose it + end + # :nocov: + end + + RSpec.configure { |c| c.extend self } if RSpec.respond_to?(:configure) + + # Contains the methods that are available from within the + # `RSpec::Matchers.define` DSL for creating custom matchers. + module Macros + # Stores the block that is used to determine whether this matcher passes + # or fails. The block should return a boolean value. When the matcher is + # passed to `expect(...).to` and the block returns `true`, then the expectation + # passes. Similarly, when the matcher is passed to `expect(...).not_to` and the + # block returns `false`, then the expectation passes. + # + # @example + # + # RSpec::Matchers.define :be_even do + # match do |actual| + # actual.even? + # end + # end + # + # expect(4).to be_even # passes + # expect(3).not_to be_even # passes + # expect(3).to be_even # fails + # expect(4).not_to be_even # fails + # + # @yield [Object] actual the actual value (i.e. the value wrapped by `expect`) + def match(&match_block) + define_user_override(:matches?, match_block) do |actual| + begin + @actual = actual + RSpec::Support.with_failure_notifier(RAISE_NOTIFIER) do + super(*actual_arg_for(match_block)) + end + rescue RSpec::Expectations::ExpectationNotMetError + false + end + end + end + + # @private + RAISE_NOTIFIER = Proc.new { |err, _opts| raise err } + + # Use this to define the block for a negative expectation (`expect(...).not_to`) + # when the positive and negative forms require different handling. This + # is rarely necessary, but can be helpful, for example, when specifying + # asynchronous processes that require different timeouts. + # + # @yield [Object] actual the actual value (i.e. the value wrapped by `expect`) + def match_when_negated(&match_block) + define_user_override(:does_not_match?, match_block) do |actual| + @actual = actual + super(*actual_arg_for(match_block)) + end + end + + # Use this instead of `match` when the block will raise an exception + # rather than returning false to indicate a failure. + # + # @example + # + # RSpec::Matchers.define :accept_as_valid do |candidate_address| + # match_unless_raises ValidationException do |validator| + # validator.validate(candidate_address) + # end + # end + # + # expect(email_validator).to accept_as_valid("person@company.com") + # + # @yield [Object] actual the actual object (i.e. the value wrapped by `expect`) + def match_unless_raises(expected_exception=Exception, &match_block) + define_user_override(:matches?, match_block) do |actual| + @actual = actual + begin + super(*actual_arg_for(match_block)) + rescue expected_exception => @rescued_exception + false + else + true + end + end + end + + # Customizes the failure messsage to use when this matcher is + # asked to positively match. Only use this when the message + # generated by default doesn't suit your needs. + # + # @example + # + # RSpec::Matchers.define :have_strength do |expected| + # match { your_match_logic } + # + # failure_message do |actual| + # "Expected strength of #{expected}, but had #{actual.strength}" + # end + # end + # + # @yield [Object] actual the actual object (i.e. the value wrapped by `expect`) + def failure_message(&definition) + define_user_override(__method__, definition) + end + + # Customize the failure messsage to use when this matcher is asked + # to negatively match. Only use this when the message generated by + # default doesn't suit your needs. + # + # @example + # + # RSpec::Matchers.define :have_strength do |expected| + # match { your_match_logic } + # + # failure_message_when_negated do |actual| + # "Expected not to have strength of #{expected}, but did" + # end + # end + # + # @yield [Object] actual the actual object (i.e. the value wrapped by `expect`) + def failure_message_when_negated(&definition) + define_user_override(__method__, definition) + end + + # Customize the description to use for one-liners. Only use this when + # the description generated by default doesn't suit your needs. + # + # @example + # + # RSpec::Matchers.define :qualify_for do |expected| + # match { your_match_logic } + # + # description do + # "qualify for #{expected}" + # end + # end + # + # @yield [Object] actual the actual object (i.e. the value wrapped by `expect`) + def description(&definition) + define_user_override(__method__, definition) + end + + # Tells the matcher to diff the actual and expected values in the failure + # message. + def diffable + define_method(:diffable?) { true } + end + + # Declares that the matcher can be used in a block expectation. + # Users will not be able to use your matcher in a block + # expectation without declaring this. + # (e.g. `expect { do_something }.to matcher`). + def supports_block_expectations + define_method(:supports_block_expectations?) { true } + end + + # Convenience for defining methods on this matcher to create a fluent + # interface. The trick about fluent interfaces is that each method must + # return self in order to chain methods together. `chain` handles that + # for you. If the method is invoked and the + # `include_chain_clauses_in_custom_matcher_descriptions` config option + # hash been enabled, the chained method name and args will be added to the + # default description and failure message. + # + # In the common case where you just want the chained method to store some + # value(s) for later use (e.g. in `match`), you can provide one or more + # attribute names instead of a block; the chained method will store its + # arguments in instance variables with those names, and the values will + # be exposed via getters. + # + # @example + # + # RSpec::Matchers.define :have_errors_on do |key| + # chain :with do |message| + # @message = message + # end + # + # match do |actual| + # actual.errors[key] == @message + # end + # end + # + # expect(minor).to have_errors_on(:age).with("Not old enough to participate") + def chain(method_name, *attr_names, &definition) + unless block_given? ^ attr_names.any? + raise ArgumentError, "You must pass either a block or some attribute names (but not both) to `chain`." + end + + definition = assign_attributes(attr_names) if attr_names.any? + + define_user_override(method_name, definition) do |*args, &block| + super(*args, &block) + @chained_method_clauses.push([method_name, args]) + self + end + end + + def assign_attributes(attr_names) + attr_reader(*attr_names) + private(*attr_names) + + lambda do |*attr_values| + attr_names.zip(attr_values) do |attr_name, attr_value| + instance_variable_set(:"@#{attr_name}", attr_value) + end + end + end + + # assign_attributes isn't defined in the private section below because + # that makes MRI 1.9.2 emit a warning about private attributes. + private :assign_attributes + + private + + # Does the following: + # + # - Defines the named method using a user-provided block + # in @user_method_defs, which is included as an ancestor + # in the singleton class in which we eval the `define` block. + # - Defines an overriden definition for the same method + # usign the provided `our_def` block. + # - Provides a default `our_def` block for the common case + # of needing to call the user's definition with `@actual` + # as an arg, but only if their block's arity can handle it. + # + # This compiles the user block into an actual method, allowing + # them to use normal method constructs like `return` + # (e.g. for a early guard statement), while allowing us to define + # an override that can provide the wrapped handling + # (e.g. assigning `@actual`, rescueing errors, etc) and + # can `super` to the user's definition. + def define_user_override(method_name, user_def, &our_def) + @user_method_defs.__send__(:define_method, method_name, &user_def) + our_def ||= lambda { super(*actual_arg_for(user_def)) } + define_method(method_name, &our_def) + end + + # Defines deprecated macro methods from RSpec 2 for backwards compatibility. + # @deprecated Use the methods from {Macros} instead. + module Deprecated + # @deprecated Use {Macros#match} instead. + def match_for_should(&definition) + RSpec.deprecate("`match_for_should`", :replacement => "`match`") + match(&definition) + end + + # @deprecated Use {Macros#match_when_negated} instead. + def match_for_should_not(&definition) + RSpec.deprecate("`match_for_should_not`", :replacement => "`match_when_negated`") + match_when_negated(&definition) + end + + # @deprecated Use {Macros#failure_message} instead. + def failure_message_for_should(&definition) + RSpec.deprecate("`failure_message_for_should`", :replacement => "`failure_message`") + failure_message(&definition) + end + + # @deprecated Use {Macros#failure_message_when_negated} instead. + def failure_message_for_should_not(&definition) + RSpec.deprecate("`failure_message_for_should_not`", :replacement => "`failure_message_when_negated`") + failure_message_when_negated(&definition) + end + end + end + + # Defines default implementations of the matcher + # protocol methods for custom matchers. You can + # override any of these using the {RSpec::Matchers::DSL::Macros Macros} methods + # from within an `RSpec::Matchers.define` block. + module DefaultImplementations + include BuiltIn::BaseMatcher::DefaultFailureMessages + + # @api private + # Used internally by objects returns by `should` and `should_not`. + def diffable? + false + end + + # The default description. + def description + english_name = EnglishPhrasing.split_words(name) + expected_list = EnglishPhrasing.list(expected) + "#{english_name}#{expected_list}#{chained_method_clause_sentences}" + end + + # Matchers do not support block expectations by default. You + # must opt-in. + def supports_block_expectations? + false + end + + # Most matchers do not expect call stack jumps. + def expects_call_stack_jump? + false + end + + private + + def chained_method_clause_sentences + return '' unless Expectations.configuration.include_chain_clauses_in_custom_matcher_descriptions? + + @chained_method_clauses.map do |(method_name, method_args)| + english_name = EnglishPhrasing.split_words(method_name) + arg_list = EnglishPhrasing.list(method_args) + " #{english_name}#{arg_list}" + end.join + end + end + + # The class used for custom matchers. The block passed to + # `RSpec::Matchers.define` will be evaluated in the context + # of the singleton class of an instance, and will have the + # {RSpec::Matchers::DSL::Macros Macros} methods available. + class Matcher + # Provides default implementations for the matcher protocol methods. + include DefaultImplementations + + # Allows expectation expressions to be used in the match block. + include RSpec::Matchers + + # Supports the matcher composability features of RSpec 3+. + include Composable + + # Makes the macro methods available to an `RSpec::Matchers.define` block. + extend Macros + extend Macros::Deprecated + + # Exposes the value being matched against -- generally the object + # object wrapped by `expect`. + attr_reader :actual + + # Exposes the exception raised during the matching by `match_unless_raises`. + # Could be useful to extract details for a failure message. + attr_reader :rescued_exception + + # The block parameter used in the expectation + attr_reader :block_arg + + # The name of the matcher. + attr_reader :name + + # @api private + def initialize(name, declarations, matcher_execution_context, *expected, &block_arg) + @name = name + @actual = nil + @expected_as_array = expected + @matcher_execution_context = matcher_execution_context + @chained_method_clauses = [] + @block_arg = block_arg + + class << self + # See `Macros#define_user_override` above, for an explanation. + include(@user_method_defs = Module.new) + self + end.class_exec(*expected, &declarations) + end + + # Provides the expected value. This will return an array if + # multiple arguments were passed to the matcher; otherwise it + # will return a single value. + # @see #expected_as_array + def expected + if expected_as_array.size == 1 + expected_as_array[0] + else + expected_as_array + end + end + + # Returns the expected value as an an array. This exists primarily + # to aid in upgrading from RSpec 2.x, since in RSpec 2, `expected` + # always returned an array. + # @see #expected + attr_reader :expected_as_array + + # Adds the name (rather than a cryptic hex number) + # so we can identify an instance of + # the matcher in error messages (e.g. for `NoMethodError`) + def inspect + "#<#{self.class.name} #{name}>" + end + + if RUBY_VERSION.to_f >= 1.9 + # Indicates that this matcher responds to messages + # from the `@matcher_execution_context` as well. + # Also, supports getting a method object for such methods. + def respond_to_missing?(method, include_private=false) + super || @matcher_execution_context.respond_to?(method, include_private) + end + else # for 1.8.7 + # :nocov: + # Indicates that this matcher responds to messages + # from the `@matcher_execution_context` as well. + def respond_to?(method, include_private=false) + super || @matcher_execution_context.respond_to?(method, include_private) + end + # :nocov: + end + + private + + def actual_arg_for(block) + block.arity.zero? ? [] : [@actual] + end + + # Takes care of forwarding unhandled messages to the + # `@matcher_execution_context` (typically the current + # running `RSpec::Core::Example`). This is needed by + # rspec-rails so that it can define matchers that wrap + # Rails' test helper methods, but it's also a useful + # feature in its own right. + def method_missing(method, *args, &block) + if @matcher_execution_context.respond_to?(method) + @matcher_execution_context.__send__ method, *args, &block + else + super(method, *args, &block) + end + end + end + end + end +end + +RSpec::Matchers.extend RSpec::Matchers::DSL diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/english_phrasing.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/english_phrasing.rb new file mode 100644 index 0000000..1491ab6 --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/english_phrasing.rb @@ -0,0 +1,42 @@ +module RSpec + module Matchers + # Facilitates converting ruby objects to English phrases. + module EnglishPhrasing + # Converts a symbol into an English expression. + # + # split_words(:banana_creme_pie) #=> "banana creme pie" + # + def self.split_words(sym) + sym.to_s.gsub(/_/, ' ') + end + + # @note The returned string has a leading space except + # when given an empty list. + # + # Converts an object (often a collection of objects) + # into an English list. + # + # list(['banana', 'kiwi', 'mango']) + # #=> " \"banana\", \"kiwi\", and \"mango\"" + # + # Given an empty collection, returns the empty string. + # + # list([]) #=> "" + # + def self.list(obj) + return " #{RSpec::Support::ObjectFormatter.format(obj)}" if !obj || Struct === obj + items = Array(obj).map { |w| RSpec::Support::ObjectFormatter.format(w) } + case items.length + when 0 + "" + when 1 + " #{items[0]}" + when 2 + " #{items[0]} and #{items[1]}" + else + " #{items[0...-1].join(', ')}, and #{items[-1]}" + end + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/expecteds_for_multiple_diffs.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/expecteds_for_multiple_diffs.rb new file mode 100644 index 0000000..1d85c5b --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/expecteds_for_multiple_diffs.rb @@ -0,0 +1,73 @@ +module RSpec + module Matchers + # @api private + # Handles list of expected values when there is a need to render + # multiple diffs. Also can handle one value. + class ExpectedsForMultipleDiffs + # @private + # Default diff label when there is only one matcher in diff + # output + DEFAULT_DIFF_LABEL = "Diff:".freeze + + # @private + # Maximum readable matcher description length + DESCRIPTION_MAX_LENGTH = 65 + + def initialize(expected_list) + @expected_list = expected_list + end + + # @api private + # Wraps provided expected value in instance of + # ExpectedForMultipleDiffs. If provided value is already an + # ExpectedForMultipleDiffs then it just returns it. + # @param [Any] expected value to be wrapped + # @return [RSpec::Matchers::ExpectedsForMultipleDiffs] + def self.from(expected) + return expected if self === expected + new([[expected, DEFAULT_DIFF_LABEL]]) + end + + # @api private + # Wraps provided matcher list in instance of + # ExpectedForMultipleDiffs. + # @param [Array] matchers list of matchers to wrap + # @return [RSpec::Matchers::ExpectedsForMultipleDiffs] + def self.for_many_matchers(matchers) + new(matchers.map { |m| [m.expected, diff_label_for(m)] }) + end + + # @api private + # Returns message with diff(s) appended for provided differ + # factory and actual value if there are any + # @param [String] message original failure message + # @param [Proc] differ + # @param [Any] actual value + # @return [String] + def message_with_diff(message, differ, actual) + diff = diffs(differ, actual) + message = "#{message}\n#{diff}" unless diff.empty? + message + end + + private + + def self.diff_label_for(matcher) + "Diff for (#{truncated(RSpec::Support::ObjectFormatter.format(matcher))}):" + end + + def self.truncated(description) + return description if description.length <= DESCRIPTION_MAX_LENGTH + description[0...DESCRIPTION_MAX_LENGTH - 3] << "..." + end + + def diffs(differ, actual) + @expected_list.map do |(expected, diff_label)| + diff = differ.diff(actual, expected) + next if diff.strip.empty? + "#{diff_label}#{diff}" + end.compact.join("\n") + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/fail_matchers.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/fail_matchers.rb new file mode 100644 index 0000000..bdd7cda --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/fail_matchers.rb @@ -0,0 +1,42 @@ +require 'rspec/expectations' + +module RSpec + module Matchers + # Matchers for testing RSpec matchers. Include them with: + # + # require 'rspec/matchers/fail_matchers' + # RSpec.configure do |config| + # config.include RSpec::Matchers::FailMatchers + # end + # + module FailMatchers + # Matches if an expectation fails + # + # @example + # expect { some_expectation }.to fail + def fail(&block) + raise_error(RSpec::Expectations::ExpectationNotMetError, &block) + end + + # Matches if an expectation fails with the provided message + # + # @example + # expect { some_expectation }.to fail_with("some failure message") + # expect { some_expectation }.to fail_with(/some failure message/) + def fail_with(message) + raise_error(RSpec::Expectations::ExpectationNotMetError, message) + end + + # Matches if an expectation fails including the provided message + # + # @example + # expect { some_expectation }.to fail_including("portion of some failure message") + def fail_including(*snippets) + raise_error( + RSpec::Expectations::ExpectationNotMetError, + a_string_including(*snippets) + ) + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/generated_descriptions.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/generated_descriptions.rb new file mode 100644 index 0000000..a17ce18 --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/generated_descriptions.rb @@ -0,0 +1,42 @@ +module RSpec + module Matchers + class << self + # @private + attr_accessor :last_matcher, :last_expectation_handler + end + + # @api private + # Used by rspec-core to clear the state used to generate + # descriptions after an example. + def self.clear_generated_description + self.last_matcher = nil + self.last_expectation_handler = nil + end + + # @api private + # Generates an an example description based on the last expectation. + # Used by rspec-core's one-liner syntax. + def self.generated_description + return nil if last_expectation_handler.nil? + "#{last_expectation_handler.verb} #{last_description}" + end + + private + + def self.last_description + last_matcher.respond_to?(:description) ? last_matcher.description : <<-MESSAGE +When you call a matcher in an example without a String, like this: + +specify { expect(object).to matcher } + +or this: + +it { is_expected.to matcher } + +RSpec expects the matcher to have a #description method. You should either +add a String to the example this matcher is being used in, or give it a +description method. Then you won't have to suffer this lengthy warning again. +MESSAGE + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/matcher_delegator.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/matcher_delegator.rb new file mode 100644 index 0000000..e17b2ee --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/matcher_delegator.rb @@ -0,0 +1,35 @@ +module RSpec + module Matchers + # Provides the necessary plumbing to wrap a matcher with a decorator. + # @private + class MatcherDelegator + include Composable + attr_reader :base_matcher + + def initialize(base_matcher) + @base_matcher = base_matcher + end + + def method_missing(*args, &block) + base_matcher.__send__(*args, &block) + end + + if ::RUBY_VERSION.to_f > 1.8 + def respond_to_missing?(name, include_all=false) + super || base_matcher.respond_to?(name, include_all) + end + else + # :nocov: + def respond_to?(name, include_all=false) + super || base_matcher.respond_to?(name, include_all) + end + # :nocov: + end + + def initialize_copy(other) + @base_matcher = @base_matcher.clone + super + end + end + end +end diff --git a/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/matcher_protocol.rb b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/matcher_protocol.rb new file mode 100644 index 0000000..c5bc432 --- /dev/null +++ b/.bundle/gems/rspec-expectations-3.3.1/lib/rspec/matchers/matcher_protocol.rb @@ -0,0 +1,99 @@ +module RSpec + module Matchers + # rspec-expectations can work with any matcher object that implements this protocol. + # + # @note This class is not loaded at runtime by rspec-expectations. It exists + # purely to provide documentation for the matcher protocol. + class MatcherProtocol + # @!group Required Methods + + # @!method matches?(actual) + # @param actual [Object] The object being matched against. + # @yield For an expression like `expect(x).to matcher do...end`, the `do/end` + # block binds to `to`. It passes that block, if there is one, on to this method. + # @return [Boolean] true if this matcher matches the provided object. + + # @!method failure_message + # This will only be called if {#matches?} returns false. + # @return [String] Explanation for the failure. + + # @!endgroup + + # @!group Optional Methods + + # @!method does_not_match?(actual) + # In a negative expectation such as `expect(x).not_to foo`, RSpec will + # call `foo.does_not_match?(x)` if this method is defined. If it's not + # defined it will fall back to using `!foo.matches?(x)`. This allows you + # to provide custom logic for the negative case. + # + # @param actual [Object] The object being matched against. + # @yield For an expression like `expect(x).not_to matcher do...end`, the `do/end` + # block binds to `not_to`. It passes that block, if there is one, on to this method. + # @return [Boolean] true if this matcher does not match the provided object. + + # @!method failure_message_when_negated + # This will only be called when a negative match fails. + # @return [String] Explanation for the failure. + # @note This method is listed as optional because matchers do not have to + # support negation. But if your matcher does support negation, this is a + # required method -- otherwise, you'll get a `NoMethodError`. + + # @!method description + # The description is used for two things: + # + # * When using RSpec's one-liner syntax + # (e.g. `it { is_expected.to matcher }`), the description + # is used to generate the example's doc string since you + # have not provided one. + # * In a composed matcher expression, the description is used + # as part of the failure message (and description) of the outer + # matcher. + # + # @return [String] Description of the matcher. + + # @!method supports_block_expectations? + # Indicates that this matcher can be used in a block expectation expression, + # such as `expect { foo }.to raise_error`. Generally speaking, this is + # only needed for matchers which operate on a side effect of a block, rather + # than on a particular object. + # @return [Boolean] true if this matcher can be used in block expressions. + # @note If not defined, RSpec assumes a value of `false` for this method. + + # @!method expects_call_stack_jump? + # Indicates that when this matcher is used in a block expectation + # expression, it expects the block to use a ruby construct that causes + # a call stack jump (such as raising an error or throwing a symbol). + # + # This is used internally for compound block expressions, as matchers + # which expect call stack jumps must be treated with care to work properly. + # + # @return [Boolean] true if the matcher expects a call stack jump + # + # @note This method is very rarely used or needed. + # @note If not defined, RSpec assumes a value of `false` for this method. + + # @!method diffable? + # @return [Boolean] true if `actual` and `expected` can be diffed. + # Indicates that this matcher provides `actual` and `expected` attributes, + # and that the values returned by these can be usefully diffed, which can + # be included in the output. + + # @!method actual + # @return [String, Object] If an object (rather than a string) is provided, + # RSpec will use the `pp` library to convert it to multi-line output in + # order to diff. + # The actual value for the purposes of a diff. + # @note This method is required if `diffable?` returns true. + + # @!method expected + # @return [String, Object] If an object (rather than a string) is provided, + # RSpec will use the `pp` library to convert it to multi-line output in + # order to diff. + # The expected value for the purposes of a diff. + # @note This method is required if `diffable?` returns true. + + # @!endgroup + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/.document b/.bundle/gems/rspec-mocks-3.3.2/.document new file mode 100644 index 0000000..050e204 --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/.document @@ -0,0 +1,5 @@ +lib/**/*.rb +- +README.md +License.txt +Changelog.md diff --git a/.bundle/gems/rspec-mocks-3.3.2/.yardopts b/.bundle/gems/rspec-mocks-3.3.2/.yardopts new file mode 100644 index 0000000..15f63ee --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/.yardopts @@ -0,0 +1,6 @@ +--exclude features +--no-private +--markup markdown +- +Changelog.md +License.txt diff --git a/.bundle/gems/rspec-mocks-3.3.2/Changelog.md b/.bundle/gems/rspec-mocks-3.3.2/Changelog.md new file mode 100644 index 0000000..969289c --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/Changelog.md @@ -0,0 +1,965 @@ +### 3.3.2 / 2015-07-15 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.3.1...v3.3.2) + +Bug Fixes: + +* Prevent thread deadlock errors during proxy creation (e.g. when using + `before_verifying_doubles` callbacks). (Jon Rowe, #980, #979) + +### 3.3.1 / 2015-06-19 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.3.0...v3.3.1) + +Bug Fixes: + +* Fix bug in `before_verifying_double` callback logic that caused it to be called + once for each class in the ancestor list when mocking or stubbing a class. Now + it is only called for the mocked or stubbed class, as you would expect. (Sam + Phippen, #974) + +### 3.3.0 / 2015-06-12 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.2.1...v3.3.0) + +Enhancements: + +* When stubbing `new` on `MyClass` or `class_double(MyClass)`, use the + method signature from `MyClass#initialize` to verify arguments. + (Myron Marston, #886) +* Use matcher descriptions when generating description of received arguments + for mock expectation failures. (Tim Wade, #891) +* Avoid loading `stringio` unnecessarily. (Myron Marston, #894) +* Verifying doubles failure messages now distinguish between class and instance + level methods. (Tim Wade, #896, #908) +* Improve mock expectation failure messages so that it combines both + number of times and the received arguments in the output. (John Ceh, #918) +* Improve how test doubles are represented in failure messages. + (Siva Gollapalli, Myron Marston, #932) +* Rename `RSpec::Mocks::Configuration#when_declaring_verifying_double` to + `RSpec::Mocks::Configuration#before_verifying_doubles` and utilise when + verifying partial doubles. (Jon Rowe, #940) +* Use rspec-support's `ObjectFormatter` for improved formatting of + arguments in failure messages so that, for example, full time + precisions is displayed for time objects. (Gavin Miller, Myron Marston, #955) + +Bug Fixes: + +* Ensure expectations that raise eagerly also raise during RSpec verification. + This means that if exceptions are caught inside test execution the test will + still fail. (Sam Phippen, #884) +* Fix `have_received(msg).with(args).exactly(n).times` and + `receive(msg).with(args).exactly(n).times` failure messages + for when the message was received the wrong number of times with + the specified args, and also received additional times with other + arguments. Previously it confusingly listed the arguments as being + mis-matched (even when the double was allowed to receive with any + args) rather than listing the count. (John Ceh, #918) +* Fix `any_args`/`anything` support so that we avoid calling `obj == anything` + on user objects that may have improperly implemented `==` in a way that + raises errors. (Myron Marston, #924) +* Fix edge case involving stubbing the same method on a class and a subclass + which previously hit a `NoMethodError` internally in RSpec. (Myron Marston #954) +* Fix edge case where the message received count would be incremented multiple + times for one failure. (Myron Marston, #957) +* Fix failure messages for when spies received the expected message with + different arguments and also received another message. (Maurício Linhares, #960) +* Silence whitespace-only diffs. (Myron Marston, #969) + +### 3.2.1 / 2015-02-23 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.2.0...v3.2.1) + +Bug Fixes: + +* Add missing `rspec/support/differ` require so that rspec-mocks can be + used w/o rspec-expectations (which also loads the differ and hided the + fact we forgot to require it). (Myron Marston, #893) +* Revert tracking of received arg mutation (added in 3.2.0 to provide an + error in a situation we can't support) as our implementation has side + effects on non-standard objects and there's no solution we could come + up with that always works. (Myron Marston, #900) + +### 3.2.0 / 2015-02-03 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.1.3...v3.2.0) + +Enhancements: + +* Treat `any_args` as an arg splat, allowing it to match an arbitrary + number of args at any point in an arg list. (Myron Marston, #786) +* Print diffs when arguments in mock expectations are mismatched. + (Sam Phippen, #751) +* Support names for verified doubles (`instance_double`, `instance_spy`, + `class_double`, `class_spy`, `object_double`, `object_spy`). (Cezary + Baginski, #826) +* Make `array_including` and `hash_including` argument matchers composable. + (Sam Phippen, #819) +* Make `allow_any_instance_of(...).to receive(...).and_wrap_original` + work. (Ryan Fitzgerald, #869) + +Bug Fixes: + +* Provide a clear error when users wrongly combine `no_args` with + additional arguments (e.g. `expect().to receive().with(no_args, 1)`). + (Myron Marston, #786) +* Provide a clear error when users wrongly use `any_args` multiple times in the + same argument list (e.g. `expect().to receive().with(any_args, 1, any_args)`. + (Myron Marston, #786) +* Prevent the error generator from using user object #description methods. + See [#685](https://github.com/rspec/rspec-mocks/issues/685). + (Sam Phippen, #751) +* Make verified doubles declared as `(instance|class)_double(SomeConst)` + work properly when `SomeConst` has previously been stubbed. + `(instance|class)_double("SomeClass")` already worked properly. + (Myron Marston, #824) +* Add a matcher description for `receive`, `receive_messages` and + `receive_message_chain`. (Myron Marston, #828) +* Validate invocation args for null object verified doubles. + (Myron Marston, #829) +* Fix `RSpec::Mocks::Constant.original` when called with an invalid + constant to return an object indicating the constant name is invalid, + rather than blowing up. (Myron Marston, #833) +* Make `extend RSpec::Mocks::ExampleMethods` on any object work properly + to add the rspec-mocks API to that object. Previously, `expect` would + be undefined. (Myron Marston, #846) +* Fix `require 'rspec/mocks/standalone'` so that it only affects `main` + and not every object. It's really only intended to be used in a REPL + like IRB, but some gems have loaded it, thinking it needs to be loaded + when using rspec-mocks outside the context of rspec-core. + (Myron Marston, #846) +* Prevent message expectations from being modified by customization methods + (e.g. `with`) after they have been invoked. (Sam Phippen and Melanie Gilman, #837) +* Handle cases where a method stub cannot be removed due to something + external to RSpec monkeying with the method definition. This can + happen, for example, when you `file.reopen(io)` after previously + stubbing a method on the `file` object. (Myron Marston, #853) +* Provide a clear error when received message args are mutated before + a `have_received(...).with(...)` expectation. (Myron Marston, #868) + +### 3.1.3 / 2014-10-08 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.1.2...v3.1.3) + +Bug Fixes: + +* Correct received messages count when used with `have_received` matcher. + (Jon Rowe, #793) +* Provide a clear error message when you use `allow_any_instance_of(...)` or + `expect_any_instance_of(...)` with the `have_received` matcher (they are + not intended to be used together and previously caused an odd internal + failure in rspec-mocks). (Jon Rowe, #799). +* Fix verified double `with` verification so that it applies to method + stubs. (Myron Marston, #790) + +### 3.1.2 / 2014-09-26 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.1.1...v3.1.2) + +Bug Fixes: + +* Provide a clear error message when you use `allow(...)` with the + `have_received` matcher (they are not intended to be used together + and previously caused an odd internal failure in rspec-mocks). (Jon Rowe, #788). + +### 3.1.1 / 2014-09-18 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.1.0...v3.1.1) + +Bug Fixes: + +* Prevent included modules being detected as prepended modules on Ruby 2.0 + when using `any_instance_of(...)`. (Tony Novak, #781) + +### 3.1.0 / 2014-09-04 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.0.4...v3.1.0) + +Enhancements: + +* Add spying methods (`spy`, `ìnstance_spy`, `class_spy` and `object_spy`) + which create doubles as null objects for use with spying in testing. (Sam + Phippen, #671) +* `have_received` matcher will raise "does not implement" errors correctly when + used with verifying doubles and partial doubles. (Xavier Shay, #722) +* Allow matchers to be used in place of keyword arguments in `with` + expectations. (Xavier Shay, #726) +* Add `thrice` modifier to message expectation interface as a synonym + for `exactly(3).times`. (Dennis Taylor, #753) +* Add more `thrice` synonyms e.g. `.at_least(:thrice)`, `.at_most(:thrice)`, + `receive(...).thrice` and `have_received(...).thrice`. (Jon Rowe, #754) +* Add `and_wrap_original` modifier for partial doubles to mutate the + response from a method. (Jon Rowe, #762) + +Bug Fixes: + +* Remove `any_number_of_times` from `any_instance` recorders that were + erroneously causing mention of the method in documentation. (Jon Rowe, #760) +* Prevent included modules being detected as prepended modules on Ruby 2.0. + (Eugene Kenny, #771) + +### 3.0.4 / 2014-08-14 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.0.3...v3.0.4) + +Bug Fixes: + +* Restore `kind_of(x)` to match using `arg.kind_of?(x)` (like RSpec 2) + rather than `x === arg`. (Jon Rowe, #750) + +### 3.0.3 / 2014-07-21 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.0.2...v3.0.3) + +Bug Fixes: + +* `have_received` matcher will raise "does not implement" errors correctly when + used with verifying doubles and partial doubles. (Xavier Shay, #722) +* Make `double.as_null_object.dup` and `double.as_null_object.clone` + make the copies be null objects. (Myron Marston, #732) +* Don't inadvertently define `BasicObject` in 1.8.7. (Chris Griego, #739) + +### 3.0.2 / 2014-06-19 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.0.1...v3.0.2) + +Bug Fixes: + +* Fix edge case that triggered "can't add a new key into hash during + iteration" during mock verification. (Sam Phippen, Myron Marston, #711) +* Fix verifying doubles so that when they accidentally leak into another + example, they provide the same clear error message that normal doubles + do. (Myron Marston, #718) +* Make `ordered` work with exact receive counts. (Sam Phippen, #713) + +### 3.0.1 / 2014-06-07 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.0.0...v3.0.1) + +Bug Fixes: + +* Fix `receive_message_chain(...)` so that it supports `with` just like + `stub_chain` did. (Jon Rowe, #697) +* Fix regression in `expect_any_instance_of` so that it expects the + message on _any_ instance rather than on _every_ instance. + (Myron Marston, #699) + +### 3.0.0 / 2014-06-01 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.0.0.rc1...v3.0.0) + +Bug Fixes: + +* Fix module prepend detection to work properly on ruby 2.0 for a case + where a module is extended onto itself. (Myron Marston) +* Fix `transfer_nested_constants` option so that transferred constants + get properly reset at the end of the example. (Myron Marston) +* Fix `config.transfer_nested_constants = true` so that you don't + erroneously get errors when stubbing a constant that is not a module + or a class. (Myron Marston) +* Fix regression that caused `double(:class => SomeClass)` to later + trigger infinite recursion. (Myron Marston) +* Fix bug in `have_received(...).with(...).ordered` where it was not + taking the args into account when checking the order. (Myron Marston) +* Fix bug in `have_received(...).ordered` where it was wrongly + considering stubs when checking the order. (Myron Marston) +* Message expectation matchers now show descriptions from argument + matchers when their expectations aren't met. (Jon Rowe) +* Display warning when encountering `TypeError` during instance method + staging on 2.0.0-p195, suffers from https://bugs.ruby-lang.org/issues/8686 + too. (Cezar Halmagean). + +### 3.0.0.rc1 / 2014-05-18 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.0.0.beta2...v3.0.0.rc1) + +Breaking Changes for 3.0.0: + +* Remove `RSpec::Mocks::TestDouble.extend_onto`. (Myron Marston) +* Remove `RSpec::Mocks::ConstantStubber`. (Jon Rowe) +* Make monkey-patch of Marshal to support dumping of stubbed objects opt-in. + (Xavier Shay) + +Enhancements: + +* Instead of crashing when cleaning up stub methods on a frozen object, it now + issues a warning explaining that it's impossible to clean up the stubs. + (Justin Coyne and Sam Phippen) +* Add meaningful descriptions to `anything`, `duck_type` and `instance_of` argument + matchers. (Jon Rowe) + +Bug Fixes: + +* Fix regression introduced in 3.0.0.beta2 that caused + `double.as_null_object.to_str` to return the double rather + than a string. (Myron Marston) +* Fix bug in `expect(dbl).to receive_message_chain(:foo, :bar)` where it was + not setting an expectation for the last message in the chain. + (Jonathan del Strother) +* Allow verifying partial doubles to have private methods stubbed. (Xavier Shay) +* Fix bug with allowing/expecting messages on Class objects which have had + their singleton class prepended to. (Jon Rowe) +* Fix an issue with 1.8.7 not running implementation blocks on partial doubles. + (Maurício Linhares) +* Prevent `StackLevelTooDeep` errors when stubbing an `any_instance` method that's + accessed in `inspect` by providing our own inspect output. (Jon Rowe) +* Fix bug in `any_instance` logic that did not allow you to mock or stub + private methods if `verify_partial_doubles` was configured. (Oren Dobzinski) +* Include useful error message when trying to observe an unimplemented method + on an any instance. (Xavier Shay) +* Fix `and_call_original` to work properly when multiple classes in an + inheritance hierarchy have been stubbed with the same method. (Myron Marston) +* Fix `any_instance` so that it updates existing instances that have + already been stubbed. (Myron Marston) +* Fix verified doubles so that their class name is included in failure + messages. (Myron Marston) +* Fix `expect_any_instance_of` so that when the message is received + on an individual instance that has been directly stubbed, it still + satisfies the expectation. (Sam Phippen, Myron Marston) +* Explicitly disallow using `any_instance` to mock or stub a method + that is defined on a module prepended onto the class. This triggered + `SystemStackError` before and is very hard to support so we are not + supporting it at this time. (Myron Marston) + +### 3.0.0.beta2 / 2014-02-17 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.0.0.beta1...v3.0.0.beta2) + +Breaking Changes for 3.0.0: + +* Rename `RSpec::Mocks::Mock` to `RSpec::Mocks::Double`. (Myron Marston) +* Change how to integrate rspec-mocks in other test frameworks. You now + need to include `RSpec::Mocks::ExampleMethods` in your test context. + (Myron Marston) +* Prevent RSpec mocks' doubles and partial doubles from being used outside of + the per-test lifecycle (e.g. from a `before(:all)` hook). (Sam Phippen) +* Remove the `host` argument of `RSpec::Mocks.setup`. Instead + `RSpec::Mocks::ExampleMethods` should be included directly in the scope where + RSpec's mocking capabilities are used. (Sam Phippen) +* Make test doubles raise errors if you attempt to use them after they + get reset, to help surface issues when you accidentally retain + references to test doubles and attempt to reuse them in another + example. (Myron Marston) +* Remove support for `and_return { value }` and `and_return` without arguments. (Yuji Nakayama) + +Enhancements: + +* Add `receive_message_chain` which provides the functionality of the old + `stub_chain` for the new allow/expect syntax. Use it like so: `allow(...).to + receive_message_chain(:foo, :bar, :bazz)`. (Sam Phippen). +* Change argument matchers to use `===` as their primary matching + protocol, since their semantics mirror that of a case or rescue statement + (which uses `===` for matching). (Myron Marston) +* Add `RSpec::Mocks.with_temporary_scope`, which allows you to create + temporary rspec-mocks scopes in arbitrary places (such as a + `before(:all)` hook). (Myron Marston) +* Support keyword arguments when checking arity with verifying doubles. + (Xavier Shay) + +Bug Fixes: + +* Fix regression in 3.0.0.beta1 that caused `double("string_name" => :value)` + to stop working. (Xavier Shay) +* Fix the way rspec-mocks and rspec-core interact so that if users + define a `let` with the same name as one of the methods + from `RSpec::Mocks::ArgumentMatchers`, the user's `let` takes + precedence. (Michi Huber, Myron Marston) +* Fix verified doubles so that their methods match the visibility + (public, protected or private) of the interface they verify + against. (Myron Marston) +* Fix verified null object doubles so that they do not wrongly + report that they respond to anything. They only respond to methods + available on the interface they verify against. (Myron Marston) +* Fix deprecation warning for use of old `:should` syntax w/o explicit + config so that it no longer is silenced by an extension gem such + as rspec-rails when it calls `config.add_stub_and_should_receive_to`. + (Sam Phippen) +* Fix `expect` syntax so that it does not wrongly emit a "You're + overriding a previous implementation for this stub" warning when + you are not actually doing that. (Myron Marston) +* Fix `any_instance.unstub` when used on sub classes for whom the super + class has had `any_instance.stub` invoked on. (Jon Rowe) +* Fix regression in `stub_chain`/`receive_message_chain` that caused + it to raise an `ArgumentError` when passing args to the stubbed + methods. (Sam Phippen) +* Correct stub of undefined parent modules all the way down when stubbing a + nested constant. (Xavier Shay) +* Raise `VerifyingDoubleNotDefinedError` when a constant is not defined for + a verifying class double. (Maurício Linhares) +* Remove `Double#to_str`, which caused confusing `raise some_double` + behavior. (Maurício Linhares) + +### 3.0.0.beta1 / 2013-11-07 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.99.4...v3.0.0.beta1) + +Breaking Changes for 3.0.0: + +* Raise an explicit error if `should_not_receive(...).and_return` is used. (Sam + Phippen) +* Remove 1.8.6 workarounds. (Jon Rowe) +* Remove `stub!` and `unstub!`. (Sam Phippen) +* Remove `mock(name, methods)` and `stub(name, methods)`, leaving + `double(name, methods)` for creating test doubles. (Sam Phippen, Michi Huber) +* Remove `any_number_of_times` since `should_receive(:msg).any_number_of_times` + is really a stub in a mock's clothing. (Sam Phippen) +* Remove support for re-using the same null-object test double in multiple + examples. Test doubles are designed to only live for one example. + (Myron Marston) +* Make `at_least(0)` raise an error. (Sam Phippen) +* Remove support for `require 'spec/mocks'` which had been kept + in place for backwards compatibility with RSpec 1. (Myron Marston) +* Blocks provided to `with` are always used as implementation. (Xavier Shay) +* The config option (added in 2.99) to yield the receiver to + `any_instance` implementation blocks now defaults to "on". (Sam Phippen) + +Enhancements: + +* Allow the `have_received` matcher to use a block to set further expectations + on arguments. (Tim Cowlishaw) +* Provide `instance_double` and `class_double` to create verifying doubles, + ported from `rspec-fire`. (Xavier Shay) +* `as_null_object` on a verifying double only responds to defined methods. + (Xavier Shay) +* Provide `object_double` to create verified doubles of specific object + instances. (Xavier Shay) +* Provide `verify_partial_doubles` configuration that provides `object_double` + like verification behaviour on partial doubles. (Xavier Shay) +* Improved performance of double creation, particularly those with many + attributes. (Xavier Shay) +* Default value of `transfer_nested_constants` option for constant stubbing can + be configured. (Xavier Shay) +* Messages can be allowed or expected on in bulk via + `receive_messages(:message => :value)`. (Jon Rowe) +* `allow(Klass.any_instance)` and `expect(Klass.any_instance)` now print a + warning. This is usually a mistake, and users usually want + `allow_any_instance_of` or `expect_any_instance_of` instead. (Sam Phippen) +* `instance_double` and `class_double` raise `ArgumentError` if the underlying + module is loaded and the arity of the method being invoked does not match the + arity of the method as it is actually implemented. (Andy Lindeman) +* Spies can now check their invocation ordering is correct. (Jon Rowe) + +Deprecations: + +* Using the old `:should` syntax without explicitly configuring it + is deprecated. It will continue to work but will emit a deprecation + warning in RSpec 3 if you do not explicitly enable it. (Sam Phippen) + +Bug Fixes: + +* Fix `and_call_original` to handle a complex edge case involving + singleton class ancestors. (Marc-André Lafortune, Myron Marston) +* When generating an error message for unexpected arguments, + use `#inspect` rather than `#description` if `#description` + returns `nil` or `''` so that you still get a useful message. + (Nick DeLuca) + +### 2.99.4 / 2015-06-19 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.99.3...v2.99.4) + +Bug Fixes: + +* Add missing deprecation for using `with` with no arguments e.g. `with()`. (Yousuke, #970) + +### 2.99.3 / 2015-01-09 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.99.2...v2.99.3) + +Bug Fixes: + +* Fix regression that caused an error when a test double was deserialized from YAML. (Yuji Nakayama, #777) + +### 2.99.2 / 2014-07-21 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.99.1...v2.99.2) + +Enhancements: + +* Warn about upcoming change to `#===` matching and `DateTime#===` behaviour. + (Jon Rowe, #735) + +### 2.99.1 / 2014-06-12 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.99.0...v2.99.1) + +Bug Fixes: + +* Fix bug that caused errors at the end of each example + when a `double.as_null_object` had been frozen. (Yuji Nakayama, #698) + +Deprecations: + +* Deprecate freezing a test double. (Yuji Nakayama, #698) + +### 2.99.0 / 2014-06-01 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.99.0.rc1...v2.99.0) + +No changes. Just taking it out of pre-release. + +### 2.99.0.rc1 / 2014-05-18 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.99.0.beta2...v2.99.0.rc1) + +Deprecations: + +* Deprecate `RSpec::Mocks::TestDouble.extend_onto`. (Myron Marston) +* Deprecate `RSpec::Mocks::ConstantStubber`. (Jon Rowe) +* Deprecate `Marshal.dump` monkey-patch without opt-in. (Xavier Shay) + +### 2.99.0.beta2 / 2014-02-17 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.99.0.beta1...v2.99.0.beta2) + +Deprecations: + +* Deprecate `RSpec::Mocks::Mock` in favor of `RSpec::Mocks::Double`. + (Myron Marston) +* Deprecate the `host` argument of `RSpec::Mocks.setup`. Instead + `RSpec::Mocks::ExampleMethods` should be included directly in the scope where + RSpec's mocking capabilities are used. (Sam Phippen) +* Deprecate using any of rspec-mocks' features outside the per-test + lifecycle (e.g. from a `before(:all)` hook). (Myron Marston) +* Deprecate re-using a test double in another example. (Myron Marston) +* Deprecate `and_return { value }` and `and_return` without arguments. (Yuji Nakayama) + +### 2.99.0.beta1 / 2013-11-07 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.14.4...v2.99.0.beta1) + +Deprecations + +* Expecting to use lambdas or other strong arity implementations for stub + methods with mis-matched arity is deprecated and support for them will be + removed in 3.0. Either provide the right amount of arguments or use a weak + arity implementation (methods with splats or procs). (Jon Rowe) +* Using the same test double instance in multiple examples is deprecated. Test + doubles are only meant to live for one example. The mocks and stubs have + always been reset between examples; however, in 2.x the `as_null_object` + state was not reset and some users relied on this to have a null object + double that is used for many examples. This behavior will be removed in 3.0. + (Myron Marston) +* Print a detailed warning when an `any_instance` implementation block is used + when the new `yield_receiver_to_any_instance_implementation_blocks` config + option is not explicitly set, as RSpec 3.0 will default to enabling this new + feature. (Sam Phippen) + +Enhancements: + +* Add a config option to yield the receiver to `any_instance` implementation + blocks. (Sam Phippen) + +### 2.14.6 / 2014-02-20 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.14.5...v2.14.6) + +Bug Fixes: + +* Ensure `any_instance` method stubs and expectations are torn down regardless of + expectation failures. (Sam Phippen) + +### 2.14.5 / 2014-02-01 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.14.4...v2.14.5) + +Bug Fixes: + +* Fix regression that caused block implementations to not receive all + args on 1.8.7 if the block also receives a block, due to Proc#arity + reporting `1` no matter how many args the block receives if it + receives a block, too. (Myron Marston) + +### 2.14.4 / 2013-10-15 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.14.3...v2.14.4) + +Bug Fixes: + +* Fix issue where unstubing methods on "any instances" would not + remove stubs on existing instances (Jon Rowe) +* Fix issue with receive(:message) do ... end precedence preventing + the usage of modifications (`and_return` etc) (Jon Rowe) + +### 2.14.3 / 2013-08-08 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.14.2...v2.14.3) + +Bug Fixes: + +* Fix stubbing some instance methods for classes whose hierarchy includes + a prepended Module (Bradley Schaefer) + +### 2.14.2 / 2013-07-30 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.14.1...v2.14.2) + +Bug Fixes: + +* Fix `as_null_object` doubles so that they return `nil` from `to_ary` + (Jon Rowe). +* Fix regression in 2.14 that made `stub!` (with an implicit receiver) + return a test double rather than stub a method (Myron Marston). + +### 2.14.1 / 2013-07-07 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.14.0...v2.14.1) + +Bug Fixes: + +* Restore `double.as_null_object` behavior from 2.13 and earlier: a + double's nullness persisted between examples in earlier examples. + While this is not an intended use case (test doubles are meant to live + for only one example), we don't want to break behavior users rely + on in a minor relase. This will be deprecated in 2.99 and removed + in 3.0. (Myron Marston) + +### 2.14.0 / 2013-07-06 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.14.0.rc1...v2.14.0) + +Enhancements: + +* Document test spies in the readme. (Adarsh Pandit) +* Add an `array_including` matcher. (Sam Phippen) +* Add a syntax-agnostic API for mocking or stubbing a method. This is + intended for use by libraries such as rspec-rails that need to mock + or stub a method, and work regardless of the syntax the user has + configured (Paul Annesley, Myron Marston and Sam Phippen). + +Bug Fixes: + +* Fix `double` so that it sets up passed stubs correctly regardless of + the configured syntax (Paul Annesley). +* Allow a block implementation to be used in combination with + `and_yield`, `and_raise`, `and_return` or `and_throw`. This got fixed + in 2.13.1 but failed to get merged into master for the 2.14.0.rc1 + release (Myron Marston). +* `Marshal.dump` does not unnecessarily duplicate objects when rspec-mocks has + not been fully initialized. This could cause errors when using `spork` or + similar preloading gems (Andy Lindeman). + +### 2.14.0.rc1 / 2013-05-27 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.13.0...v2.14.0.rc1) + +Enhancements: + +* Refactor internals so that the mock proxy methods and state are held + outside of the mocked object rather than inside it. This paves the way + for future syntax enhancements and removes the need for some hacky + work arounds for `any_instance` dup'ing and `YAML` serialization, + among other things. Note that the code now relies upon `__id__` + returning a unique, consistent value for any object you want to + mock or stub (Myron Marston). +* Add support for test spies. This allows you to verify a message + was received afterwards using the `have_received` matcher. + Note that you must first stub the method or use a null double. + (Joe Ferris and Joël Quenneville) +* Make `at_least` and `at_most` style receive expectations print that they were + expecting at least or at most some number of calls, rather than just the + number of calls given in the expectation (Sam Phippen) +* Make `with` style receive expectations print the args they were expecting, and + the args that they got (Sam Phippen) +* Fix some warnings seen under ruby 2.0.0p0 (Sam Phippen). +* Add a new `:expect` syntax for message expectations + (Myron Marston and Sam Phippen). + +Bug fixes + +* Fix `any_instance` so that a frozen object can be `dup`'d when methods + have been stubbed on that type using `any_instance` (Jon Rowe). +* Fix `and_call_original` so that it properly raises an `ArgumentError` + when the wrong number of args are passed (Jon Rowe). +* Fix `double` on 1.9.2 so you can wrap them in an Array + using `Array(my_double)` (Jon Rowe). +* Fix `stub_const` and `hide_const` to handle constants that redefine `send` + (Sam Phippen). +* Fix `Marshal.dump` extension so that it correctly handles nil. + (Luke Imhoff, Jon Rowe) +* Fix isolation of `allow_message_expectations_on_nil` (Jon Rowe) +* Use inspect to format actual arguments on expectations in failure messages (#280, Ben Langfeld) +* Protect against improperly initialised test doubles (#293) (Joseph Shraibman and Jon Rowe) + +Deprecations + +* Deprecate `stub` and `mock` as aliases for `double`. `double` is the + best term for creating a test double, and it reduces confusion to + have only one term (Michi Huber). +* Deprecate `stub!` and `unstub!` in favor of `stub` and `unstub` + (Jon Rowe). +* Deprecate `at_least(0).times` and `any_number_of_times` (Michi Huber). + +### 2.13.1 / 2013-04-06 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.13.0...v2.13.1) + +Bug fixes + +* Allow a block implementation to be used in combination with + `and_yield`, `and_raise`, `and_return` or `and_throw` (Myron Marston). + +### 2.13.0 / 2013-02-23 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.12.2...v2.13.0) + +Bug fixes + +* Fix bug that caused weird behavior when a method that had + previously been stubbed with multiple return values (e.g. + `obj.stub(:foo).and_return(1, 2)`) was later mocked with a + single return value (e.g. `obj.should_receive(:foo).once.and_return(1)`). + (Myron Marston) +* Fix bug related to a mock expectation for a method that already had + multiple stubs with different `with` constraints. Previously, the + first stub was used, even though it may not have matched the passed + args. The fix defers this decision until the message is received so + that the proper stub response can be chosen based on the passed + arguments (Myron Marston). +* Do not call `nil?` extra times on a mocked object, in case `nil?` + itself is expected a set number of times (Myron Marston). +* Fix `missing_default_stub_error` message so array args are handled + properly (Myron Marston). +* Explicitly disallow `any_instance.unstub!` (Ryan Jones). +* Fix `any_instance` stubbing so that it works with `Delegator` + subclasses (Myron Marston). +* Fix `and_call_original` so that it works with `Delegator` subclasses + (Myron Marston). +* Fix `any_instance.should_not_receive` when `any_instance.should_receive` + is used on the same class in the same example. Previously it would + wrongly report a failure even when the message was not received + (Myron Marston). + +### 2.12.2 / 2013-01-27 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.12.1...v.2.12.2) + +Bug fixes + +* Fix `and_call_original` to work properly for methods defined + on a module extended onto an object instance (Myron Marston). +* Fix `stub_const` with an undefined constnat name to work properly + with constant strings that are prefixed with `::` -- and edge case + I missed in the bug fix in the 2.12.1 release (Myron Marston). +* Ensure method visibility on a partial mock is restored after reseting + method stubs, even on a singleton module (created via `extend self`) + when the method visibility differs between the instance and singleton + versions (Andy Lindeman). + +### 2.12.1 / 2012-12-21 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.12.0...v2.12.1) + +Bug fixes + +* Fix `any_instance` to support `and_call_original`. + (Myron Marston) +* Properly restore stubbed aliased methods on rubies + that report the incorrect owner (Myron Marston and Andy Lindeman). +* Fix `hide_const` and `stub_const` with a defined constnat name to + work properly with constant strings that are prefixed with `::` (Myron Marston). + +### 2.12.0 / 2012-11-12 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.11.3...v2.12.0) + +Enhancements + +* `and_raise` can accept an exception class and message, more closely + matching `Kernel#raise` (e.g., `foo.stub(:bar).and_raise(RuntimeError, "message")`) + (Bas Vodde) +* Add `and_call_original`, which will delegate the message to the + original method (Myron Marston). + +Deprecations: + +* Add deprecation warning when using `and_return` with `should_not_receive` + (Neha Kumari) + +### 2.11.3 / 2012-09-19 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.11.2...v2.11.3) + +Bug fixes + +* Fix `:transfer_nested_constants` option of `stub_const` so that it + doesn't blow up when there are inherited constants. (Myron Marston) +* `any_instance` stubs can be used on classes that override `Object#method`. + (Andy Lindeman) +* Methods stubbed with `any_instance` are unstubbed after the test finishes. + (Andy Lindeman) +* Fix confusing error message when calling a mocked class method an + extra time with the wrong arguments (Myron Marston). + +### 2.11.2 / 2012-08-11 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.11.1...v2.11.2) + +Bug fixes + +* Don't modify `dup` on classes that don't support `dup` (David Chelimsky) +* Fix `any_instance` so that it works properly with methods defined on + a superclass. (Daniel Eguzkiza) +* Fix `stub_const` so that it works properly for nested constants that + share a name with a top-level constant (e.g. "MyGem::Hash"). (Myron + Marston) + +### 2.11.1 / 2012-07-09 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.11.0...v2.11.1) + +Bug fixes + +* Fix `should_receive` so that when it is called on an `as_null_object` + double with no implementation, and there is a previous explicit stub + for the same method, the explicit stub remains (rather than being + overriden with the null object implementation--`return self`). (Myron Marston) + +### 2.11.0 / 2012-07-07 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.10.1...v2.11.0) + +Enhancements + +* Expose ArgumentListMatcher as a formal API + * supports use by 3rd party mock frameworks like Surrogate +* Add `stub_const` API to stub constants for the duration of an + example (Myron Marston). + +Bug fixes + +* Fix regression of edge case behavior. `double.should_receive(:foo) { a }` + was causing a NoMethodError when `double.stub(:foo).and_return(a, b)` + had been setup before (Myron Marston). +* Infinite loop generated by using `any_instance` and `dup`. (Sidu Ponnappa @kaiwren) +* `double.should_receive(:foo).at_least(:once).and_return(a)` always returns a + even if `:foo` is already stubbed. +* Prevent infinite loop when interpolating a null double into a string + as an integer (`"%i" % double.as_null_object`). (Myron Marston) +* Fix `should_receive` so that null object behavior (e.g. returning + self) is preserved if no implementation is given (Myron Marston). +* Fix `and_raise` so that it raises `RuntimeError` rather than + `Exception` by default, just like ruby does. (Andrew Marshall) + +### 2.10.1 / 2012-05-05 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.10.0...v2.10.1) + +Bug fixes + +* fix regression of edge case behavior + (https://github.com/rspec/rspec-mocks/issues/132) + * fixed failure of `object.should_receive(:message).at_least(0).times.and_return value` + * fixed failure of `object.should_not_receive(:message).and_return value` + +### 2.10.0 / 2012-05-03 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.9.0...v2.10.0) + +Bug fixes + +* fail fast when an `exactly` or `at_most` expectation is exceeded + +### 2.9.0 / 2012-03-17 +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.8.0...v2.9.0) + +Enhancements + +* Support order constraints across objects (preethiramdev) + +Bug fixes + +* Allow a `as_null_object` to be passed to `with` +* Pass proc to block passed to stub (Aubrey Rhodes) +* Initialize child message expectation args to match any args (#109 - + preethiramdev) + +### 2.8.0 / 2012-01-04 + +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.8.0.rc2...v2.8.0) + +No changes for this release. Just releasing with the other rspec gems. + +### 2.8.0.rc2 / 2011-12-19 + +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.8.0.rc1...v2.8.0.rc2) + +No changes for this release. Just releasing with the other rspec gems. + +### 2.8.0.rc1 / 2011-11-06 + +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.7.0...v2.8.0.rc1) + +Enhancements + +* Eliminate Ruby warnings (Matijs van Zuijlen) + +### 2.7.0 / 2011-10-16 + +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.6.0...v2.7.0) + +Enhancements + +* Use `__send__` rather than `send` (alextk) +* Add support for `any_instance.stub_chain` (Sidu Ponnappa) +* Add support for `any_instance` argument matching based on `with` (Sidu + Ponnappa and Andy Lindeman) + +Changes + +* Check for `failure_message_for_should` or `failure_message` instead of + `description` to detect a matcher (Tibor Claassen) + +Bug fixes + +* pass a hash to `any_instance.stub`. (Justin Ko) +* allow `to_ary` to be called without raising `NoMethodError` (Mikhail + Dieterle) +* `any_instance` properly restores private methods (Sidu Ponnappa) + +### 2.6.0 / 2011-05-12 + +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.5.0...v2.6.0) + +Enhancements + +* Add support for `any_instance.stub` and `any_instance.should_receive` (Sidu + Ponnappa and Andy Lindeman) + +Bug fixes + +* fix bug in which multiple chains with shared messages ending in hashes failed + to return the correct value + +### 2.5.0 / 2011-02-05 + +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.4.0...v2.5.0) + +Bug fixes + +* message expectation counts now work in combination with a stub (Damian + Nurzynski) +* fix failure message when message received with incorrect args (Josep M. + Bach) + +### 2.4.0 / 2011-01-02 + +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.3.0...v2.4.0) + +No functional changes in this release, which was made to align with the +rspec-core-2.4.0 release. + +### 2.3.0 / 2010-12-12 + +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.2.0...v2.3.0) + +Bug fixes + +* Fix our Marshal extension so that it does not interfere with objects that + have their own `@mock_proxy` instance variable. (Myron Marston) + +### 2.2.0 / 2010-11-28 + +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.1.0...v2.2.0) + +Enhancements + +* Added "rspec/mocks/standalone" for exploring the rspec-mocks in irb. + +Bug fix + +* Eliminate warning on splat args without parens (Gioele Barabucci) +* Fix bug where `obj.should_receive(:foo).with(stub.as_null_object)` would pass + with a false positive. + +### 2.1.0 / 2010-11-07 + +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.0.1...v2.1.0) + +Bug fixes + +* Fix serialization of stubbed object (Josep M Bach) + +### 2.0.0 / 2010-10-10 + +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.0.0.beta.22...v2.0.0) + +### 2.0.0.rc / 2010-10-05 + +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.0.0.beta.22...v2.0.0.rc) + +Enhancements + +* support passing a block to an expectation block (Nicolas Braem) + * `obj.should_receive(:msg) {|&block| ... }` + +Bug fixes + +* Fix YAML serialization of stub (Myron Marston) +* Fix rdoc rake task (Hans de Graaff) + +### 2.0.0.beta.22 / 2010-09-12 + +[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.0.0.beta.20...v2.0.0.beta.22) + +Bug fixes + +* fixed regression that broke `obj.stub_chain(:a, :b => :c)` +* fixed regression that broke `obj.stub_chain(:a, :b) { :c }` +* `respond_to?` always returns true when using `as_null_object` diff --git a/.bundle/gems/rspec-mocks-3.3.2/License.txt b/.bundle/gems/rspec-mocks-3.3.2/License.txt new file mode 100644 index 0000000..91cfc94 --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/License.txt @@ -0,0 +1,24 @@ +(The MIT License) + +Copyright (c) 2012 David Chelimsky, Myron Marston +Copyright (c) 2006 David Chelimsky, The RSpec Development Team +Copyright (c) 2005 Steven Baker + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/.bundle/gems/rspec-mocks-3.3.2/README.md b/.bundle/gems/rspec-mocks-3.3.2/README.md new file mode 100644 index 0000000..7010117 --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/README.md @@ -0,0 +1,430 @@ +# RSpec Mocks [![Build Status](https://secure.travis-ci.org/rspec/rspec-mocks.svg?branch=master)](http://travis-ci.org/rspec/rspec-mocks) [![Code Climate](https://codeclimate.com/github/rspec/rspec-mocks.svg)](https://codeclimate.com/github/rspec/rspec-mocks) +rspec-mocks is a test-double framework for rspec with support for method stubs, +fakes, and message expectations on generated test-doubles and real objects +alike. + +## Install + + gem install rspec # for rspec-core, rspec-expectations, rspec-mocks + gem install rspec-mocks # for rspec-mocks only + +Want to run against the `master` branch? You'll need to include the dependent +RSpec repos as well. Add the following to your `Gemfile`: + +```ruby +%w[rspec-core rspec-expectations rspec-mocks rspec-support].each do |lib| + gem lib, :git => "git://github.com/rspec/#{lib}.git", :branch => 'master' +end +``` + +## Test Doubles + +A test double is an object that stands in for another object in your system +during a code example. Use the `double` method, passing in an optional identifier, to create one: + +```ruby +book = double("book") +``` + +Most of the time you will want some confidence that your doubles resemble an +existing object in your system. Verifying doubles are provided for this +purpose. If the existing object is available, they will prevent you from adding +stubs and expectations for methods that do not exist or that have an invalid +number of parameters. + +```ruby +book = instance_double("Book", :pages => 250) +``` + +Verifying doubles have some clever tricks to enable you to both test in +isolation without your dependencies loaded while still being able to validate +them against real objects. More detail is available in [their +documentation](https://github.com/rspec/rspec-mocks/blob/master/features/verifying_doubles). + +Verifying doubles can also accept custom identifiers, just like double(), e.g.: + +```ruby +books = [] +books << instance_double("Book", :rspec_book, :pages => 250) +books << instance_double("Book", "(Untitled)", :pages => 5000) + +puts books.inspect # with names, it's clearer which were actually added +``` + +## Method Stubs + +A method stub is an implementation that returns a pre-determined value. Method +stubs can be declared on test doubles or real objects using the same syntax. +rspec-mocks supports 3 forms for declaring method stubs: + +```ruby +allow(book).to receive(:title) { "The RSpec Book" } +allow(book).to receive(:title).and_return("The RSpec Book") +allow(book).to receive_messages( + :title => "The RSpec Book", + :subtitle => "Behaviour-Driven Development with RSpec, Cucumber, and Friends") +``` + +You can also use this shortcut, which creates a test double and declares a +method stub in one statement: + +```ruby +book = double("book", :title => "The RSpec Book") +``` + +The first argument is a name, which is used for documentation and appears in +failure messages. If you don't care about the name, you can leave it out, +making the combined instantiation/stub declaration very terse: + +```ruby +double(:foo => 'bar') +``` + +This is particularly nice when providing a list of test doubles to a method +that iterates through them: + +```ruby +order.calculate_total_price(double(:price => 1.99), double(:price => 2.99)) +``` + +## Consecutive return values + +When a stub might be invoked more than once, you can provide additional +arguments to `and_return`. The invocations cycle through the list. The last +value is returned for any subsequent invocations: + +```ruby +allow(die).to receive(:roll).and_return(1, 2, 3) +die.roll # => 1 +die.roll # => 2 +die.roll # => 3 +die.roll # => 3 +die.roll # => 3 +``` + +To return an array in a single invocation, declare an array: + +```ruby +allow(team).to receive(:players).and_return([double(:name => "David")]) +``` + +## Message Expectations + +A message expectation is an expectation that the test double will receive a +message some time before the example ends. If the message is received, the +expectation is satisfied. If not, the example fails. + +```ruby +validator = double("validator") +expect(validator).to receive(:validate) { "02134" } +zipcode = Zipcode.new("02134", validator) +zipcode.valid? +``` + +## Test Spies + +Verifies the given object received the expected message during the course of +the test. For a message to be verified, the given object must be setup to spy +on it, either by having it explicitly stubbed or by being a null object double +(e.g. `double(...).as_null_object`). Convenience methods are provided to easily +create null object doubles for this purpose: + +```ruby +spy("invitation") # => same as `double("invitation").as_null_object` +instance_spy("Invitation") # => same as `instance_double("Invitation").as_null_object` +class_spy("Invitation") # => same as `class_double("Invitation").as_null_object` +object_spy("Invitation") # => same as `object_double("Invitation").as_null_object` +``` + +Verifying messages received in this way implements the Test Spy pattern. + +```ruby +invitation = spy('invitation') + +user.accept_invitation(invitation) + +expect(invitation).to have_received(:accept) + +# You can also use other common message expectations. For example: +expect(invitation).to have_received(:accept).with(mailer) +expect(invitation).to have_received(:accept).twice +expect(invitation).to_not have_received(:accept).with(mailer) + +# One can specify a return value on the spy the same way one would a double. +invitation = spy('invitation', :accept => true) +expect(invitation).to have_received(:accept).with(mailer) +expect(invitation.accept).to eq(true) +``` + +Note that `have_received(...).with(...)` is unable to work properly when +passed arguments are mutated after the spy records the received message. +For example, this does not work properly: + +```ruby +greeter = spy("greeter") + +message = "Hello" +greeter.greet_with(message) +message << ", World" + +expect(greeter).to have_received(:greet_with).with("Hello") +``` + +## Nomenclature + +### Mock Objects and Test Stubs + +The names Mock Object and Test Stub suggest specialized Test Doubles. i.e. +a Test Stub is a Test Double that only supports method stubs, and a Mock +Object is a Test Double that supports message expectations and method +stubs. + +There is a lot of overlapping nomenclature here, and there are many +variations of these patterns (fakes, spies, etc). Keep in mind that most of +the time we're talking about method-level concepts that are variations of +method stubs and message expectations, and we're applying to them to _one_ +generic kind of object: a Test Double. + +### Test-Specific Extension + +a.k.a. Partial Double, a Test-Specific Extension is an extension of a +real object in a system that is instrumented with test-double like +behaviour in the context of a test. This technique is very common in Ruby +because we often see class objects acting as global namespaces for methods. +For example, in Rails: + +```ruby +person = double("person") +allow(Person).to receive(:find) { person } +``` + +In this case we're instrumenting Person to return the person object we've +defined whenever it receives the `find` message. We can also set a message +expectation so that the example fails if `find` is not called: + +```ruby +person = double("person") +expect(Person).to receive(:find) { person } +``` + +RSpec replaces the method we're stubbing or mocking with its own +test-double-like method. At the end of the example, RSpec verifies any message +expectations, and then restores the original methods. + +## Expecting Arguments + +```ruby +expect(double).to receive(:msg).with(*args) +expect(double).to_not receive(:msg).with(*args) +``` + +You can set multiple expectations for the same message if you need to: + +```ruby +expect(double).to receive(:msg).with("A", 1, 3) +expect(double).to receive(:msg).with("B", 2, 4) +``` + +## Argument Matchers + +Arguments that are passed to `with` are compared with actual arguments +received using ==. In cases in which you want to specify things about the +arguments rather than the arguments themselves, you can use any of the +matchers that ship with rspec-expectations. They don't all make syntactic +sense (they were primarily designed for use with RSpec::Expectations), but +you are free to create your own custom RSpec::Matchers. + +rspec-mocks also adds some keyword Symbols that you can use to +specify certain kinds of arguments: + +```ruby +expect(double).to receive(:msg).with(no_args) +expect(double).to receive(:msg).with(any_args) +expect(double).to receive(:msg).with(1, any_args) # any args acts like an arg splat and can go anywhere +expect(double).to receive(:msg).with(1, kind_of(Numeric), "b") #2nd argument can be any kind of Numeric +expect(double).to receive(:msg).with(1, boolean(), "b") #2nd argument can be true or false +expect(double).to receive(:msg).with(1, /abc/, "b") #2nd argument can be any String matching the submitted Regexp +expect(double).to receive(:msg).with(1, anything(), "b") #2nd argument can be anything at all +expect(double).to receive(:msg).with(1, duck_type(:abs, :div), "b") #2nd argument can be object that responds to #abs and #div +expect(double).to receive(:msg).with(hash_including(:a => 5)) # first arg is a hash with a: 5 as one of the key-values +expect(double).to receive(:msg).with(array_including(5)) # first arg is an array with 5 as one of the key-values +expect(double).to receive(:msg).with(hash_excluding(:a => 5)) # first arg is a hash without a: 5 as one of the key-values +``` + +## Receive Counts + +```ruby +expect(double).to receive(:msg).once +expect(double).to receive(:msg).twice +expect(double).to receive(:msg).exactly(n).times +expect(double).to receive(:msg).at_least(:once) +expect(double).to receive(:msg).at_least(:twice) +expect(double).to receive(:msg).at_least(n).times +expect(double).to receive(:msg).at_most(:once) +expect(double).to receive(:msg).at_most(:twice) +expect(double).to receive(:msg).at_most(n).times +``` + +## Ordering + +```ruby +expect(double).to receive(:msg).ordered +expect(double).to receive(:other_msg).ordered + # This will fail if the messages are received out of order +``` + +This can include the same message with different arguments: + +```ruby +expect(double).to receive(:msg).with("A", 1, 3).ordered +expect(double).to receive(:msg).with("B", 2, 4).ordered +``` + +## Setting Responses + +Whether you are setting a message expectation or a method stub, you can +tell the object precisely how to respond. The most generic way is to pass +a block to `receive`: + +```ruby +expect(double).to receive(:msg) { value } +``` + +When the double receives the `msg` message, it evaluates the block and returns +the result. + +```ruby +expect(double).to receive(:msg).and_return(value) +expect(double).to receive(:msg).exactly(3).times.and_return(value1, value2, value3) + # returns value1 the first time, value2 the second, etc +expect(double).to receive(:msg).and_raise(error) + # error can be an instantiated object or a class + # if it is a class, it must be instantiable with no args +expect(double).to receive(:msg).and_throw(:msg) +expect(double).to receive(:msg).and_yield(values, to, yield) +expect(double).to receive(:msg).and_yield(values, to, yield).and_yield(some, other, values, this, time) + # for methods that yield to a block multiple times +``` + +Any of these responses can be applied to a stub as well + +```ruby +allow(double).to receive(:msg).and_return(value) +allow(double).to receive(:msg).and_return(value1, value2, value3) +allow(double).to receive(:msg).and_raise(error) +allow(double).to receive(:msg).and_throw(:msg) +allow(double).to receive(:msg).and_yield(values, to, yield) +allow(double).to receive(:msg).and_yield(values, to, yield).and_yield(some, other, values, this, time) +``` + +## Arbitrary Handling + +Once in a while you'll find that the available expectations don't solve the +particular problem you are trying to solve. Imagine that you expect the message +to come with an Array argument that has a specific length, but you don't care +what is in it. You could do this: + +```ruby +expect(double).to receive(:msg) do |arg| + expect(arg.size).to eq 7 +end +``` + +If the method being stubbed itself takes a block, and you need to yield to it +in some special way, you can use this: + +```ruby +expect(double).to receive(:msg) do |&arg| + begin + arg.call + ensure + # cleanup + end +end +``` + +## Delegating to the Original Implementation + +When working with a partial mock object, you may occasionally +want to set a message expecation without interfering with how +the object responds to the message. You can use `and_call_original` +to achieve this: + +```ruby +expect(Person).to receive(:find).and_call_original +Person.find # => executes the original find method and returns the result +``` + +## Combining Expectation Details + +Combining the message name with specific arguments, receive counts and responses +you can get quite a bit of detail in your expectations: + +```ruby +expect(double).to receive(:<<).with("illegal value").once.and_raise(ArgumentError) +``` + +While this is a good thing when you really need it, you probably don't really +need it! Take care to specify only the things that matter to the behavior of +your code. + +## Stubbing and Hiding Constants + +See the [mutating constants +README](https://github.com/rspec/rspec-mocks/blob/master/features/mutating_constants/README.md) +for info on this feature. + +## Use `before(:example)`, not `before(:context)` + +Stubs in `before(:context)` are not supported. The reason is that all stubs and mocks get cleared out after each example, so any stub that is set in `before(:context)` would work in the first example that happens to run in that group, but not for any others. + +Instead of `before(:context)`, use `before(:example)`. + +## Settings mocks or stubs on any instance of a class + +rspec-mocks provides two methods, `allow_any_instance_of` and +`expect_any_instance_of`, that will allow you to stub or mock any instance +of a class. They are used in place of `allow` or `expect`: + +```ruby +allow_any_instance_of(Widget).to receive(:name).and_return("Wibble") +expect_any_instance_of(Widget).to receive(:name).and_return("Wobble") +``` + +These methods add the appropriate stub or expectation to all instances of +`Widget`. + +This feature is sometimes useful when working with legacy code, though in +general we discourage its use for a number of reasons: + +* The `rspec-mocks` API is designed for individual object instances, but this + feature operates on entire classes of objects. As a result there are some + semantically confusing edge cases. For example in + `expect_any_instance_of(Widget).to receive(:name).twice` it isn't clear + whether each specific instance is expected to receive `name` twice, or if two + receives total are expected. (It's the former.) +* Using this feature is often a design smell. It may be + that your test is trying to do too much or that the object under test is too + complex. +* It is the most complicated feature of `rspec-mocks`, and has historically + received the most bug reports. (None of the core team actively use it, + which doesn't help.) + + +## Further Reading + +There are many different viewpoints about the meaning of mocks and stubs. If +you are interested in learning more, here is some recommended reading: + +* Mock Objects: http://www.mockobjects.com/ +* Endo-Testing: http://www.ccs.neu.edu/research/demeter/related-work/extreme-programming/MockObjectsFinal.PDF +* Mock Roles, Not Objects: http://www.jmock.org/oopsla2004.pdf +* Test Double: http://www.martinfowler.com/bliki/TestDouble.html +* Test Double Patterns: http://xunitpatterns.com/Test%20Double%20Patterns.html +* Mocks aren't stubs: http://www.martinfowler.com/articles/mocksArentStubs.html + +## Also see + +* [http://github.com/rspec/rspec](http://github.com/rspec/rspec) +* [http://github.com/rspec/rspec-core](http://github.com/rspec/rspec-core) +* [http://github.com/rspec/rspec-expectations](http://github.com/rspec/rspec-expectations) diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks.rb new file mode 100644 index 0000000..17b2831 --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks.rb @@ -0,0 +1,126 @@ +require 'rspec/support' +RSpec::Support.require_rspec_support 'caller_filter' +RSpec::Support.require_rspec_support 'warnings' +RSpec::Support.require_rspec_support 'ruby_features' + +RSpec::Support.define_optimized_require_for_rspec(:mocks) { |f| require_relative f } + +%w[ + instance_method_stasher + method_double + argument_matchers + example_methods + proxy + test_double + argument_list_matcher + message_expectation + order_group + error_generator + space + mutate_const + targets + syntax + configuration + verifying_double + version +].each { |name| RSpec::Support.require_rspec_mocks name } + +# Share the top-level RSpec namespace, because we are a core supported +# extension. +module RSpec + # Contains top-level utility methods. While this contains a few + # public methods, these are not generally meant to be called from + # a test or example. They exist primarily for integration with + # test frameworks (such as rspec-core). + module Mocks + # Performs per-test/example setup. This should be called before + # an test or example begins. + def self.setup + @space_stack << (@space = space.new_scope) + end + + # Verifies any message expectations that were set during the + # test or example. This should be called at the end of an example. + def self.verify + space.verify_all + end + + # Cleans up all test double state (including any methods that were + # redefined on partial doubles). This _must_ be called after + # each example, even if an error was raised during the example. + def self.teardown + space.reset_all + @space_stack.pop + @space = @space_stack.last || @root_space + end + + # Adds an allowance (stub) on `subject` + # + # @param subject the subject to which the message will be added + # @param message a symbol, representing the message that will be + # added. + # @param opts a hash of options, :expected_from is used to set the + # original call site + # @yield an optional implementation for the allowance + # + # @example Defines the implementation of `foo` on `bar`, using the passed block + # x = 0 + # RSpec::Mocks.allow_message(bar, :foo) { x += 1 } + def self.allow_message(subject, message, opts={}, &block) + space.proxy_for(subject).add_stub(message, opts, &block) + end + + # Sets a message expectation on `subject`. + # @param subject the subject on which the message will be expected + # @param message a symbol, representing the message that will be + # expected. + # @param opts a hash of options, :expected_from is used to set the + # original call site + # @yield an optional implementation for the expectation + # + # @example Expect the message `foo` to receive `bar`, then call it + # RSpec::Mocks.expect_message(bar, :foo) + # bar.foo + def self.expect_message(subject, message, opts={}, &block) + space.proxy_for(subject).add_message_expectation(message, opts, &block) + end + + # Call the passed block and verify mocks after it has executed. This allows + # mock usage in arbitrary places, such as a `before(:all)` hook. + def self.with_temporary_scope + setup + + begin + yield + verify + ensure + teardown + end + end + + class << self + # @private + attr_reader :space + end + @space_stack = [] + @root_space = @space = RSpec::Mocks::RootSpace.new + + # @private + IGNORED_BACKTRACE_LINE = 'this backtrace line is ignored' + + # To speed up boot time a bit, delay loading optional or rarely + # used features until their first use. + autoload :AnyInstance, "rspec/mocks/any_instance" + autoload :ExpectChain, "rspec/mocks/message_chain" + autoload :StubChain, "rspec/mocks/message_chain" + autoload :MarshalExtension, "rspec/mocks/marshal_extension" + + # Namespace for mock-related matchers. + module Matchers + autoload :HaveReceived, "rspec/mocks/matchers/have_received" + autoload :Receive, "rspec/mocks/matchers/receive" + autoload :ReceiveMessageChain, "rspec/mocks/matchers/receive_message_chain" + autoload :ReceiveMessages, "rspec/mocks/matchers/receive_messages" + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance.rb new file mode 100644 index 0000000..41eae81 --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance.rb @@ -0,0 +1,11 @@ +%w[ + any_instance/chain + any_instance/error_generator + any_instance/stub_chain + any_instance/stub_chain_chain + any_instance/expect_chain_chain + any_instance/expectation_chain + any_instance/message_chains + any_instance/recorder + any_instance/proxy +].each { |f| RSpec::Support.require_rspec_mocks(f) } diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/chain.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/chain.rb new file mode 100644 index 0000000..c9ce232 --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/chain.rb @@ -0,0 +1,110 @@ +module RSpec + module Mocks + # @private + module AnyInstance + # @private + class Chain + def initialize(recorder, *args, &block) + @recorder = recorder + @expectation_args = args + @expectation_block = block + @argument_list_matcher = ArgumentListMatcher::MATCH_ALL + end + + # @private + # + # Provides convenience methods for recording customizations on message + # expectations. + module Customizations + # @macro [attach] record + # @method $1(*args, &block) + # Records the `$1` message for playback against an instance that + # invokes a method stubbed or mocked using `any_instance`. + # + # @see RSpec::Mocks::MessageExpectation#$1 + # + def self.record(method_name) + define_method(method_name) do |*args, &block| + record(method_name, *args, &block) + end + end + + record :and_return + record :and_raise + record :and_throw + record :and_yield + record :and_call_original + record :and_wrap_original + record :with + record :once + record :twice + record :thrice + record :exactly + record :times + record :never + record :at_least + record :at_most + end + + include Customizations + + # @private + def playback!(instance) + message_expectation = create_message_expectation_on(instance) + messages.inject(message_expectation) do |object, message| + object.__send__(*message.first, &message.last) + end + end + + # @private + def constrained_to_any_of?(*constraints) + constraints.any? do |constraint| + messages.any? do |message| + message.first.first == constraint + end + end + end + + # @private + def matches_args?(*args) + @argument_list_matcher.args_match?(*args) + end + + # @private + def expectation_fulfilled! + @expectation_fulfilled = true + end + + def never + AnyInstance.error_generator.raise_double_negation_error("expect_any_instance_of(MyClass)") if negated? + super + end + + def with(*args, &block) + @argument_list_matcher = ArgumentListMatcher.new(*args) + super + end + + private + + def negated? + messages.any? { |(message, *_), _| message == :never } + end + + def messages + @messages ||= [] + end + + def last_message + messages.last.first.first unless messages.empty? + end + + def record(rspec_method_name, *args, &block) + verify_invocation_order(rspec_method_name, *args, &block) + messages << [args.unshift(rspec_method_name), block] + self + end + end + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/error_generator.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/error_generator.rb new file mode 100644 index 0000000..d1046cb --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/error_generator.rb @@ -0,0 +1,31 @@ +module RSpec + module Mocks + module AnyInstance + # @private + class ErrorGenerator < ::RSpec::Mocks::ErrorGenerator + def raise_second_instance_received_message_error(unfulfilled_expectations) + __raise "Exactly one instance should have received the following " \ + "message(s) but didn't: #{unfulfilled_expectations.sort.join(', ')}" + end + + def raise_does_not_implement_error(klass, method_name) + __raise "#{klass} does not implement ##{method_name}" + end + + def raise_message_already_received_by_other_instance_error(method_name, object_inspect, invoked_instance) + __raise "The message '#{method_name}' was received by #{object_inspect} " \ + "but has already been received by #{invoked_instance}" + end + + def raise_not_supported_with_prepend_error(method_name, problem_mod) + __raise "Using `any_instance` to stub a method (#{method_name}) that has been " \ + "defined on a prepended module (#{problem_mod}) is not supported." + end + end + + def self.error_generator + @error_generator ||= ErrorGenerator.new + end + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/expect_chain_chain.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/expect_chain_chain.rb new file mode 100644 index 0000000..0d13402 --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/expect_chain_chain.rb @@ -0,0 +1,35 @@ +module RSpec + module Mocks + module AnyInstance + # @private + class ExpectChainChain < StubChain + def initialize(*args) + super + @expectation_fulfilled = false + end + + def expectation_fulfilled? + @expectation_fulfilled + end + + def playback!(instance) + super.tap { @expectation_fulfilled = true } + end + + private + + def create_message_expectation_on(instance) + ::RSpec::Mocks::ExpectChain.expect_chain_on(instance, *@expectation_args, &@expectation_block) + end + + def invocation_order + @invocation_order ||= { + :and_return => [nil], + :and_raise => [nil], + :and_yield => [nil] + } + end + end + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/expectation_chain.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/expectation_chain.rb new file mode 100644 index 0000000..02b55e8 --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/expectation_chain.rb @@ -0,0 +1,48 @@ +module RSpec + module Mocks + module AnyInstance + # @private + class ExpectationChain < Chain + def expectation_fulfilled? + @expectation_fulfilled || constrained_to_any_of?(:never) + end + + def initialize(*args, &block) + @expectation_fulfilled = false + super + end + + private + + def verify_invocation_order(_rspec_method_name, *_args, &_block) + end + end + + # @private + class PositiveExpectationChain < ExpectationChain + private + + def create_message_expectation_on(instance) + proxy = ::RSpec::Mocks.space.proxy_for(instance) + method_name, opts = @expectation_args + opts = (opts || {}).merge(:expected_form => IGNORED_BACKTRACE_LINE) + + me = proxy.add_message_expectation(method_name, opts, &@expectation_block) + if RSpec::Mocks.configuration.yield_receiver_to_any_instance_implementation_blocks? + me.and_yield_receiver_to_implementation + end + + me + end + + def invocation_order + @invocation_order ||= { + :with => [nil], + :and_return => [:with, nil], + :and_raise => [:with, nil] + } + end + end + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/message_chains.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/message_chains.rb new file mode 100644 index 0000000..7298643 --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/message_chains.rb @@ -0,0 +1,83 @@ +module RSpec + module Mocks + module AnyInstance + # @private + class MessageChains + def initialize + @chains_by_method_name = Hash.new { |h, k| h[k] = [] } + end + + # @private + def [](method_name) + @chains_by_method_name[method_name] + end + + # @private + def add(method_name, chain) + @chains_by_method_name[method_name] << chain + chain + end + + # @private + def remove_stub_chains_for!(method_name) + @chains_by_method_name[method_name].reject! do |chain| + StubChain === chain + end + end + + # @private + def has_expectation?(method_name) + @chains_by_method_name[method_name].find do |chain| + ExpectationChain === chain + end + end + + # @private + def each_unfulfilled_expectation_matching(method_name, *args) + @chains_by_method_name[method_name].each do |chain| + yield chain if !chain.expectation_fulfilled? && chain.matches_args?(*args) + end + end + + # @private + def all_expectations_fulfilled? + @chains_by_method_name.all? do |_method_name, chains| + chains.all? { |chain| chain.expectation_fulfilled? } + end + end + + # @private + def unfulfilled_expectations + @chains_by_method_name.map do |method_name, chains| + method_name.to_s if ExpectationChain === chains.last unless chains.last.expectation_fulfilled? + end.compact + end + + # @private + def received_expected_message!(method_name) + @chains_by_method_name[method_name].each do |chain| + chain.expectation_fulfilled! + end + end + + # @private + def playback!(instance, method_name) + raise_if_second_instance_to_receive_message(instance) + @chains_by_method_name[method_name].each do |chain| + chain.playback!(instance) + end + end + + private + + def raise_if_second_instance_to_receive_message(instance) + @instance_with_expectation ||= instance if ExpectationChain === instance + return unless ExpectationChain === instance + return if @instance_with_expectation.equal?(instance) + + AnyInstance.error_generator.raise_second_instance_received_message_error(unfulfilled_expectations) + end + end + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/proxy.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/proxy.rb new file mode 100644 index 0000000..fc66d39 --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/proxy.rb @@ -0,0 +1,116 @@ +module RSpec + module Mocks + module AnyInstance + # @private + # The `AnyInstance::Recorder` is responsible for redefining the klass's + # instance method in order to add any stubs/expectations the first time + # the method is called. It's not capable of updating a stub on an instance + # that's already been previously stubbed (either directly, or via + # `any_instance`). + # + # This proxy sits in front of the recorder and delegates both to it + # and to the `RSpec::Mocks::Proxy` for each already mocked or stubbed + # instance of the class, in order to propogates changes to the instances. + # + # Note that unlike `RSpec::Mocks::Proxy`, this proxy class is stateless + # and is not persisted in `RSpec::Mocks.space`. + # + # Proxying for the message expectation fluent interface (typically chained + # off of the return value of one of these methods) is provided by the + # `FluentInterfaceProxy` class below. + class Proxy + def initialize(recorder, target_proxies) + @recorder = recorder + @target_proxies = target_proxies + end + + def klass + @recorder.klass + end + + def stub(method_name_or_method_map, &block) + if Hash === method_name_or_method_map + method_name_or_method_map.each do |method_name, return_value| + stub(method_name).and_return(return_value) + end + else + perform_proxying(__method__, [method_name_or_method_map], block) do |proxy| + proxy.add_stub(method_name_or_method_map, &block) + end + end + end + + def unstub(method_name) + perform_proxying(__method__, [method_name], nil) do |proxy| + proxy.remove_stub_if_present(method_name) + end + end + + def stub_chain(*chain, &block) + perform_proxying(__method__, chain, block) do |proxy| + Mocks::StubChain.stub_chain_on(proxy.object, *chain, &block) + end + end + + def expect_chain(*chain, &block) + perform_proxying(__method__, chain, block) do |proxy| + Mocks::ExpectChain.expect_chain_on(proxy.object, *chain, &block) + end + end + + def should_receive(method_name, &block) + perform_proxying(__method__, [method_name], block) do |proxy| + # Yeah, this is a bit odd...but if we used `add_message_expectation` + # then it would act like `expect_every_instance_of(klass).to receive`. + # The any_instance recorder takes care of validating that an instance + # received the message. + proxy.add_stub(method_name, &block) + end + end + + def should_not_receive(method_name, &block) + perform_proxying(__method__, [method_name], block) do |proxy| + proxy.add_message_expectation(method_name, &block).never + end + end + + private + + def perform_proxying(method_name, args, block, &target_proxy_block) + recorder_value = @recorder.__send__(method_name, *args, &block) + proxy_values = @target_proxies.map(&target_proxy_block) + FluentInterfaceProxy.new([recorder_value] + proxy_values) + end + end + + # @private + # Delegates messages to each of the given targets in order to + # provide the fluent interface that is available off of message + # expectations when dealing with `any_instance`. + # + # `targets` will typically contain 1 of the `AnyInstance::Recorder` + # return values and N `MessageExpectation` instances (one per instance + # of the `any_instance` klass). + class FluentInterfaceProxy + def initialize(targets) + @targets = targets + end + + if RUBY_VERSION.to_f > 1.8 + def respond_to_missing?(method_name, include_private=false) + super || @targets.first.respond_to?(method_name, include_private) + end + else + def respond_to?(method_name, include_private=false) + super || @targets.first.respond_to?(method_name, include_private) + end + end + + def method_missing(*args, &block) + return_values = @targets.map { |t| t.__send__(*args, &block) } + FluentInterfaceProxy.new(return_values) + end + end + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/recorder.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/recorder.rb new file mode 100644 index 0000000..943728a --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/recorder.rb @@ -0,0 +1,264 @@ +module RSpec + module Mocks + module AnyInstance + # Given a class `TheClass`, `TheClass.any_instance` returns a `Recorder`, + # which records stubs and message expectations for later playback on + # instances of `TheClass`. + # + # Further constraints are stored in instances of [Chain](Chain). + # + # @see AnyInstance + # @see Chain + class Recorder + # @private + attr_reader :message_chains, :stubs, :klass + + def initialize(klass) + @message_chains = MessageChains.new + @stubs = Hash.new { |hash, key| hash[key] = [] } + @observed_methods = [] + @played_methods = {} + @klass = klass + @expectation_set = false + end + + # Initializes the recording a stub to be played back against any + # instance of this object that invokes the submitted method. + # + # @see Methods#stub + def stub(method_name, &block) + observe!(method_name) + message_chains.add(method_name, StubChain.new(self, method_name, &block)) + end + + # Initializes the recording a stub chain to be played back against any + # instance of this object that invokes the method matching the first + # argument. + # + # @see Methods#stub_chain + def stub_chain(*method_names_and_optional_return_values, &block) + normalize_chain(*method_names_and_optional_return_values) do |method_name, args| + observe!(method_name) + message_chains.add(method_name, StubChainChain.new(self, *args, &block)) + end + end + + # @private + def expect_chain(*method_names_and_optional_return_values, &block) + @expectation_set = true + normalize_chain(*method_names_and_optional_return_values) do |method_name, args| + observe!(method_name) + message_chains.add(method_name, ExpectChainChain.new(self, *args, &block)) + end + end + + # Initializes the recording a message expectation to be played back + # against any instance of this object that invokes the submitted + # method. + # + # @see Methods#should_receive + def should_receive(method_name, &block) + @expectation_set = true + observe!(method_name) + message_chains.add(method_name, PositiveExpectationChain.new(self, method_name, &block)) + end + + # The opposite of `should_receive` + # + # @see Methods#should_not_receive + def should_not_receive(method_name, &block) + should_receive(method_name, &block).never + end + + # Removes any previously recorded stubs, stub_chains or message + # expectations that use `method_name`. + # + # @see Methods#unstub + def unstub(method_name) + unless @observed_methods.include?(method_name.to_sym) + AnyInstance.error_generator.raise_method_not_stubbed_error(method_name) + end + message_chains.remove_stub_chains_for!(method_name) + stubs[method_name].clear + stop_observing!(method_name) unless message_chains.has_expectation?(method_name) + end + + # @api private + # + # Used internally to verify that message expectations have been + # fulfilled. + def verify + return unless @expectation_set + return if message_chains.all_expectations_fulfilled? + + AnyInstance.error_generator.raise_second_instance_received_message_error(message_chains.unfulfilled_expectations) + end + + # @private + def stop_all_observation! + @observed_methods.each { |method_name| restore_method!(method_name) } + end + + # @private + def playback!(instance, method_name) + RSpec::Mocks.space.ensure_registered(instance) + message_chains.playback!(instance, method_name) + @played_methods[method_name] = instance + received_expected_message!(method_name) if message_chains.has_expectation?(method_name) + end + + # @private + def instance_that_received(method_name) + @played_methods[method_name] + end + + # @private + def build_alias_method_name(method_name) + "__#{method_name}_without_any_instance__" + end + + # @private + def already_observing?(method_name) + @observed_methods.include?(method_name) || super_class_observing?(method_name) + end + + # @private + def notify_received_message(_object, message, args, _blk) + has_expectation = false + + message_chains.each_unfulfilled_expectation_matching(message, *args) do |expectation| + has_expectation = true + expectation.expectation_fulfilled! + end + + return unless has_expectation + + restore_method!(message) + mark_invoked!(message) + end + + protected + + def stop_observing!(method_name) + restore_method!(method_name) + @observed_methods.delete(method_name) + super_class_observers_for(method_name).each do |ancestor| + ::RSpec::Mocks.space. + any_instance_recorder_for(ancestor).stop_observing!(method_name) + end + end + + private + + def ancestor_is_an_observer?(method_name) + lambda do |ancestor| + unless ancestor == @klass + ::RSpec::Mocks.space. + any_instance_recorder_for(ancestor).already_observing?(method_name) + end + end + end + + def super_class_observers_for(method_name) + @klass.ancestors.select(&ancestor_is_an_observer?(method_name)) + end + + def super_class_observing?(method_name) + @klass.ancestors.any?(&ancestor_is_an_observer?(method_name)) + end + + def normalize_chain(*args) + args.shift.to_s.split('.').map { |s| s.to_sym }.reverse.each { |a| args.unshift a } + yield args.first, args + end + + def received_expected_message!(method_name) + message_chains.received_expected_message!(method_name) + restore_method!(method_name) + mark_invoked!(method_name) + end + + def restore_method!(method_name) + if public_protected_or_private_method_defined?(build_alias_method_name(method_name)) + restore_original_method!(method_name) + else + remove_dummy_method!(method_name) + end + end + + def restore_original_method!(method_name) + return unless @klass.instance_method(method_name).owner == @klass + + alias_method_name = build_alias_method_name(method_name) + @klass.class_exec do + remove_method method_name + alias_method method_name, alias_method_name + remove_method alias_method_name + end + end + + def remove_dummy_method!(method_name) + @klass.class_exec do + remove_method method_name + end + end + + def backup_method!(method_name) + alias_method_name = build_alias_method_name(method_name) + @klass.class_exec do + alias_method alias_method_name, method_name + end if public_protected_or_private_method_defined?(method_name) + end + + def public_protected_or_private_method_defined?(method_name) + MethodReference.method_defined_at_any_visibility?(@klass, method_name) + end + + def observe!(method_name) + allow_no_prepended_module_definition_of(method_name) + + if RSpec::Mocks.configuration.verify_partial_doubles? + unless public_protected_or_private_method_defined?(method_name) + AnyInstance.error_generator.raise_does_not_implement_error(@klass, method_name) + end + end + + stop_observing!(method_name) if already_observing?(method_name) + @observed_methods << method_name + backup_method!(method_name) + recorder = self + @klass.__send__(:define_method, method_name) do |*args, &blk| + recorder.playback!(self, method_name) + __send__(method_name, *args, &blk) + end + end + + def mark_invoked!(method_name) + backup_method!(method_name) + recorder = self + @klass.__send__(:define_method, method_name) do |*_args, &_blk| + invoked_instance = recorder.instance_that_received(method_name) + inspect = "#<#{self.class}:#{object_id} #{instance_variables.map { |name| "#{name}=#{instance_variable_get name}" }.join(', ')}>" + AnyInstance.error_generator.raise_message_already_received_by_other_instance_error( + method_name, inspect, invoked_instance + ) + end + end + + if Support::RubyFeatures.module_prepends_supported? + def allow_no_prepended_module_definition_of(method_name) + prepended_modules = RSpec::Mocks::Proxy.prepended_modules_of(@klass) + problem_mod = prepended_modules.find { |mod| mod.method_defined?(method_name) } + return unless problem_mod + + AnyInstance.error_generator.raise_not_supported_with_prepend_error(method_name, problem_mod) + end + else + def allow_no_prepended_module_definition_of(_method_name) + # nothing to do; prepends aren't supported on this version of ruby + end + end + end + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/stub_chain.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/stub_chain.rb new file mode 100644 index 0000000..adc4e6b --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/stub_chain.rb @@ -0,0 +1,46 @@ +module RSpec + module Mocks + module AnyInstance + # @private + class StubChain < Chain + # @private + def expectation_fulfilled? + true + end + + private + + def create_message_expectation_on(instance) + proxy = ::RSpec::Mocks.space.proxy_for(instance) + method_name, opts = @expectation_args + opts = (opts || {}).merge(:expected_form => IGNORED_BACKTRACE_LINE) + + stub = proxy.add_stub(method_name, opts, &@expectation_block) + @recorder.stubs[stub.message] << stub + + if RSpec::Mocks.configuration.yield_receiver_to_any_instance_implementation_blocks? + stub.and_yield_receiver_to_implementation + end + + stub + end + + def invocation_order + @invocation_order ||= { + :with => [nil], + :and_return => [:with, nil], + :and_raise => [:with, nil], + :and_yield => [:with, nil], + :and_call_original => [:with, nil], + :and_wrap_original => [:with, nil] + } + end + + def verify_invocation_order(rspec_method_name, *_args, &_block) + return if invocation_order[rspec_method_name].include?(last_message) + raise NoMethodError, "Undefined method #{rspec_method_name}" + end + end + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/stub_chain_chain.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/stub_chain_chain.rb new file mode 100644 index 0000000..c056967 --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/any_instance/stub_chain_chain.rb @@ -0,0 +1,27 @@ +module RSpec + module Mocks + module AnyInstance + # @private + class StubChainChain < StubChain + def initialize(*args) + super + @expectation_fulfilled = false + end + + private + + def create_message_expectation_on(instance) + ::RSpec::Mocks::StubChain.stub_chain_on(instance, *@expectation_args, &@expectation_block) + end + + def invocation_order + @invocation_order ||= { + :and_return => [nil], + :and_raise => [nil], + :and_yield => [nil] + } + end + end + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/argument_list_matcher.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/argument_list_matcher.rb new file mode 100644 index 0000000..1ee647b --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/argument_list_matcher.rb @@ -0,0 +1,100 @@ +# We intentionally do not use the `RSpec::Support.require...` methods +# here so that this file can be loaded individually, as documented +# below. +require 'rspec/mocks/argument_matchers' +require 'rspec/support/fuzzy_matcher' + +module RSpec + module Mocks + # Wrapper for matching arguments against a list of expected values. Used by + # the `with` method on a `MessageExpectation`: + # + # expect(object).to receive(:message).with(:a, 'b', 3) + # object.message(:a, 'b', 3) + # + # Values passed to `with` can be literal values or argument matchers that + # match against the real objects .e.g. + # + # expect(object).to receive(:message).with(hash_including(:a => 'b')) + # + # Can also be used directly to match the contents of any `Array`. This + # enables 3rd party mocking libs to take advantage of rspec's argument + # matching without using the rest of rspec-mocks. + # + # require 'rspec/mocks/argument_list_matcher' + # include RSpec::Mocks::ArgumentMatchers + # + # arg_list_matcher = RSpec::Mocks::ArgumentListMatcher.new(123, hash_including(:a => 'b')) + # arg_list_matcher.args_match?(123, :a => 'b') + # + # This class is immutable. + # + # @see ArgumentMatchers + class ArgumentListMatcher + # @private + attr_reader :expected_args + + # @api public + # @param [Array] expected_args a list of expected literals and/or argument matchers + # + # Initializes an `ArgumentListMatcher` with a collection of literal + # values and/or argument matchers. + # + # @see ArgumentMatchers + # @see #args_match? + def initialize(*expected_args) + @expected_args = expected_args + ensure_expected_args_valid! + end + + # @api public + # @param [Array] args + # + # Matches each element in the `expected_args` against the element in the same + # position of the arguments passed to `new`. + # + # @see #initialize + def args_match?(*args) + Support::FuzzyMatcher.values_match?(resolve_expected_args_based_on(args), args) + end + + # @private + # Resolves abstract arg placeholders like `no_args` and `any_args` into + # a more concrete arg list based on the provided `actual_args`. + def resolve_expected_args_based_on(actual_args) + return [] if [ArgumentMatchers::NoArgsMatcher::INSTANCE] == expected_args + + any_args_index = expected_args.index { |a| ArgumentMatchers::AnyArgsMatcher::INSTANCE == a } + return expected_args unless any_args_index + + replace_any_args_with_splat_of_anything(any_args_index, actual_args.count) + end + + private + + def replace_any_args_with_splat_of_anything(before_count, actual_args_count) + any_args_count = actual_args_count - expected_args.count + 1 + after_count = expected_args.count - before_count - 1 + + any_args = 1.upto(any_args_count).map { ArgumentMatchers::AnyArgMatcher::INSTANCE } + expected_args.first(before_count) + any_args + expected_args.last(after_count) + end + + def ensure_expected_args_valid! + if expected_args.count { |a| ArgumentMatchers::AnyArgsMatcher::INSTANCE == a } > 1 + raise ArgumentError, "`any_args` can only be passed to " \ + "`with` once but you have passed it multiple times." + elsif expected_args.count > 1 && expected_args.any? { |a| ArgumentMatchers::NoArgsMatcher::INSTANCE == a } + raise ArgumentError, "`no_args` can only be passed as a " \ + "singleton argument to `with` (i.e. `with(no_args)`), " \ + "but you have passed additional arguments." + end + end + + # Value that will match all argument lists. + # + # @private + MATCH_ALL = new(ArgumentMatchers::AnyArgsMatcher::INSTANCE) + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/argument_matchers.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/argument_matchers.rb new file mode 100644 index 0000000..8fcfd02 --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/argument_matchers.rb @@ -0,0 +1,320 @@ +# This cannot take advantage of our relative requires, since this file is a +# dependency of `rspec/mocks/argument_list_matcher.rb`. See comment there for +# details. +require 'rspec/support/matcher_definition' + +module RSpec + module Mocks + # ArgumentMatchers are placeholders that you can include in message + # expectations to match arguments against a broader check than simple + # equality. + # + # With the exception of `any_args` and `no_args`, they all match against + # the arg in same position in the argument list. + # + # @see ArgumentListMatcher + module ArgumentMatchers + # Acts like an arg splat, matching any number of args at any point in an arg list. + # + # @example + # expect(object).to receive(:message).with(1, 2, any_args) + # + # # matches any of these: + # object.message(1, 2) + # object.message(1, 2, 3) + # object.message(1, 2, 3, 4) + def any_args + AnyArgsMatcher::INSTANCE + end + + # Matches any argument at all. + # + # @example + # expect(object).to receive(:message).with(anything) + def anything + AnyArgMatcher::INSTANCE + end + + # Matches no arguments. + # + # @example + # expect(object).to receive(:message).with(no_args) + def no_args + NoArgsMatcher::INSTANCE + end + + # Matches if the actual argument responds to the specified messages. + # + # @example + # expect(object).to receive(:message).with(duck_type(:hello)) + # expect(object).to receive(:message).with(duck_type(:hello, :goodbye)) + def duck_type(*args) + DuckTypeMatcher.new(*args) + end + + # Matches a boolean value. + # + # @example + # expect(object).to receive(:message).with(boolean()) + def boolean + BooleanMatcher::INSTANCE + end + + # Matches a hash that includes the specified key(s) or key/value pairs. + # Ignores any additional keys. + # + # @example + # expect(object).to receive(:message).with(hash_including(:key => val)) + # expect(object).to receive(:message).with(hash_including(:key)) + # expect(object).to receive(:message).with(hash_including(:key, :key2 => val2)) + def hash_including(*args) + HashIncludingMatcher.new(ArgumentMatchers.anythingize_lonely_keys(*args)) + end + + # Matches an array that includes the specified items at least once. + # Ignores duplicates and additional values + # + # @example + # expect(object).to receive(:message).with(array_including(1,2,3)) + # expect(object).to receive(:message).with(array_including([1,2,3])) + def array_including(*args) + actually_an_array = Array === args.first && args.count == 1 ? args.first : args + ArrayIncludingMatcher.new(actually_an_array) + end + + # Matches a hash that doesn't include the specified key(s) or key/value. + # + # @example + # expect(object).to receive(:message).with(hash_excluding(:key => val)) + # expect(object).to receive(:message).with(hash_excluding(:key)) + # expect(object).to receive(:message).with(hash_excluding(:key, :key2 => :val2)) + def hash_excluding(*args) + HashExcludingMatcher.new(ArgumentMatchers.anythingize_lonely_keys(*args)) + end + + alias_method :hash_not_including, :hash_excluding + + # Matches if `arg.instance_of?(klass)` + # + # @example + # expect(object).to receive(:message).with(instance_of(Thing)) + def instance_of(klass) + InstanceOf.new(klass) + end + + alias_method :an_instance_of, :instance_of + + # Matches if `arg.kind_of?(klass)` + # + # @example + # expect(object).to receive(:message).with(kind_of(Thing)) + def kind_of(klass) + KindOf.new(klass) + end + + alias_method :a_kind_of, :kind_of + + # @private + def self.anythingize_lonely_keys(*args) + hash = args.last.class == Hash ? args.delete_at(-1) : {} + args.each { | arg | hash[arg] = AnyArgMatcher::INSTANCE } + hash + end + + # Intended to be subclassed by stateless, immutable argument matchers. + # Provides a `::INSTANCE` constant for accessing a global + # singleton instance of the matcher. There is no need to construct + # multiple instance since there is no state. It also facilities the + # special case logic we need for some of these matchers, by making it + # easy to do comparisons like: `[klass::INSTANCE] == args` rather than + # `args.count == 1 && klass === args.first`. + # + # @private + class SingletonMatcher + private_class_method :new + + def self.inherited(subklass) + subklass.const_set(:INSTANCE, subklass.send(:new)) + end + end + + # @private + class AnyArgsMatcher < SingletonMatcher + def description + "*(any args)" + end + end + + # @private + class AnyArgMatcher < SingletonMatcher + def ===(_other) + true + end + + def description + "anything" + end + end + + # @private + class NoArgsMatcher < SingletonMatcher + def description + "no args" + end + end + + # @private + class BooleanMatcher < SingletonMatcher + def ===(value) + true == value || false == value + end + + def description + "boolean" + end + end + + # @private + class BaseHashMatcher + def initialize(expected) + @expected = expected + end + + def ===(predicate, actual) + @expected.__send__(predicate) do |k, v| + actual.key?(k) && Support::FuzzyMatcher.values_match?(v, actual[k]) + end + rescue NoMethodError + false + end + + def description(name) + "#{name}(#{formatted_expected_hash.inspect.sub(/^\{/, "").sub(/\}$/, "")})" + end + + private + + def formatted_expected_hash + Hash[ + @expected.map do |k, v| + k = RSpec::Support.rspec_description_for_object(k) + v = RSpec::Support.rspec_description_for_object(v) + + [k, v] + end + ] + end + end + + # @private + class HashIncludingMatcher < BaseHashMatcher + def ===(actual) + super(:all?, actual) + end + + def description + super("hash_including") + end + end + + # @private + class HashExcludingMatcher < BaseHashMatcher + def ===(actual) + super(:none?, actual) + end + + def description + super("hash_not_including") + end + end + + # @private + class ArrayIncludingMatcher + def initialize(expected) + @expected = expected + end + + def ===(actual) + actual = actual.uniq + @expected.uniq.all? do |expected_element| + actual.any? do |actual_element| + RSpec::Support::FuzzyMatcher.values_match?(expected_element, actual_element) + end + end + end + + def description + "array_including(#{formatted_expected_values})" + end + + private + + def formatted_expected_values + @expected.map do |x| + RSpec::Support.rspec_description_for_object(x) + end.join(", ") + end + end + + # @private + class DuckTypeMatcher + def initialize(*methods_to_respond_to) + @methods_to_respond_to = methods_to_respond_to + end + + def ===(value) + @methods_to_respond_to.all? { |message| value.respond_to?(message) } + end + + def description + "duck_type(#{@methods_to_respond_to.map(&:inspect).join(', ')})" + end + end + + # @private + class InstanceOf + def initialize(klass) + @klass = klass + end + + def ===(actual) + actual.instance_of?(@klass) + end + + def description + "an_instance_of(#{@klass.name})" + end + end + + # @private + class KindOf + def initialize(klass) + @klass = klass + end + + def ===(actual) + actual.kind_of?(@klass) + end + + def description + "kind of #{@klass.name}" + end + end + + matcher_namespace = name + '::' + ::RSpec::Support.register_matcher_definition do |object| + # This is the best we have for now. We should tag all of our matchers + # with a module or something so we can test for it directly. + # + # (Note Module#parent in ActiveSupport is defined in a similar way.) + begin + object.class.name.include?(matcher_namespace) + rescue NoMethodError + # Some objects, like BasicObject, don't implemented standard + # reflection methods. + false + end + end + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/configuration.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/configuration.rb new file mode 100644 index 0000000..e09a12a --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/configuration.rb @@ -0,0 +1,188 @@ +module RSpec + module Mocks + # Provides configuration options for rspec-mocks. + class Configuration + def initialize + @yield_receiver_to_any_instance_implementation_blocks = true + @verify_doubled_constant_names = false + @transfer_nested_constants = false + @verify_partial_doubles = false + end + + def yield_receiver_to_any_instance_implementation_blocks? + @yield_receiver_to_any_instance_implementation_blocks + end + + # Sets whether or not RSpec will yield the receiving instance of a + # message to blocks that are used for any_instance stub implementations. + # When set, the first yielded argument will be the receiving instance. + # Defaults to `true`. + # + # @example + # RSpec.configure do |rspec| + # rspec.mock_with :rspec do |mocks| + # mocks.yield_receiver_to_any_instance_implementation_blocks = false + # end + # end + attr_writer :yield_receiver_to_any_instance_implementation_blocks + + # Adds `stub` and `should_receive` to the given + # modules or classes. This is usually only necessary + # if you application uses some proxy classes that + # "strip themselves down" to a bare minimum set of + # methods and remove `stub` and `should_receive` in + # the process. + # + # @example + # RSpec.configure do |rspec| + # rspec.mock_with :rspec do |mocks| + # mocks.add_stub_and_should_receive_to Delegator + # end + # end + # + def add_stub_and_should_receive_to(*modules) + modules.each do |mod| + Syntax.enable_should(mod) + end + end + + # Provides the ability to set either `expect`, + # `should` or both syntaxes. RSpec uses `expect` + # syntax by default. This is needed if you want to + # explicitly enable `should` syntax and/or explicitly + # disable `expect` syntax. + # + # @example + # RSpec.configure do |rspec| + # rspec.mock_with :rspec do |mocks| + # mocks.syntax = [:expect, :should] + # end + # end + # + def syntax=(*values) + syntaxes = values.flatten + if syntaxes.include?(:expect) + Syntax.enable_expect + else + Syntax.disable_expect + end + + if syntaxes.include?(:should) + Syntax.enable_should + else + Syntax.disable_should + end + end + + # Returns an array with a list of syntaxes + # that are enabled. + # + # @example + # unless RSpec::Mocks.configuration.syntax.include?(:expect) + # raise "this RSpec extension gem requires the rspec-mocks `:expect` syntax" + # end + # + def syntax + syntaxes = [] + syntaxes << :should if Syntax.should_enabled? + syntaxes << :expect if Syntax.expect_enabled? + syntaxes + end + + def verify_doubled_constant_names? + !!@verify_doubled_constant_names + end + + # When this is set to true, an error will be raised when + # `instance_double` or `class_double` is given the name of an undefined + # constant. You probably only want to set this when running your entire + # test suite, with all production code loaded. Setting this for an + # isolated unit test will prevent you from being able to isolate it! + attr_writer :verify_doubled_constant_names + + # Provides a way to perform customisations when verifying doubles. + # + # @example + # RSpec::Mocks.configuration.before_verifying_doubles do |ref| + # ref.some_method! + # end + def before_verifying_doubles(&block) + verifying_double_callbacks << block + end + alias :when_declaring_verifying_double :before_verifying_doubles + + # @api private + # Returns an array of blocks to call when verifying doubles + def verifying_double_callbacks + @verifying_double_callbacks ||= [] + end + + def transfer_nested_constants? + !!@transfer_nested_constants + end + + # Sets the default for the `transfer_nested_constants` option when + # stubbing constants. + attr_writer :transfer_nested_constants + + # When set to true, partial mocks will be verified the same as object + # doubles. Any stubs will have their arguments checked against the original + # method, and methods that do not exist cannot be stubbed. + def verify_partial_doubles=(val) + @verify_partial_doubles = !!val + end + + def verify_partial_doubles? + @verify_partial_doubles + end + + if ::RSpec.respond_to?(:configuration) + def color? + ::RSpec.configuration.color_enabled? + end + else + # Indicates whether or not diffs should be colored. + # Delegates to rspec-core's color option if rspec-core + # is loaded; otherwise you can set it here. + attr_writer :color + + # Indicates whether or not diffs should be colored. + # Delegates to rspec-core's color option if rspec-core + # is loaded; otherwise you can set it here. + def color? + @color + end + end + + # Monkey-patch `Marshal.dump` to enable dumping of mocked or stubbed + # objects. By default this will not work since RSpec mocks works by + # adding singleton methods that cannot be serialized. This patch removes + # these singleton methods before serialization. Setting to falsey removes + # the patch. + # + # This method is idempotent. + def patch_marshal_to_support_partial_doubles=(val) + if val + RSpec::Mocks::MarshalExtension.patch! + else + RSpec::Mocks::MarshalExtension.unpatch! + end + end + + # @api private + # Resets the configured syntax to the default. + def reset_syntaxes_to_default + self.syntax = [:should, :expect] + RSpec::Mocks::Syntax.warn_about_should! + end + end + + # Mocks specific configuration, as distinct from `RSpec.configuration` + # which is core RSpec configuration. + def self.configuration + @configuration ||= Configuration.new + end + + configuration.reset_syntaxes_to_default + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/error_generator.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/error_generator.rb new file mode 100644 index 0000000..c8dfa61 --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/error_generator.rb @@ -0,0 +1,362 @@ +RSpec::Support.require_rspec_support "object_formatter" + +module RSpec + module Mocks + # Raised when a message expectation is not satisfied. + MockExpectationError = Class.new(Exception) + + # Raised when a test double is used after it has been torn + # down (typically at the end of an rspec-core example). + ExpiredTestDoubleError = Class.new(MockExpectationError) + + # Raised when doubles or partial doubles are used outside of the per-test lifecycle. + OutsideOfExampleError = Class.new(StandardError) + + # Raised when an expectation customization method (e.g. `with`, + # `and_return`) is called on a message expectation which has already been + # invoked. + MockExpectationAlreadyInvokedError = Class.new(Exception) + + # Raised for situations that RSpec cannot support due to mutations made + # externally on arguments that RSpec is holding onto to use for later + # comparisons. + # + # @deprecated We no longer raise this error but the constant remains until + # RSpec 4 for SemVer reasons. + CannotSupportArgMutationsError = Class.new(StandardError) + + # @private + UnsupportedMatcherError = Class.new(StandardError) + # @private + NegationUnsupportedError = Class.new(StandardError) + # @private + VerifyingDoubleNotDefinedError = Class.new(StandardError) + + # @private + class ErrorGenerator + attr_writer :opts + + def initialize(target=nil) + @target = target + end + + # @private + def opts + @opts ||= {} + end + + # @private + def raise_unexpected_message_error(message, args) + __raise "#{intro} received unexpected message :#{message} with #{format_args(args)}" + end + + # @private + def raise_unexpected_message_args_error(expectation, args_for_multiple_calls, source_id=nil) + __raise error_message(expectation, args_for_multiple_calls), nil, source_id + end + + # @private + def raise_missing_default_stub_error(expectation, args_for_multiple_calls) + message = error_message(expectation, args_for_multiple_calls) + message << "\n Please stub a default value first if message might be received with other args as well. \n" + + __raise message + end + + # @private + def raise_similar_message_args_error(expectation, args_for_multiple_calls, backtrace_line=nil) + __raise error_message(expectation, args_for_multiple_calls), backtrace_line + end + + def default_error_message(expectation, expected_args, actual_args) + [ + intro, + "received", + expectation.message.inspect, + unexpected_arguments_message(expected_args, actual_args), + ].join(" ") + end + + # rubocop:disable Style/ParameterLists + # @private + def raise_expectation_error(message, expected_received_count, argument_list_matcher, + actual_received_count, expectation_count_type, args, + backtrace_line=nil, source_id=nil) + expected_part = expected_part_of_expectation_error(expected_received_count, expectation_count_type, argument_list_matcher) + received_part = received_part_of_expectation_error(actual_received_count, args) + __raise "(#{intro(:unwrapped)}).#{message}#{format_args(args)}\n #{expected_part}\n #{received_part}", backtrace_line, source_id + end + # rubocop:enable Style/ParameterLists + + # @private + def raise_unimplemented_error(doubled_module, method_name, object) + message = case object + when InstanceVerifyingDouble + "the %s class does not implement the instance method: %s" << + if ObjectMethodReference.for(doubled_module, method_name).implemented? + ". Perhaps you meant to use `class_double` instead?" + else + "" + end + when ClassVerifyingDouble + "the %s class does not implement the class method: %s" << + if InstanceMethodReference.for(doubled_module, method_name).implemented? + ". Perhaps you meant to use `instance_double` instead?" + else + "" + end + else + "%s does not implement: %s" + end + + __raise message % [doubled_module.description, method_name] + end + + # @private + def raise_non_public_error(method_name, visibility) + raise NoMethodError, "%s method `%s' called on %s" % [ + visibility, method_name, intro + ] + end + + # @private + def raise_invalid_arguments_error(verifier) + __raise verifier.error_message + end + + # @private + def raise_expired_test_double_error + raise ExpiredTestDoubleError, + "#{intro} was originally created in one example but has leaked into " \ + "another example and can no longer be used. rspec-mocks' doubles are " \ + "designed to only last for one example, and you need to create a new " \ + "one in each example you wish to use it for." + end + + # @private + def describe_expectation(verb, message, expected_received_count, _actual_received_count, args) + "#{verb} #{message}#{format_args(args)} #{count_message(expected_received_count)}" + end + + # @private + def raise_out_of_order_error(message) + __raise "#{intro} received :#{message} out of order" + end + + # @private + def raise_missing_block_error(args_to_yield) + __raise "#{intro} asked to yield |#{arg_list(args_to_yield)}| but no block was passed" + end + + # @private + def raise_wrong_arity_error(args_to_yield, signature) + __raise "#{intro} yielded |#{arg_list(args_to_yield)}| to block with #{signature.description}" + end + + # @private + def raise_only_valid_on_a_partial_double(method) + __raise "#{intro} is a pure test double. `#{method}` is only " \ + "available on a partial double." + end + + # @private + def raise_expectation_on_unstubbed_method(method) + __raise "#{intro} expected to have received #{method}, but that " \ + "object is not a spy or method has not been stubbed." + end + + # @private + def raise_expectation_on_mocked_method(method) + __raise "#{intro} expected to have received #{method}, but that " \ + "method has been mocked instead of stubbed or spied." + end + + # @private + def raise_double_negation_error(wrapped_expression) + __raise "Isn't life confusing enough? You've already set a " \ + "negative message expectation and now you are trying to " \ + "negate it again with `never`. What does an expression like " \ + "`#{wrapped_expression}.not_to receive(:msg).never` even mean?" + end + + # @private + def raise_verifying_double_not_defined_error(ref) + notify(VerifyingDoubleNotDefinedError.new( + "#{ref.description.inspect} is not a defined constant. " \ + "Perhaps you misspelt it? " \ + "Disable check with `verify_doubled_constant_names` configuration option." + )) + end + + # @private + def raise_have_received_disallowed(type, reason) + __raise "Using #{type}(...) with the `have_received` " \ + "matcher is not supported#{reason}." + end + + # @private + def raise_cant_constrain_count_for_negated_have_received_error(count_constraint) + __raise "can't use #{count_constraint} when negative" + end + + # @private + def raise_method_not_stubbed_error(method_name) + __raise "The method `#{method_name}` was not stubbed or was already unstubbed" + end + + # @private + def raise_already_invoked_error(message, calling_customization) + error_message = "The message expectation for #{intro}.#{message} has already been invoked " \ + "and cannot be modified further (e.g. using `#{calling_customization}`). All message expectation " \ + "customizations must be applied before it is used for the first time." + + notify MockExpectationAlreadyInvokedError.new(error_message) + end + + private + + def received_part_of_expectation_error(actual_received_count, args) + "received: #{count_message(actual_received_count)}" + + method_call_args_description(args) do + actual_received_count > 0 && args.length > 0 + end + end + + def expected_part_of_expectation_error(expected_received_count, expectation_count_type, argument_list_matcher) + "expected: #{count_message(expected_received_count, expectation_count_type)}" + + method_call_args_description(argument_list_matcher.expected_args) do + argument_list_matcher.expected_args.length > 0 + end + end + + def method_call_args_description(args) + case args.first + when ArgumentMatchers::AnyArgsMatcher then " with any arguments" + when ArgumentMatchers::NoArgsMatcher then " with no arguments" + else + if yield + " with arguments: #{format_args(args)}" + else + "" + end + end + end + + def unexpected_arguments_message(expected_args_string, actual_args_string) + "with unexpected arguments\n expected: #{expected_args_string}\n got: #{actual_args_string}" + end + + def error_message(expectation, args_for_multiple_calls) + expected_args = format_args(expectation.expected_args) + actual_args = format_received_args(args_for_multiple_calls) + message = default_error_message(expectation, expected_args, actual_args) + + if args_for_multiple_calls.one? + diff = diff_message(expectation.expected_args, args_for_multiple_calls.first) + message << "\nDiff:#{diff}" unless diff.strip.empty? + end + + message + end + + def diff_message(expected_args, actual_args) + formatted_expected_args = expected_args.map do |x| + RSpec::Support.rspec_description_for_object(x) + end + + formatted_expected_args, actual_args = unpack_string_args(formatted_expected_args, actual_args) + + differ.diff(actual_args, formatted_expected_args) + end + + def unpack_string_args(formatted_expected_args, actual_args) + if [formatted_expected_args, actual_args].all? { |x| list_of_exactly_one_string?(x) } + [formatted_expected_args.first, actual_args.first] + else + [formatted_expected_args, actual_args] + end + end + + def list_of_exactly_one_string?(args) + Array === args && args.count == 1 && String === args.first + end + + def differ + RSpec::Support::Differ.new(:color => RSpec::Mocks.configuration.color?) + end + + def intro(unwrapped=false) + case @target + when TestDouble then TestDoubleFormatter.format(@target, unwrapped) + when Class then + formatted = "#{@target.inspect} (class)" + return formatted if unwrapped + "#<#{formatted}>" + when NilClass then "nil" + else @target + end + end + + def __raise(message, backtrace_line=nil, source_id=nil) + message = opts[:message] unless opts[:message].nil? + exception = RSpec::Mocks::MockExpectationError.new(message) + prepend_to_backtrace(exception, backtrace_line) if backtrace_line + notify exception, :source_id => source_id + end + + if RSpec::Support::Ruby.jruby? + def prepend_to_backtrace(exception, line) + raise exception + rescue RSpec::Mocks::MockExpectationError => with_backtrace + with_backtrace.backtrace.unshift(line) + end + else + def prepend_to_backtrace(exception, line) + exception.set_backtrace(caller.unshift line) + end + end + + def notify(*args) + RSpec::Support.notify_failure(*args) + end + + def format_args(args) + return "(no args)" if args.empty? + "(#{arg_list(args)})" + end + + def arg_list(args) + args.map { |arg| RSpec::Support::ObjectFormatter.format(arg) }.join(", ") + end + + def format_received_args(args_for_multiple_calls) + grouped_args(args_for_multiple_calls).map do |args_for_one_call, index| + "#{format_args(args_for_one_call)}#{group_count(index, args_for_multiple_calls)}" + end.join("\n ") + end + + def count_message(count, expectation_count_type=nil) + return "at least #{times(count.abs)}" if count < 0 || expectation_count_type == :at_least + return "at most #{times(count)}" if expectation_count_type == :at_most + times(count) + end + + def times(count) + "#{count} time#{count == 1 ? '' : 's'}" + end + + def grouped_args(args) + Hash[args.group_by { |x| x }.map { |k, v| [k, v.count] }] + end + + def group_count(index, args) + " (#{times(index)})" if args.size > 1 || index > 1 + end + end + + # @private + def self.error_generator + @error_generator ||= ErrorGenerator.new + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/example_methods.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/example_methods.rb new file mode 100644 index 0000000..4de71a2 --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/example_methods.rb @@ -0,0 +1,421 @@ +RSpec::Support.require_rspec_mocks 'object_reference' + +module RSpec + module Mocks + # Contains methods intended to be used from within code examples. + # Mix this in to your test context (such as a test framework base class) + # to use rspec-mocks with your test framework. If you're using rspec-core, + # it'll take care of doing this for you. + module ExampleMethods + include RSpec::Mocks::ArgumentMatchers + + # @overload double() + # @overload double(name) + # @param name [String/Symbol] name or description to be used in failure messages + # @overload double(stubs) + # @param stubs (Hash) hash of message/return-value pairs + # @overload double(name, stubs) + # @param name [String/Symbol] name or description to be used in failure messages + # @param stubs (Hash) hash of message/return-value pairs + # @return (Double) + # + # Constructs an instance of [RSpec::Mocks::Double](RSpec::Mocks::Double) configured + # with an optional name, used for reporting in failure messages, and an optional + # hash of message/return-value pairs. + # + # @example + # book = double("book", :title => "The RSpec Book") + # book.title #=> "The RSpec Book" + # + # card = double("card", :suit => "Spades", :rank => "A") + # card.suit #=> "Spades" + # card.rank #=> "A" + # + def double(*args) + ExampleMethods.declare_double(Double, *args) + end + + # @overload instance_double(doubled_class) + # @param doubled_class [String, Class] + # @overload instance_double(doubled_class, name) + # @param doubled_class [String, Class] + # @param name [String/Symbol] name or description to be used in failure messages + # @overload instance_double(doubled_class, stubs) + # @param doubled_class [String, Class] + # @param stubs [Hash] hash of message/return-value pairs + # @overload instance_double(doubled_class, name, stubs) + # @param doubled_class [String, Class] + # @param name [String/Symbol] name or description to be used in failure messages + # @param stubs [Hash] hash of message/return-value pairs + # @return InstanceVerifyingDouble + # + # Constructs a test double against a specific class. If the given class + # name has been loaded, only instance methods defined on the class are + # allowed to be stubbed. In all other ways it behaves like a + # [double](double). + def instance_double(doubled_class, *args) + ref = ObjectReference.for(doubled_class) + ExampleMethods.declare_verifying_double(InstanceVerifyingDouble, ref, *args) + end + + # @overload class_double(doubled_class) + # @param doubled_class [String, Module] + # @overload class_double(doubled_class, name) + # @param doubled_class [String, Module] + # @param name [String/Symbol] name or description to be used in failure messages + # @overload class_double(doubled_class, stubs) + # @param doubled_class [String, Module] + # @param stubs [Hash] hash of message/return-value pairs + # @overload class_double(doubled_class, name, stubs) + # @param doubled_class [String, Module] + # @param name [String/Symbol] name or description to be used in failure messages + # @param stubs [Hash] hash of message/return-value pairs + # @return ClassVerifyingDouble + # + # Constructs a test double against a specific class. If the given class + # name has been loaded, only class methods defined on the class are + # allowed to be stubbed. In all other ways it behaves like a + # [double](double). + def class_double(doubled_class, *args) + ref = ObjectReference.for(doubled_class) + ExampleMethods.declare_verifying_double(ClassVerifyingDouble, ref, *args) + end + + # @overload object_double(object_or_name) + # @param object_or_name [String, Object] + # @overload object_double(object_or_name, name) + # @param object_or_name [String, Object] + # @param name [String/Symbol] name or description to be used in failure messages + # @overload object_double(object_or_name, stubs) + # @param object_or_name [String, Object] + # @param stubs [Hash] hash of message/return-value pairs + # @overload object_double(object_or_name, name, stubs) + # @param object_or_name [String, Object] + # @param name [String/Symbol] name or description to be used in failure messages + # @param stubs [Hash] hash of message/return-value pairs + # @return ObjectVerifyingDouble + # + # Constructs a test double against a specific object. Only the methods + # the object responds to are allowed to be stubbed. If a String argument + # is provided, it is assumed to reference a constant object which is used + # for verification. In all other ways it behaves like a [double](double). + def object_double(object_or_name, *args) + ref = ObjectReference.for(object_or_name, :allow_direct_object_refs) + ExampleMethods.declare_verifying_double(ObjectVerifyingDouble, ref, *args) + end + + # @overload spy() + # @overload spy(name) + # @param name [String/Symbol] name or description to be used in failure messages + # @overload spy(stubs) + # @param stubs (Hash) hash of message/return-value pairs + # @overload spy(name, stubs) + # @param name [String/Symbol] name or description to be used in failure messages + # @param stubs (Hash) hash of message/return-value pairs + # @return (Double) + # + # Constructs a test double that is optimized for use with + # `have_received`. With a normal double one has to stub methods in order + # to be able to spy them. A spy automatically spies on all methods. + def spy(*args) + double(*args).as_null_object + end + + # @overload instance_spy(doubled_class) + # @param doubled_class [String, Class] + # @overload instance_spy(doubled_class, name) + # @param doubled_class [String, Class] + # @param name [String/Symbol] name or description to be used in failure messages + # @overload instance_spy(doubled_class, stubs) + # @param doubled_class [String, Class] + # @param stubs [Hash] hash of message/return-value pairs + # @overload instance_spy(doubled_class, name, stubs) + # @param doubled_class [String, Class] + # @param name [String/Symbol] name or description to be used in failure messages + # @param stubs [Hash] hash of message/return-value pairs + # @return InstanceVerifyingDouble + # + # Constructs a test double that is optimized for use with `have_received` + # against a specific class. If the given class name has been loaded, only + # instance methods defined on the class are allowed to be stubbed. With + # a normal double one has to stub methods in order to be able to spy + # them. An instance_spy automatically spies on all instance methods to + # which the class responds. + def instance_spy(*args) + instance_double(*args).as_null_object + end + + # @overload object_spy(object_or_name) + # @param object_or_name [String, Object] + # @overload object_spy(object_or_name, name) + # @param object_or_name [String, Class] + # @param name [String/Symbol] name or description to be used in failure messages + # @overload object_spy(object_or_name, stubs) + # @param object_or_name [String, Object] + # @param stubs [Hash] hash of message/return-value pairs + # @overload object_spy(object_or_name, name, stubs) + # @param object_or_name [String, Class] + # @param name [String/Symbol] name or description to be used in failure messages + # @param stubs [Hash] hash of message/return-value pairs + # @return ObjectVerifyingDouble + # + # Constructs a test double that is optimized for use with `have_received` + # against a specific object. Only instance methods defined on the object + # are allowed to be stubbed. With a normal double one has to stub + # methods in order to be able to spy them. An object_spy automatically + # spies on all methods to which the object responds. + def object_spy(*args) + object_double(*args).as_null_object + end + + # @overload class_spy(doubled_class) + # @param doubled_class [String, Module] + # @overload class_spy(doubled_class, name) + # @param doubled_class [String, Class] + # @param name [String/Symbol] name or description to be used in failure messages + # @overload class_spy(doubled_class, stubs) + # @param doubled_class [String, Module] + # @param stubs [Hash] hash of message/return-value pairs + # @overload class_spy(doubled_class, name, stubs) + # @param doubled_class [String, Class] + # @param name [String/Symbol] name or description to be used in failure messages + # @param stubs [Hash] hash of message/return-value pairs + # @return ClassVerifyingDouble + # + # Constructs a test double that is optimized for use with `have_received` + # against a specific class. If the given class name has been loaded, + # only class methods defined on the class are allowed to be stubbed. + # With a normal double one has to stub methods in order to be able to spy + # them. An class_spy automatically spies on all class methods to which the + # class responds. + def class_spy(*args) + class_double(*args).as_null_object + end + + # Disables warning messages about expectations being set on nil. + # + # By default warning messages are issued when expectations are set on + # nil. This is to prevent false-positives and to catch potential bugs + # early on. + def allow_message_expectations_on_nil + RSpec::Mocks.space.proxy_for(nil).warn_about_expectations = false + end + + # Stubs the named constant with the given value. + # Like method stubs, the constant will be restored + # to its original value (or lack of one, if it was + # undefined) when the example completes. + # + # @param constant_name [String] The fully qualified name of the constant. The current + # constant scoping at the point of call is not considered. + # @param value [Object] The value to make the constant refer to. When the + # example completes, the constant will be restored to its prior state. + # @param options [Hash] Stubbing options. + # @option options :transfer_nested_constants [Boolean, Array] Determines + # what nested constants, if any, will be transferred from the original value + # of the constant to the new value of the constant. This only works if both + # the original and new values are modules (or classes). + # @return [Object] the stubbed value of the constant + # + # @example + # stub_const("MyClass", Class.new) # => Replaces (or defines) MyClass with a new class object. + # stub_const("SomeModel::PER_PAGE", 5) # => Sets SomeModel::PER_PAGE to 5. + # + # class CardDeck + # SUITS = [:Spades, :Diamonds, :Clubs, :Hearts] + # NUM_CARDS = 52 + # end + # + # stub_const("CardDeck", Class.new) + # CardDeck::SUITS # => uninitialized constant error + # CardDeck::NUM_CARDS # => uninitialized constant error + # + # stub_const("CardDeck", Class.new, :transfer_nested_constants => true) + # CardDeck::SUITS # => our suits array + # CardDeck::NUM_CARDS # => 52 + # + # stub_const("CardDeck", Class.new, :transfer_nested_constants => [:SUITS]) + # CardDeck::SUITS # => our suits array + # CardDeck::NUM_CARDS # => uninitialized constant error + def stub_const(constant_name, value, options={}) + ConstantMutator.stub(constant_name, value, options) + end + + # Hides the named constant with the given value. The constant will be + # undefined for the duration of the test. + # + # Like method stubs, the constant will be restored to its original value + # when the example completes. + # + # @param constant_name [String] The fully qualified name of the constant. + # The current constant scoping at the point of call is not considered. + # + # @example + # hide_const("MyClass") # => MyClass is now an undefined constant + def hide_const(constant_name) + ConstantMutator.hide(constant_name) + end + + # Verifies that the given object received the expected message during the + # course of the test. On a spy objects or as null object doubles this + # works for any method, on other objects the method must have + # been stubbed beforehand in order for messages to be verified. + # + # Stubbing and verifying messages received in this way implements the + # Test Spy pattern. + # + # @param method_name [Symbol] name of the method expected to have been + # called. + # + # @example + # invitation = double('invitation', accept: true) + # user.accept_invitation(invitation) + # expect(invitation).to have_received(:accept) + # + # # You can also use most message expectations: + # expect(invitation).to have_received(:accept).with(mailer).once + # + # @note `have_received(...).with(...)` is unable to work properly when + # passed arguments are mutated after the spy records the received message. + def have_received(method_name, &block) + Matchers::HaveReceived.new(method_name, &block) + end + + # @method expect + # Used to wrap an object in preparation for setting a mock expectation + # on it. + # + # @example + # expect(obj).to receive(:foo).with(5).and_return(:return_value) + # + # @note This method is usually provided by rspec-expectations. However, + # if you use rspec-mocks without rspec-expectations, there's a definition + # of it that is made available here. If you disable the `:expect` syntax + # this method will be undefined. + + # @method allow + # Used to wrap an object in preparation for stubbing a method + # on it. + # + # @example + # allow(dbl).to receive(:foo).with(5).and_return(:return_value) + # + # @note If you disable the `:expect` syntax this method will be undefined. + + # @method expect_any_instance_of + # Used to wrap a class in preparation for setting a mock expectation + # on instances of it. + # + # @example + # expect_any_instance_of(MyClass).to receive(:foo) + # + # @note If you disable the `:expect` syntax this method will be undefined. + + # @method allow_any_instance_of + # Used to wrap a class in preparation for stubbing a method + # on instances of it. + # + # @example + # allow_any_instance_of(MyClass).to receive(:foo) + # + # @note This is only available when you have enabled the `expect` syntax. + + # @method receive + # Used to specify a message that you expect or allow an object + # to receive. The object returned by `receive` supports the same + # fluent interface that `should_receive` and `stub` have always + # supported, allowing you to constrain the arguments or number of + # times, and configure how the object should respond to the message. + # + # @example + # expect(obj).to receive(:hello).with("world").exactly(3).times + # + # @note If you disable the `:expect` syntax this method will be undefined. + + # @method receive_messages + # Shorthand syntax used to setup message(s), and their return value(s), + # that you expect or allow an object to receive. The method takes a hash + # of messages and their respective return values. Unlike with `receive`, + # you cannot apply further customizations using a block or the fluent + # interface. + # + # @example + # allow(obj).to receive_messages(:speak => "Hello World") + # allow(obj).to receive_messages(:speak => "Hello", :meow => "Meow") + # + # @note If you disable the `:expect` syntax this method will be undefined. + + # @method receive_message_chain + # @overload receive_message_chain(method1, method2) + # @overload receive_message_chain("method1.method2") + # @overload receive_message_chain(method1, method_to_value_hash) + # + # stubs/mocks a chain of messages on an object or test double. + # + # ## Warning: + # + # Chains can be arbitrarily long, which makes it quite painless to + # violate the Law of Demeter in violent ways, so you should consider any + # use of `receive_message_chain` a code smell. Even though not all code smells + # indicate real problems (think fluent interfaces), `receive_message_chain` still + # results in brittle examples. For example, if you write + # `allow(foo).to receive_message_chain(:bar, :baz => 37)` in a spec and then the + # implementation calls `foo.baz.bar`, the stub will not work. + # + # @example + # allow(double).to receive_message_chain("foo.bar") { :baz } + # allow(double).to receive_message_chain(:foo, :bar => :baz) + # allow(double).to receive_message_chain(:foo, :bar) { :baz } + # + # # Given any of ^^ these three forms ^^: + # double.foo.bar # => :baz + # + # # Common use in Rails/ActiveRecord: + # allow(Article).to receive_message_chain("recent.published") { [Article.new] } + # + # @note If you disable the `:expect` syntax this method will be undefined. + + # @private + def self.included(klass) + klass.class_exec do + # This gets mixed in so that if `RSpec::Matchers` is included in + # `klass` later, it's definition of `expect` will take precedence. + include ExpectHost unless method_defined?(:expect) + end + end + + # @private + def self.extended(object) + # This gets extended in so that if `RSpec::Matchers` is included in + # `klass` later, it's definition of `expect` will take precedence. + object.extend ExpectHost unless object.respond_to?(:expect) + end + + # @private + def self.declare_verifying_double(type, ref, *args) + if RSpec::Mocks.configuration.verify_doubled_constant_names? && + !ref.defined? + + RSpec::Mocks.error_generator.raise_verifying_double_not_defined_error(ref) + end + + RSpec::Mocks.configuration.verifying_double_callbacks.each do |block| + block.call(ref) + end + + declare_double(type, ref, *args) + end + + # @private + def self.declare_double(type, *args) + args << {} unless Hash === args.last + type.new(*args) + end + + # This module exists to host the `expect` method for cases where + # rspec-mocks is used w/o rspec-expectations. + module ExpectHost + end + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/instance_method_stasher.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/instance_method_stasher.rb new file mode 100644 index 0000000..44145ca --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/instance_method_stasher.rb @@ -0,0 +1,135 @@ +module RSpec + module Mocks + # @private + class InstanceMethodStasher + def initialize(object, method) + @object = object + @method = method + @klass = (class << object; self; end) + + @original_method = nil + @method_is_stashed = false + end + + attr_reader :original_method + + if RUBY_VERSION.to_f < 1.9 + # @private + def method_is_stashed? + @method_is_stashed + end + + # @private + def stash + return if !method_defined_directly_on_klass? || @method_is_stashed + + @klass.__send__(:alias_method, stashed_method_name, @method) + @method_is_stashed = true + end + + # @private + def stashed_method_name + "obfuscated_by_rspec_mocks__#{@method}" + end + private :stashed_method_name + + # @private + def restore + return unless @method_is_stashed + + if @klass.__send__(:method_defined?, @method) + @klass.__send__(:undef_method, @method) + end + @klass.__send__(:alias_method, @method, stashed_method_name) + @klass.__send__(:remove_method, stashed_method_name) + @method_is_stashed = false + end + else + + # @private + def method_is_stashed? + !!@original_method + end + + # @private + def stash + return unless method_defined_directly_on_klass? + @original_method ||= ::RSpec::Support.method_handle_for(@object, @method) + end + + # @private + def restore + return unless @original_method + + if @klass.__send__(:method_defined?, @method) + @klass.__send__(:undef_method, @method) + end + + handle_restoration_failures do + @klass.__send__(:define_method, @method, @original_method) + end + + @original_method = nil + end + end + + if RUBY_DESCRIPTION.include?('2.0.0p247') || RUBY_DESCRIPTION.include?('2.0.0p195') + # ruby 2.0.0-p247 and 2.0.0-p195 both have a bug that we can't work around :(. + # https://bugs.ruby-lang.org/issues/8686 + def handle_restoration_failures + yield + rescue TypeError + RSpec.warn_with( + "RSpec failed to properly restore a partial double (#{@object.inspect}) " \ + "to its original state due to a known bug in MRI 2.0.0-p195 & p247 " \ + "(https://bugs.ruby-lang.org/issues/8686). This object may remain " \ + "screwed up for the rest of this process. Please upgrade to 2.0.0-p353 or above.", + :call_site => nil, :use_spec_location_as_call_site => true + ) + end + else + def handle_restoration_failures + # No known reasons for restoration to fail on other rubies. + yield + end + end + + private + + # @private + def method_defined_directly_on_klass? + method_defined_on_klass? && method_owned_by_klass? + end + + # @private + def method_defined_on_klass?(klass=@klass) + MethodReference.method_defined_at_any_visibility?(klass, @method) + end + + def method_owned_by_klass? + owner = @klass.instance_method(@method).owner + + # On Ruby 2.0.0+ the owner of a method on a class which has been + # `prepend`ed may actually be an instance, e.g. + # `#`, rather than the expected `MyClass`. + owner = owner.class unless Module === owner + + # On some 1.9s (e.g. rubinius) aliased methods + # can report the wrong owner. Example: + # class MyClass + # class << self + # alias alternate_new new + # end + # end + # + # MyClass.owner(:alternate_new) returns `Class` when incorrect, + # but we need to consider the owner to be `MyClass` because + # it is not actually available on `Class` but is on `MyClass`. + # Hence, we verify that the owner actually has the method defined. + # If the given owner does not have the method defined, we assume + # that the method is actually owned by @klass. + owner == @klass || !(method_defined_on_klass?(owner)) + end + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/marshal_extension.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/marshal_extension.rb new file mode 100644 index 0000000..cfa9c1a --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/marshal_extension.rb @@ -0,0 +1,41 @@ +module RSpec + module Mocks + # Support for `patch_marshal_to_support_partial_doubles` configuration. + # + # @private + class MarshalExtension + def self.patch! + return if Marshal.respond_to?(:dump_with_rspec_mocks) + + Marshal.instance_eval do + class << self + def dump_with_rspec_mocks(object, *rest) + if !::RSpec::Mocks.space.registered?(object) || NilClass === object + dump_without_rspec_mocks(object, *rest) + else + dump_without_rspec_mocks(object.dup, *rest) + end + end + + alias_method :dump_without_rspec_mocks, :dump + undef_method :dump + alias_method :dump, :dump_with_rspec_mocks + end + end + end + + def self.unpatch! + return unless Marshal.respond_to?(:dump_with_rspec_mocks) + + Marshal.instance_eval do + class << self + undef_method :dump_with_rspec_mocks + undef_method :dump + alias_method :dump, :dump_without_rspec_mocks + undef_method :dump_without_rspec_mocks + end + end + end + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/matchers/expectation_customization.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/matchers/expectation_customization.rb new file mode 100644 index 0000000..81e6427 --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/matchers/expectation_customization.rb @@ -0,0 +1,20 @@ +module RSpec + module Mocks + module Matchers + # @private + class ExpectationCustomization + attr_accessor :block + + def initialize(method_name, args, block) + @method_name = method_name + @args = args + @block = block + end + + def playback_onto(expectation) + expectation.__send__(@method_name, *@args, &@block) + end + end + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/matchers/have_received.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/matchers/have_received.rb new file mode 100644 index 0000000..127b358 --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/matchers/have_received.rb @@ -0,0 +1,116 @@ +module RSpec + module Mocks + module Matchers + # @private + class HaveReceived + COUNT_CONSTRAINTS = %w[exactly at_least at_most times once twice thrice] + ARGS_CONSTRAINTS = %w[with] + CONSTRAINTS = COUNT_CONSTRAINTS + ARGS_CONSTRAINTS + %w[ordered] + + def initialize(method_name, &block) + @method_name = method_name + @block = block + @constraints = [] + @subject = nil + end + + def name + "have_received" + end + + def matches?(subject, &block) + @block ||= block + @subject = subject + @expectation = expect + mock_proxy.ensure_implemented(@method_name) + + expected_messages_received_in_order? + end + + def does_not_match?(subject) + @subject = subject + ensure_count_unconstrained + @expectation = expect.never + mock_proxy.ensure_implemented(@method_name) + expected_messages_received_in_order? + end + + def failure_message + generate_failure_message + end + + def failure_message_when_negated + generate_failure_message + end + + def description + (@expectation ||= expect).description_for("have received") + end + + CONSTRAINTS.each do |expectation| + define_method expectation do |*args| + @constraints << [expectation, *args] + self + end + end + + def setup_allowance(_subject, &_block) + disallow("allow", " as it would have no effect") + end + + def setup_any_instance_allowance(_subject, &_block) + disallow("allow_any_instance_of") + end + + def setup_any_instance_expectation(_subject, &_block) + disallow("expect_any_instance_of") + end + + private + + def disallow(type, reason="") + RSpec::Mocks.error_generator.raise_have_received_disallowed(type, reason) + end + + def expect + expectation = mock_proxy.build_expectation(@method_name) + apply_constraints_to expectation + expectation + end + + def apply_constraints_to(expectation) + @constraints.each do |constraint| + expectation.send(*constraint) + end + end + + def ensure_count_unconstrained + return unless count_constraint + RSpec::Mocks.error_generator.raise_cant_constrain_count_for_negated_have_received_error(count_constraint) + end + + def count_constraint + @constraints.map(&:first).find do |constraint| + COUNT_CONSTRAINTS.include?(constraint) + end + end + + def generate_failure_message + RSpec::Support.with_failure_notifier(Proc.new { |err, _opt| return err.message }) do + mock_proxy.check_for_unexpected_arguments(@expectation) + @expectation.generate_error + end + end + + def expected_messages_received_in_order? + mock_proxy.replay_received_message_on @expectation, &@block + @expectation.expected_messages_received? && @expectation.ensure_expected_ordering_received! + end + + def mock_proxy + RSpec::Mocks.space.proxy_for(@subject) + end + end + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/matchers/receive.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/matchers/receive.rb new file mode 100644 index 0000000..a16b28f --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/matchers/receive.rb @@ -0,0 +1,130 @@ +RSpec::Support.require_rspec_mocks 'matchers/expectation_customization' + +module RSpec + module Mocks + module Matchers + # @private + class Receive + def initialize(message, block) + @message = message + @block = block + @recorded_customizations = [] + end + + def name + "receive" + end + + def description + describable.description_for("receive") + end + + def setup_expectation(subject, &block) + warn_if_any_instance("expect", subject) + @describable = setup_mock_proxy_method_substitute(subject, :add_message_expectation, block) + end + alias matches? setup_expectation + + def setup_negative_expectation(subject, &block) + # ensure `never` goes first for cases like `never.and_return(5)`, + # where `and_return` is meant to raise an error + @recorded_customizations.unshift ExpectationCustomization.new(:never, [], nil) + + warn_if_any_instance("expect", subject) + + setup_expectation(subject, &block) + end + alias does_not_match? setup_negative_expectation + + def setup_allowance(subject, &block) + warn_if_any_instance("allow", subject) + setup_mock_proxy_method_substitute(subject, :add_stub, block) + end + + def setup_any_instance_expectation(subject, &block) + setup_any_instance_method_substitute(subject, :should_receive, block) + end + + def setup_any_instance_negative_expectation(subject, &block) + setup_any_instance_method_substitute(subject, :should_not_receive, block) + end + + def setup_any_instance_allowance(subject, &block) + setup_any_instance_method_substitute(subject, :stub, block) + end + + MessageExpectation.public_instance_methods(false).each do |method| + next if method_defined?(method) + + define_method(method) do |*args, &block| + @recorded_customizations << ExpectationCustomization.new(method, args, block) + self + end + end + + private + + def describable + @describable ||= DefaultDescribable.new(@message) + end + + def warn_if_any_instance(expression, subject) + return unless AnyInstance::Proxy === subject + + RSpec.warning( + "`#{expression}(#{subject.klass}.any_instance).to` " \ + "is probably not what you meant, it does not operate on " \ + "any instance of `#{subject.klass}`. " \ + "Use `#{expression}_any_instance_of(#{subject.klass}).to` instead." + ) + end + + def setup_mock_proxy_method_substitute(subject, method, block) + proxy = ::RSpec::Mocks.space.proxy_for(subject) + setup_method_substitute(proxy, method, block) + end + + def setup_any_instance_method_substitute(subject, method, block) + proxy = ::RSpec::Mocks.space.any_instance_proxy_for(subject) + setup_method_substitute(proxy, method, block) + end + + def setup_method_substitute(host, method, block, *args) + args << @message.to_sym + block = move_block_to_last_customization(block) + + expectation = host.__send__(method, *args, &(@block || block)) + + @recorded_customizations.each do |customization| + customization.playback_onto(expectation) + end + expectation + end + + def move_block_to_last_customization(block) + last = @recorded_customizations.last + return block unless last + + last.block ||= block + nil + end + + # MessageExpectation objects are able to describe themselves in detail. + # We use this as a fall back when a MessageExpectation is not available. + # @private + class DefaultDescribable + def initialize(message) + @message = message + end + + # This is much simpler for the `any_instance` case than what the + # user may want, but I'm not up for putting a bunch of effort + # into full descriptions for `any_instance` expectations at this point :(. + def description_for(verb) + "#{verb} #{@message}" + end + end + end + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/matchers/receive_message_chain.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/matchers/receive_message_chain.rb new file mode 100644 index 0000000..d831cd3 --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/matchers/receive_message_chain.rb @@ -0,0 +1,80 @@ +RSpec::Support.require_rspec_mocks 'matchers/expectation_customization' + +module RSpec + module Mocks + module Matchers + # @private + class ReceiveMessageChain + def initialize(chain, &block) + @chain = chain + @block = block + @recorded_customizations = [] + end + + [:with, :and_return, :and_throw, :and_raise, :and_yield, :and_call_original].each do |msg| + define_method(msg) do |*args, &block| + @recorded_customizations << ExpectationCustomization.new(msg, args, block) + self + end + end + + def name + "receive_message_chain" + end + + def description + "receive message chain #{formatted_chain}" + end + + def setup_allowance(subject, &block) + chain = StubChain.stub_chain_on(subject, *@chain, &(@block || block)) + replay_customizations(chain) + end + + def setup_any_instance_allowance(subject, &block) + proxy = ::RSpec::Mocks.space.any_instance_proxy_for(subject) + chain = proxy.stub_chain(*@chain, &(@block || block)) + replay_customizations(chain) + end + + def setup_any_instance_expectation(subject, &block) + proxy = ::RSpec::Mocks.space.any_instance_proxy_for(subject) + chain = proxy.expect_chain(*@chain, &(@block || block)) + replay_customizations(chain) + end + + def setup_expectation(subject, &block) + chain = ExpectChain.expect_chain_on(subject, *@chain, &(@block || block)) + replay_customizations(chain) + end + + def setup_negative_expectation(*_args) + raise NegationUnsupportedError, + "`expect(...).not_to receive_message_chain` is not supported " \ + "since it doesn't really make sense. What would it even mean?" + end + + alias matches? setup_expectation + alias does_not_match? setup_negative_expectation + + private + + def replay_customizations(chain) + @recorded_customizations.each do |customization| + customization.playback_onto(chain) + end + end + + def formatted_chain + @formatted_chain ||= @chain.map do |part| + if Hash === part + part.keys.first.to_s + else + part.to_s + end + end.join(".") + end + end + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/matchers/receive_messages.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/matchers/receive_messages.rb new file mode 100644 index 0000000..b6316aa --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/matchers/receive_messages.rb @@ -0,0 +1,75 @@ +module RSpec + module Mocks + module Matchers + # @private + class ReceiveMessages + def initialize(message_return_value_hash) + @message_return_value_hash = message_return_value_hash + @backtrace_line = CallerFilter.first_non_rspec_line + end + + def name + "receive_messages" + end + + def description + "receive messages: #{@message_return_value_hash.inspect}" + end + + def setup_expectation(subject) + warn_about_block if block_given? + each_message_on(proxy_on(subject)) do |host, message, return_value| + host.add_simple_expectation(message, return_value, @backtrace_line) + end + end + alias matches? setup_expectation + + def setup_negative_expectation(_subject) + raise NegationUnsupportedError, + "`expect(...).to_not receive_messages` is not supported since it " \ + "doesn't really make sense. What would it even mean?" + end + alias does_not_match? setup_negative_expectation + + def setup_allowance(subject) + warn_about_block if block_given? + each_message_on(proxy_on(subject)) do |host, message, return_value| + host.add_simple_stub(message, return_value) + end + end + + def setup_any_instance_expectation(subject) + warn_about_block if block_given? + each_message_on(any_instance_of(subject)) do |host, message, return_value| + host.should_receive(message).and_return(return_value) + end + end + + def setup_any_instance_allowance(subject) + warn_about_block if block_given? + any_instance_of(subject).stub(@message_return_value_hash) + end + + def warn_about_block + raise "Implementation blocks aren't supported with `receive_messages`" + end + + private + + def proxy_on(subject) + ::RSpec::Mocks.space.proxy_for(subject) + end + + def any_instance_of(subject) + ::RSpec::Mocks.space.any_instance_proxy_for(subject) + end + + def each_message_on(host) + @message_return_value_hash.each do |message, value| + yield host, message, value + end + end + end + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/message_chain.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/message_chain.rb new file mode 100644 index 0000000..907d14b --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/message_chain.rb @@ -0,0 +1,87 @@ +module RSpec + module Mocks + # @private + class MessageChain + attr_reader :object, :chain, :block + + def initialize(object, *chain, &blk) + @object = object + @chain, @block = format_chain(*chain, &blk) + end + + # @api private + def setup_chain + if chain.length > 1 + if (matching_stub = find_matching_stub) + chain.shift + chain_on(matching_stub.invoke(nil), *chain, &@block) + elsif (matching_expectation = find_matching_expectation) + chain.shift + chain_on(matching_expectation.invoke_without_incrementing_received_count(nil), *chain, &@block) + else + next_in_chain = Double.new + expectation(object, chain.shift) { next_in_chain } + chain_on(next_in_chain, *chain, &@block) + end + else + expectation(object, chain.shift, &@block) + end + end + + private + + def chain_on(object, *chain, &block) + initialize(object, *chain, &block) + setup_chain + end + + def format_chain(*chain, &blk) + if Hash === chain.last + hash = chain.pop + hash.each do |k, v| + chain << k + blk = Proc.new { v } + end + end + return chain.join('.').split('.'), blk + end + + def find_matching_stub + ::RSpec::Mocks.space.proxy_for(object). + __send__(:find_matching_method_stub, chain.first.to_sym) + end + + def find_matching_expectation + ::RSpec::Mocks.space.proxy_for(object). + __send__(:find_matching_expectation, chain.first.to_sym) + end + end + + # @private + class ExpectChain < MessageChain + # @api private + def self.expect_chain_on(object, *chain, &blk) + new(object, *chain, &blk).setup_chain + end + + private + + def expectation(object, message, &return_block) + ::RSpec::Mocks.expect_message(object, message, {}, &return_block) + end + end + + # @private + class StubChain < MessageChain + def self.stub_chain_on(object, *chain, &blk) + new(object, *chain, &blk).setup_chain + end + + private + + def expectation(object, message, &return_block) + ::RSpec::Mocks.allow_message(object, message, {}, &return_block) + end + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/message_expectation.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/message_expectation.rb new file mode 100644 index 0000000..75d59ec --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/message_expectation.rb @@ -0,0 +1,717 @@ +module RSpec + module Mocks + # A message expectation that only allows concrete return values to be set + # for a message. While this same effect can be achieved using a standard + # MessageExpecation, this version is much faster and so can be used as an + # optimization. + # + # @private + class SimpleMessageExpectation + def initialize(message, response, error_generator, backtrace_line=nil) + @message, @response, @error_generator, @backtrace_line = message.to_sym, response, error_generator, backtrace_line + @received = false + end + + def invoke(*_) + @received = true + @response + end + + def matches?(message, *_) + @message == message.to_sym + end + + def called_max_times? + false + end + + def verify_messages_received + return if @received + @error_generator.raise_expectation_error( + @message, 1, ArgumentListMatcher::MATCH_ALL, 0, nil, [], @backtrace_line + ) + end + + def unadvise(_) + end + end + + # Represents an individual method stub or message expectation. The methods + # defined here can be used to configure how it behaves. The methods return + # `self` so that they can be chained together to form a fluent interface. + class MessageExpectation + # @!group Configuring Responses + + # @overload and_return(value) + # @overload and_return(first_value, second_value) + # + # Tells the object to return a value when it receives the message. Given + # more than one value, the first value is returned the first time the + # message is received, the second value is returned the next time, etc, + # etc. + # + # If the message is received more times than there are values, the last + # value is received for every subsequent call. + # + # @return [nil] No further chaining is supported after this. + # @example + # allow(counter).to receive(:count).and_return(1) + # counter.count # => 1 + # counter.count # => 1 + # + # allow(counter).to receive(:count).and_return(1,2,3) + # counter.count # => 1 + # counter.count # => 2 + # counter.count # => 3 + # counter.count # => 3 + # counter.count # => 3 + # # etc + def and_return(first_value, *values) + raise_already_invoked_error_if_necessary(__method__) + if negative? + raise "`and_return` is not supported with negative message expectations" + end + + if block_given? + raise ArgumentError, "Implementation blocks aren't supported with `and_return`" + end + + values.unshift(first_value) + @expected_received_count = [@expected_received_count, values.size].max unless ignoring_args? || (@expected_received_count == 0 && @at_least) + self.terminal_implementation_action = AndReturnImplementation.new(values) + + nil + end + + # Tells the object to delegate to the original unmodified method + # when it receives the message. + # + # @note This is only available on partial doubles. + # + # @return [nil] No further chaining is supported after this. + # @example + # expect(counter).to receive(:increment).and_call_original + # original_count = counter.count + # counter.increment + # expect(counter.count).to eq(original_count + 1) + def and_call_original + and_wrap_original do |original, *args, &block| + original.call(*args, &block) + end + end + + # Decorates the stubbed method with the supplied block. The original + # unmodified method is passed to the block along with any method call + # arguments so you can delegate to it, whilst still being able to + # change what args are passed to it and/or change the return value. + # + # @note This is only available on partial doubles. + # + # @return [nil] No further chaining is supported after this. + # @example + # expect(api).to receive(:large_list).and_wrap_original do |original_method, *args, &block| + # original_method.call(*args, &block).first(10) + # end + def and_wrap_original(&block) + if RSpec::Mocks::TestDouble === @method_double.object + @error_generator.raise_only_valid_on_a_partial_double(:and_call_original) + else + warn_about_stub_override if implementation.inner_action + @implementation = AndWrapOriginalImplementation.new(@method_double.original_implementation_callable, block) + @yield_receiver_to_implementation_block = false + end + + nil + end + + # @overload and_raise + # @overload and_raise(ExceptionClass) + # @overload and_raise(ExceptionClass, message) + # @overload and_raise(exception_instance) + # + # Tells the object to raise an exception when the message is received. + # + # @return [nil] No further chaining is supported after this. + # @note + # When you pass an exception class, the MessageExpectation will raise + # an instance of it, creating it with `exception` and passing `message` + # if specified. If the exception class initializer requires more than + # one parameters, you must pass in an instance and not the class, + # otherwise this method will raise an ArgumentError exception. + # + # @example + # allow(car).to receive(:go).and_raise + # allow(car).to receive(:go).and_raise(OutOfGas) + # allow(car).to receive(:go).and_raise(OutOfGas, "At least 2 oz of gas needed to drive") + # allow(car).to receive(:go).and_raise(OutOfGas.new(2, :oz)) + def and_raise(*args) + raise_already_invoked_error_if_necessary(__method__) + self.terminal_implementation_action = Proc.new { raise(*args) } + nil + end + + # @overload and_throw(symbol) + # @overload and_throw(symbol, object) + # + # Tells the object to throw a symbol (with the object if that form is + # used) when the message is received. + # + # @return [nil] No further chaining is supported after this. + # @example + # allow(car).to receive(:go).and_throw(:out_of_gas) + # allow(car).to receive(:go).and_throw(:out_of_gas, :level => 0.1) + def and_throw(*args) + raise_already_invoked_error_if_necessary(__method__) + self.terminal_implementation_action = Proc.new { throw(*args) } + nil + end + + # Tells the object to yield one or more args to a block when the message + # is received. + # + # @return [MessageExpecation] self, to support further chaining. + # @example + # stream.stub(:open).and_yield(StringIO.new) + def and_yield(*args, &block) + raise_already_invoked_error_if_necessary(__method__) + yield @eval_context = Object.new if block + + # Initialize args to yield now that it's being used, see also: comment + # in constructor. + @args_to_yield ||= [] + + @args_to_yield << args + self.initial_implementation_action = AndYieldImplementation.new(@args_to_yield, @eval_context, @error_generator) + self + end + # @!endgroup + + # @!group Constraining Receive Counts + + # Constrain a message expectation to be received a specific number of + # times. + # + # @return [MessageExpecation] self, to support further chaining. + # @example + # expect(dealer).to receive(:deal_card).exactly(10).times + def exactly(n, &block) + raise_already_invoked_error_if_necessary(__method__) + self.inner_implementation_action = block + set_expected_received_count :exactly, n + self + end + + # Constrain a message expectation to be received at least a specific + # number of times. + # + # @return [MessageExpecation] self, to support further chaining. + # @example + # expect(dealer).to receive(:deal_card).at_least(9).times + def at_least(n, &block) + raise_already_invoked_error_if_necessary(__method__) + set_expected_received_count :at_least, n + + if n == 0 + raise "at_least(0) has been removed, use allow(...).to receive(:message) instead" + end + + self.inner_implementation_action = block + + self + end + + # Constrain a message expectation to be received at most a specific + # number of times. + # + # @return [MessageExpecation] self, to support further chaining. + # @example + # expect(dealer).to receive(:deal_card).at_most(10).times + def at_most(n, &block) + raise_already_invoked_error_if_necessary(__method__) + self.inner_implementation_action = block + set_expected_received_count :at_most, n + self + end + + # Syntactic sugar for `exactly`, `at_least` and `at_most` + # + # @return [MessageExpecation] self, to support further chaining. + # @example + # expect(dealer).to receive(:deal_card).exactly(10).times + # expect(dealer).to receive(:deal_card).at_least(10).times + # expect(dealer).to receive(:deal_card).at_most(10).times + def times(&block) + self.inner_implementation_action = block + self + end + + # Expect a message not to be received at all. + # + # @return [MessageExpecation] self, to support further chaining. + # @example + # expect(car).to receive(:stop).never + def never + error_generator.raise_double_negation_error("expect(obj)") if negative? + @expected_received_count = 0 + self + end + + # Expect a message to be received exactly one time. + # + # @return [MessageExpecation] self, to support further chaining. + # @example + # expect(car).to receive(:go).once + def once(&block) + self.inner_implementation_action = block + set_expected_received_count :exactly, 1 + self + end + + # Expect a message to be received exactly two times. + # + # @return [MessageExpecation] self, to support further chaining. + # @example + # expect(car).to receive(:go).twice + def twice(&block) + self.inner_implementation_action = block + set_expected_received_count :exactly, 2 + self + end + + # Expect a message to be received exactly three times. + # + # @return [MessageExpecation] self, to support further chaining. + # @example + # expect(car).to receive(:go).thrice + def thrice(&block) + self.inner_implementation_action = block + set_expected_received_count :exactly, 3 + self + end + # @!endgroup + + # @!group Other Constraints + + # Constrains a stub or message expectation to invocations with specific + # arguments. + # + # With a stub, if the message might be received with other args as well, + # you should stub a default value first, and then stub or mock the same + # message using `with` to constrain to specific arguments. + # + # A message expectation will fail if the message is received with different + # arguments. + # + # @return [MessageExpecation] self, to support further chaining. + # @example + # allow(cart).to receive(:add) { :failure } + # allow(cart).to receive(:add).with(Book.new(:isbn => 1934356379)) { :success } + # cart.add(Book.new(:isbn => 1234567890)) + # # => :failure + # cart.add(Book.new(:isbn => 1934356379)) + # # => :success + # + # expect(cart).to receive(:add).with(Book.new(:isbn => 1934356379)) { :success } + # cart.add(Book.new(:isbn => 1234567890)) + # # => failed expectation + # cart.add(Book.new(:isbn => 1934356379)) + # # => passes + def with(*args, &block) + raise_already_invoked_error_if_necessary(__method__) + if args.empty? + raise ArgumentError, + "`with` must have at least one argument. Use `no_args` matcher to set the expectation of receiving no arguments." + end + + self.inner_implementation_action = block + @argument_list_matcher = ArgumentListMatcher.new(*args) + self + end + + # Expect messages to be received in a specific order. + # + # @return [MessageExpecation] self, to support further chaining. + # @example + # expect(api).to receive(:prepare).ordered + # expect(api).to receive(:run).ordered + # expect(api).to receive(:finish).ordered + def ordered(&block) + self.inner_implementation_action = block + additional_expected_calls.times do + @order_group.register(self) + end + @ordered = true + self + end + + # @private + # Contains the parts of `MessageExpecation` that aren't part of + # rspec-mocks' public API. The class is very big and could really use + # some collaborators it delegates to for this stuff but for now this was + # the simplest way to split the public from private stuff to make it + # easier to publish the docs for the APIs we want published. + module ImplementationDetails + attr_accessor :error_generator, :implementation + attr_reader :message + attr_reader :orig_object + attr_writer :expected_received_count, :expected_from, :argument_list_matcher + protected :expected_received_count=, :expected_from=, :error_generator, :error_generator=, :implementation= + + # rubocop:disable Style/ParameterLists + def initialize(error_generator, expectation_ordering, expected_from, method_double, + type=:expectation, opts={}, &implementation_block) + @error_generator = error_generator + @error_generator.opts = opts + @expected_from = expected_from + @method_double = method_double + @orig_object = @method_double.object + @message = @method_double.method_name + @actual_received_count = 0 + @expected_received_count = type == :expectation ? 1 : :any + @argument_list_matcher = ArgumentListMatcher::MATCH_ALL + @order_group = expectation_ordering + @order_group.register(self) unless type == :stub + @expectation_type = type + @ordered = false + @at_least = @at_most = @exactly = nil + + # Initialized to nil so that we don't allocate an array for every + # mock or stub. See also comment in `and_yield`. + @args_to_yield = nil + @eval_context = nil + @yield_receiver_to_implementation_block = false + + @implementation = Implementation.new + self.inner_implementation_action = implementation_block + end + # rubocop:enable Style/ParameterLists + + def expected_args + @argument_list_matcher.expected_args + end + + def and_yield_receiver_to_implementation + @yield_receiver_to_implementation_block = true + self + end + + def yield_receiver_to_implementation_block? + @yield_receiver_to_implementation_block + end + + def matches?(message, *args) + @message == message && @argument_list_matcher.args_match?(*args) + end + + def safe_invoke(parent_stub, *args, &block) + invoke_incrementing_actual_calls_by(1, false, parent_stub, *args, &block) + end + + def invoke(parent_stub, *args, &block) + invoke_incrementing_actual_calls_by(1, true, parent_stub, *args, &block) + end + + def invoke_without_incrementing_received_count(parent_stub, *args, &block) + invoke_incrementing_actual_calls_by(0, true, parent_stub, *args, &block) + end + + def negative? + @expected_received_count == 0 && !@at_least + end + + def called_max_times? + @expected_received_count != :any && + !@at_least && + @expected_received_count > 0 && + @actual_received_count >= @expected_received_count + end + + def matches_name_but_not_args(message, *args) + @message == message && !@argument_list_matcher.args_match?(*args) + end + + def verify_messages_received + return if expected_messages_received? + generate_error + end + + def expected_messages_received? + ignoring_args? || matches_exact_count? || matches_at_least_count? || matches_at_most_count? + end + + def ensure_expected_ordering_received! + @order_group.verify_invocation_order(self) if @ordered + true + end + + def ignoring_args? + @expected_received_count == :any + end + + def matches_at_least_count? + @at_least && @actual_received_count >= @expected_received_count + end + + def matches_at_most_count? + @at_most && @actual_received_count <= @expected_received_count + end + + def matches_exact_count? + @expected_received_count == @actual_received_count + end + + def similar_messages + @similar_messages ||= [] + end + + def advise(*args) + similar_messages << args + end + + def unadvise(args) + similar_messages.delete_if { |message| args.include?(message) } + end + + def generate_error + if similar_messages.empty? + @error_generator.raise_expectation_error( + @message, @expected_received_count, @argument_list_matcher, + @actual_received_count, expectation_count_type, expected_args, + @expected_from, exception_source_id + ) + else + @error_generator.raise_similar_message_args_error( + self, @similar_messages, @expected_from + ) + end + end + + def raise_unexpected_message_args_error(args_for_multiple_calls) + @error_generator.raise_unexpected_message_args_error(self, args_for_multiple_calls, exception_source_id) + end + + def expectation_count_type + return :at_least if @at_least + return :at_most if @at_most + nil + end + + def description_for(verb) + @error_generator.describe_expectation( + verb, @message, @expected_received_count, + @actual_received_count, expected_args + ) + end + + def raise_out_of_order_error + @error_generator.raise_out_of_order_error @message + end + + def additional_expected_calls + return 0 if @expectation_type == :stub || !@exactly + @expected_received_count - 1 + end + + def ordered? + @ordered + end + + def negative_expectation_for?(message) + @message == message && negative? + end + + def actual_received_count_matters? + @at_least || @at_most || @exactly + end + + def increase_actual_received_count! + @actual_received_count += 1 + end + + private + + def exception_source_id + @exception_source_id ||= "#{self.class.name} #{__id__}" + end + + def invoke_incrementing_actual_calls_by(increment, allowed_to_fail, parent_stub, *args, &block) + args.unshift(orig_object) if yield_receiver_to_implementation_block? + + if negative? || (allowed_to_fail && (@exactly || @at_most) && (@actual_received_count == @expected_received_count)) + # args are the args we actually received, @argument_list_matcher is the + # list of args we were expecting + @error_generator.raise_expectation_error( + @message, @expected_received_count, + @argument_list_matcher, + @actual_received_count + increment, + expectation_count_type, args, nil, exception_source_id + ) + end + + @order_group.handle_order_constraint self + + if implementation.present? + implementation.call(*args, &block) + elsif parent_stub + parent_stub.invoke(nil, *args, &block) + end + ensure + @actual_received_count += increment + end + + def has_been_invoked? + @actual_received_count > 0 + end + + def raise_already_invoked_error_if_necessary(calling_customization) + return unless has_been_invoked? + + error_generator.raise_already_invoked_error(message, calling_customization) + end + + def set_expected_received_count(relativity, n) + @at_least = (relativity == :at_least) + @at_most = (relativity == :at_most) + @exactly = (relativity == :exactly) + @expected_received_count = case n + when Numeric then n + when :once then 1 + when :twice then 2 + when :thrice then 3 + end + end + + def initial_implementation_action=(action) + implementation.initial_action = action + end + + def inner_implementation_action=(action) + return unless action + warn_about_stub_override if implementation.inner_action + implementation.inner_action = action + end + + def terminal_implementation_action=(action) + implementation.terminal_action = action + end + + def warn_about_stub_override + RSpec.warning( + "You're overriding a previous stub implementation of `#{@message}`. " \ + "Called from #{CallerFilter.first_non_rspec_line}." + ) + end + end + + include ImplementationDetails + end + + # Handles the implementation of an `and_yield` declaration. + # @private + class AndYieldImplementation + def initialize(args_to_yield, eval_context, error_generator) + @args_to_yield = args_to_yield + @eval_context = eval_context + @error_generator = error_generator + end + + def call(*_args_to_ignore, &block) + return if @args_to_yield.empty? && @eval_context.nil? + + @error_generator.raise_missing_block_error @args_to_yield unless block + value = nil + block_signature = Support::BlockSignature.new(block) + + @args_to_yield.each do |args| + unless Support::StrictSignatureVerifier.new(block_signature, args).valid? + @error_generator.raise_wrong_arity_error(args, block_signature) + end + + value = @eval_context ? @eval_context.instance_exec(*args, &block) : block.call(*args) + end + value + end + end + + # Handles the implementation of an `and_return` implementation. + # @private + class AndReturnImplementation + def initialize(values_to_return) + @values_to_return = values_to_return + end + + def call(*_args_to_ignore, &_block) + if @values_to_return.size > 1 + @values_to_return.shift + else + @values_to_return.first + end + end + end + + # Represents a configured implementation. Takes into account + # any number of sub-implementations. + # @private + class Implementation + attr_accessor :initial_action, :inner_action, :terminal_action + + def call(*args, &block) + actions.map do |action| + action.call(*args, &block) + end.last + end + + def present? + actions.any? + end + + private + + def actions + [initial_action, inner_action, terminal_action].compact + end + end + + # Represents an `and_call_original` implementation. + # @private + class AndWrapOriginalImplementation + def initialize(method, block) + @method = method + @block = block + end + + CannotModifyFurtherError = Class.new(StandardError) + + def initial_action=(_value) + raise cannot_modify_further_error + end + + def inner_action=(_value) + raise cannot_modify_further_error + end + + def terminal_action=(_value) + raise cannot_modify_further_error + end + + def present? + true + end + + def inner_action + true + end + + def call(*args, &block) + @block.call(@method, *args, &block) + end + + private + + def cannot_modify_further_error + CannotModifyFurtherError.new "This method has already been configured " \ + "to call the original implementation, and cannot be modified further." + end + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/method_double.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/method_double.rb new file mode 100644 index 0000000..53e6efd --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/method_double.rb @@ -0,0 +1,287 @@ +module RSpec + module Mocks + # @private + class MethodDouble + # @private + attr_reader :method_name, :object, :expectations, :stubs + + # @private + def initialize(object, method_name, proxy) + @method_name = method_name + @object = object + @proxy = proxy + + @original_visibility = nil + @method_stasher = InstanceMethodStasher.new(object, method_name) + @method_is_proxied = false + @expectations = [] + @stubs = [] + end + + def original_implementation_callable + # If original method is not present, uses the `method_missing` + # handler of the object. This accounts for cases where the user has not + # correctly defined `respond_to?`, and also 1.8 which does not provide + # method handles for missing methods even if `respond_to?` is correct. + @original_implementation_callable ||= original_method || + Proc.new do |*args, &block| + @object.__send__(:method_missing, @method_name, *args, &block) + end + end + + alias_method :save_original_implementation_callable!, :original_implementation_callable + + def original_method + @original_method ||= + @method_stasher.original_method || + @proxy.original_method_handle_for(method_name) + end + + # @private + def visibility + @proxy.visibility_for(@method_name) + end + + # @private + def object_singleton_class + class << @object; self; end + end + + # @private + def configure_method + @original_visibility = visibility + @method_stasher.stash unless @method_is_proxied + define_proxy_method + end + + # @private + def define_proxy_method + return if @method_is_proxied + + save_original_implementation_callable! + definition_target.class_exec(self, method_name, visibility) do |method_double, method_name, visibility| + define_method(method_name) do |*args, &block| + method_double.proxy_method_invoked(self, *args, &block) + end + __send__(visibility, method_name) + end + + @method_is_proxied = true + end + + # The implementation of the proxied method. Subclasses may override this + # method to perform additional operations. + # + # @private + def proxy_method_invoked(_obj, *args, &block) + @proxy.message_received method_name, *args, &block + end + + # @private + def restore_original_method + return show_frozen_warning if object_singleton_class.frozen? + return unless @method_is_proxied + + remove_method_from_definition_target + @method_stasher.restore if @method_stasher.method_is_stashed? + restore_original_visibility + + @method_is_proxied = false + end + + # @private + def show_frozen_warning + RSpec.warn_with( + "WARNING: rspec-mocks was unable to restore the original `#{@method_name}` " \ + "method on #{@object.inspect} because it has been frozen. If you reuse this " \ + "object, `#{@method_name}` will continue to respond with its stub implementation.", + :call_site => nil, + :use_spec_location_as_call_site => true + ) + end + + # @private + def restore_original_visibility + return unless @original_visibility && + MethodReference.method_defined_at_any_visibility?(object_singleton_class, @method_name) + + object_singleton_class.__send__(@original_visibility, method_name) + end + + # @private + def verify + expectations.each { |e| e.verify_messages_received } + end + + # @private + def reset + restore_original_method + clear + end + + # @private + def clear + expectations.clear + stubs.clear + end + + # The type of message expectation to create has been extracted to its own + # method so that subclasses can override it. + # + # @private + def message_expectation_class + MessageExpectation + end + + # @private + def add_expectation(error_generator, expectation_ordering, expected_from, opts, &implementation) + configure_method + expectation = message_expectation_class.new(error_generator, expectation_ordering, + expected_from, self, :expectation, opts, &implementation) + expectations << expectation + expectation + end + + # @private + def build_expectation(error_generator, expectation_ordering) + expected_from = IGNORED_BACKTRACE_LINE + message_expectation_class.new(error_generator, expectation_ordering, expected_from, self) + end + + # @private + def add_stub(error_generator, expectation_ordering, expected_from, opts={}, &implementation) + configure_method + stub = message_expectation_class.new(error_generator, expectation_ordering, expected_from, + self, :stub, opts, &implementation) + stubs.unshift stub + stub + end + + # A simple stub can only return a concrete value for a message, and + # cannot match on arguments. It is used as an optimization over + # `add_stub` / `add_expectation` where it is known in advance that this + # is all that will be required of a stub, such as when passing attributes + # to the `double` example method. They do not stash or restore existing method + # definitions. + # + # @private + def add_simple_stub(method_name, response) + setup_simple_method_double method_name, response, stubs + end + + # @private + def add_simple_expectation(method_name, response, error_generator, backtrace_line) + setup_simple_method_double method_name, response, expectations, error_generator, backtrace_line + end + + # @private + def setup_simple_method_double(method_name, response, collection, error_generator=nil, backtrace_line=nil) + define_proxy_method + + me = SimpleMessageExpectation.new(method_name, response, error_generator, backtrace_line) + collection.unshift me + me + end + + # @private + def add_default_stub(*args, &implementation) + return if stubs.any? + add_stub(*args, &implementation) + end + + # @private + def remove_stub + raise_method_not_stubbed_error if stubs.empty? + remove_stub_if_present + end + + # @private + def remove_stub_if_present + expectations.empty? ? reset : stubs.clear + end + + # @private + def raise_method_not_stubbed_error + RSpec::Mocks.error_generator.raise_method_not_stubbed_error(method_name) + end + + # In Ruby 2.0.0 and above prepend will alter the method lookup chain. + # We use an object's singleton class to define method doubles upon, + # however if the object has had it's singleton class (as opposed to + # it's actual class) prepended too then the the method lookup chain + # will look in the prepended module first, **before** the singleton + # class. + # + # This code works around that by providing a mock definition target + # that is either the singleton class, or if necessary, a prepended module + # of our own. + # + if Support::RubyFeatures.module_prepends_supported? + + private + + # We subclass `Module` in order to be able to easily detect our prepended module. + RSpecPrependedModule = Class.new(Module) + + def definition_target + @definition_target ||= usable_rspec_prepended_module || object_singleton_class + end + + def usable_rspec_prepended_module + @proxy.prepended_modules_of_singleton_class.each do |mod| + # If we have one of our modules prepended before one of the user's + # modules that defines the method, use that, since our module's + # definition will take precedence. + return mod if RSpecPrependedModule === mod + + # If we hit a user module with the method defined first, + # we must create a new prepend module, even if one exists later, + # because ours will only take precedence if it comes first. + return new_rspec_prepended_module if mod.method_defined?(method_name) + end + + nil + end + + def new_rspec_prepended_module + RSpecPrependedModule.new.tap do |mod| + object_singleton_class.__send__ :prepend, mod + end + end + + else + + private + + def definition_target + object_singleton_class + end + + end + + private + + def remove_method_from_definition_target + definition_target.__send__(:remove_method, @method_name) + rescue NameError + # This can happen when the method has been monkeyed with by + # something outside RSpec. This happens, for example, when + # `file.write` has been stubbed, and then `file.reopen(other_io)` + # is later called, as `File#reopen` appears to redefine `write`. + # + # Note: we could avoid rescuing this by checking + # `definition_target.instance_method(@method_name).owner == definition_target`, + # saving us from the cost of the expensive exception, but this error is + # extremely rare (it was discovered on 2014-12-30, only happens on + # RUBY_VERSION < 2.0 and our spec suite only hits this condition once), + # so we'd rather avoid the cost of that check for every method double, + # and risk the rare situation where this exception will get raised. + RSpec.warn_with( + "WARNING: RSpec could not fully restore #{@object.inspect}." \ + "#{@method_name}, possibly because the method has been redefined " \ + "by something outside of RSpec." + ) + end + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/method_reference.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/method_reference.rb new file mode 100644 index 0000000..513706e --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/method_reference.rb @@ -0,0 +1,192 @@ +module RSpec + module Mocks + # Represents a method on an object that may or may not be defined. + # The method may be an instance method on a module or a method on + # any object. + # + # @private + class MethodReference + def self.for(object_reference, method_name) + new(object_reference, method_name) + end + + def initialize(object_reference, method_name) + @object_reference = object_reference + @method_name = method_name + end + + # A method is implemented if sending the message does not result in + # a `NoMethodError`. It might be dynamically implemented by + # `method_missing`. + def implemented? + @object_reference.when_loaded do |m| + method_implemented?(m) + end + end + + # Returns true if we definitively know that sending the method + # will result in a `NoMethodError`. + # + # This is not simply the inverse of `implemented?`: there are + # cases when we don't know if a method is implemented and + # both `implemented?` and `unimplemented?` will return false. + def unimplemented? + @object_reference.when_loaded do |_m| + return !implemented? + end + + # If it's not loaded, then it may be implemented but we can't check. + false + end + + # A method is defined if we are able to get a `Method` object for it. + # In that case, we can assert against metadata like the arity. + def defined? + @object_reference.when_loaded do |m| + method_defined?(m) + end + end + + def with_signature + return unless (original = original_method) + yield Support::MethodSignature.new(original) + end + + def visibility + @object_reference.when_loaded do |m| + return visibility_from(m) + end + + # When it's not loaded, assume it's public. We don't want to + # wrongly treat the method as private. + :public + end + + private + + def original_method + @object_reference.when_loaded do |m| + self.defined? && find_method(m) + end + end + + def self.instance_method_visibility_for(klass, method_name) + if klass.public_method_defined?(method_name) + :public + elsif klass.private_method_defined?(method_name) + :private + elsif klass.protected_method_defined?(method_name) + :protected + end + end + + class << self + alias method_defined_at_any_visibility? instance_method_visibility_for + end + + def self.method_visibility_for(object, method_name) + instance_method_visibility_for(class << object; self; end, method_name).tap do |vis| + # If the method is not defined on the class, `instance_method_visibility_for` + # returns `nil`. However, it may be handled dynamically by `method_missing`, + # so here we check `respond_to` (passing false to not check private methods). + # + # This only considers the public case, but I don't think it's possible to + # write `method_missing` in such a way that it handles a dynamic message + # with private or protected visibility. Ruby doesn't provide you with + # the caller info. + return :public if vis.nil? && object.respond_to?(method_name, false) + end + end + end + + # @private + class InstanceMethodReference < MethodReference + private + + def method_implemented?(mod) + MethodReference.method_defined_at_any_visibility?(mod, @method_name) + end + + # Ideally, we'd use `respond_to?` for `method_implemented?` but we need a + # reference to an instance to do that and we don't have one. Note that + # we may get false negatives: if the method is implemented via + # `method_missing`, we'll return `false` even though it meets our + # definition of "implemented". However, it's the best we can do. + alias method_defined? method_implemented? + + # works around the fact that repeated calls for method parameters will + # falsely return empty arrays on JRuby in certain circumstances, this + # is necessary here because we can't dup/clone UnboundMethods. + # + # This is necessary due to a bug in JRuby prior to 1.7.5 fixed in: + # https://github.com/jruby/jruby/commit/99a0613fe29935150d76a9a1ee4cf2b4f63f4a27 + if RUBY_PLATFORM == 'java' && JRUBY_VERSION.split('.')[-1].to_i < 5 + def find_method(mod) + mod.dup.instance_method(@method_name) + end + else + def find_method(mod) + mod.instance_method(@method_name) + end + end + + def visibility_from(mod) + MethodReference.instance_method_visibility_for(mod, @method_name) + end + end + + # @private + class ObjectMethodReference < MethodReference + def self.for(object_reference, method_name) + if ClassNewMethodReference.applies_to?(method_name) { object_reference.when_loaded { |o| o } } + ClassNewMethodReference.new(object_reference, method_name) + else + super + end + end + + private + + def method_implemented?(object) + object.respond_to?(@method_name, true) + end + + def method_defined?(object) + (class << object; self; end).method_defined?(@method_name) + end + + def find_method(object) + object.method(@method_name) + end + + def visibility_from(object) + MethodReference.method_visibility_for(object, @method_name) + end + end + + # When a class's `.new` method is stubbed, we want to use the method + # signature from `#initialize` because `.new`'s signature is a generic + # `def new(*args)` and it simply delegates to `#initialize` and forwards + # all args...so the method with the actually used signature is `#initialize`. + # + # This method reference implementation handles that specific case. + # @private + class ClassNewMethodReference < ObjectMethodReference + def self.applies_to?(method_name) + return false unless method_name == :new + klass = yield + return false unless klass.respond_to?(:new, true) + + # We only want to apply our special logic to normal `new` methods. + # Methods that the user has monkeyed with should be left as-is. + klass.method(:new).owner == ::Class + end + + def with_signature + @object_reference.when_loaded do |klass| + yield Support::MethodSignature.new(klass.instance_method(:initialize)) + end + end + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/mutate_const.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/mutate_const.rb new file mode 100644 index 0000000..7cb1c92 --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/mutate_const.rb @@ -0,0 +1,335 @@ +RSpec::Support.require_rspec_support 'recursive_const_methods' + +module RSpec + module Mocks + # Provides information about constants that may (or may not) + # have been mutated by rspec-mocks. + class Constant + extend Support::RecursiveConstMethods + + # @api private + def initialize(name) + @name = name + @previously_defined = false + @stubbed = false + @hidden = false + @valid_name = true + yield self if block_given? + end + + # @return [String] The fully qualified name of the constant. + attr_reader :name + + # @return [Object, nil] The original value (e.g. before it + # was mutated by rspec-mocks) of the constant, or + # nil if the constant was not previously defined. + attr_accessor :original_value + + # @private + attr_writer :previously_defined, :stubbed, :hidden, :valid_name + + # @return [Boolean] Whether or not the constant was defined + # before the current example. + def previously_defined? + @previously_defined + end + + # @return [Boolean] Whether or not rspec-mocks has mutated + # (stubbed or hidden) this constant. + def mutated? + @stubbed || @hidden + end + + # @return [Boolean] Whether or not rspec-mocks has stubbed + # this constant. + def stubbed? + @stubbed + end + + # @return [Boolean] Whether or not rspec-mocks has hidden + # this constant. + def hidden? + @hidden + end + + # @return [Boolean] Whether or not the provided constant name + # is a valid Ruby constant name. + def valid_name? + @valid_name + end + + # The default `to_s` isn't very useful, so a custom version is provided. + def to_s + "#<#{self.class.name} #{name}>" + end + alias inspect to_s + + # @private + def self.unmutated(name) + previously_defined = recursive_const_defined?(name) + rescue NameError + new(name) do |c| + c.valid_name = false + end + else + new(name) do |const| + const.previously_defined = previously_defined + const.original_value = recursive_const_get(name) if previously_defined + end + end + + # Queries rspec-mocks to find out information about the named constant. + # + # @param [String] name the name of the constant + # @return [Constant] an object contaning information about the named + # constant. + def self.original(name) + mutator = ::RSpec::Mocks.space.constant_mutator_for(name) + mutator ? mutator.to_constant : unmutated(name) + end + end + + # Provides a means to stub constants. + class ConstantMutator + extend Support::RecursiveConstMethods + + # Stubs a constant. + # + # @param (see ExampleMethods#stub_const) + # @option (see ExampleMethods#stub_const) + # @return (see ExampleMethods#stub_const) + # + # @see ExampleMethods#stub_const + # @note It's recommended that you use `stub_const` in your + # examples. This is an alternate public API that is provided + # so you can stub constants in other contexts (e.g. helper + # classes). + def self.stub(constant_name, value, options={}) + mutator = if recursive_const_defined?(constant_name, &raise_on_invalid_const) + DefinedConstantReplacer + else + UndefinedConstantSetter + end + + mutate(mutator.new(constant_name, value, options[:transfer_nested_constants])) + value + end + + # Hides a constant. + # + # @param (see ExampleMethods#hide_const) + # + # @see ExampleMethods#hide_const + # @note It's recommended that you use `hide_const` in your + # examples. This is an alternate public API that is provided + # so you can hide constants in other contexts (e.g. helper + # classes). + def self.hide(constant_name) + mutate(ConstantHider.new(constant_name, nil, {})) + nil + end + + # Contains common functionality used by all of the constant mutators. + # + # @private + class BaseMutator + include Support::RecursiveConstMethods + + attr_reader :original_value, :full_constant_name + + def initialize(full_constant_name, mutated_value, transfer_nested_constants) + @full_constant_name = normalize_const_name(full_constant_name) + @mutated_value = mutated_value + @transfer_nested_constants = transfer_nested_constants + @context_parts = @full_constant_name.split('::') + @const_name = @context_parts.pop + @reset_performed = false + end + + def to_constant + const = Constant.new(full_constant_name) + const.original_value = original_value + + const + end + + def idempotently_reset + reset unless @reset_performed + @reset_performed = true + end + end + + # Hides a defined constant for the duration of an example. + # + # @private + class ConstantHider < BaseMutator + def mutate + return unless (@defined = recursive_const_defined?(full_constant_name)) + @context = recursive_const_get(@context_parts.join('::')) + @original_value = get_const_defined_on(@context, @const_name) + + @context.__send__(:remove_const, @const_name) + end + + def to_constant + return Constant.unmutated(full_constant_name) unless @defined + + const = super + const.hidden = true + const.previously_defined = true + + const + end + + def reset + return unless @defined + @context.const_set(@const_name, @original_value) + end + end + + # Replaces a defined constant for the duration of an example. + # + # @private + class DefinedConstantReplacer < BaseMutator + def initialize(*args) + super + @constants_to_transfer = [] + end + + def mutate + @context = recursive_const_get(@context_parts.join('::')) + @original_value = get_const_defined_on(@context, @const_name) + + @constants_to_transfer = verify_constants_to_transfer! + + @context.__send__(:remove_const, @const_name) + @context.const_set(@const_name, @mutated_value) + + transfer_nested_constants + end + + def to_constant + const = super + const.stubbed = true + const.previously_defined = true + + const + end + + def reset + @constants_to_transfer.each do |const| + @mutated_value.__send__(:remove_const, const) + end + + @context.__send__(:remove_const, @const_name) + @context.const_set(@const_name, @original_value) + end + + def transfer_nested_constants + @constants_to_transfer.each do |const| + @mutated_value.const_set(const, get_const_defined_on(original_value, const)) + end + end + + def verify_constants_to_transfer! + return [] unless should_transfer_nested_constants? + + { @original_value => "the original value", @mutated_value => "the stubbed value" }.each do |value, description| + next if value.respond_to?(:constants) + + raise ArgumentError, + "Cannot transfer nested constants for #{@full_constant_name} " \ + "since #{description} is not a class or module and only classes " \ + "and modules support nested constants." + end + + if Array === @transfer_nested_constants + @transfer_nested_constants = @transfer_nested_constants.map(&:to_s) if RUBY_VERSION == '1.8.7' + undefined_constants = @transfer_nested_constants - constants_defined_on(@original_value) + + if undefined_constants.any? + available_constants = constants_defined_on(@original_value) - @transfer_nested_constants + raise ArgumentError, + "Cannot transfer nested constant(s) #{undefined_constants.join(' and ')} " \ + "for #{@full_constant_name} since they are not defined. Did you mean " \ + "#{available_constants.join(' or ')}?" + end + + @transfer_nested_constants + else + constants_defined_on(@original_value) + end + end + + def should_transfer_nested_constants? + return true if @transfer_nested_constants + return false unless RSpec::Mocks.configuration.transfer_nested_constants? + @original_value.respond_to?(:constants) && @mutated_value.respond_to?(:constants) + end + end + + # Sets an undefined constant for the duration of an example. + # + # @private + class UndefinedConstantSetter < BaseMutator + def mutate + @parent = @context_parts.inject(Object) do |klass, name| + if const_defined_on?(klass, name) + get_const_defined_on(klass, name) + else + ConstantMutator.stub(name_for(klass, name), Module.new) + end + end + + @parent.const_set(@const_name, @mutated_value) + end + + def to_constant + const = super + const.stubbed = true + const.previously_defined = false + + const + end + + def reset + @parent.__send__(:remove_const, @const_name) + end + + private + + def name_for(parent, name) + root = if parent == Object + '' + else + parent.name + end + root + '::' + name + end + end + + # Uses the mutator to mutate (stub or hide) a constant. Ensures that + # the mutator is correctly registered so it can be backed out at the end + # of the test. + # + # @private + def self.mutate(mutator) + ::RSpec::Mocks.space.register_constant_mutator(mutator) + mutator.mutate + end + + # Used internally by the constant stubbing to raise a helpful + # error when a constant like "A::B::C" is stubbed and A::B is + # not a module (and thus, it's impossible to define "A::B::C" + # since only modules can have nested constants). + # + # @api private + def self.raise_on_invalid_const + lambda do |const_name, failed_name| + raise "Cannot stub constant #{failed_name} on #{const_name} " \ + "since #{const_name} is not a module." + end + end + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/mutex.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/mutex.rb new file mode 100644 index 0000000..add4238 --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/mutex.rb @@ -0,0 +1,73 @@ +module RSpec + module Mocks + # On 1.8.7, it's in the stdlib. + # We don't want to load the stdlib, b/c this is a test tool, and can affect + # the test environment, causing tests to pass where they should fail. + # + # So we're transcribing/modifying it from + # https://github.com/ruby/ruby/blob/v1_8_7_374/lib/thread.rb#L56 + # Some methods we don't need are deleted. Anything I don't + # understand (there's quite a bit, actually) is left in. + # + # Some formating changes are made to appease the robot overlord: + # https://travis-ci.org/rspec/rspec-core/jobs/54410874 + # @private + class Mutex + def initialize + @waiting = [] + @locked = false + @waiting.taint + taint + end + + # @private + def lock + while Thread.critical = true && @locked + @waiting.push Thread.current + Thread.stop + end + @locked = true + Thread.critical = false + self + end + + # @private + def unlock + return unless @locked + Thread.critical = true + @locked = false + wakeup_and_run_waiting_thread + self + end + + # @private + def synchronize + lock + begin + yield + ensure + unlock + end + end + + private + + def wakeup_and_run_waiting_thread + begin + t = @waiting.shift + t.wakeup if t + rescue ThreadError + retry + end + Thread.critical = false + begin + t.run if t + rescue ThreadError + :noop + end + end + + # Avoid warnings for library wide checks spec + end unless defined?(::RSpec::Mocks::Mutex) || defined?(::Mutex) + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/object_reference.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/object_reference.rb new file mode 100644 index 0000000..cce2c33 --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/object_reference.rb @@ -0,0 +1,149 @@ +module RSpec + module Mocks + # @private + class ObjectReference + # Returns an appropriate Object or Module reference based + # on the given argument. + def self.for(object_module_or_name, allow_direct_object_refs=false) + case object_module_or_name + when Module + if anonymous_module?(object_module_or_name) + DirectObjectReference.new(object_module_or_name) + else + # Use a `NamedObjectReference` if it has a name because this + # will use the original value of the constant in case it has + # been stubbed. + NamedObjectReference.new(name_of(object_module_or_name)) + end + when String + NamedObjectReference.new(object_module_or_name) + else + if allow_direct_object_refs + DirectObjectReference.new(object_module_or_name) + else + raise ArgumentError, + "Module or String expected, got #{object_module_or_name.inspect}" + end + end + end + + if Module.new.name.nil? + def self.anonymous_module?(mod) + !name_of(mod) + end + else # 1.8.7 + def self.anonymous_module?(mod) + name_of(mod) == "" + end + end + private_class_method :anonymous_module? + + def self.name_of(mod) + MODULE_NAME_METHOD.bind(mod).call + end + private_class_method :name_of + + # @private + MODULE_NAME_METHOD = Module.instance_method(:name) + end + + # An implementation of rspec-mocks' reference interface. + # Used when an object is passed to {ExampleMethods#object_double}, or + # an anonymous class or module is passed to {ExampleMethods#instance_double} + # or {ExampleMethods#class_double}. + # Represents a reference to that object. + # @see NamedObjectReference + class DirectObjectReference + # @param object [Object] the object to which this refers + def initialize(object) + @object = object + end + + # @return [String] the object's description (via `#inspect`). + def description + @object.inspect + end + + # Defined for interface parity with the other object reference + # implementations. Raises an `ArgumentError` to indicate that `as_stubbed_const` + # is invalid when passing an object argument to `object_double`. + def const_to_replace + raise ArgumentError, + "Can not perform constant replacement with an anonymous object." + end + + # The target of the verifying double (the object itself). + # + # @return [Object] + def target + @object + end + + # Always returns true for an object as the class is defined. + # + # @return [true] + def defined? + true + end + + # Yields if the reference target is loaded, providing a generic mechanism + # to optionally run a bit of code only when a reference's target is + # loaded. + # + # This specific implementation always yields because direct references + # are always loaded. + # + # @yield [Object] the target of this reference. + def when_loaded + yield @object + end + end + + # An implementation of rspec-mocks' reference interface. + # Used when a string is passed to {ExampleMethods#object_double}, + # and when a string, named class or named module is passed to + # {ExampleMethods#instance_double}, or {ExampleMethods#class_double}. + # Represents a reference to the object named (via a constant lookup) + # by the string. + # @see DirectObjectReference + class NamedObjectReference + # @param const_name [String] constant name + def initialize(const_name) + @const_name = const_name + end + + # @return [Boolean] true if the named constant is defined, false otherwise. + def defined? + !!object + end + + # @return [String] the constant name to replace with a double. + def const_to_replace + @const_name + end + alias description const_to_replace + + # @return [Object, nil] the target of the verifying double (the named object), or + # nil if it is not defined. + def target + object + end + + # Yields if the reference target is loaded, providing a generic mechanism + # to optionally run a bit of code only when a reference's target is + # loaded. + # + # @yield [Object] the target object + def when_loaded + yield object if object + end + + private + + def object + return @object if defined?(@object) + @object = Constant.original(@const_name).original_value + end + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/order_group.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/order_group.rb new file mode 100644 index 0000000..a994799 --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/order_group.rb @@ -0,0 +1,81 @@ +module RSpec + module Mocks + # @private + class OrderGroup + def initialize + @expectations = [] + @invocation_order = [] + @index = 0 + end + + # @private + def register(expectation) + @expectations << expectation + end + + def invoked(message) + @invocation_order << message + end + + # @private + def ready_for?(expectation) + remaining_expectations.find(&:ordered?) == expectation + end + + # @private + def consume + remaining_expectations.each_with_index do |expectation, index| + next unless expectation.ordered? + + @index += index + 1 + return expectation + end + nil + end + + # @private + def handle_order_constraint(expectation) + return unless expectation.ordered? && remaining_expectations.include?(expectation) + return consume if ready_for?(expectation) + expectation.raise_out_of_order_error + end + + def verify_invocation_order(expectation) + expectation.raise_out_of_order_error unless expectations_invoked_in_order? + true + end + + def clear + @index = 0 + @invocation_order.clear + @expectations.clear + end + + def empty? + @expectations.empty? + end + + private + + def remaining_expectations + @expectations[@index..-1] || [] + end + + def expectations_invoked_in_order? + invoked_expectations == expected_invocations + end + + def invoked_expectations + @expectations.select { |e| e.ordered? && @invocation_order.include?(e) } + end + + def expected_invocations + @invocation_order.map { |invocation| expectation_for(invocation) }.compact + end + + def expectation_for(message) + @expectations.find { |e| message == e } + end + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/proxy.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/proxy.rb new file mode 100644 index 0000000..97f0f68 --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/proxy.rb @@ -0,0 +1,439 @@ +module RSpec + module Mocks + # @private + class Proxy + SpecificMessage = Struct.new(:object, :message, :args) do + def ==(expectation) + expectation.orig_object == object && expectation.matches?(message, *args) + end + end + + # @private + def ensure_implemented(*_args) + # noop for basic proxies, see VerifyingProxy for behaviour. + end + + # @private + def initialize(object, order_group, options={}) + @object = object + @order_group = order_group + @error_generator = ErrorGenerator.new(object) + @messages_received = [] + @options = options + @null_object = false + @method_doubles = Hash.new { |h, k| h[k] = MethodDouble.new(@object, k, self) } + end + + # @private + attr_reader :object + + # @private + def null_object? + @null_object + end + + # @private + # Tells the object to ignore any messages that aren't explicitly set as + # stubs or message expectations. + def as_null_object + @null_object = true + @object + end + + # @private + def original_method_handle_for(_message) + nil + end + + DEFAULT_MESSAGE_EXPECTATION_OPTS = {}.freeze + + # @private + def add_message_expectation(method_name, opts=DEFAULT_MESSAGE_EXPECTATION_OPTS, &block) + location = opts.fetch(:expected_from) { CallerFilter.first_non_rspec_line } + meth_double = method_double_for(method_name) + + if null_object? && !block + meth_double.add_default_stub(@error_generator, @order_group, location, opts) do + @object + end + end + + meth_double.add_expectation @error_generator, @order_group, location, opts, &block + end + + # @private + def add_simple_expectation(method_name, response, location) + method_double_for(method_name).add_simple_expectation method_name, response, @error_generator, location + end + + # @private + def build_expectation(method_name) + meth_double = method_double_for(method_name) + + meth_double.build_expectation( + @error_generator, + @order_group + ) + end + + # @private + def replay_received_message_on(expectation, &block) + expected_method_name = expectation.message + meth_double = method_double_for(expected_method_name) + + if meth_double.expectations.any? + @error_generator.raise_expectation_on_mocked_method(expected_method_name) + end + + unless null_object? || meth_double.stubs.any? + @error_generator.raise_expectation_on_unstubbed_method(expected_method_name) + end + + @messages_received.each do |(actual_method_name, args, _)| + next unless expectation.matches?(actual_method_name, *args) + + expectation.safe_invoke(nil) + block.call(*args) if block + end + end + + # @private + def check_for_unexpected_arguments(expectation) + return if @messages_received.empty? + + return if @messages_received.any? { |method_name, args, _| expectation.matches?(method_name, *args) } + + name_but_not_args, others = @messages_received.partition do |(method_name, args, _)| + expectation.matches_name_but_not_args(method_name, *args) + end + + return if name_but_not_args.empty? && !others.empty? + + expectation.raise_unexpected_message_args_error(name_but_not_args.map { |args| args[1] }) + end + + # @private + def add_stub(method_name, opts={}, &implementation) + location = opts.fetch(:expected_from) { CallerFilter.first_non_rspec_line } + method_double_for(method_name).add_stub @error_generator, @order_group, location, opts, &implementation + end + + # @private + def add_simple_stub(method_name, response) + method_double_for(method_name).add_simple_stub method_name, response + end + + # @private + def remove_stub(method_name) + method_double_for(method_name).remove_stub + end + + # @private + def remove_stub_if_present(method_name) + method_double_for(method_name).remove_stub_if_present + end + + # @private + def verify + @method_doubles.each_value { |d| d.verify } + end + + # @private + def reset + @messages_received.clear + end + + # @private + def received_message?(method_name, *args, &block) + @messages_received.any? { |array| array == [method_name, args, block] } + end + + # @private + def messages_arg_list + @messages_received.map { |_, args, _| args } + end + + # @private + def has_negative_expectation?(message) + method_double_for(message).expectations.find { |expectation| expectation.negative_expectation_for?(message) } + end + + # @private + def record_message_received(message, *args, &block) + @order_group.invoked SpecificMessage.new(object, message, args) + @messages_received << [message, args, block] + end + + # @private + def message_received(message, *args, &block) + record_message_received message, *args, &block + + expectation = find_matching_expectation(message, *args) + stub = find_matching_method_stub(message, *args) + + if (stub && expectation && expectation.called_max_times?) || (stub && !expectation) + expectation.increase_actual_received_count! if expectation && expectation.actual_received_count_matters? + if (expectation = find_almost_matching_expectation(message, *args)) + expectation.advise(*args) unless expectation.expected_messages_received? + end + stub.invoke(nil, *args, &block) + elsif expectation + expectation.unadvise(messages_arg_list) + expectation.invoke(stub, *args, &block) + elsif (expectation = find_almost_matching_expectation(message, *args)) + expectation.advise(*args) if null_object? unless expectation.expected_messages_received? + + if null_object? || !has_negative_expectation?(message) + expectation.raise_unexpected_message_args_error([args]) + end + elsif (stub = find_almost_matching_stub(message, *args)) + stub.advise(*args) + raise_missing_default_stub_error(stub, [args]) + elsif Class === @object + @object.superclass.__send__(message, *args, &block) + else + @object.__send__(:method_missing, message, *args, &block) + end + end + + # @private + def raise_unexpected_message_error(method_name, args) + @error_generator.raise_unexpected_message_error method_name, args + end + + # @private + def raise_missing_default_stub_error(expectation, args_for_multiple_calls) + @error_generator.raise_missing_default_stub_error(expectation, args_for_multiple_calls) + end + + # @private + def visibility_for(_method_name) + # This is the default (for test doubles). Subclasses override this. + :public + end + + if Support::RubyFeatures.module_prepends_supported? + def self.prepended_modules_of(klass) + ancestors = klass.ancestors + + # `|| 0` is necessary for Ruby 2.0, where the singleton class + # is only in the ancestor list when there are prepended modules. + singleton_index = ancestors.index(klass) || 0 + + ancestors[0, singleton_index] + end + + def prepended_modules_of_singleton_class + @prepended_modules_of_singleton_class ||= RSpec::Mocks::Proxy.prepended_modules_of(@object.singleton_class) + end + end + + private + + def method_double_for(message) + @method_doubles[message.to_sym] + end + + def find_matching_expectation(method_name, *args) + find_best_matching_expectation_for(method_name) do |expectation| + expectation.matches?(method_name, *args) + end + end + + def find_almost_matching_expectation(method_name, *args) + find_best_matching_expectation_for(method_name) do |expectation| + expectation.matches_name_but_not_args(method_name, *args) + end + end + + def find_best_matching_expectation_for(method_name) + first_match = nil + + method_double_for(method_name).expectations.each do |expectation| + next unless yield expectation + return expectation unless expectation.called_max_times? + first_match ||= expectation + end + + first_match + end + + def find_matching_method_stub(method_name, *args) + method_double_for(method_name).stubs.find { |stub| stub.matches?(method_name, *args) } + end + + def find_almost_matching_stub(method_name, *args) + method_double_for(method_name).stubs.find { |stub| stub.matches_name_but_not_args(method_name, *args) } + end + end + + # @private + class TestDoubleProxy < Proxy + def reset + @method_doubles.clear + object.__disallow_further_usage! + super + end + end + + # @private + class PartialDoubleProxy < Proxy + def original_method_handle_for(message) + if any_instance_class_recorder_observing_method?(@object.class, message) + message = ::RSpec::Mocks.space. + any_instance_recorder_for(@object.class). + build_alias_method_name(message) + end + + ::RSpec::Support.method_handle_for(@object, message) + rescue NameError + nil + end + + # @private + def add_simple_expectation(method_name, response, location) + method_double_for(method_name).configure_method + super + end + + # @private + def add_simple_stub(method_name, response) + method_double_for(method_name).configure_method + super + end + + # @private + def visibility_for(method_name) + # We fall back to :public because by default we allow undefined methods + # to be stubbed, and when we do so, we make them public. + MethodReference.method_visibility_for(@object, method_name) || :public + end + + def reset + @method_doubles.each_value { |d| d.reset } + super + end + + def message_received(message, *args, &block) + RSpec::Mocks.space.any_instance_recorders_from_ancestry_of(object).each do |subscriber| + subscriber.notify_received_message(object, message, args, block) + end + super + end + + private + + def any_instance_class_recorder_observing_method?(klass, method_name) + only_return_existing = true + recorder = ::RSpec::Mocks.space.any_instance_recorder_for(klass, only_return_existing) + return true if recorder && recorder.already_observing?(method_name) + + superklass = klass.superclass + return false if superklass.nil? + any_instance_class_recorder_observing_method?(superklass, method_name) + end + end + + # @private + # When we mock or stub a method on a class, we have to treat it a bit different, + # because normally singleton method definitions only affect the object on which + # they are defined, but on classes they affect subclasses, too. As a result, + # we need some special handling to get the original method. + module PartialClassDoubleProxyMethods + def initialize(source_space, *args) + @source_space = source_space + super(*args) + end + + # Consider this situation: + # + # class A; end + # class B < A; end + # + # allow(A).to receive(:new) + # expect(B).to receive(:new).and_call_original + # + # When getting the original definition for `B.new`, we cannot rely purely on + # using `B.method(:new)` before our redefinition is defined on `B`, because + # `B.method(:new)` will return a method that will execute the stubbed version + # of the method on `A` since singleton methods on classes are in the lookup + # hierarchy. + # + # To do it properly, we need to find the original definition of `new` from `A` + # from _before_ `A` was stubbed, and we need to rebind it to `B` so that it will + # run with the proper `self`. + # + # That's what this method (together with `original_unbound_method_handle_from_ancestor_for`) + # does. + def original_method_handle_for(message) + unbound_method = superclass_proxy && + superclass_proxy.original_unbound_method_handle_from_ancestor_for(message.to_sym) + + return super unless unbound_method + unbound_method.bind(object) + end + + protected + + def original_unbound_method_handle_from_ancestor_for(message) + method_double = @method_doubles.fetch(message) do + # The fact that there is no method double for this message indicates + # that it has not been redefined by rspec-mocks. We need to continue + # looking up the ancestor chain. + return superclass_proxy && + superclass_proxy.original_unbound_method_handle_from_ancestor_for(message) + end + + method_double.original_method.unbind + end + + def superclass_proxy + return @superclass_proxy if defined?(@superclass_proxy) + + if (superclass = object.superclass) + @superclass_proxy = @source_space.superclass_proxy_for(superclass) + else + @superclass_proxy = nil + end + end + end + + # @private + class PartialClassDoubleProxy < PartialDoubleProxy + include PartialClassDoubleProxyMethods + end + + # @private + class ProxyForNil < PartialDoubleProxy + def initialize(order_group) + @warn_about_expectations = true + super(nil, order_group) + end + + attr_accessor :warn_about_expectations + alias warn_about_expectations? warn_about_expectations + + def add_message_expectation(method_name, opts={}, &block) + warn(method_name) if warn_about_expectations? + super + end + + def add_negative_message_expectation(location, method_name, &implementation) + warn(method_name) if warn_about_expectations? + super + end + + def add_stub(method_name, opts={}, &implementation) + warn(method_name) if warn_about_expectations? + super + end + + private + + def warn(method_name) + source = CallerFilter.first_non_rspec_line + Kernel.warn("An expectation of :#{method_name} was set on nil. Called from #{source}. Use allow_message_expectations_on_nil to disable warnings.") + end + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/reentrant_mutex.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/reentrant_mutex.rb new file mode 100644 index 0000000..2b03239 --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/reentrant_mutex.rb @@ -0,0 +1,53 @@ +module RSpec + module Mocks + # Allows a thread to lock out other threads from a critical section of code, + # while allowing the thread with the lock to reenter that section. + # + # Based on Monitor as of 2.2 - + # https://github.com/ruby/ruby/blob/eb7ddaa3a47bf48045d26c72eb0f263a53524ebc/lib/monitor.rb#L9 + # + # Depends on Mutex, but Mutex is only available as part of core since 1.9.1: + # exists - http://ruby-doc.org/core-1.9.1/Mutex.html + # dne - http://ruby-doc.org/core-1.9.0/Mutex.html + # + # @private + class ReentrantMutex + def initialize + @owner = nil + @count = 0 + @mutex = Mutex.new + end + + def synchronize + enter + yield + ensure + exit + end + + private + + def enter + @mutex.lock if @owner != Thread.current + @owner = Thread.current + @count += 1 + end + + def exit + @count -= 1 + return unless @count == 0 + @owner = nil + @mutex.unlock + end + end + + if defined? ::Mutex + # On 1.9 and up, this is in core, so we just use the real one + Mutex = ::Mutex + else # For 1.8.7 + # :nocov: + RSpec::Support.require_rspec_mocks "mutex" + # :nocov: + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/space.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/space.rb new file mode 100644 index 0000000..f25cedf --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/space.rb @@ -0,0 +1,238 @@ +RSpec::Support.require_rspec_mocks 'reentrant_mutex' + +module RSpec + module Mocks + # @private + # Provides a default space implementation for outside + # the scope of an example. Called "root" because it serves + # as the root of the space stack. + class RootSpace + def proxy_for(*_args) + raise_lifecycle_message + end + + def any_instance_recorder_for(*_args) + raise_lifecycle_message + end + + def any_instance_proxy_for(*_args) + raise_lifecycle_message + end + + def register_constant_mutator(_mutator) + raise_lifecycle_message + end + + def any_instance_recorders_from_ancestry_of(_object) + raise_lifecycle_message + end + + def reset_all + end + + def verify_all + end + + def registered?(_object) + false + end + + def superclass_proxy_for(*_args) + raise_lifecycle_message + end + + def new_scope + Space.new + end + + private + + def raise_lifecycle_message + raise OutsideOfExampleError, + "The use of doubles or partial doubles from rspec-mocks outside of the per-test lifecycle is not supported." + end + end + + # @private + class Space + attr_reader :proxies, :any_instance_recorders, :proxy_mutex, :any_instance_mutex + + def initialize + @proxies = {} + @any_instance_recorders = {} + @constant_mutators = [] + @expectation_ordering = OrderGroup.new + @proxy_mutex = new_mutex + @any_instance_mutex = new_mutex + end + + def new_scope + NestedSpace.new(self) + end + + def verify_all + proxies.values.each { |proxy| proxy.verify } + any_instance_recorders.each_value { |recorder| recorder.verify } + end + + def reset_all + proxies.each_value { |proxy| proxy.reset } + @constant_mutators.reverse.each { |mut| mut.idempotently_reset } + any_instance_recorders.each_value { |recorder| recorder.stop_all_observation! } + any_instance_recorders.clear + end + + def register_constant_mutator(mutator) + @constant_mutators << mutator + end + + def constant_mutator_for(name) + @constant_mutators.find { |m| m.full_constant_name == name } + end + + def any_instance_recorder_for(klass, only_return_existing=false) + any_instance_mutex.synchronize do + id = klass.__id__ + any_instance_recorders.fetch(id) do + return nil if only_return_existing + any_instance_recorder_not_found_for(id, klass) + end + end + end + + def any_instance_proxy_for(klass) + AnyInstance::Proxy.new(any_instance_recorder_for(klass), proxies_of(klass)) + end + + def proxies_of(klass) + proxies.values.select { |proxy| klass === proxy.object } + end + + def proxy_for(object) + proxy_mutex.synchronize do + id = id_for(object) + proxies.fetch(id) { proxy_not_found_for(id, object) } + end + end + + def superclass_proxy_for(klass) + proxy_mutex.synchronize do + id = id_for(klass) + proxies.fetch(id) { superclass_proxy_not_found_for(id, klass) } + end + end + + alias ensure_registered proxy_for + + def registered?(object) + proxies.key?(id_for object) + end + + def any_instance_recorders_from_ancestry_of(object) + # Optimization: `any_instance` is a feature we generally + # recommend not using, so we can often early exit here + # without doing an O(N) linear search over the number of + # ancestors in the object's class hierarchy. + return [] if any_instance_recorders.empty? + + # We access the ancestors through the singleton class, to avoid calling + # `class` in case `class` has been stubbed. + (class << object; ancestors; end).map do |klass| + any_instance_recorders[klass.__id__] + end.compact + end + + private + + def new_mutex + Mocks::ReentrantMutex.new + end + + def proxy_not_found_for(id, object) + proxies[id] = case object + when NilClass then ProxyForNil.new(@expectation_ordering) + when TestDouble then object.__build_mock_proxy_unless_expired(@expectation_ordering) + when Class + class_proxy_with_callback_verification_strategy(object, CallbackInvocationStrategy.new) + else + if RSpec::Mocks.configuration.verify_partial_doubles? + VerifyingPartialDoubleProxy.new(object, @expectation_ordering) + else + PartialDoubleProxy.new(object, @expectation_ordering) + end + end + end + + def superclass_proxy_not_found_for(id, object) + raise "superclass_proxy_not_found_for called with something that is not a class" unless Class === object + proxies[id] = class_proxy_with_callback_verification_strategy(object, NoCallbackInvocationStrategy.new) + end + + def class_proxy_with_callback_verification_strategy(object, strategy) + if RSpec::Mocks.configuration.verify_partial_doubles? + VerifyingPartialClassDoubleProxy.new( + self, + object, + @expectation_ordering, + strategy + ) + else + PartialClassDoubleProxy.new(self, object, @expectation_ordering) + end + end + + def any_instance_recorder_not_found_for(id, klass) + any_instance_recorders[id] = AnyInstance::Recorder.new(klass) + end + + if defined?(::BasicObject) && !::BasicObject.method_defined?(:__id__) # for 1.9.2 + require 'securerandom' + + def id_for(object) + id = object.__id__ + + return id if object.equal?(::ObjectSpace._id2ref(id)) + # this suggests that object.__id__ is proxying through to some wrapped object + + object.instance_exec do + @__id_for_rspec_mocks_space ||= ::SecureRandom.uuid + end + end + else + def id_for(object) + object.__id__ + end + end + end + + # @private + class NestedSpace < Space + def initialize(parent) + @parent = parent + super() + end + + def proxies_of(klass) + super + @parent.proxies_of(klass) + end + + def constant_mutator_for(name) + super || @parent.constant_mutator_for(name) + end + + def registered?(object) + super || @parent.registered?(object) + end + + private + + def proxy_not_found_for(id, object) + @parent.proxies[id] || super + end + + def any_instance_recorder_not_found_for(id, klass) + @parent.any_instance_recorders[id] || super + end + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/standalone.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/standalone.rb new file mode 100644 index 0000000..74317b0 --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/standalone.rb @@ -0,0 +1,3 @@ +require 'rspec/mocks' +extend RSpec::Mocks::ExampleMethods +RSpec::Mocks.setup diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/syntax.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/syntax.rb new file mode 100644 index 0000000..1ba4dcd --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/syntax.rb @@ -0,0 +1,325 @@ +module RSpec + module Mocks + # @api private + # Provides methods for enabling and disabling the available syntaxes + # provided by rspec-mocks. + module Syntax + # @private + def self.warn_about_should! + @warn_about_should = true + end + + # @private + def self.warn_unless_should_configured(method_name , replacement="the new `:expect` syntax or explicitly enable `:should`") + if @warn_about_should + RSpec.deprecate( + "Using `#{method_name}` from rspec-mocks' old `:should` syntax without explicitly enabling the syntax", + :replacement => replacement + ) + + @warn_about_should = false + end + end + + # @api private + # Enables the should syntax (`dbl.stub`, `dbl.should_receive`, etc). + def self.enable_should(syntax_host=default_should_syntax_host) + @warn_about_should = false if syntax_host == default_should_syntax_host + return if should_enabled?(syntax_host) + + syntax_host.class_exec do + def should_receive(message, opts={}, &block) + ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__) + ::RSpec::Mocks.expect_message(self, message, opts, &block) + end + + def should_not_receive(message, &block) + ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__) + ::RSpec::Mocks.expect_message(self, message, {}, &block).never + end + + def stub(message_or_hash, opts={}, &block) + ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__) + if ::Hash === message_or_hash + message_or_hash.each { |message, value| stub(message).and_return value } + else + ::RSpec::Mocks.allow_message(self, message_or_hash, opts, &block) + end + end + + def unstub(message) + ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__, "`allow(...).to_receive(...).and_call_original` or explicitly enable `:should`") + ::RSpec::Mocks.space.proxy_for(self).remove_stub(message) + end + + def stub_chain(*chain, &blk) + ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__) + ::RSpec::Mocks::StubChain.stub_chain_on(self, *chain, &blk) + end + + def as_null_object + ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__) + @_null_object = true + ::RSpec::Mocks.space.proxy_for(self).as_null_object + end + + def null_object? + ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__) + defined?(@_null_object) + end + + def received_message?(message, *args, &block) + ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__) + ::RSpec::Mocks.space.proxy_for(self).received_message?(message, *args, &block) + end + + unless Class.respond_to? :any_instance + Class.class_exec do + def any_instance + ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__) + ::RSpec::Mocks.space.any_instance_proxy_for(self) + end + end + end + end + end + + # @api private + # Disables the should syntax (`dbl.stub`, `dbl.should_receive`, etc). + def self.disable_should(syntax_host=default_should_syntax_host) + return unless should_enabled?(syntax_host) + + syntax_host.class_exec do + undef should_receive + undef should_not_receive + undef stub + undef unstub + undef stub_chain + undef as_null_object + undef null_object? + undef received_message? + end + + Class.class_exec do + undef any_instance + end + end + + # @api private + # Enables the expect syntax (`expect(dbl).to receive`, `allow(dbl).to receive`, etc). + def self.enable_expect(syntax_host=::RSpec::Mocks::ExampleMethods) + return if expect_enabled?(syntax_host) + + syntax_host.class_exec do + def receive(method_name, &block) + Matchers::Receive.new(method_name, block) + end + + def receive_messages(message_return_value_hash) + matcher = Matchers::ReceiveMessages.new(message_return_value_hash) + matcher.warn_about_block if block_given? + matcher + end + + def receive_message_chain(*messages, &block) + Matchers::ReceiveMessageChain.new(messages, &block) + end + + def allow(target) + AllowanceTarget.new(target) + end + + def expect_any_instance_of(klass) + AnyInstanceExpectationTarget.new(klass) + end + + def allow_any_instance_of(klass) + AnyInstanceAllowanceTarget.new(klass) + end + end + + RSpec::Mocks::ExampleMethods::ExpectHost.class_exec do + def expect(target) + ExpectationTarget.new(target) + end + end + end + + # @api private + # Disables the expect syntax (`expect(dbl).to receive`, `allow(dbl).to receive`, etc). + def self.disable_expect(syntax_host=::RSpec::Mocks::ExampleMethods) + return unless expect_enabled?(syntax_host) + + syntax_host.class_exec do + undef receive + undef receive_messages + undef receive_message_chain + undef allow + undef expect_any_instance_of + undef allow_any_instance_of + end + + RSpec::Mocks::ExampleMethods::ExpectHost.class_exec do + undef expect + end + end + + # @api private + # Indicates whether or not the should syntax is enabled. + def self.should_enabled?(syntax_host=default_should_syntax_host) + syntax_host.method_defined?(:should_receive) + end + + # @api private + # Indicates whether or not the expect syntax is enabled. + def self.expect_enabled?(syntax_host=::RSpec::Mocks::ExampleMethods) + syntax_host.method_defined?(:allow) + end + + # @api private + # Determines where the methods like `should_receive`, and `stub` are added. + def self.default_should_syntax_host + # JRuby 1.7.4 introduces a regression whereby `defined?(::BasicObject) => nil` + # yet `BasicObject` still exists and patching onto ::Object breaks things + # e.g. SimpleDelegator expectations won't work + # + # See: https://github.com/jruby/jruby/issues/814 + if defined?(JRUBY_VERSION) && JRUBY_VERSION == '1.7.4' && RUBY_VERSION.to_f > 1.8 + return ::BasicObject + end + + # On 1.8.7, Object.ancestors.last == Kernel but + # things blow up if we include `RSpec::Mocks::Methods` + # into Kernel...not sure why. + return Object unless defined?(::BasicObject) + + # MacRuby has BasicObject but it's not the root class. + return Object unless Object.ancestors.last == ::BasicObject + + ::BasicObject + end + end + end +end + +if defined?(BasicObject) + # The legacy `:should` syntax adds the following methods directly to + # `BasicObject` so that they are available off of any object. Note, however, + # that this syntax does not always play nice with delegate/proxy objects. + # We recommend you use the non-monkeypatching `:expect` syntax instead. + # @see Class + class BasicObject + # @method should_receive + # Sets an expectation that this object should receive a message before + # the end of the example. + # + # @example + # logger = double('logger') + # thing_that_logs = ThingThatLogs.new(logger) + # logger.should_receive(:log) + # thing_that_logs.do_something_that_logs_a_message + # + # @note This is only available when you have enabled the `should` syntax. + # @see RSpec::Mocks::ExampleMethods#expect + + # @method should_not_receive + # Sets and expectation that this object should _not_ receive a message + # during this example. + # @see RSpec::Mocks::ExampleMethods#expect + + # @method stub + # Tells the object to respond to the message with the specified value. + # + # @example + # counter.stub(:count).and_return(37) + # counter.stub(:count => 37) + # counter.stub(:count) { 37 } + # + # @note This is only available when you have enabled the `should` syntax. + # @see RSpec::Mocks::ExampleMethods#allow + + # @method unstub + # Removes a stub. On a double, the object will no longer respond to + # `message`. On a real object, the original method (if it exists) is + # restored. + # + # This is rarely used, but can be useful when a stub is set up during a + # shared `before` hook for the common case, but you want to replace it + # for a special case. + # + # @note This is only available when you have enabled the `should` syntax. + + # @method stub_chain + # @overload stub_chain(method1, method2) + # @overload stub_chain("method1.method2") + # @overload stub_chain(method1, method_to_value_hash) + # + # Stubs a chain of methods. + # + # ## Warning: + # + # Chains can be arbitrarily long, which makes it quite painless to + # violate the Law of Demeter in violent ways, so you should consider any + # use of `stub_chain` a code smell. Even though not all code smells + # indicate real problems (think fluent interfaces), `stub_chain` still + # results in brittle examples. For example, if you write + # `foo.stub_chain(:bar, :baz => 37)` in a spec and then the + # implementation calls `foo.baz.bar`, the stub will not work. + # + # @example + # double.stub_chain("foo.bar") { :baz } + # double.stub_chain(:foo, :bar => :baz) + # double.stub_chain(:foo, :bar) { :baz } + # + # # Given any of ^^ these three forms ^^: + # double.foo.bar # => :baz + # + # # Common use in Rails/ActiveRecord: + # Article.stub_chain("recent.published") { [Article.new] } + # + # @note This is only available when you have enabled the `should` syntax. + # @see RSpec::Mocks::ExampleMethods#receive_message_chain + + # @method as_null_object + # Tells the object to respond to all messages. If specific stub values + # are declared, they'll work as expected. If not, the receiver is + # returned. + # + # @note This is only available when you have enabled the `should` syntax. + + # @method null_object? + # Returns true if this object has received `as_null_object` + # + # @note This is only available when you have enabled the `should` syntax. + end +end + +# The legacy `:should` syntax adds the `any_instance` to `Class`. +# We generally recommend you use the newer `:expect` syntax instead, +# which allows you to stub any instance of a class using +# `allow_any_instance_of(klass)` or mock any instance using +# `expect_any_instance_of(klass)`. +# @see BasicObject +class Class + # @method any_instance + # Used to set stubs and message expectations on any instance of a given + # class. Returns a [Recorder](Recorder), which records messages like + # `stub` and `should_receive` for later playback on instances of the + # class. + # + # @example + # Car.any_instance.should_receive(:go) + # race = Race.new + # race.cars << Car.new + # race.go # assuming this delegates to all of its cars + # # this example would pass + # + # Account.any_instance.stub(:balance) { Money.new(:USD, 25) } + # Account.new.balance # => Money.new(:USD, 25)) + # + # @return [Recorder] + # + # @note This is only available when you have enabled the `should` syntax. + # @see RSpec::Mocks::ExampleMethods#expect_any_instance_of + # @see RSpec::Mocks::ExampleMethods#allow_any_instance_of +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/targets.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/targets.rb new file mode 100644 index 0000000..43436cc --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/targets.rb @@ -0,0 +1,97 @@ +module RSpec + module Mocks + # @private + class TargetBase + def initialize(target) + @target = target + end + + def self.delegate_to(matcher_method) + define_method(:to) do |matcher, &block| + unless matcher_allowed?(matcher) + raise_unsupported_matcher(:to, matcher) + end + define_matcher(matcher, matcher_method, &block) + end + end + + def self.delegate_not_to(matcher_method, options={}) + method_name = options.fetch(:from) + define_method(method_name) do |matcher, &block| + case matcher + when Matchers::Receive + define_matcher(matcher, matcher_method, &block) + when Matchers::ReceiveMessages, Matchers::ReceiveMessageChain + raise_negation_unsupported(method_name, matcher) + else + raise_unsupported_matcher(method_name, matcher) + end + end + end + + def self.disallow_negation(method_name) + define_method(method_name) do |matcher, *_args| + raise_negation_unsupported(method_name, matcher) + end + end + + private + + def matcher_allowed?(matcher) + matcher.class.name.start_with?("RSpec::Mocks::Matchers".freeze) + end + + def define_matcher(matcher, name, &block) + matcher.__send__(name, @target, &block) + end + + def raise_unsupported_matcher(method_name, matcher) + raise UnsupportedMatcherError, + "only the `receive` or `receive_messages` matchers are supported " \ + "with `#{expression}(...).#{method_name}`, but you have provided: #{matcher}" + end + + def raise_negation_unsupported(method_name, matcher) + raise NegationUnsupportedError, + "`#{expression}(...).#{method_name} #{matcher.name}` is not supported since it " \ + "doesn't really make sense. What would it even mean?" + end + + def expression + self.class::EXPRESSION + end + end + + # @private + class AllowanceTarget < TargetBase + EXPRESSION = :allow + delegate_to :setup_allowance + disallow_negation :not_to + disallow_negation :to_not + end + + # @private + class ExpectationTarget < TargetBase + EXPRESSION = :expect + delegate_to :setup_expectation + delegate_not_to :setup_negative_expectation, :from => :not_to + delegate_not_to :setup_negative_expectation, :from => :to_not + end + + # @private + class AnyInstanceAllowanceTarget < TargetBase + EXPRESSION = :allow_any_instance_of + delegate_to :setup_any_instance_allowance + disallow_negation :not_to + disallow_negation :to_not + end + + # @private + class AnyInstanceExpectationTarget < TargetBase + EXPRESSION = :expect_any_instance_of + delegate_to :setup_any_instance_expectation + delegate_not_to :setup_any_instance_negative_expectation, :from => :not_to + delegate_not_to :setup_any_instance_negative_expectation, :from => :to_not + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/test_double.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/test_double.rb new file mode 100644 index 0000000..3321ce1 --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/test_double.rb @@ -0,0 +1,170 @@ +module RSpec + module Mocks + # Implements the methods needed for a pure test double. RSpec::Mocks::Double + # includes this module, and it is provided for cases where you want a + # pure test double without subclassing RSpec::Mocks::Double. + module TestDouble + # Creates a new test double with a `name` (that will be used in error + # messages only) + def initialize(name=nil, stubs={}) + @__expired = false + if Hash === name && stubs.empty? + stubs = name + @name = nil + else + @name = name + end + assign_stubs(stubs) + end + + # Tells the object to respond to all messages. If specific stub values + # are declared, they'll work as expected. If not, the receiver is + # returned. + def as_null_object + __mock_proxy.as_null_object + end + + # Returns true if this object has received `as_null_object` + def null_object? + __mock_proxy.null_object? + end + + # This allows for comparing the mock to other objects that proxy such as + # ActiveRecords belongs_to proxy objects. By making the other object run + # the comparison, we're sure the call gets delegated to the proxy + # target. + def ==(other) + other == __mock_proxy + end + + # @private + def inspect + TestDoubleFormatter.format(self) + end + + # @private + def to_s + inspect.gsub('<', '[').gsub('>', ']') + end + + # @private + def respond_to?(message, incl_private=false) + __mock_proxy.null_object? ? true : super + end + + # @private + def __build_mock_proxy_unless_expired(order_group) + __raise_expired_error || __build_mock_proxy(order_group) + end + + # @private + def __disallow_further_usage! + @__expired = true + end + + # Override for default freeze implementation to prevent freezing of test + # doubles. + def freeze + RSpec.warn_with("WARNING: you attempted to freeze a test double. This is explicitly a no-op as freezing doubles can lead to undesired behaviour when resetting tests.") + end + + private + + def method_missing(message, *args, &block) + proxy = __mock_proxy + proxy.record_message_received(message, *args, &block) + + if proxy.null_object? + case message + when :to_int then return 0 + when :to_a, :to_ary then return nil + when :to_str then return to_s + else return self + end + end + + # Defined private and protected methods will still trigger `method_missing` + # when called publicly. We want ruby's method visibility error to get raised, + # so we simply delegate to `super` in that case. + # ...well, we would delegate to `super`, but there's a JRuby + # bug, so we raise our own visibility error instead: + # https://github.com/jruby/jruby/issues/1398 + visibility = proxy.visibility_for(message) + if visibility == :private || visibility == :protected + ErrorGenerator.new(self).raise_non_public_error( + message, visibility + ) + end + + # Required wrapping doubles in an Array on Ruby 1.9.2 + raise NoMethodError if [:to_a, :to_ary].include? message + proxy.raise_unexpected_message_error(message, args) + end + + def assign_stubs(stubs) + stubs.each_pair do |message, response| + __mock_proxy.add_simple_stub(message, response) + end + end + + def __mock_proxy + ::RSpec::Mocks.space.proxy_for(self) + end + + def __build_mock_proxy(order_group) + TestDoubleProxy.new(self, order_group) + end + + def __raise_expired_error + return false unless @__expired + ErrorGenerator.new(self).raise_expired_test_double_error + end + + def initialize_copy(other) + as_null_object if other.null_object? + super + end + end + + # A generic test double object. `double`, `instance_double` and friends + # return an instance of this. + class Double + include TestDouble + end + + # @private + module TestDoubleFormatter + def self.format(dbl, unwrap=false) + format = "#{type_desc(dbl)}#{verified_module_desc(dbl)} #{name_desc(dbl)}" + return format if unwrap + "#<#{format}>" + end + + class << self + private + + def type_desc(dbl) + case dbl + when InstanceVerifyingDouble then "InstanceDouble" + when ClassVerifyingDouble then "ClassDouble" + when ObjectVerifyingDouble then "ObjectDouble" + else "Double" + end + end + + # @private + IVAR_GET = Object.instance_method(:instance_variable_get) + + def verified_module_desc(dbl) + return nil unless VerifyingDouble === dbl + "(#{IVAR_GET.bind(dbl).call(:@doubled_module).description})" + end + + def name_desc(dbl) + return "(anonymous)" unless (name = IVAR_GET.bind(dbl).call(:@name)) + name.inspect + end + end + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/verifying_double.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/verifying_double.rb new file mode 100644 index 0000000..39723b9 --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/verifying_double.rb @@ -0,0 +1,129 @@ +RSpec::Support.require_rspec_mocks 'verifying_proxy' + +module RSpec + module Mocks + # @private + module VerifyingDouble + def respond_to?(message, include_private=false) + return super unless null_object? + + method_ref = __mock_proxy.method_reference[message] + + case method_ref.visibility + when :public then true + when :private then include_private + when :protected then include_private || RUBY_VERSION.to_f < 2.0 + else !method_ref.unimplemented? + end + end + + def method_missing(message, *args, &block) + # Null object conditional is an optimization. If not a null object, + # validity of method expectations will have been checked at definition + # time. + if null_object? + if @__sending_message == message + __mock_proxy.ensure_implemented(message) + else + __mock_proxy.ensure_publicly_implemented(message, self) + end + + __mock_proxy.validate_arguments!(message, args) + end + + super + end + + # @private + module SilentIO + def self.method_missing(*); end + def self.respond_to?(*) + true + end + end + + # Redefining `__send__` causes ruby to issue a warning. + old, $stderr = $stderr, SilentIO + def __send__(name, *args, &block) + @__sending_message = name + super + ensure + @__sending_message = nil + end + $stderr = old + + def send(name, *args, &block) + __send__(name, *args, &block) + end + + def initialize(doubled_module, *args) + @doubled_module = doubled_module + + possible_name = args.first + name = if String === possible_name || Symbol === possible_name + args.shift + end + + super(name, *args) + @__sending_message = nil + end + end + + # A mock providing a custom proxy that can verify the validity of any + # method stubs or expectations against the public instance methods of the + # given class. + # + # @private + class InstanceVerifyingDouble + include TestDouble + include VerifyingDouble + + def __build_mock_proxy(order_group) + VerifyingProxy.new(self, order_group, + @doubled_module, + InstanceMethodReference + ) + end + end + + # An awkward module necessary because we cannot otherwise have + # ClassVerifyingDouble inherit from Module and still share these methods. + # + # @private + module ObjectVerifyingDoubleMethods + include TestDouble + include VerifyingDouble + + def as_stubbed_const(options={}) + ConstantMutator.stub(@doubled_module.const_to_replace, self, options) + self + end + + private + + def __build_mock_proxy(order_group) + VerifyingProxy.new(self, order_group, + @doubled_module, + ObjectMethodReference + ) + end + end + + # Similar to an InstanceVerifyingDouble, except that it verifies against + # public methods of the given object. + # + # @private + class ObjectVerifyingDouble + include ObjectVerifyingDoubleMethods + end + + # Effectively the same as an ObjectVerifyingDouble (since a class is a type + # of object), except with Module in the inheritance chain so that + # transferring nested constants to work. + # + # @private + class ClassVerifyingDouble < Module + include ObjectVerifyingDoubleMethods + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/verifying_message_expecation.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/verifying_message_expecation.rb new file mode 100644 index 0000000..c81ef32 --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/verifying_message_expecation.rb @@ -0,0 +1,54 @@ +RSpec::Support.require_rspec_support 'method_signature_verifier' + +module RSpec + module Mocks + # A message expectation that knows about the real implementation of the + # message being expected, so that it can verify that any expectations + # have the valid arguments. + # @api private + class VerifyingMessageExpectation < MessageExpectation + # A level of indirection is used here rather than just passing in the + # method itself, since method look up is expensive and we only want to + # do it if actually needed. + # + # Conceptually the method reference makes more sense as a constructor + # argument since it should be immutable, but it is significantly more + # straight forward to build the object in pieces so for now it stays as + # an accessor. + attr_accessor :method_reference + + def initialize(*args) + super + end + + # @private + def with(*args, &block) + super(*args, &block).tap do + validate_expected_arguments! do |signature| + example_call_site_args = [:an_arg] * signature.min_non_kw_args + example_call_site_args << :kw_args_hash if signature.required_kw_args.any? + @argument_list_matcher.resolve_expected_args_based_on(example_call_site_args) + end + end + end + + private + + def validate_expected_arguments! + return if method_reference.nil? + + method_reference.with_signature do |signature| + args = yield signature + verifier = Support::LooseSignatureVerifier.new(signature, args) + + unless verifier.valid? + # Fail fast is required, otherwise the message expecation will fail + # as well ("expected method not called") and clobber this one. + @failed_fast = true + @error_generator.raise_invalid_arguments_error(verifier) + end + end + end + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/verifying_proxy.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/verifying_proxy.rb new file mode 100644 index 0000000..198b099 --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/verifying_proxy.rb @@ -0,0 +1,213 @@ +RSpec::Support.require_rspec_mocks 'verifying_message_expecation' +RSpec::Support.require_rspec_mocks 'method_reference' + +module RSpec + module Mocks + # @private + class CallbackInvocationStrategy + def call(doubled_module) + RSpec::Mocks.configuration.verifying_double_callbacks.each do |block| + block.call doubled_module + end + end + end + + # @private + class NoCallbackInvocationStrategy + def call(_doubled_module) + end + end + + # @private + module VerifyingProxyMethods + def add_stub(method_name, opts={}, &implementation) + ensure_implemented(method_name) + super + end + + def add_simple_stub(method_name, *args) + ensure_implemented(method_name) + super + end + + def add_message_expectation(method_name, opts={}, &block) + ensure_implemented(method_name) + super + end + + def ensure_implemented(method_name) + return unless method_reference[method_name].unimplemented? + + @error_generator.raise_unimplemented_error( + @doubled_module, + method_name, + @object + ) + end + + def ensure_publicly_implemented(method_name, _object) + ensure_implemented(method_name) + visibility = method_reference[method_name].visibility + + return if visibility == :public + @error_generator.raise_non_public_error(method_name, visibility) + end + end + + # A verifying proxy mostly acts like a normal proxy, except that it + # contains extra logic to try and determine the validity of any expectation + # set on it. This includes whether or not methods have been defined and the + # validatiy of arguments on method calls. + # + # In all other ways this behaves like a normal proxy. It only adds the + # verification behaviour to specific methods then delegates to the parent + # implementation. + # + # These checks are only activated if the doubled class has already been + # loaded, otherwise they are disabled. This allows for testing in + # isolation. + # + # @private + class VerifyingProxy < TestDoubleProxy + include VerifyingProxyMethods + + def initialize(object, order_group, doubled_module, method_reference_class) + super(object, order_group) + @object = object + @doubled_module = doubled_module + @method_reference_class = method_reference_class + + # A custom method double is required to pass through a way to lookup + # methods to determine their parameters. This is only relevant if the doubled + # class is loaded. + @method_doubles = Hash.new do |h, k| + h[k] = VerifyingMethodDouble.new(@object, k, self, method_reference[k]) + end + end + + def method_reference + @method_reference ||= Hash.new do |h, k| + h[k] = @method_reference_class.for(@doubled_module, k) + end + end + + def visibility_for(method_name) + method_reference[method_name].visibility + end + + def validate_arguments!(method_name, args) + @method_doubles[method_name].validate_arguments!(args) + end + end + + # @private + DEFAULT_CALLBACK_INVOCATION_STRATEGY = CallbackInvocationStrategy.new + + # @private + class VerifyingPartialDoubleProxy < PartialDoubleProxy + include VerifyingProxyMethods + + def initialize(object, expectation_ordering, optional_callback_invocation_strategy=DEFAULT_CALLBACK_INVOCATION_STRATEGY) + super(object, expectation_ordering) + @doubled_module = DirectObjectReference.new(object) + + # A custom method double is required to pass through a way to lookup + # methods to determine their parameters. + @method_doubles = Hash.new do |h, k| + h[k] = VerifyingExistingMethodDouble.for(object, k, self) + end + + optional_callback_invocation_strategy.call(@doubled_module) + end + + def method_reference + @method_doubles + end + end + + # @private + class VerifyingPartialClassDoubleProxy < VerifyingPartialDoubleProxy + include PartialClassDoubleProxyMethods + end + + # @private + class VerifyingMethodDouble < MethodDouble + def initialize(object, method_name, proxy, method_reference) + super(object, method_name, proxy) + @method_reference = method_reference + end + + def message_expectation_class + VerifyingMessageExpectation + end + + def add_expectation(*args, &block) + # explict params necessary for 1.8.7 see #626 + super(*args, &block).tap { |x| x.method_reference = @method_reference } + end + + def add_stub(*args, &block) + # explict params necessary for 1.8.7 see #626 + super(*args, &block).tap { |x| x.method_reference = @method_reference } + end + + def proxy_method_invoked(obj, *args, &block) + validate_arguments!(args) + super + end + + def validate_arguments!(actual_args) + @method_reference.with_signature do |signature| + verifier = Support::StrictSignatureVerifier.new(signature, actual_args) + raise ArgumentError, verifier.error_message unless verifier.valid? + end + end + end + + # A VerifyingMethodDouble fetches the method to verify against from the + # original object, using a MethodReference. This works for pure doubles, + # but when the original object is itself the one being modified we need to + # collapse the reference and the method double into a single object so that + # we can access the original pristine method definition. + # + # @private + class VerifyingExistingMethodDouble < VerifyingMethodDouble + def initialize(object, method_name, proxy) + super(object, method_name, proxy, self) + + @valid_method = object.respond_to?(method_name, true) + + # Trigger an eager find of the original method since if we find it any + # later we end up getting a stubbed method with incorrect arity. + save_original_implementation_callable! + end + + def with_signature + yield Support::MethodSignature.new(original_implementation_callable) + end + + def unimplemented? + !@valid_method + end + + def self.for(object, method_name, proxy) + if ClassNewMethodReference.applies_to?(method_name) { object } + VerifyingExistingClassNewMethodDouble + else + self + end.new(object, method_name, proxy) + end + end + + # Used in place of a `VerifyingExistingMethodDouble` for the specific case + # of mocking or stubbing a `new` method on a class. In this case, we substitute + # the method signature from `#initialize` since new's signature is just `*args`. + # + # @private + class VerifyingExistingClassNewMethodDouble < VerifyingExistingMethodDouble + def with_signature + yield Support::MethodSignature.new(object.instance_method(:initialize)) + end + end + end +end diff --git a/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/version.rb b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/version.rb new file mode 100644 index 0000000..7829f9c --- /dev/null +++ b/.bundle/gems/rspec-mocks-3.3.2/lib/rspec/mocks/version.rb @@ -0,0 +1,9 @@ +module RSpec + module Mocks + # Version information for RSpec mocks. + module Version + # Version of RSpec mocks currently in use in SemVer format. + STRING = '3.3.2' + end + end +end diff --git a/.bundle/gems/rspec-support-3.3.0/Changelog.md b/.bundle/gems/rspec-support-3.3.0/Changelog.md new file mode 100644 index 0000000..101c0d8 --- /dev/null +++ b/.bundle/gems/rspec-support-3.3.0/Changelog.md @@ -0,0 +1,125 @@ +### 3.3.0 / 2015-06-12 +[Full Changelog](http://github.com/rspec/rspec-support/compare/v3.2.2...v3.3.0) + +Enhancements: + +* Improve formatting of arrays and hashes in failure messages so they + use our custom formatting of matchers, time objects, etc. + (Myron Marston, Nicholas Chmielewski, #205) +* Use improved formatting for diffs as well. (Nicholas Chmielewski, #205) + +Bug Fixes: + +* Fix `FuzzyMatcher` so that it checks `expected == actual` rather than + `actual == expected`, which avoids errors in situations where the + `actual` object's `==` is improperly implemented to assume that only + objects of the same type will be given. This allows rspec-mocks' + `anything` to match against objects with buggy `==` definitions. + (Myron Marston, #193) + +### 3.2.2 / 2015-02-23 +[Full Changelog](http://github.com/rspec/rspec-support/compare/v3.2.1...v3.2.2) + +Bug Fixes: + +* Fix an encoding issue with `EncodedString#split` when encountering an + invalid byte string. (Benjamin Fleischer, #1760) + +### 3.2.1 / 2015-02-04 +[Full Changelog](http://github.com/rspec/rspec-support/compare/v3.2.0...v3.2.1) + +Bug Fixes: + +* Fix `RSpec::CallerFilter` to work on Rubinius 2.2. + (Myron Marston, #169) + +### 3.2.0 / 2015-02-03 +[Full Changelog](http://github.com/rspec/rspec-support/compare/v3.1.2...v3.2.0) + +Enhancements: + +* Add extra Ruby type detection. (Jon Rowe, #133) +* Make differ instance re-usable. (Alexey Fedorov, #160) + +Bug Fixes: + +* Do not consider `[]` and `{}` to match when performing fuzzy matching. + (Myron Marston, #157) + +### 3.1.2 / 2014-10-08 +[Full Changelog](http://github.com/rspec/rspec-support/compare/v3.1.1...v3.1.2) + +Bug Fixes: + +* Fix method signature to not blow up with a `NoMethodError` on 1.8.7 when + verifying against an RSpec matcher. (Myron Marston, #116) + +### 3.1.1 / 2014-09-26 +[Full Changelog](http://github.com/rspec/rspec-support/compare/v3.1.0...v3.1.1) + +Bug Fixes: + +* Fix `RSpec::Support::DirectoryMaker` (used by `rspec --init` and + `rails generate rspec:install`) so that it detects absolute paths + on Windows properly. (Scott Archer, #107, #108, #109) (Jon Rowe, #110) + +### 3.1.0 / 2014-09-04 +[Full Changelog](http://github.com/rspec/rspec-support/compare/v3.0.4...v3.1.0) + +Bug Fixes: + +* Fix `FuzzyMatcher` so that it does not wrongly match a struct against + an array. (Myron Marston, #97) +* Prevent infinitely recursing `#flatten` methods from causing the differ + to hang. (Jon Rowe, #101) + +### 3.0.4 / 2014-08-14 +[Full Changelog](http://github.com/rspec/rspec-support/compare/v3.0.3...v3.0.4) + +Bug Fixes: + +* Fix `FuzzyMatcher` so that it does not silence `ArgumentError` raised + from broken implementations of `==`. (Myron Marston, #94) + +### 3.0.3 / 2014-07-21 +[Full Changelog](http://github.com/rspec/rspec-support/compare/v3.0.2...v3.0.3) + +Bug Fixes: + +* Fix regression in `Support#method_handle_for` where proxy objects + with method delegated would wrongly not return a method handle. + (Jon Rowe, #90) +* Properly detect Module#prepend support in Ruby 2.1+ (Ben Langfeld, #91) +* Fix `rspec/support/warnings.rb` so it can be loaded and used in + isolation. (Myron Marston, #93) + +### 3.0.2 / 2014-06-20 +[Full Changelog](http://github.com/rspec/rspec-support/compare/v3.0.1...v3.0.2) + +* Revert `BlockSignature` change from 3.0.1 because of a ruby bug that + caused it to change the block's behavior (https://bugs.ruby-lang.org/issues/9967). + (Myron Marston, rspec-mocks#721) + +### 3.0.1 / 2014-06-19 +[Full Changelog](http://github.com/rspec/rspec-support/compare/v3.0.0...v3.0.1) + +* Fix `BlockSignature` so that it correctly differentiates between + required and optional block args. (Myron Marston, rspec-mocks#714) + +### 3.0.0 / 2014-06-01 +[Full Changelog](http://github.com/rspec/rspec-support/compare/v3.0.0.rc1...v3.0.0) + +### 3.0.0.rc1 / 2014-05-18 +[Full Changelog](http://github.com/rspec/rspec-support/compare/v3.0.0.beta2...v3.0.0.rc1) + +### 3.0.0.beta2 / 2014-02-17 +[Full Changelog](http://github.com/rspec/rspec-support/compare/v3.0.0.beta1...v3.0.0.beta2) + +Bug Fixes: + +* Issue message when :replacement is passed to `RSpec.warn_with`. (Jon Rowe) + +### 3.0.0.beta1 / 2013-11-07 +[Full Changelog](https://github.com/rspec/rspec-support/compare/0dc12d1bdbbacc757a9989f8c09cd08ef3a4837e...v3.0.0.beta1) + +Initial release. diff --git a/.bundle/gems/rspec-support-3.3.0/LICENSE.txt b/.bundle/gems/rspec-support-3.3.0/LICENSE.txt new file mode 100644 index 0000000..ecb71df --- /dev/null +++ b/.bundle/gems/rspec-support-3.3.0/LICENSE.txt @@ -0,0 +1,22 @@ +Copyright (c) 2013 David Chelimsky, Myron Marston, Jon Rowe, Sam Phippen, Xavier Shay, Bradley Schaefer + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/.bundle/gems/rspec-support-3.3.0/README.md b/.bundle/gems/rspec-support-3.3.0/README.md new file mode 100644 index 0000000..7c433a2 --- /dev/null +++ b/.bundle/gems/rspec-support-3.3.0/README.md @@ -0,0 +1,26 @@ +# RSpec::Support + +`RSpec::Support` provides common functionality to `RSpec::Core`, +`RSpec::Expectations` and `RSpec::Mocks`. It is considered +suitable for internal use only at this time. + +## Installation / Usage + +Install one or more of the `RSpec` gems. + +Want to run against the `master` branch? You'll need to include the dependent +RSpec repos as well. Add the following to your `Gemfile`: + +```ruby +%w[rspec-core rspec-expectations rspec-mocks rspec-support].each do |lib| + gem lib, :git => "git://github.com/rspec/#{lib}.git", :branch => 'master' +end +``` + +## Contributing + +1. Fork it +2. Create your feature branch (`git checkout -b my-new-feature`) +3. Commit your changes (`git commit -am 'Add some feature'`) +4. Push to the branch (`git push origin my-new-feature`) +5. Create new Pull Request diff --git a/.bundle/gems/rspec-support-3.3.0/lib/rspec/support.rb b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support.rb new file mode 100644 index 0000000..48f477b --- /dev/null +++ b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support.rb @@ -0,0 +1,111 @@ +module RSpec + module Support + # @api private + # + # Defines a helper method that is optimized to require files from the + # named lib. The passed block MUST be `{ |f| require_relative f }` + # because for `require_relative` to work properly from within the named + # lib the line of code must be IN that lib. + # + # `require_relative` is preferred when available because it is always O(1), + # regardless of the number of dirs in $LOAD_PATH. `require`, on the other + # hand, does a linear O(N) search over the dirs in the $LOAD_PATH until + # it can resolve the file relative to one of the dirs. + def self.define_optimized_require_for_rspec(lib, &require_relative) + name = "require_rspec_#{lib}" + + if Kernel.respond_to?(:require_relative) + (class << self; self; end).__send__(:define_method, name) do |f| + require_relative.call("#{lib}/#{f}") + end + else + (class << self; self; end).__send__(:define_method, name) do |f| + require "rspec/#{lib}/#{f}" + end + end + end + + define_optimized_require_for_rspec(:support) { |f| require_relative(f) } + require_rspec_support "version" + require_rspec_support "ruby_features" + + # @api private + KERNEL_METHOD_METHOD = ::Kernel.instance_method(:method) + + # @api private + # + # Used internally to get a method handle for a particular object + # and method name. + # + # Includes handling for a few special cases: + # + # - Objects that redefine #method (e.g. an HTTPRequest struct) + # - BasicObject subclasses that mixin a Kernel dup (e.g. SimpleDelegator) + # - Objects that undefine method and delegate everything to another + # object (e.g. Mongoid association objects) + if RubyFeatures.supports_rebinding_module_methods? + def self.method_handle_for(object, method_name) + KERNEL_METHOD_METHOD.bind(object).call(method_name) + rescue NameError => original + begin + handle = object.method(method_name) + raise original unless handle.is_a? Method + handle + rescue Exception + raise original + end + end + else + def self.method_handle_for(object, method_name) + if ::Kernel === object + KERNEL_METHOD_METHOD.bind(object).call(method_name) + else + object.method(method_name) + end + rescue NameError => original + begin + handle = object.method(method_name) + raise original unless handle.is_a? Method + handle + rescue Exception + raise original + end + end + end + + # A single thread local variable so we don't excessively pollute that namespace. + def self.thread_local_data + Thread.current[:__rspec] ||= {} + end + + def self.failure_notifier=(callable) + thread_local_data[:failure_notifier] = callable + end + + # @private + DEFAULT_FAILURE_NOTIFIER = lambda { |failure, _opts| raise failure } + + def self.failure_notifier + thread_local_data[:failure_notifier] || DEFAULT_FAILURE_NOTIFIER + end + + def self.notify_failure(failure, options={}) + failure_notifier.call(failure, options) + end + + def self.with_failure_notifier(callable) + orig_notifier = failure_notifier + self.failure_notifier = callable + yield + ensure + self.failure_notifier = orig_notifier + end + + # The Differ is only needed when a a spec fails with a diffable failure. + # In the more common case of all specs passing or the only failures being + # non-diffable, we can avoid the extra cost of loading the differ, diff-lcs, + # pp, etc by avoiding an unnecessary require. Instead, autoload will take + # care of loading the differ on first use. + autoload :Differ, "rspec/support/differ" + end +end diff --git a/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/caller_filter.rb b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/caller_filter.rb new file mode 100644 index 0000000..eb6f4dc --- /dev/null +++ b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/caller_filter.rb @@ -0,0 +1,83 @@ +RSpec::Support.require_rspec_support "ruby_features" + +module RSpec + # Consistent implementation for "cleaning" the caller method to strip out + # non-rspec lines. This enables errors to be reported at the call site in + # the code using the library, which is far more useful than the particular + # internal method that raised an error. + class CallerFilter + RSPEC_LIBS = %w[ + core + mocks + expectations + support + matchers + rails + ] + + ADDITIONAL_TOP_LEVEL_FILES = %w[ autorun ] + + LIB_REGEX = %r{/lib/rspec/(#{(RSPEC_LIBS + ADDITIONAL_TOP_LEVEL_FILES).join('|')})(\.rb|/)} + + # rubygems/core_ext/kernel_require.rb isn't actually part of rspec (obviously) but we want + # it ignored when we are looking for the first meaningful line of the backtrace outside + # of RSpec. It can show up in the backtrace as the immediate first caller + # when `CallerFilter.first_non_rspec_line` is called from the top level of a required + # file, but it depends on if rubygems is loaded or not. We don't want to have to deal + # with this complexity in our `RSpec.deprecate` calls, so we ignore it here. + IGNORE_REGEX = Regexp.union(LIB_REGEX, "rubygems/core_ext/kernel_require.rb") + + if RSpec::Support::RubyFeatures.caller_locations_supported? + # This supports args because it's more efficient when the caller specifies + # these. It allows us to skip frames the caller knows are part of RSpec, + # and to decrease the increment size if the caller is confident the line will + # be found in a small number of stack frames from `skip_frames`. + # + # Note that there is a risk to passing a `skip_frames` value that is too high: + # If it skippped the first non-rspec line, then this method would return the + # 2nd or 3rd (or whatever) non-rspec line. Thus, you generally shouldn't pass + # values for these parameters, particularly since most places that use this are + # not hot spots (generally it gets used for deprecation warnings). However, + # if you do have a hot spot that calls this, passing `skip_frames` can make + # a significant difference. Just make sure that that particular use is tested + # so that if the provided `skip_frames` changes to no longer be accurate in + # such a way that would return the wrong stack frame, a test will fail to tell you. + # + # See benchmarks/skip_frames_for_caller_filter.rb for measurements. + def self.first_non_rspec_line(skip_frames=3, increment=5) + # Why a default `skip_frames` of 3? + # By the time `caller_locations` is called below, the first 3 frames are: + # lib/rspec/support/caller_filter.rb:63:in `block in first_non_rspec_line' + # lib/rspec/support/caller_filter.rb:62:in `loop' + # lib/rspec/support/caller_filter.rb:62:in `first_non_rspec_line' + + # `caller` is an expensive method that scales linearly with the size of + # the stack. The performance hit for fetching it in chunks is small, + # and since the target line is probably near the top of the stack, the + # overall improvement of a chunked search like this is significant. + # + # See benchmarks/caller.rb for measurements. + + # The default increment of 5 for this method are mostly arbitrary, but + # is chosen to give good performance on the common case of creating a double. + + loop do + stack = caller_locations(skip_frames, increment) + raise "No non-lib lines in stack" unless stack + + line = stack.find { |l| l.path !~ IGNORE_REGEX } + return line.to_s if line + + skip_frames += increment + increment *= 2 # The choice of two here is arbitrary. + end + end + else + # Earlier rubies do not support the two argument form of `caller`. This + # fallback is logically the same, but slower. + def self.first_non_rspec_line(*) + caller.find { |line| line !~ IGNORE_REGEX } + end + end + end +end diff --git a/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/differ.rb b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/differ.rb new file mode 100644 index 0000000..fa7e5f1 --- /dev/null +++ b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/differ.rb @@ -0,0 +1,215 @@ +RSpec::Support.require_rspec_support 'encoded_string' +RSpec::Support.require_rspec_support 'hunk_generator' +RSpec::Support.require_rspec_support "object_formatter" + +require 'pp' + +module RSpec + module Support + # rubocop:disable ClassLength + class Differ + def diff(actual, expected) + diff = "" + + if actual && expected + if all_strings?(actual, expected) + if any_multiline_strings?(actual, expected) + diff = diff_as_string(coerce_to_string(actual), coerce_to_string(expected)) + end + elsif no_procs?(actual, expected) && no_numbers?(actual, expected) + diff = diff_as_object(actual, expected) + end + end + + diff.to_s + end + + # rubocop:disable MethodLength + def diff_as_string(actual, expected) + encoding = EncodedString.pick_encoding(actual, expected) + + actual = EncodedString.new(actual, encoding) + expected = EncodedString.new(expected, encoding) + + output = EncodedString.new("\n", encoding) + hunks = build_hunks(actual, expected) + + hunks.each_cons(2) do |prev_hunk, current_hunk| + begin + if current_hunk.overlaps?(prev_hunk) + add_old_hunk_to_hunk(current_hunk, prev_hunk) + else + add_to_output(output, prev_hunk.diff(format_type).to_s) + end + ensure + add_to_output(output, "\n") + end + end + + finalize_output(output, hunks.last.diff(format_type).to_s) if hunks.last + + color_diff output + rescue Encoding::CompatibilityError + handle_encoding_errors(actual, expected) + end + # rubocop:enable MethodLength + + def diff_as_object(actual, expected) + actual_as_string = object_to_string(actual) + expected_as_string = object_to_string(expected) + diff_as_string(actual_as_string, expected_as_string) + end + + def color? + @color + end + + def initialize(opts={}) + @color = opts.fetch(:color, false) + @object_preparer = opts.fetch(:object_preparer, lambda { |string| string }) + end + + private + + def no_procs?(*args) + safely_flatten(args).none? { |a| Proc === a } + end + + def all_strings?(*args) + safely_flatten(args).all? { |a| String === a } + end + + def any_multiline_strings?(*args) + all_strings?(*args) && safely_flatten(args).any? { |a| multiline?(a) } + end + + def no_numbers?(*args) + safely_flatten(args).none? { |a| Numeric === a } + end + + def coerce_to_string(string_or_array) + return string_or_array unless Array === string_or_array + diffably_stringify(string_or_array).join("\n") + end + + def diffably_stringify(array) + array.map do |entry| + if Array === entry + entry.inspect + else + entry.to_s.gsub("\n", "\\n") + end + end + end + + if String.method_defined?(:encoding) + def multiline?(string) + string.include?("\n".encode(string.encoding)) + end + else + def multiline?(string) + string.include?("\n") + end + end + + def build_hunks(actual, expected) + HunkGenerator.new(actual, expected).hunks + end + + def finalize_output(output, final_line) + add_to_output(output, final_line) + add_to_output(output, "\n") + end + + def add_to_output(output, string) + output << string + end + + def add_old_hunk_to_hunk(hunk, oldhunk) + hunk.merge(oldhunk) + end + + def safely_flatten(array) + array = array.flatten(1) until (array == array.flatten(1)) + array + end + + def format_type + :unified + end + + def color(text, color_code) + "\e[#{color_code}m#{text}\e[0m" + end + + def red(text) + color(text, 31) + end + + def green(text) + color(text, 32) + end + + def blue(text) + color(text, 34) + end + + def normal(text) + color(text, 0) + end + + def color_diff(diff) + return diff unless color? + + diff.lines.map do |line| + case line[0].chr + when "+" + green line + when "-" + red line + when "@" + line[1].chr == "@" ? blue(line) : normal(line) + else + normal(line) + end + end.join + end + + def object_to_string(object) + object = @object_preparer.call(object) + case object + when Hash + hash_to_string(object) + when Array + PP.pp(ObjectFormatter.prepare_for_inspection(object), "") + when String + object =~ /\n/ ? object : object.inspect + else + PP.pp(object, "") + end + end + + def hash_to_string(hash) + formatted_hash = ObjectFormatter.prepare_for_inspection(hash) + formatted_hash.keys.sort_by { |k| k.to_s }.map do |key| + pp_key = PP.singleline_pp(key, "") + pp_value = PP.singleline_pp(formatted_hash[key], "") + + "#{pp_key} => #{pp_value}," + end.join("\n") + end + + def handle_encoding_errors(actual, expected) + if actual.source_encoding != expected.source_encoding + "Could not produce a diff because the encoding of the actual string " \ + "(#{actual.source_encoding}) differs from the encoding of the expected " \ + "string (#{expected.source_encoding})" + else + "Could not produce a diff because of the encoding of the string " \ + "(#{expected.source_encoding})" + end + end + end + # rubocop:enable ClassLength + end +end diff --git a/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/directory_maker.rb b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/directory_maker.rb new file mode 100644 index 0000000..39a280e --- /dev/null +++ b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/directory_maker.rb @@ -0,0 +1,63 @@ +RSpec::Support.require_rspec_support 'ruby_features' + +module RSpec + module Support + # @api private + # + # Replacement for fileutils#mkdir_p because we don't want to require parts + # of stdlib in RSpec. + class DirectoryMaker + # @api private + # + # Implements nested directory construction + def self.mkdir_p(path) + stack = generate_stack(path) + path.split(File::SEPARATOR).each do |part| + stack = generate_path(stack, part) + begin + Dir.mkdir(stack) unless directory_exists?(stack) + rescue Errno::EEXIST => e + raise e unless directory_exists?(stack) + rescue Errno::ENOTDIR => e + raise Errno::EEXIST, e.message + end + end + end + + if OS.windows_file_path? + def self.generate_stack(path) + if path.start_with?(File::SEPARATOR) + File::SEPARATOR + elsif path[1] == ':' + '' + else + '.' + end + end + def self.generate_path(stack, part) + if stack == '' + part + elsif stack == File::SEPARATOR + File.join('', part) + else + File.join(stack, part) + end + end + else + def self.generate_stack(path) + path.start_with?(File::SEPARATOR) ? File::SEPARATOR : "." + end + def self.generate_path(stack, part) + File.join(stack, part) + end + end + + def self.directory_exists?(dirname) + File.exist?(dirname) && File.directory?(dirname) + end + private_class_method :directory_exists? + private_class_method :generate_stack + private_class_method :generate_path + end + end +end diff --git a/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/encoded_string.rb b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/encoded_string.rb new file mode 100644 index 0000000..eae1a92 --- /dev/null +++ b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/encoded_string.rb @@ -0,0 +1,155 @@ +module RSpec + module Support + # @private + class EncodedString + # Reduce allocations by storing constants. + UTF_8 = "UTF-8" + US_ASCII = "US-ASCII" + # + # In MRI 2.1 'invalid: :replace' changed to also replace an invalid byte sequence + # see https://github.com/ruby/ruby/blob/v2_1_0/NEWS#L176 + # https://www.ruby-forum.com/topic/6861247 + # https://twitter.com/nalsh/status/553413844685438976 + # + # For example, given: + # "\x80".force_encoding("Emacs-Mule").encode(:invalid => :replace).bytes.to_a + # + # On MRI 2.1 or above: 63 # '?' + # else : 128 # "\x80" + # + # Ruby's default replacement string is: + # U+FFFD ("\xEF\xBF\xBD"), for Unicode encoding forms, else + # ? ("\x3F") + REPLACE = "?" + ENCODE_UNCONVERTABLE_BYTES = { + :invalid => :replace, + :undef => :replace, + :replace => REPLACE + } + ENCODE_NO_CONVERTER = { + :invalid => :replace, + :replace => REPLACE + } + + def initialize(string, encoding=nil) + @encoding = encoding + @source_encoding = detect_source_encoding(string) + @string = matching_encoding(string) + end + attr_reader :source_encoding + + delegated_methods = String.instance_methods.map(&:to_s) & %w[eql? lines == encoding empty?] + delegated_methods.each do |name| + define_method(name) { |*args, &block| @string.__send__(name, *args, &block) } + end + + def <<(string) + @string << matching_encoding(string) + end + + def split(regex_or_string) + @string.split(matching_encoding(regex_or_string)) + end + + def to_s + @string + end + alias :to_str :to_s + + if String.method_defined?(:encoding) + + private + + # Encoding Exceptions: + # + # Raised by Encoding and String methods: + # Encoding::UndefinedConversionError: + # when a transcoding operation fails + # if the String contains characters invalid for the target encoding + # e.g. "\x80".encode('UTF-8','ASCII-8BIT') + # vs "\x80".encode('UTF-8','ASCII-8BIT', undef: :replace, replace: '') + # # => '' + # Encoding::CompatibilityError + # when Encoding.compatibile?(str1, str2) is nil + # e.g. utf_16le_emoji_string.split("\n") + # e.g. valid_unicode_string.encode(utf8_encoding) << ascii_string + # Encoding::InvalidByteSequenceError: + # when the string being transcoded contains a byte invalid for + # either the source or target encoding + # e.g. "\x80".encode('UTF-8','US-ASCII') + # vs "\x80".encode('UTF-8','US-ASCII', invalid: :replace, replace: '') + # # => '' + # ArgumentError + # when operating on a string with invalid bytes + # e.g."\x80".split("\n") + # TypeError + # when a symbol is passed as an encoding + # Encoding.find(:"UTF-8") + # when calling force_encoding on an object + # that doesn't respond to #to_str + # + # Raised by transcoding methods: + # Encoding::ConverterNotFoundError: + # when a named encoding does not correspond with a known converter + # e.g. 'abc'.force_encoding('UTF-8').encode('foo') + # or a converter path cannot be found + # e.g. "\x80".force_encoding('ASCII-8BIT').encode('Emacs-Mule') + # + # Raised by byte <-> char conversions + # RangeError: out of char range + # e.g. the UTF-16LE emoji: 128169.chr + def matching_encoding(string) + string = remove_invalid_bytes(string) + string.encode(@encoding) + rescue Encoding::UndefinedConversionError, Encoding::InvalidByteSequenceError + string.encode(@encoding, ENCODE_UNCONVERTABLE_BYTES) + rescue Encoding::ConverterNotFoundError + string.dup.force_encoding(@encoding).encode(ENCODE_NO_CONVERTER) + end + + # Prevents raising ArgumentError + if String.method_defined?(:scrub) + # https://github.com/ruby/ruby/blob/eeb05e8c11/doc/NEWS-2.1.0#L120-L123 + # https://github.com/ruby/ruby/blob/v2_1_0/string.c#L8242 + # https://github.com/hsbt/string-scrub + # https://github.com/rubinius/rubinius/blob/v2.5.2/kernel/common/string.rb#L1913-L1972 + def remove_invalid_bytes(string) + string.scrub(REPLACE) + end + else + # http://stackoverflow.com/a/8711118/879854 + # Loop over chars in a string replacing chars + # with invalid encoding, which is a pretty good proxy + # for the invalid byte sequence that causes an ArgumentError + def remove_invalid_bytes(string) + string.chars.map do |char| + char.valid_encoding? ? char : REPLACE + end.join + end + end + + def detect_source_encoding(string) + string.encoding + end + + def self.pick_encoding(source_a, source_b) + Encoding.compatible?(source_a, source_b) || Encoding.default_external + end + else + + def self.pick_encoding(_source_a, _source_b) + end + + private + + def matching_encoding(string) + string + end + + def detect_source_encoding(_string) + US_ASCII + end + end + end + end +end diff --git a/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/fuzzy_matcher.rb b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/fuzzy_matcher.rb new file mode 100644 index 0000000..4151949 --- /dev/null +++ b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/fuzzy_matcher.rb @@ -0,0 +1,48 @@ +module RSpec + module Support + # Provides a means to fuzzy-match between two arbitrary objects. + # Understands array/hash nesting. Uses `===` or `==` to + # perform the matching. + module FuzzyMatcher + # @api private + def self.values_match?(expected, actual) + if Hash === actual + return hashes_match?(expected, actual) if Hash === expected + elsif Array === expected && Enumerable === actual && !(Struct === actual) + return arrays_match?(expected, actual.to_a) + end + + return true if expected == actual + + begin + expected === actual + rescue ArgumentError + # Some objects, like 0-arg lambdas on 1.9+, raise + # ArgumentError for `expected === actual`. + false + end + end + + # @private + def self.arrays_match?(expected_list, actual_list) + return false if expected_list.size != actual_list.size + + expected_list.zip(actual_list).all? do |expected, actual| + values_match?(expected, actual) + end + end + + # @private + def self.hashes_match?(expected_hash, actual_hash) + return false if expected_hash.size != actual_hash.size + + expected_hash.all? do |expected_key, expected_value| + actual_value = actual_hash.fetch(expected_key) { return false } + values_match?(expected_value, actual_value) + end + end + + private_class_method :arrays_match?, :hashes_match? + end + end +end diff --git a/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/hunk_generator.rb b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/hunk_generator.rb new file mode 100644 index 0000000..382579e --- /dev/null +++ b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/hunk_generator.rb @@ -0,0 +1,47 @@ +require 'diff/lcs' +require 'diff/lcs/hunk' + +module RSpec + module Support + # @private + class HunkGenerator + def initialize(actual, expected) + @actual = actual + @expected = expected + end + + def hunks + @file_length_difference = 0 + @hunks ||= diffs.map do |piece| + build_hunk(piece) + end + end + + private + + def diffs + Diff::LCS.diff(expected_lines, actual_lines) + end + + def expected_lines + @expected.split("\n").map! { |e| e.chomp } + end + + def actual_lines + @actual.split("\n").map! { |e| e.chomp } + end + + def build_hunk(piece) + Diff::LCS::Hunk.new( + expected_lines, actual_lines, piece, context_lines, @file_length_difference + ).tap do |h| + @file_length_difference = h.file_length_difference + end + end + + def context_lines + 3 + end + end + end +end diff --git a/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/matcher_definition.rb b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/matcher_definition.rb new file mode 100644 index 0000000..d653cc1 --- /dev/null +++ b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/matcher_definition.rb @@ -0,0 +1,42 @@ +module RSpec + module Support + # @private + def self.matcher_definitions + @matcher_definitions ||= [] + end + + # Used internally to break cyclic dependency between mocks, expectations, + # and support. We don't currently have a consistent implementation of our + # matchers, though we are considering changing that: + # https://github.com/rspec/rspec-mocks/issues/513 + # + # @private + def self.register_matcher_definition(&block) + matcher_definitions << block + end + + # Remove a previously registered matcher. Useful for cleaning up after + # yourself in specs. + # + # @private + def self.deregister_matcher_definition(&block) + matcher_definitions.delete(block) + end + + # @private + def self.is_a_matcher?(object) + matcher_definitions.any? { |md| md.call(object) } + end + + # @api private + # + # gives a string representation of an object for use in RSpec descriptions + def self.rspec_description_for_object(object) + if RSpec::Support.is_a_matcher?(object) && object.respond_to?(:description) + object.description + else + object + end + end + end +end diff --git a/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/method_signature_verifier.rb b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/method_signature_verifier.rb new file mode 100644 index 0000000..0ab85ca --- /dev/null +++ b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/method_signature_verifier.rb @@ -0,0 +1,273 @@ +require 'rspec/support' +RSpec::Support.require_rspec_support "ruby_features" +RSpec::Support.require_rspec_support "matcher_definition" + +module RSpec + module Support + # Extracts info about the number of arguments and allowed/required + # keyword args of a given method. + # + # @private + class MethodSignature + attr_reader :min_non_kw_args, :max_non_kw_args, :optional_kw_args, :required_kw_args + + def initialize(method) + @method = method + @optional_kw_args = [] + @required_kw_args = [] + classify_parameters + end + + def non_kw_args_arity_description + case max_non_kw_args + when min_non_kw_args then min_non_kw_args.to_s + when INFINITY then "#{min_non_kw_args} or more" + else "#{min_non_kw_args} to #{max_non_kw_args}" + end + end + + def valid_non_kw_args?(positional_arg_count) + min_non_kw_args <= positional_arg_count && + positional_arg_count <= max_non_kw_args + end + + if RubyFeatures.optional_and_splat_args_supported? + def description + @description ||= begin + parts = [] + + unless non_kw_args_arity_description == "0" + parts << "arity of #{non_kw_args_arity_description}" + end + + if @optional_kw_args.any? + parts << "optional keyword args (#{@optional_kw_args.map(&:inspect).join(", ")})" + end + + if @required_kw_args.any? + parts << "required keyword args (#{@required_kw_args.map(&:inspect).join(", ")})" + end + + parts << "any additional keyword args" if @allows_any_kw_args + + parts.join(" and ") + end + end + + def missing_kw_args_from(given_kw_args) + @required_kw_args - given_kw_args + end + + def invalid_kw_args_from(given_kw_args) + return [] if @allows_any_kw_args + given_kw_args - @allowed_kw_args + end + + def has_kw_args_in?(args) + Hash === args.last && could_contain_kw_args?(args) + end + + # Without considering what the last arg is, could it + # contain keyword arguments? + def could_contain_kw_args?(args) + return false if args.count <= min_non_kw_args + @allows_any_kw_args || @allowed_kw_args.any? + end + + def classify_parameters + optional_non_kw_args = @min_non_kw_args = 0 + @allows_any_kw_args = false + + @method.parameters.each do |(type, name)| + case type + # def foo(a:) + when :keyreq then @required_kw_args << name + # def foo(a: 1) + when :key then @optional_kw_args << name + # def foo(**kw_args) + when :keyrest then @allows_any_kw_args = true + # def foo(a) + when :req then @min_non_kw_args += 1 + # def foo(a = 1) + when :opt then optional_non_kw_args += 1 + # def foo(*a) + when :rest then optional_non_kw_args = INFINITY + end + end + + @max_non_kw_args = @min_non_kw_args + optional_non_kw_args + @allowed_kw_args = @required_kw_args + @optional_kw_args + end + else + def description + "arity of #{non_kw_args_arity_description}" + end + + def missing_kw_args_from(_given_kw_args) + [] + end + + def invalid_kw_args_from(_given_kw_args) + [] + end + + def has_kw_args_in?(_args) + false + end + + def could_contain_kw_args?(*) + false + end + + def classify_parameters + arity = @method.arity + if arity < 0 + # `~` inverts the one's complement and gives us the + # number of required args + @min_non_kw_args = ~arity + @max_non_kw_args = INFINITY + else + @min_non_kw_args = arity + @max_non_kw_args = arity + end + end + end + + INFINITY = 1 / 0.0 + end + + # Deals with the slightly different semantics of block arguments. + # For methods, arguments are required unless a default value is provided. + # For blocks, arguments are optional, even if no default value is provided. + # + # However, we want to treat block args as required since you virtually + # always want to pass a value for each received argument and our + # `and_yield` has treated block args as required for many years. + # + # @api private + class BlockSignature < MethodSignature + if RubyFeatures.optional_and_splat_args_supported? + def classify_parameters + super + @min_non_kw_args = @max_non_kw_args unless @max_non_kw_args == INFINITY + end + end + end + + # Abstract base class for signature verifiers. + # + # @api private + class MethodSignatureVerifier + attr_reader :non_kw_args, :kw_args + + def initialize(signature, args) + @signature = signature + @non_kw_args, @kw_args = split_args(*args) + end + + def valid? + missing_kw_args.empty? && + invalid_kw_args.empty? && + valid_non_kw_args? + end + + def error_message + if missing_kw_args.any? + "Missing required keyword arguments: %s" % [ + missing_kw_args.join(", ") + ] + elsif invalid_kw_args.any? + "Invalid keyword arguments provided: %s" % [ + invalid_kw_args.join(", ") + ] + elsif !valid_non_kw_args? + "Wrong number of arguments. Expected %s, got %s." % [ + @signature.non_kw_args_arity_description, + non_kw_args.length + ] + end + end + + private + + def valid_non_kw_args? + @signature.valid_non_kw_args?(non_kw_args.length) + end + + def missing_kw_args + @signature.missing_kw_args_from(kw_args) + end + + def invalid_kw_args + @signature.invalid_kw_args_from(kw_args) + end + + def split_args(*args) + kw_args = if @signature.has_kw_args_in?(args) + args.pop.keys + else + [] + end + + [args, kw_args] + end + end + + # Figures out wether a given method can accept various arguments. + # Surprisingly non-trivial. + # + # @private + StrictSignatureVerifier = MethodSignatureVerifier + + # Allows matchers to be used instead of providing keyword arguments. In + # practice, when this happens only the arity of the method is verified. + # + # @private + class LooseSignatureVerifier < MethodSignatureVerifier + private + + def split_args(*args) + if RSpec::Support.is_a_matcher?(args.last) && @signature.could_contain_kw_args?(args) + args.pop + @signature = SignatureWithKeywordArgumentsMatcher.new(@signature) + end + + super(*args) + end + + # If a matcher is used in a signature in place of keyword arguments, all + # keyword argument validation needs to be skipped since the matcher is + # opaque. + # + # Instead, keyword arguments will be validated when the method is called + # and they are actually known. + # + # @private + class SignatureWithKeywordArgumentsMatcher + def initialize(signature) + @signature = signature + end + + def missing_kw_args_from(_kw_args) + [] + end + + def invalid_kw_args_from(_kw_args) + [] + end + + def non_kw_args_arity_description + @signature.non_kw_args_arity_description + end + + def valid_non_kw_args?(*args) + @signature.valid_non_kw_args?(*args) + end + + def has_kw_args_in?(args) + @signature.has_kw_args_in?(args) + end + end + end + end +end diff --git a/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/object_formatter.rb b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/object_formatter.rb new file mode 100644 index 0000000..122513b --- /dev/null +++ b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/object_formatter.rb @@ -0,0 +1,93 @@ +module RSpec + module Support + # Provide additional output details beyond what `inspect` provides when + # printing Time, DateTime, or BigDecimal + module ObjectFormatter + # @api private + def self.format(object) + prepare_for_inspection(object).inspect + end + + # rubocop:disable MethodLength + + # @private + # Prepares the provided object to be formatted by wrapping it as needed + # in something that, when `inspect` is called on it, will produce the + # desired output. + # + # This allows us to apply the desired formatting to hash/array data structures + # at any level of nesting, simply by walking that structure and replacing items + # with custom items that have `inspect` defined to return the desired output + # for that item. Then we can just use `Array#inspect` or `Hash#inspect` to + # format the entire thing. + def self.prepare_for_inspection(object) + case object + when Array + return object.map { |o| prepare_for_inspection(o) } + when Hash + return prepare_hash(object) + when Time + inspection = format_time(object) + else + if defined?(DateTime) && DateTime === object + inspection = format_date_time(object) + elsif defined?(BigDecimal) && BigDecimal === object + inspection = "#{object.to_s 'F'} (#{object.inspect})" + elsif RSpec::Support.is_a_matcher?(object) && object.respond_to?(:description) + inspection = object.description + else + return object + end + end + + InspectableItem.new(inspection) + end + # rubocop:enable MethodLength + + # @private + def self.prepare_hash(input) + input.inject({}) do |hash, (k, v)| + hash[prepare_for_inspection(k)] = prepare_for_inspection(v) + hash + end + end + + TIME_FORMAT = "%Y-%m-%d %H:%M:%S" + + if Time.method_defined?(:nsec) + # @private + def self.format_time(time) + time.strftime("#{TIME_FORMAT}.#{"%09d" % time.nsec} %z") + end + else # for 1.8.7 + # @private + def self.format_time(time) + time.strftime("#{TIME_FORMAT}.#{"%06d" % time.usec} %z") + end + end + + DATE_TIME_FORMAT = "%a, %d %b %Y %H:%M:%S.%N %z" + # ActiveSupport sometimes overrides inspect. If `ActiveSupport` is + # defined use a custom format string that includes more time precision. + # @private + def self.format_date_time(date_time) + if defined?(ActiveSupport) + date_time.strftime(DATE_TIME_FORMAT) + else + date_time.inspect + end + end + + # @private + InspectableItem = Struct.new(:inspection) do + def inspect + inspection + end + + def pretty_print(pp) + pp.text inspection + end + end + end + end +end diff --git a/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/recursive_const_methods.rb b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/recursive_const_methods.rb new file mode 100644 index 0000000..f88abfe --- /dev/null +++ b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/recursive_const_methods.rb @@ -0,0 +1,76 @@ +module RSpec + module Support + # Provides recursive constant lookup methods useful for + # constant stubbing. + module RecursiveConstMethods + # We only want to consider constants that are defined directly on a + # particular module, and not include top-level/inherited constants. + # Unfortunately, the constant API changed between 1.8 and 1.9, so + # we need to conditionally define methods to ignore the top-level/inherited + # constants. + # + # Given: + # class A; B = 1; end + # class C < A; end + # + # On 1.8: + # - C.const_get("Hash") # => ::Hash + # - C.const_defined?("Hash") # => false + # - C.constants # => ["B"] + # - None of these methods accept the extra `inherit` argument + # On 1.9: + # - C.const_get("Hash") # => ::Hash + # - C.const_defined?("Hash") # => true + # - C.const_get("Hash", false) # => raises NameError + # - C.const_defined?("Hash", false) # => false + # - C.constants # => [:B] + # - C.constants(false) #=> [] + if Module.method(:const_defined?).arity == 1 + def const_defined_on?(mod, const_name) + mod.const_defined?(const_name) + end + + def get_const_defined_on(mod, const_name) + return mod.const_get(const_name) if const_defined_on?(mod, const_name) + + raise NameError, "uninitialized constant #{mod.name}::#{const_name}" + end + + def constants_defined_on(mod) + mod.constants.select { |c| const_defined_on?(mod, c) } + end + else + def const_defined_on?(mod, const_name) + mod.const_defined?(const_name, false) + end + + def get_const_defined_on(mod, const_name) + mod.const_get(const_name, false) + end + + def constants_defined_on(mod) + mod.constants(false) + end + end + + def recursive_const_get(const_name) + normalize_const_name(const_name).split('::').inject(Object) do |mod, name| + get_const_defined_on(mod, name) + end + end + + def recursive_const_defined?(const_name) + parts = normalize_const_name(const_name).split('::') + parts.inject([Object, '']) do |(mod, full_name), name| + yield(full_name, name) if block_given? && !(Module === mod) + return false unless const_defined_on?(mod, name) + [get_const_defined_on(mod, name), [mod, name].join('::')] + end + end + + def normalize_const_name(const_name) + const_name.sub(/\A::/, '') + end + end + end +end diff --git a/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/ruby_features.rb b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/ruby_features.rb new file mode 100644 index 0000000..44813f9 --- /dev/null +++ b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/ruby_features.rb @@ -0,0 +1,118 @@ +require 'rbconfig' + +module RSpec + module Support + # @api private + # + # Provides query methods for different OS or OS features. + module OS + module_function + + def windows? + RbConfig::CONFIG['host_os'] =~ /cygwin|mswin|mingw|bccwin|wince|emx/ + end + + def windows_file_path? + ::File::ALT_SEPARATOR == '\\' + end + end + + # @api private + # + # Provides query methods for different rubies + module Ruby + module_function + + def jruby? + RUBY_PLATFORM == 'java' + end + + def rbx? + defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx' + end + + def non_mri? + !mri? + end + + def mri? + !defined?(RUBY_ENGINE) || RUBY_ENGINE == 'ruby' + end + end + + # @api private + # + # Provides query methods for ruby features that differ among + # implementations. + module RubyFeatures + module_function + + def optional_and_splat_args_supported? + Method.method_defined?(:parameters) + end + + def caller_locations_supported? + respond_to?(:caller_locations, true) + end + + if Ruby.mri? + def kw_args_supported? + RUBY_VERSION >= '2.0.0' + end + + def required_kw_args_supported? + RUBY_VERSION >= '2.1.0' + end + + def supports_rebinding_module_methods? + RUBY_VERSION.to_i >= 2 + end + else + # RBX / JRuby et al support is unknown for keyword arguments + # rubocop:disable Lint/Eval + begin + eval("o = Object.new; def o.m(a: 1); end;"\ + " raise SyntaxError unless o.method(:m).parameters.include?([:key, :a])") + + def kw_args_supported? + true + end + rescue SyntaxError + def kw_args_supported? + false + end + end + + begin + eval("o = Object.new; def o.m(a: ); end;"\ + "raise SyntaxError unless o.method(:m).parameters.include?([:keyreq, :a])") + + def required_kw_args_supported? + true + end + rescue SyntaxError + def required_kw_args_supported? + false + end + end + + begin + Module.new { def foo; end }.instance_method(:foo).bind(Object.new) + + def supports_rebinding_module_methods? + true + end + rescue TypeError + def supports_rebinding_module_methods? + false + end + end + # rubocop:enable Lint/Eval + end + + def module_prepends_supported? + Module.method_defined?(:prepend) || Module.private_method_defined?(:prepend) + end + end + end +end diff --git a/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec.rb b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec.rb new file mode 100644 index 0000000..d488a2d --- /dev/null +++ b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec.rb @@ -0,0 +1,81 @@ +require 'rspec/support' +require 'rspec/support/spec/in_sub_process' + +RSpec::Support.require_rspec_support "spec/deprecation_helpers" +RSpec::Support.require_rspec_support "spec/with_isolated_stderr" +RSpec::Support.require_rspec_support "spec/stderr_splitter" +RSpec::Support.require_rspec_support "spec/formatting_support" +RSpec::Support.require_rspec_support "spec/with_isolated_directory" +RSpec::Support.require_rspec_support "ruby_features" + +warning_preventer = $stderr = RSpec::Support::StdErrSplitter.new($stderr) + +RSpec.configure do |c| + c.include RSpecHelpers + c.include RSpec::Support::WithIsolatedStdErr + c.include RSpec::Support::FormattingSupport + c.include RSpec::Support::InSubProcess + + unless defined?(Debugger) # debugger causes warnings when used + c.before do + warning_preventer.reset! + end + + c.after do + warning_preventer.verify_no_warnings! + end + end + + if c.files_to_run.one? + c.full_backtrace = true + c.default_formatter = 'doc' + end + + c.filter_run :focus + c.run_all_when_everything_filtered = true + c.example_status_persistence_file_path = "./spec/examples.txt" + + c.define_derived_metadata :failing_on_appveyor do |meta| + meta[:pending] ||= "This spec fails on AppVeyor and needs someone to fix it." + end if ENV['APPVEYOR'] +end + +module RSpec + module Support + module Spec + def self.setup_simplecov(&block) + # Simplecov emits some ruby warnings when loaded, so silence them. + old_verbose, $VERBOSE = $VERBOSE, false + + return if ENV['NO_COVERAGE'] || RUBY_VERSION < '1.9.3' + return if RUBY_ENGINE != 'ruby' || RSpec::Support::OS.windows? + + # Don't load it when we're running a single isolated + # test file rather than the whole suite. + return if RSpec.configuration.files_to_run.one? + + require 'simplecov' + start_simplecov(&block) + rescue LoadError + warn "Simplecov could not be loaded" + ensure + $VERBOSE = old_verbose + end + + def self.start_simplecov(&block) + SimpleCov.start do + add_filter "./bundle/" + add_filter "./tmp/" + add_filter do |source_file| + # Filter out `spec` directory except when it is under `lib` + # (as is the case in rspec-support) + source_file.filename.include?('/spec/') && !source_file.filename.include?('/lib/') + end + + instance_eval(&block) if block + end + end + private_class_method :start_simplecov + end + end +end diff --git a/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/deprecation_helpers.rb b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/deprecation_helpers.rb new file mode 100644 index 0000000..ed66332 --- /dev/null +++ b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/deprecation_helpers.rb @@ -0,0 +1,64 @@ +module RSpecHelpers + def expect_no_deprecation + expect(RSpec.configuration.reporter).not_to receive(:deprecation) + end + + def expect_deprecation_with_call_site(file, line, snippet=//) + expect(RSpec.configuration.reporter).to receive(:deprecation) do |options| + expect(options[:call_site]).to include([file, line].join(':')) + expect(options[:deprecated]).to match(snippet) + end + end + + def expect_deprecation_without_call_site(snippet=//) + expect(RSpec.configuration.reporter).to receive(:deprecation) do |options| + expect(options[:call_site]).to eq nil + expect(options[:deprecated]).to match(snippet) + end + end + + def expect_warn_deprecation_with_call_site(file, line, snippet=//) + expect(RSpec.configuration.reporter).to receive(:deprecation) do |options| + message = options[:message] + expect(message).to match(snippet) + expect(message).to include([file, line].join(':')) + end + end + + def expect_warn_deprecation(snippet=//) + expect(RSpec.configuration.reporter).to receive(:deprecation) do |options| + message = options[:message] + expect(message).to match(snippet) + end + end + + def allow_deprecation + allow(RSpec.configuration.reporter).to receive(:deprecation) + end + + def expect_no_deprecations + expect(RSpec.configuration.reporter).not_to receive(:deprecation) + end + + def expect_warning_without_call_site(expected=//) + expect(::Kernel).to receive(:warn) do |message| + expect(message).to match expected + expect(message).to_not match(/Called from/) + end + end + + def expect_warning_with_call_site(file, line, expected=//) + expect(::Kernel).to receive(:warn) do |message| + expect(message).to match expected + expect(message).to match(/Called from #{file}:#{line}/) + end + end + + def expect_no_warnings + expect(::Kernel).not_to receive(:warn) + end + + def allow_warning + allow(::Kernel).to receive(:warn) + end +end diff --git a/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/formatting_support.rb b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/formatting_support.rb new file mode 100644 index 0000000..7e61cef --- /dev/null +++ b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/formatting_support.rb @@ -0,0 +1,9 @@ +module RSpec + module Support + module FormattingSupport + def dedent(string) + string.gsub(/^\s+\|/, '').chomp + end + end + end +end diff --git a/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/in_sub_process.rb b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/in_sub_process.rb new file mode 100644 index 0000000..0c1d9c1 --- /dev/null +++ b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/in_sub_process.rb @@ -0,0 +1,52 @@ +module RSpec + module Support + module InSubProcess + if Process.respond_to?(:fork) && !(Ruby.jruby? && RUBY_VERSION == '1.8.7') + + # Useful as a way to isolate a global change to a subprocess. + + # rubocop:disable MethodLength + def in_sub_process(prevent_warnings=true) + readme, writeme = IO.pipe + + pid = Process.fork do + exception = nil + warning_preventer = $stderr = RSpec::Support::StdErrSplitter.new($stderr) + + begin + yield + warning_preventer.verify_no_warnings! if prevent_warnings + rescue Exception => e + exception = e + end + + writeme.write Marshal.dump(exception) + + readme.close + writeme.close + exit! # prevent at_exit hooks from running (e.g. minitest) + end + + writeme.close + Process.waitpid(pid) + + exception = Marshal.load(readme.read) + readme.close + + raise exception if exception + end + # rubocop:enable MethodLength + alias :in_sub_process_if_possible :in_sub_process + else + def in_sub_process(*) + skip "This spec requires forking to work properly, " \ + "and your platform does not support forking" + end + + def in_sub_process_if_possible(*) + yield + end + end + end + end +end diff --git a/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/library_wide_checks.rb b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/library_wide_checks.rb new file mode 100644 index 0000000..220d709 --- /dev/null +++ b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/library_wide_checks.rb @@ -0,0 +1,145 @@ +require 'rspec/support/spec/shell_out' + +RSpec.shared_examples_for "library wide checks" do |lib, options| + consider_a_test_env_file = options.fetch(:consider_a_test_env_file, /MATCHES NOTHING/) + allowed_loaded_feature_regexps = options.fetch(:allowed_loaded_feature_regexps, []) + preamble_for_lib = options[:preamble_for_lib] + preamble_for_spec = "require 'rspec/core'; require 'spec_helper'" + skip_spec_files = options.fetch(:skip_spec_files, /MATCHES NOTHING/) + + include RSpec::Support::ShellOut + + define_method :files_to_require_for do |sub_dir| + slash = File::SEPARATOR + lib_path_re = /#{slash + lib}[^#{slash}]*#{slash}lib/ + load_path = $LOAD_PATH.grep(lib_path_re).first + directory = load_path.sub(/lib$/, sub_dir) + files = Dir["#{directory}/**/*.rb"] + extract_regex = /#{Regexp.escape(directory) + File::SEPARATOR}(.+)\.rb$/ + + # We sort to ensure the files are loaded in a consistent order, regardless + # of OS. Otherwise, it could load in a different order on Travis than + # locally, and potentially trigger a "circular require considered harmful" + # warning or similar. + files.sort.map { |file| file[extract_regex, 1] } + end + + def command_from(code_lines) + code_lines.join("\n") + end + + def load_all_files(files, preamble, postamble=nil) + requires = files.map { |f| "require '#{f}'" } + command = command_from(Array(preamble) + requires + Array(postamble)) + + stdout, stderr, status = with_env 'NO_COVERAGE' => '1' do + options = %w[ -w ] + options << "--disable=gem" if RUBY_VERSION.to_f >= 1.9 && RSpec::Support::Ruby.mri? + run_ruby_with_current_load_path(command, *options) + end + + # Ignore bundler warning. + stderr = stderr.split("\n").reject { |l| l =~ %r{bundler/source/rubygems} }.join("\n") + [stdout, stderr, status.exitstatus] + end + + define_method :load_all_lib_files do + files = all_lib_files - lib_test_env_files + preamble = ['orig_loaded_features = $".dup', preamble_for_lib] + postamble = ['puts(($" - orig_loaded_features).join("\n"))'] + + @loaded_feature_lines, stderr, exitstatus = load_all_files(files, preamble, postamble) + ["", stderr, exitstatus] + end + + define_method :load_all_spec_files do + files = files_to_require_for("spec") + lib_test_env_files + files = files.reject { |f| f =~ skip_spec_files } + load_all_files(files, preamble_for_spec) + end + + attr_reader :all_lib_files, :lib_test_env_files, + :lib_file_results, :spec_file_results + + before(:context) do + @all_lib_files = files_to_require_for("lib") + @lib_test_env_files = all_lib_files.grep(consider_a_test_env_file) + + @lib_file_results, @spec_file_results = [ + # Load them in parallel so it's faster... + Thread.new { load_all_lib_files }, + Thread.new { load_all_spec_files } + ].map(&:join).map(&:value) + end + + def have_successful_no_warnings_output + eq ["", "", 0] + end + + it "issues no warnings when loaded", :slow do + expect(lib_file_results).to have_successful_no_warnings_output + end + + it "issues no warnings when the spec files are loaded", :slow do + expect(spec_file_results).to have_successful_no_warnings_output + end + + it 'only loads a known set of stdlibs so gem authors are forced ' \ + 'to load libs they use to have passing specs', :slow do + loaded_features = @loaded_feature_lines.split("\n") + if RUBY_VERSION == '1.8.7' + # On 1.8.7, $" returns the relative require path if that was used + # to require the file. LIB_REGEX will not match the relative version + # since it has a `/lib` prefix. Here we deal with this by expanding + # relative files relative to the $LOAD_PATH dir (lib). + Dir.chdir("lib") { loaded_features.map! { |f| File.expand_path(f) } } + end + + loaded_features.reject! { |feature| RSpec::CallerFilter::LIB_REGEX =~ feature } + loaded_features.reject! { |feature| allowed_loaded_feature_regexps.any? { |r| r =~ feature } } + + expect(loaded_features).to eq([]) + end + + # This malformed whitespace detection logic has been borrowed from bundler: + # https://github.com/bundler/bundler/blob/v1.8.0/spec/quality_spec.rb + def check_for_tab_characters(filename) + failing_lines = [] + File.readlines(filename).each_with_index do |line, number| + failing_lines << number + 1 if line =~ /\t/ + end + + return if failing_lines.empty? + "#{filename} has tab characters on lines #{failing_lines.join(', ')}" + end + + def check_for_extra_spaces(filename) + failing_lines = [] + File.readlines(filename).each_with_index do |line, number| + next if line =~ /^\s+#.*\s+\n$/ + failing_lines << number + 1 if line =~ /\s+\n$/ + end + + return if failing_lines.empty? + "#{filename} has spaces on the EOL on lines #{failing_lines.join(', ')}" + end + + RSpec::Matchers.define :be_well_formed do + match do |actual| + actual.empty? + end + + failure_message do |actual| + actual.join("\n") + end + end + + it "has no malformed whitespace", :slow do + error_messages = [] + `git ls-files -z`.split("\x0").each do |filename| + error_messages << check_for_tab_characters(filename) + error_messages << check_for_extra_spaces(filename) + end + expect(error_messages.compact).to be_well_formed + end +end diff --git a/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/shell_out.rb b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/shell_out.rb new file mode 100644 index 0000000..02ea79e --- /dev/null +++ b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/shell_out.rb @@ -0,0 +1,71 @@ +require 'open3' +require 'rake/file_utils' +require 'shellwords' + +module RSpec + module Support + module ShellOut + def with_env(vars) + original = ENV.to_hash + vars.each { |k, v| ENV[k] = v } + + begin + yield + ensure + ENV.replace(original) + end + end + + if Open3.respond_to?(:capture3) # 1.9+ + def shell_out(*command) + stdout, stderr, status = Open3.capture3(*command) + return stdout, filter(stderr), status + end + else # 1.8.7 + # popen3 doesn't provide the exit status so we fake it out. + FakeProcessStatus = Struct.new(:exitstatus) + + def shell_out(*command) + stdout = stderr = nil + + Open3.popen3(*command) do |_in, out, err| + stdout = out.read + stderr = err.read + end + + status = FakeProcessStatus.new(0) + return stdout, filter(stderr), status + end + end + + def run_ruby_with_current_load_path(ruby_command, *flags) + command = [ + FileUtils::RUBY, + "-I#{$LOAD_PATH.map(&:shellescape).join(File::PATH_SEPARATOR)}", + "-e", ruby_command, *flags + ] + + # Unset these env vars because `ruby -w` will issue warnings whenever + # they are set to non-default values. + with_env 'RUBY_GC_HEAP_FREE_SLOTS' => nil, 'RUBY_GC_MALLOC_LIMIT' => nil, + 'RUBY_FREE_MIN' => nil do + shell_out(*command) + end + end + + private + + if Ruby.jruby? + def filter(output) + output.each_line.reject do |line| + line.include?("lib/ruby/shared/rubygems/defaults/jruby") + end.join($/) + end + else + def filter(output) + output + end + end + end + end +end diff --git a/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/stderr_splitter.rb b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/stderr_splitter.rb new file mode 100644 index 0000000..f797a23 --- /dev/null +++ b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/stderr_splitter.rb @@ -0,0 +1,63 @@ +require 'stringio' + +module RSpec + module Support + class StdErrSplitter + def initialize(original) + @orig_stderr = original + @output_tracker = ::StringIO.new + end + + respond_to_name = (::RUBY_VERSION.to_f < 1.9) ? :respond_to? : :respond_to_missing? + define_method respond_to_name do |*args| + @orig_stderr.respond_to?(*args) || super(*args) + end + + def method_missing(name, *args, &block) + @output_tracker.__send__(name, *args, &block) if @output_tracker.respond_to?(name) + @orig_stderr.__send__(name, *args, &block) + end + + def ==(other) + @orig_stderr == other + end + + def reopen(*args) + reset! + @orig_stderr.reopen(*args) + end + + # To work around JRuby error: + # can't convert RSpec::Support::StdErrSplitter into String + def to_io + @orig_stderr.to_io + end + + # To work around JRuby error: + # TypeError: $stderr must have write method, RSpec::StdErrSplitter given + def write(line) + return if line =~ %r{^\S+/gems/\S+:\d+: warning:} # http://rubular.com/r/kqeUIZOfPG + + @orig_stderr.write(line) + @output_tracker.write(line) + end + + def has_output? + !output.empty? + end + + def reset! + @output_tracker = ::StringIO.new + end + + def verify_no_warnings! + raise "Warnings were generated: #{output}" if has_output? + reset! + end + + def output + @output_tracker.string + end + end + end +end diff --git a/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/string_matcher.rb b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/string_matcher.rb new file mode 100644 index 0000000..9e16231 --- /dev/null +++ b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/string_matcher.rb @@ -0,0 +1,46 @@ +require 'rspec/matchers' +# Special matcher for comparing encoded strings so that +# we don't run any expectation failures through the Differ, +# which also relies on EncodedString. Instead, confirm the +# strings have the same bytes. +RSpec::Matchers.define :be_identical_string do |expected| + + if String.method_defined?(:encoding) + match do + expected_encoding? && + actual.bytes.to_a == expected.bytes.to_a + end + + failure_message do + "expected\n#{actual.inspect} (#{actual.encoding.name}) to be identical to\n"\ + "#{expected.inspect} (#{expected.encoding.name})\n"\ + "The exact bytes are printed below for more detail:\n"\ + "#{actual.bytes.to_a}\n"\ + "#{expected.bytes.to_a}\n"\ + end + + # Depends on chaining :with_same_encoding for it to + # check for string encoding. + def expected_encoding? + if defined?(@expect_same_encoding) && @expect_same_encoding + actual.encoding == expected.encoding + else + true + end + end + else + match do + actual.split(//) == expected.split(//) + end + + failure_message do + "expected\n#{actual.inspect} to be identical to\n#{expected.inspect}\n" + end + end + + chain :with_same_encoding do + @expect_same_encoding ||= true + end +end +RSpec::Matchers.alias_matcher :a_string_identical_to, :be_identical_string +RSpec::Matchers.alias_matcher :be_diffed_as, :be_identical_string diff --git a/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/with_isolated_directory.rb b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/with_isolated_directory.rb new file mode 100644 index 0000000..c0a2bda --- /dev/null +++ b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/with_isolated_directory.rb @@ -0,0 +1,9 @@ +require 'tmpdir' + +RSpec.shared_context "isolated directory", :isolated_directory => true do + around do |ex| + Dir.mktmpdir do |tmp_dir| + Dir.chdir(tmp_dir, &ex) + end + end +end diff --git a/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/with_isolated_stderr.rb b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/with_isolated_stderr.rb new file mode 100644 index 0000000..8884c2f --- /dev/null +++ b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/spec/with_isolated_stderr.rb @@ -0,0 +1,13 @@ +module RSpec + module Support + module WithIsolatedStdErr + def with_isolated_stderr + original = $stderr + $stderr = StringIO.new + yield + ensure + $stderr = original + end + end + end +end diff --git a/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/version.rb b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/version.rb new file mode 100644 index 0000000..65fe083 --- /dev/null +++ b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/version.rb @@ -0,0 +1,7 @@ +module RSpec + module Support + module Version + STRING = '3.3.0' + end + end +end diff --git a/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/version_checker.rb b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/version_checker.rb new file mode 100644 index 0000000..679211e --- /dev/null +++ b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/version_checker.rb @@ -0,0 +1,53 @@ +module RSpec + module Support + LibraryVersionTooLowError = Class.new(StandardError) + + # @private + class VersionChecker + def initialize(library_name, library_version, min_patch_level) + @library_name, @library_version = library_name, library_version + @min_patch_level = min_patch_level + + @major, @minor, @patch = parse_version(library_version) + @min_major, @min_minor, @min_patch = parse_version(min_patch_level) + + @comparison_result = compare_version + end + + def check_version! + raise_too_low_error if too_low? + end + + private + + def too_low? + @comparison_result == :too_low + end + + def raise_too_low_error + raise LibraryVersionTooLowError, + "You are using #{@library_name} #{@library_version}. " \ + "RSpec requires version #{version_requirement}." + end + + def compare_version + case + when @major < @min_major then :too_low + when @major > @min_major then :ok + when @minor < @min_minor then :too_low + when @minor > @min_minor then :ok + when @patch < @min_patch then :too_low + else :ok + end + end + + def version_requirement + ">= #{@min_patch_level}" + end + + def parse_version(version) + version.split('.').map { |v| v.to_i } + end + end + end +end diff --git a/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/warnings.rb b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/warnings.rb new file mode 100644 index 0000000..1d0a632 --- /dev/null +++ b/.bundle/gems/rspec-support-3.3.0/lib/rspec/support/warnings.rb @@ -0,0 +1,39 @@ +require 'rspec/support' +RSpec::Support.require_rspec_support "caller_filter" + +module RSpec + module Support + module Warnings + def deprecate(deprecated, options={}) + warn_with "DEPRECATION: #{deprecated} is deprecated.", options + end + + # @private + # + # Used internally to print deprecation warnings + # when rspec-core isn't loaded + def warn_deprecation(message, options={}) + warn_with "DEPRECATION: \n #{message}", options + end + + # @private + # + # Used internally to print warnings + def warning(text, options={}) + warn_with "WARNING: #{text}.", options + end + + # @private + # + # Used internally to print longer warnings + def warn_with(message, options={}) + call_site = options.fetch(:call_site) { CallerFilter.first_non_rspec_line } + message << " Use #{options[:replacement]} instead." if options[:replacement] + message << " Called from #{call_site}." if call_site + ::Kernel.warn message + end + end + end + + extend RSpec::Support::Warnings +end diff --git a/.bundle/gems/slop-3.6.0/.gitignore b/.bundle/gems/slop-3.6.0/.gitignore new file mode 100644 index 0000000..e20dac6 --- /dev/null +++ b/.bundle/gems/slop-3.6.0/.gitignore @@ -0,0 +1,7 @@ +.rvmrc +.yardoc +doc +*.swp +*.gem +*.rbc +Gemfile.lock diff --git a/.bundle/gems/slop-3.6.0/.travis.yml b/.bundle/gems/slop-3.6.0/.travis.yml new file mode 100644 index 0000000..6fba0ce --- /dev/null +++ b/.bundle/gems/slop-3.6.0/.travis.yml @@ -0,0 +1,9 @@ +rvm: + - 1.9.3 + - 2.1 + - ruby-head + - jruby-19mode +notifications: + email: + on_success: change + on_failure: always diff --git a/.bundle/gems/slop-3.6.0/CHANGES.md b/.bundle/gems/slop-3.6.0/CHANGES.md new file mode 100644 index 0000000..c500beb --- /dev/null +++ b/.bundle/gems/slop-3.6.0/CHANGES.md @@ -0,0 +1,309 @@ +3.6.0 (2014-06-18) +------------------ + +* Add example of rest arguments usage in the readme file #139 +* Default values on options are printed in the help message #134 + +3.5.0 (2014-03-12) +------------------ + +* Add support for `as: Regexp` #132 + +3.4.7 (2013-11-14) +------------------ + +* Ensure trash is cleared on every parse so you can parse multiple + times with the same instance (#130) + +3.4.5 (2013-05-14) +------------------ + +* Allow specifying long options starting with numbers (#110, Peter Zotov) +* Ensure short-options still consume trailing arguments, ie `-abc foo` + should assign `foo` to the option `c` if it expects an argument (#114). + +3.4.4 (2013-03-12) +------------------ + +* Disable the run callback when the help option is used and `-h` + or `--help` is passed. #106 +* Ensure default `--help` option exits by default (#107, Autumn Perrault). + +3.4.3 (2013-01-14) +------------------ + +* Ensure `parse!` removes commands and their options. + +3.4.2 (2013-01-14) +------------------ + +* Expose the Hash commands as public API. +* Deprecated `Slop.optspec`. +* Ensure help output prints to stdout, not stderr. + +3.4.1 (2013-01-13) +------------------ + +* Ensure options replace any existing duplicates +* Command config options now inherit config options from top level Slop. +* Command help output now adds command in usage string. + +3.4.0 (2013-01-12) +------------------ + +* Implement new command system (#95) +* Deprecate Slop::Commands +* Ensure 'no-foo' options are not inverted when parsing '--no-foo' (#86) +* Code refactoring and simplification (Kenichi Kamiya, #84, #85) + +3.3.3 (2012-08-29) +------------------ + +* Ensure autocreate arguments are not created as options (#77) +* Ensure options are not swallowed when using short options with argument + included (#74) + +3.3.2 (2012-06-26) +------------------ + +* Ensure multiple options are not executed unless they exist (#70) + +3.3.1 (2012-05-31) +------------------ + +* Stop multiple switches from trashing arguments (Conrad Irwin, #66) + +3.3.0 (2012-05-30) +------------------ + +* Fix `:as => :count` when using multiple switches. +* Ensure range typecast allows negative range values. +* Ignore nil objects send to #parse instead of choking. + +3.2.0 (2012-05-15) +------------------ + +* Ensure boolean options appear correctly in `to_hash` output. (#59) + +3.1.1 (2012-04-24) +------------------ + +* Ensure separators before any options are still being processed (#62) + +3.1.0 (2012-04-23) +------------------ + +* Allow options to be fetched via underscores instead of dashes + (as a fallback) (Eric Anderson, #51) +* Added `Slop#strict?` method. +* Added strict checks for Integer/Float type casting. (Amon Sha) +* Ensure separators are not replacing existing separators (#61) + +3.0.4 (2012-01-31) +------------------ + +* Ensure `option=argument` syntax does not consume following arguments (#55). + +3.0.3 (2012-01-30) +------------------ + +* Ensure options passed after option terminator do not raise an exception + (#54, Amon Sha) + +3.0.2 (2012-01-27) +------------------ + +* Ensure `--option=value` is being evaluated before multiple switches (#52) + +3.0.1 (2012-01-27) +------------------ + +* Ensure tests run green on 1.8.7 +* Ensure `:argument => :optional` works with `:option=` format. +* Ruby 1.8.7 compat fix (dont chain Enumerable methods!) (Eric Anderson) + +3.0.0 (2012-01-24) +------------------ + +* value_to_range returns an x..x range if the value looks like an integer. +* Lots of code refactoring +* Use TomDoc documentation +* Added `Slop::Commands` and removed existing command system +* Configuration options altered: + * `:optional` has been renamed to `:optional_argument` + * Added `:required` for mandatory options + * `:argument` now accepts an `:optional` symbol as well as boolean value +* Removed Slop instance methods: + * description=, description + * summary=, summary + * command + * on_empty + * on_noopts + * execute + * to_struct +* Added Slop instance methods: + * separator + * fetch_option + * add_callback + +2.4.3 (2012-01-16) +------------------ + +* Allow the `:as` option to accept an object responding to :call for + custom type conversions (#45) +* Ensure negative integers are not parsed as possible options (#46) + +2.4.2 (2011-12-18) +------------------ + +* Fix checking of required options (Dominik Honnef) + +2.4.1 (2011-12-08) +------------------ + +* Ensure optional arguments are returned correctly + +2.4.0 (2011-11-26) +------------------ + +* Avoid `define_method` for checking an options presence (and caching it) #37 +* Ensure the short option allows an appended `=` for accepting arguments +* Implement `respond_to?` + +2.3.1 (2011-11-11) +------------------ + +* Return `nil` for any options using casting which don't expect arguments (#33) +* Fix parenthesis warning on 1.8.7 (@shevegen) +* Ensure long argument is a string before attempting to use `#[]` method on it + +2.3.0 (2011-11-04) +------------------ + +* Allow flags to have suffixed `=` char for options which accept an argument + +2.2.0 (2011-11-02) +------------------ + +* Support `bup.options` style optspec parsing + * http://apenwarr.ca/log/?m=201111 + +* Allow `:as` to accept a `count` value (Conrad Irwin): + + `on :v, :verbose, :as => :count # -vv; opts[:verbose] #=> 2` + +2.1.0 (2011-08-03) +------------------ + +* Added `Slop#missing` for returning a list of missing options parsed +* Allow `Slop#present?` to accept multiple arguments +* Added `:all_accept_arguments` to Slop configuration options, this saves + having to specify that every option takes an argument +* Added `Slop#to_struct` for building new classes from options + +2.0.0 (2011-07-07) +------------------ + +* Deprecations: + * Removed `Slop::Options#to_hash` continue using `Slop#to_hash` directly. + This method also now returns symbols by default instead of strings. If + you want strings use `opts.to_hash(false)` + * `:multiple_switches` is now enabled by default, to parse `fbar` as the + option `f` with value `bar` you must disable `:multiple_switches` + * Removed `Slop::Options#to_help` and merged its contents into `Slop#help` + * Removed `lib/slop/options.rb` and merged `Slop::Options` into slop.rb + * Removed `lib/slop/option.rb` and merged `Slop::Option` into slop.rb + * These changes make Slop much easier to vendor in libraries +* `Slop::Option` now inherits from `Struct.new` +* Added Slop::Error subclassing from StandardError which all exception + classes should inherit from +* Added Slop::MissingOptionError and `:required` option to Slop::Option. + This exception is raised when a mandatory option is not used + +1.9.1 (2011-06-16) +------------------ + +* Ensure optional items with no arguments still return true when searching + for presence + +1.9.0 (2011-06-15) +------------------ + +* Add command completion and support for an error message when ambiguous + commands are used +* Add command aliases +* Fix: Ensure parsed elements are removed from original arguments when using + `:multiple_switches` +* Ensure anything after `--` is parsed as an argument and not option even + if prefixed with `/--?/` +* Performance improvements when making many calls to `Slop#option?` for + checking an options presence (Rob Gleeson) +* Ensure `execute` passes command arguments to the block +* Support for summary and description (Denis Defreyne) + +1.8.0 (2011-06-12) +------------------ + +* Added `execute` method to Slop for commands. This block will be invoked + when a specific command is used. The Slop object will be yielded to the + block +* Allow passing a class name to `on` to be used as an `:as` option. ie: + `on :people, 'Some people', Array` +* Get smart with parsing options optparse style: `on '--name NAME'` and + `on 'password [OPTIONAL]'` +* Feature: `:arguments` setting to enable argument passing for all options + +1.7.0 (2011-06-06) +------------------ + +* Feature: Autocreate (auto create options at parse time, making assumptions) +* Feature: When parsing options as arrays, push multiple arguments into a + single array + +1.6.1 (2011-06-01) +------------------ + +* Fix tests and using a temporary Array for ARGV, fixes RubyGems Test issues +* General cleanup of code + +1.6.0 (2011-05-18) +------------------ + +* Add `:ignore_case` to Slop options for case insensitive option matching +* Add `:on_noopts` for triggering an event when the arguments contain no + options +* Add `:unless` to Slop::Option for omitting execution of the Options block + when this object exists in the Array of items passed to Slop.new +* Bugfix: Do not parse negative integers as options. A valid option must + start with an alphabet character +* Bugfix: Allow a Range to accept a negative Integer at either end + +1.5.5 (2011-05-03) +------------------ + +* Bugfix: only attempt to extract options prefixed with `-` + +1.5.4 (2011-05-01) +------------------ + +* Bugfix: `parse!` should not remove items with the same value as items used + in option arguments. Fixes #22 (Utkarsh Kukreti) + +1.5.3 (2011-04-22) +------------------ + +* Bugfix: Use integers when fetching array indexes, not strings + +1.5.2 (2011-04-17) +------------------ + +* Bugfix: Ensure `ARGV` is empty when using the `on_empty` event + +1.5.0 (2011-04-15) +------------------ + +* Add `Slop#get` as alias to `Slop#[]` +* Add `Slop#present?` as alias for `Slop#