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..8cf9c60 --- /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..0fd2462 --- /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..4155bee --- /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..1f13a77 --- /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..0a3c82e --- /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 0000000..20f2911 Binary files /dev/null and b/.bundle/cache/coderay-1.1.0.gem differ 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 0000000..e4436cc Binary files /dev/null and b/.bundle/cache/diff-lcs-1.2.5.gem differ 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 0000000..842453a Binary files /dev/null and b/.bundle/cache/method_source-0.8.2.gem differ diff --git a/.bundle/cache/pry-0.10.1.gem b/.bundle/cache/pry-0.10.1.gem new file mode 100644 index 0000000..2586875 Binary files /dev/null and b/.bundle/cache/pry-0.10.1.gem differ diff --git a/.bundle/cache/rspec-3.3.0.gem b/.bundle/cache/rspec-3.3.0.gem new file mode 100644 index 0000000..3a9ad2b Binary files /dev/null and b/.bundle/cache/rspec-3.3.0.gem differ 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 0000000..978694e Binary files /dev/null and b/.bundle/cache/rspec-core-3.3.2.gem differ diff --git a/.bundle/cache/rspec-expectations-3.3.1.gem b/.bundle/cache/rspec-expectations-3.3.1.gem new file mode 100644 index 0000000..b8ba962 Binary files /dev/null and b/.bundle/cache/rspec-expectations-3.3.1.gem differ 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 0000000..81e6e94 Binary files /dev/null and b/.bundle/cache/rspec-mocks-3.3.2.gem differ 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 0000000..9b9e706 Binary files /dev/null and b/.bundle/cache/rspec-support-3.3.0.gem differ diff --git a/.bundle/cache/slop-3.6.0.gem b/.bundle/cache/slop-3.6.0.gem new file mode 100644 index 0000000..153a673 Binary files /dev/null and b/.bundle/cache/slop-3.6.0.gem differ 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.1/LICENSE b/.bundle/gems/pry-0.10.1/LICENSE new file mode 100644 index 0000000..1258004 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/README.md b/.bundle/gems/pry-0.10.1/README.md new file mode 100644 index 0000000..b42c87a --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/bin/pry b/.bundle/gems/pry-0.10.1/bin/pry new file mode 100755 index 0000000..3904fe9 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry.rb b/.bundle/gems/pry-0.10.1/lib/pry.rb new file mode 100644 index 0000000..a8e81c0 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/cli.rb b/.bundle/gems/pry-0.10.1/lib/pry/cli.rb new file mode 100644 index 0000000..ef73869 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/code.rb b/.bundle/gems/pry-0.10.1/lib/pry/code.rb new file mode 100644 index 0000000..f58189e --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/code/code_file.rb b/.bundle/gems/pry-0.10.1/lib/pry/code/code_file.rb new file mode 100644 index 0000000..9ccb23b --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/code/code_range.rb b/.bundle/gems/pry-0.10.1/lib/pry/code/code_range.rb new file mode 100644 index 0000000..043be02 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/code/loc.rb b/.bundle/gems/pry-0.10.1/lib/pry/code/loc.rb new file mode 100644 index 0000000..905c704 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/code_object.rb b/.bundle/gems/pry-0.10.1/lib/pry/code_object.rb new file mode 100644 index 0000000..11a3aa6 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/color_printer.rb b/.bundle/gems/pry-0.10.1/lib/pry/color_printer.rb new file mode 100644 index 0000000..218a821 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/command.rb b/.bundle/gems/pry-0.10.1/lib/pry/command.rb new file mode 100644 index 0000000..0cf334f --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/command_set.rb b/.bundle/gems/pry-0.10.1/lib/pry/command_set.rb new file mode 100644 index 0000000..9483ab0 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands.rb new file mode 100644 index 0000000..4b85ada --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/amend_line.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/amend_line.rb new file mode 100644 index 0000000..d30c9a0 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/bang.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/bang.rb new file mode 100644 index 0000000..8843458 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/bang_pry.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/bang_pry.rb new file mode 100644 index 0000000..71f81ef --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/cat.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/cat.rb new file mode 100644 index 0000000..8ca537f --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/cat/abstract_formatter.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/cat/abstract_formatter.rb new file mode 100644 index 0000000..c554647 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/cat/exception_formatter.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/cat/exception_formatter.rb new file mode 100644 index 0000000..af10e9d --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/cat/file_formatter.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/cat/file_formatter.rb new file mode 100644 index 0000000..a7a8679 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/cat/input_expression_formatter.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/cat/input_expression_formatter.rb new file mode 100644 index 0000000..8791ac3 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/cd.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/cd.rb new file mode 100644 index 0000000..667453a --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/change_inspector.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/change_inspector.rb new file mode 100644 index 0000000..183dec4 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/change_prompt.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/change_prompt.rb new file mode 100644 index 0000000..13d36cb --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/code_collector.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/code_collector.rb new file mode 100644 index 0000000..72e8181 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/disable_pry.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/disable_pry.rb new file mode 100644 index 0000000..69bfc4e --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/disabled_commands.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/disabled_commands.rb new file mode 100644 index 0000000..9866f90 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/easter_eggs.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/easter_eggs.rb new file mode 100644 index 0000000..84a97df --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/edit.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/edit.rb new file mode 100644 index 0000000..cf2cc1c --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/edit/exception_patcher.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/edit/exception_patcher.rb new file mode 100644 index 0000000..07e13bc --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/edit/file_and_line_locator.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/edit/file_and_line_locator.rb new file mode 100644 index 0000000..5f712f3 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/exit.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/exit.rb new file mode 100644 index 0000000..32c0c2e --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/exit_all.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/exit_all.rb new file mode 100644 index 0000000..1136de3 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/exit_program.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/exit_program.rb new file mode 100644 index 0000000..a4d9168 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/find_method.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/find_method.rb new file mode 100644 index 0000000..c1ee2c5 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/fix_indent.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/fix_indent.rb new file mode 100644 index 0000000..75c48c7 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/gem_cd.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/gem_cd.rb new file mode 100644 index 0000000..da1907a --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/gem_install.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/gem_install.rb new file mode 100644 index 0000000..873e106 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/gem_list.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/gem_list.rb new file mode 100644 index 0000000..e4a5d00 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/gem_open.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/gem_open.rb new file mode 100644 index 0000000..e21723a --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/gist.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/gist.rb new file mode 100644 index 0000000..83cdf2b --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/help.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/help.rb new file mode 100644 index 0000000..3f29c2c --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/hist.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/hist.rb new file mode 100644 index 0000000..083d3f5 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/import_set.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/import_set.rb new file mode 100644 index 0000000..5689883 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/install_command.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/install_command.rb new file mode 100644 index 0000000..acafe7b --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/jump_to.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/jump_to.rb new file mode 100644 index 0000000..4179fc7 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/list_inspectors.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/list_inspectors.rb new file mode 100644 index 0000000..c96c395 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/list_prompts.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/list_prompts.rb new file mode 100644 index 0000000..436f719 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/ls.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/ls.rb new file mode 100644 index 0000000..9f0e68f --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/ls/constants.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/ls/constants.rb new file mode 100644 index 0000000..3db8162 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/ls/formatter.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/ls/formatter.rb new file mode 100644 index 0000000..9ad117a --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/ls/globals.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/ls/globals.rb new file mode 100644 index 0000000..2b3d0fd --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/ls/grep.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/ls/grep.rb new file mode 100644 index 0000000..14e6b00 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/ls/instance_vars.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/ls/instance_vars.rb new file mode 100644 index 0000000..2f33677 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/ls/interrogatable.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/ls/interrogatable.rb new file mode 100644 index 0000000..5904d1b --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/ls/jruby_hacks.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/ls/jruby_hacks.rb new file mode 100644 index 0000000..0f73e08 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/ls/local_names.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/ls/local_names.rb new file mode 100644 index 0000000..9d6350b --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/ls/local_vars.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/ls/local_vars.rb new file mode 100644 index 0000000..d48ddae --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/ls/ls_entity.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/ls/ls_entity.rb new file mode 100644 index 0000000..3d69bcd --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/ls/methods.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/ls/methods.rb new file mode 100644 index 0000000..c085f42 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/ls/methods_helper.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/ls/methods_helper.rb new file mode 100644 index 0000000..f0b4414 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/ls/self_methods.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/ls/self_methods.rb new file mode 100644 index 0000000..91f3490 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/nesting.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/nesting.rb new file mode 100644 index 0000000..f9c0297 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/play.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/play.rb new file mode 100644 index 0000000..5498d38 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/pry_backtrace.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/pry_backtrace.rb new file mode 100644 index 0000000..6795aa3 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/pry_version.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/pry_version.rb new file mode 100644 index 0000000..8cb8fd8 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/raise_up.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/raise_up.rb new file mode 100644 index 0000000..70ad087 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/reload_code.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/reload_code.rb new file mode 100644 index 0000000..7041338 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/reset.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/reset.rb new file mode 100644 index 0000000..4414cbb --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/ri.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/ri.rb new file mode 100644 index 0000000..d29c426 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/save_file.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/save_file.rb new file mode 100644 index 0000000..d22a692 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/shell_command.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/shell_command.rb new file mode 100644 index 0000000..78fccd5 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/shell_mode.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/shell_mode.rb new file mode 100644 index 0000000..ee521d3 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/show_doc.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/show_doc.rb new file mode 100644 index 0000000..4969bcd --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/show_info.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/show_info.rb new file mode 100644 index 0000000..92958cb --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/show_input.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/show_input.rb new file mode 100644 index 0000000..8b72787 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/show_source.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/show_source.rb new file mode 100644 index 0000000..f8e3a5b --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/simple_prompt.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/simple_prompt.rb new file mode 100644 index 0000000..4d1e6ec --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/stat.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/stat.rb new file mode 100644 index 0000000..06a191b --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/switch_to.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/switch_to.rb new file mode 100644 index 0000000..ad3e71c --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/toggle_color.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/toggle_color.rb new file mode 100644 index 0000000..602c293 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/watch_expression.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/watch_expression.rb new file mode 100644 index 0000000..d93b7c7 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/watch_expression/expression.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/watch_expression/expression.rb new file mode 100644 index 0000000..514b95d --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/whereami.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/whereami.rb new file mode 100644 index 0000000..ac70164 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/commands/wtf.rb b/.bundle/gems/pry-0.10.1/lib/pry/commands/wtf.rb new file mode 100644 index 0000000..2d47dfa --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/config.rb b/.bundle/gems/pry-0.10.1/lib/pry/config.rb new file mode 100644 index 0000000..73b7742 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/config/behavior.rb b/.bundle/gems/pry-0.10.1/lib/pry/config/behavior.rb new file mode 100644 index 0000000..d2669dd --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/config/convenience.rb b/.bundle/gems/pry-0.10.1/lib/pry/config/convenience.rb new file mode 100644 index 0000000..ddd39f4 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/config/default.rb b/.bundle/gems/pry-0.10.1/lib/pry/config/default.rb new file mode 100644 index 0000000..db4d8aa --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/core_extensions.rb b/.bundle/gems/pry-0.10.1/lib/pry/core_extensions.rb new file mode 100644 index 0000000..a418daf --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/editor.rb b/.bundle/gems/pry-0.10.1/lib/pry/editor.rb new file mode 100644 index 0000000..43e649f --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/exceptions.rb b/.bundle/gems/pry-0.10.1/lib/pry/exceptions.rb new file mode 100644 index 0000000..0204d84 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/lib/pry/exceptions.rb @@ -0,0 +1,77 @@ +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", + ].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.1/lib/pry/helpers.rb b/.bundle/gems/pry-0.10.1/lib/pry/helpers.rb new file mode 100644 index 0000000..f59c308 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/helpers/base_helpers.rb b/.bundle/gems/pry-0.10.1/lib/pry/helpers/base_helpers.rb new file mode 100644 index 0000000..5dade46 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/helpers/command_helpers.rb b/.bundle/gems/pry-0.10.1/lib/pry/helpers/command_helpers.rb new file mode 100644 index 0000000..7f7e226 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/helpers/documentation_helpers.rb b/.bundle/gems/pry-0.10.1/lib/pry/helpers/documentation_helpers.rb new file mode 100644 index 0000000..9f9870e --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/helpers/options_helpers.rb b/.bundle/gems/pry-0.10.1/lib/pry/helpers/options_helpers.rb new file mode 100644 index 0000000..e566d3b --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/helpers/table.rb b/.bundle/gems/pry-0.10.1/lib/pry/helpers/table.rb new file mode 100644 index 0000000..56e7e59 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/helpers/text.rb b/.bundle/gems/pry-0.10.1/lib/pry/helpers/text.rb new file mode 100644 index 0000000..13867cf --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/history.rb b/.bundle/gems/pry-0.10.1/lib/pry/history.rb new file mode 100644 index 0000000..81b7417 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/history_array.rb b/.bundle/gems/pry-0.10.1/lib/pry/history_array.rb new file mode 100644 index 0000000..60e41bc --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/hooks.rb b/.bundle/gems/pry-0.10.1/lib/pry/hooks.rb new file mode 100644 index 0000000..48291ee --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/indent.rb b/.bundle/gems/pry-0.10.1/lib/pry/indent.rb new file mode 100644 index 0000000..72fbf69 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/input_completer.rb b/.bundle/gems/pry-0.10.1/lib/pry/input_completer.rb new file mode 100644 index 0000000..363baa4 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/input_lock.rb b/.bundle/gems/pry-0.10.1/lib/pry/input_lock.rb new file mode 100644 index 0000000..8adfed4 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/inspector.rb b/.bundle/gems/pry-0.10.1/lib/pry/inspector.rb new file mode 100644 index 0000000..c56b02f --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/last_exception.rb b/.bundle/gems/pry-0.10.1/lib/pry/last_exception.rb new file mode 100644 index 0000000..2841113 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/method.rb b/.bundle/gems/pry-0.10.1/lib/pry/method.rb new file mode 100644 index 0000000..03eb60a --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/method/disowned.rb b/.bundle/gems/pry-0.10.1/lib/pry/method/disowned.rb new file mode 100644 index 0000000..35908c9 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/method/patcher.rb b/.bundle/gems/pry-0.10.1/lib/pry/method/patcher.rb new file mode 100644 index 0000000..3f736f6 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/method/weird_method_locator.rb b/.bundle/gems/pry-0.10.1/lib/pry/method/weird_method_locator.rb new file mode 100644 index 0000000..a668d16 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/lib/pry/method/weird_method_locator.rb @@ -0,0 +1,186 @@ +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 + else + guess = guess.super + 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.1/lib/pry/module_candidate.rb b/.bundle/gems/pry-0.10.1/lib/pry/module_candidate.rb new file mode 100644 index 0000000..4c97f13 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/object_path.rb b/.bundle/gems/pry-0.10.1/lib/pry/object_path.rb new file mode 100644 index 0000000..5bffb02 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/output.rb b/.bundle/gems/pry-0.10.1/lib/pry/output.rb new file mode 100644 index 0000000..b5f6bb3 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/pager.rb b/.bundle/gems/pry-0.10.1/lib/pry/pager.rb new file mode 100644 index 0000000..e5451d2 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/plugins.rb b/.bundle/gems/pry-0.10.1/lib/pry/plugins.rb new file mode 100644 index 0000000..1d05195 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/prompt.rb b/.bundle/gems/pry-0.10.1/lib/pry/prompt.rb new file mode 100644 index 0000000..62f0bc1 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/pry_class.rb b/.bundle/gems/pry-0.10.1/lib/pry/pry_class.rb new file mode 100644 index 0000000..69f68e4 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/pry_instance.rb b/.bundle/gems/pry-0.10.1/lib/pry/pry_instance.rb new file mode 100644 index 0000000..0877ab2 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/rbx_path.rb b/.bundle/gems/pry-0.10.1/lib/pry/rbx_path.rb new file mode 100644 index 0000000..bd969c6 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/repl.rb b/.bundle/gems/pry-0.10.1/lib/pry/repl.rb new file mode 100644 index 0000000..4748785 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/repl_file_loader.rb b/.bundle/gems/pry-0.10.1/lib/pry/repl_file_loader.rb new file mode 100644 index 0000000..cd8de9a --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/rubygem.rb b/.bundle/gems/pry-0.10.1/lib/pry/rubygem.rb new file mode 100644 index 0000000..36f788d --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/terminal.rb b/.bundle/gems/pry-0.10.1/lib/pry/terminal.rb new file mode 100644 index 0000000..d04f7bd --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/test/helper.rb b/.bundle/gems/pry-0.10.1/lib/pry/test/helper.rb new file mode 100644 index 0000000..8ddf144 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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.1/lib/pry/version.rb b/.bundle/gems/pry-0.10.1/lib/pry/version.rb new file mode 100644 index 0000000..547171e --- /dev/null +++ b/.bundle/gems/pry-0.10.1/lib/pry/version.rb @@ -0,0 +1,3 @@ +class Pry + VERSION = "0.10.1" +end diff --git a/.bundle/gems/pry-0.10.1/lib/pry/wrapped_module.rb b/.bundle/gems/pry-0.10.1/lib/pry/wrapped_module.rb new file mode 100644 index 0000000..bfa5793 --- /dev/null +++ b/.bundle/gems/pry-0.10.1/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#