rspec-core 3.3.2 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - checksums.yaml.gz.sig +0 -0
 - data.tar.gz.sig +0 -0
 - data/.document +1 -1
 - data/.yardopts +1 -1
 - data/Changelog.md +69 -0
 - data/{License.txt → LICENSE.md} +6 -5
 - data/README.md +18 -3
 - data/lib/rspec/core/bisect/example_minimizer.rb +78 -39
 - data/lib/rspec/core/configuration.rb +87 -25
 - data/lib/rspec/core/configuration_options.rb +1 -1
 - data/lib/rspec/core/example.rb +54 -7
 - data/lib/rspec/core/example_group.rb +28 -8
 - data/lib/rspec/core/example_status_persister.rb +16 -16
 - data/lib/rspec/core/formatters.rb +1 -0
 - data/lib/rspec/core/formatters/bisect_progress_formatter.rb +44 -15
 - data/lib/rspec/core/formatters/exception_presenter.rb +146 -59
 - data/lib/rspec/core/formatters/helpers.rb +1 -1
 - data/lib/rspec/core/formatters/html_formatter.rb +2 -2
 - data/lib/rspec/core/formatters/html_printer.rb +2 -3
 - data/lib/rspec/core/formatters/html_snippet_extractor.rb +116 -0
 - data/lib/rspec/core/formatters/protocol.rb +9 -0
 - data/lib/rspec/core/formatters/snippet_extractor.rb +124 -97
 - data/lib/rspec/core/hooks.rb +2 -2
 - data/lib/rspec/core/memoized_helpers.rb +2 -2
 - data/lib/rspec/core/metadata.rb +3 -2
 - data/lib/rspec/core/metadata_filter.rb +11 -6
 - data/lib/rspec/core/notifications.rb +3 -2
 - data/lib/rspec/core/option_parser.rb +22 -4
 - data/lib/rspec/core/project_initializer/spec/spec_helper.rb +2 -2
 - data/lib/rspec/core/rake_task.rb +12 -3
 - data/lib/rspec/core/reporter.rb +18 -2
 - data/lib/rspec/core/ruby_project.rb +1 -1
 - data/lib/rspec/core/shared_example_group.rb +2 -0
 - data/lib/rspec/core/source.rb +76 -0
 - data/lib/rspec/core/source/location.rb +13 -0
 - data/lib/rspec/core/source/node.rb +93 -0
 - data/lib/rspec/core/source/syntax_highlighter.rb +71 -0
 - data/lib/rspec/core/source/token.rb +43 -0
 - data/lib/rspec/core/version.rb +1 -1
 - data/lib/rspec/core/world.rb +25 -6
 - metadata +12 -9
 - metadata.gz.sig +0 -0
 - data/lib/rspec/core/bisect/subset_enumerator.rb +0 -39
 - data/lib/rspec/core/mutex.rb +0 -63
 - data/lib/rspec/core/reentrant_mutex.rb +0 -52
 
    
        data/lib/rspec/core/metadata.rb
    CHANGED
    
    | 
         @@ -147,12 +147,13 @@ module RSpec 
     | 
|
| 
       147 
147 
     | 
    
         
             
                                               end
         
     | 
| 
       148 
148 
     | 
    
         | 
| 
       149 
149 
     | 
    
         
             
                      relative_file_path            = Metadata.relative_path(file_path)
         
     | 
| 
      
 150 
     | 
    
         
            +
                      absolute_file_path            = File.expand_path(relative_file_path)
         
     | 
| 
       150 
151 
     | 
    
         
             
                      metadata[:file_path]          = relative_file_path
         
     | 
| 
       151 
152 
     | 
    
         
             
                      metadata[:line_number]        = line_number.to_i
         
     | 
| 
       152 
153 
     | 
    
         
             
                      metadata[:location]           = "#{relative_file_path}:#{line_number}"
         
     | 
| 
       153 
     | 
    
         
            -
                      metadata[:absolute_file_path] =  
     | 
| 
      
 154 
     | 
    
         
            +
                      metadata[:absolute_file_path] = absolute_file_path
         
     | 
| 
       154 
155 
     | 
    
         
             
                      metadata[:rerun_file_path]  ||= relative_file_path
         
     | 
| 
       155 
     | 
    
         
            -
                      metadata[:scoped_id]          = build_scoped_id_for( 
     | 
| 
      
 156 
     | 
    
         
            +
                      metadata[:scoped_id]          = build_scoped_id_for(absolute_file_path)
         
     | 
| 
       156 
157 
     | 
    
         
             
                    end
         
     | 
| 
       157 
158 
     | 
    
         | 
| 
       158 
159 
     | 
    
         
             
                    def file_path_and_line_number_from(backtrace)
         
     | 
| 
         @@ -15,22 +15,19 @@ module RSpec 
     | 
|
| 
       15 
15 
     | 
    
         
             
                    # @private
         
     | 
| 
       16 
16 
     | 
    
         
             
                    def filter_applies?(key, value, metadata)
         
     | 
| 
       17 
17 
     | 
    
         
             
                      silence_metadata_example_group_deprecations do
         
     | 
| 
       18 
     | 
    
         
            -
                        return filter_applies_to_any_value?(key, value, metadata) if Array === metadata[key] && !(Proc === value)
         
     | 
| 
       19 
18 
     | 
    
         
             
                        return location_filter_applies?(value, metadata)          if key == :locations
         
     | 
| 
       20 
19 
     | 
    
         
             
                        return id_filter_applies?(value, metadata)                if key == :ids
         
     | 
| 
       21 
20 
     | 
    
         
             
                        return filters_apply?(key, value, metadata)               if Hash === value
         
     | 
| 
       22 
21 
     | 
    
         | 
| 
       23 
22 
     | 
    
         
             
                        return false unless metadata.key?(key)
         
     | 
| 
      
 23 
     | 
    
         
            +
                        return true if TrueClass === value && !!metadata[key]
         
     | 
| 
      
 24 
     | 
    
         
            +
                        return filter_applies_to_any_value?(key, value, metadata) if Array === metadata[key] && !(Proc === value)
         
     | 
| 
       24 
25 
     | 
    
         | 
| 
       25 
26 
     | 
    
         
             
                        case value
         
     | 
| 
       26 
27 
     | 
    
         
             
                        when Regexp
         
     | 
| 
       27 
28 
     | 
    
         
             
                          metadata[key] =~ value
         
     | 
| 
       28 
29 
     | 
    
         
             
                        when Proc
         
     | 
| 
       29 
     | 
    
         
            -
                           
     | 
| 
       30 
     | 
    
         
            -
                          when 0 then value.call
         
     | 
| 
       31 
     | 
    
         
            -
                          when 2 then value.call(metadata[key], metadata)
         
     | 
| 
       32 
     | 
    
         
            -
                          else value.call(metadata[key])
         
     | 
| 
       33 
     | 
    
         
            -
                          end
         
     | 
| 
      
 30 
     | 
    
         
            +
                          proc_filter_applies?(key, value, metadata)
         
     | 
| 
       34 
31 
     | 
    
         
             
                        else
         
     | 
| 
       35 
32 
     | 
    
         
             
                          metadata[key].to_s == value.to_s
         
     | 
| 
       36 
33 
     | 
    
         
             
                        end
         
     | 
| 
         @@ -61,6 +58,14 @@ module RSpec 
     | 
|
| 
       61 
58 
     | 
    
         
             
                      !(relevant_line_numbers(metadata) & preceding_declaration_lines).empty?
         
     | 
| 
       62 
59 
     | 
    
         
             
                    end
         
     | 
| 
       63 
60 
     | 
    
         | 
| 
      
 61 
     | 
    
         
            +
                    def proc_filter_applies?(key, proc, metadata)
         
     | 
| 
      
 62 
     | 
    
         
            +
                      case proc.arity
         
     | 
| 
      
 63 
     | 
    
         
            +
                      when 0 then proc.call
         
     | 
| 
      
 64 
     | 
    
         
            +
                      when 2 then proc.call(metadata[key], metadata)
         
     | 
| 
      
 65 
     | 
    
         
            +
                      else proc.call(metadata[key])
         
     | 
| 
      
 66 
     | 
    
         
            +
                      end
         
     | 
| 
      
 67 
     | 
    
         
            +
                    end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
       64 
69 
     | 
    
         
             
                    def relevant_line_numbers(metadata)
         
     | 
| 
       65 
70 
     | 
    
         
             
                      Metadata.ascend(metadata).map { |meta| meta[:line_number] }
         
     | 
| 
       66 
71 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -1,7 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            RSpec::Support.require_rspec_core "formatters/exception_presenter"
         
     | 
| 
       2 
2 
     | 
    
         
             
            RSpec::Support.require_rspec_core "formatters/helpers"
         
     | 
| 
       3 
3 
     | 
    
         
             
            RSpec::Support.require_rspec_core "shell_escape"
         
     | 
| 
       4 
     | 
    
         
            -
            RSpec::Support.require_rspec_support "encoded_string"
         
     | 
| 
       5 
4 
     | 
    
         | 
| 
       6 
5 
     | 
    
         
             
            module RSpec::Core
         
     | 
| 
       7 
6 
     | 
    
         
             
              # Notifications are value objects passed to formatters to provide them
         
     | 
| 
         @@ -10,6 +9,7 @@ module RSpec::Core 
     | 
|
| 
       10 
9 
     | 
    
         
             
                # @private
         
     | 
| 
       11 
10 
     | 
    
         
             
                module NullColorizer
         
     | 
| 
       12 
11 
     | 
    
         
             
                  module_function
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
       13 
13 
     | 
    
         
             
                  def wrap(line, _code_or_symbol)
         
     | 
| 
       14 
14 
     | 
    
         
             
                    line
         
     | 
| 
       15 
15 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -281,7 +281,8 @@ module RSpec::Core 
     | 
|
| 
       281 
281 
     | 
    
         
             
                # @attr pending_examples [Array<RSpec::Core::Example>] the pending examples
         
     | 
| 
       282 
282 
     | 
    
         
             
                # @attr load_time [Float] the number of seconds taken to boot RSpec
         
     | 
| 
       283 
283 
     | 
    
         
             
                #                         and load the spec files
         
     | 
| 
       284 
     | 
    
         
            -
                SummaryNotification = Struct.new(:duration, :examples, :failed_examples, 
     | 
| 
      
 284 
     | 
    
         
            +
                SummaryNotification = Struct.new(:duration, :examples, :failed_examples,
         
     | 
| 
      
 285 
     | 
    
         
            +
                                                 :pending_examples, :load_time)
         
     | 
| 
       285 
286 
     | 
    
         
             
                class SummaryNotification
         
     | 
| 
       286 
287 
     | 
    
         
             
                  # @api
         
     | 
| 
       287 
288 
     | 
    
         
             
                  # @return [Fixnum] the number of examples run
         
     | 
| 
         @@ -34,6 +34,8 @@ module RSpec::Core 
     | 
|
| 
       34 
34 
     | 
    
         
             
              private
         
     | 
| 
       35 
35 
     | 
    
         | 
| 
       36 
36 
     | 
    
         
             
                # rubocop:disable MethodLength
         
     | 
| 
      
 37 
     | 
    
         
            +
                # rubocop:disable Metrics/AbcSize
         
     | 
| 
      
 38 
     | 
    
         
            +
                # rubocop:disable CyclomaticComplexity
         
     | 
| 
       37 
39 
     | 
    
         
             
                def parser(options)
         
     | 
| 
       38 
40 
     | 
    
         
             
                  OptionParser.new do |parser|
         
     | 
| 
       39 
41 
     | 
    
         
             
                    parser.banner = "Usage: rspec [options] [files or directories]\n\n"
         
     | 
| 
         @@ -69,7 +71,18 @@ module RSpec::Core 
     | 
|
| 
       69 
71 
     | 
    
         
             
                      bisect_and_exit(argument)
         
     | 
| 
       70 
72 
     | 
    
         
             
                    end
         
     | 
| 
       71 
73 
     | 
    
         | 
| 
       72 
     | 
    
         
            -
                    parser.on('--[no-]fail-fast', 'Abort the run  
     | 
| 
      
 74 
     | 
    
         
            +
                    parser.on('--[no-]fail-fast[=COUNT]', 'Abort the run after a certain number of failures (1 by default).') do |argument|
         
     | 
| 
      
 75 
     | 
    
         
            +
                      if argument == true
         
     | 
| 
      
 76 
     | 
    
         
            +
                        value = 1
         
     | 
| 
      
 77 
     | 
    
         
            +
                      elsif argument == false || argument == 0
         
     | 
| 
      
 78 
     | 
    
         
            +
                        value = false
         
     | 
| 
      
 79 
     | 
    
         
            +
                      else
         
     | 
| 
      
 80 
     | 
    
         
            +
                        begin
         
     | 
| 
      
 81 
     | 
    
         
            +
                          value = Integer(argument)
         
     | 
| 
      
 82 
     | 
    
         
            +
                        rescue ArgumentError
         
     | 
| 
      
 83 
     | 
    
         
            +
                          RSpec.warning "Expected an integer value for `--fail-fast`, got: #{argument.inspect}", :call_site => nil
         
     | 
| 
      
 84 
     | 
    
         
            +
                        end
         
     | 
| 
      
 85 
     | 
    
         
            +
                      end
         
     | 
| 
       73 
86 
     | 
    
         
             
                      set_fail_fast(options, value)
         
     | 
| 
       74 
87 
     | 
    
         
             
                    end
         
     | 
| 
       75 
88 
     | 
    
         | 
| 
         @@ -174,12 +187,16 @@ FILTERING 
     | 
|
| 
       174 
187 
     | 
    
         
             
                    parser.on("--next-failure", "Apply `--only-failures` and abort after one failure.",
         
     | 
| 
       175 
188 
     | 
    
         
             
                              "  (Equivalent to `--only-failures --fail-fast --order defined`)") do
         
     | 
| 
       176 
189 
     | 
    
         
             
                      configure_only_failures(options)
         
     | 
| 
       177 
     | 
    
         
            -
                      set_fail_fast(options,  
     | 
| 
      
 190 
     | 
    
         
            +
                      set_fail_fast(options, 1)
         
     | 
| 
       178 
191 
     | 
    
         
             
                      options[:order] ||= 'defined'
         
     | 
| 
       179 
192 
     | 
    
         
             
                    end
         
     | 
| 
       180 
193 
     | 
    
         | 
| 
       181 
194 
     | 
    
         
             
                    parser.on('-P', '--pattern PATTERN', 'Load files matching pattern (default: "spec/**/*_spec.rb").') do |o|
         
     | 
| 
       182 
     | 
    
         
            -
                      options[:pattern] 
     | 
| 
      
 195 
     | 
    
         
            +
                      if options[:pattern]
         
     | 
| 
      
 196 
     | 
    
         
            +
                        options[:pattern] += ',' + o
         
     | 
| 
      
 197 
     | 
    
         
            +
                      else
         
     | 
| 
      
 198 
     | 
    
         
            +
                        options[:pattern] = o
         
     | 
| 
      
 199 
     | 
    
         
            +
                      end
         
     | 
| 
       183 
200 
     | 
    
         
             
                    end
         
     | 
| 
       184 
201 
     | 
    
         | 
| 
       185 
202 
     | 
    
         
             
                    parser.on('--exclude-pattern PATTERN',
         
     | 
| 
         @@ -246,10 +263,11 @@ FILTERING 
     | 
|
| 
       246 
263 
     | 
    
         
             
                        raise OptionParser::InvalidOption.new
         
     | 
| 
       247 
264 
     | 
    
         
             
                      end
         
     | 
| 
       248 
265 
     | 
    
         
             
                    end
         
     | 
| 
       249 
     | 
    
         
            -
             
     | 
| 
       250 
266 
     | 
    
         
             
                  end
         
     | 
| 
       251 
267 
     | 
    
         
             
                end
         
     | 
| 
      
 268 
     | 
    
         
            +
                # rubocop:enable Metrics/AbcSize
         
     | 
| 
       252 
269 
     | 
    
         
             
                # rubocop:enable MethodLength
         
     | 
| 
      
 270 
     | 
    
         
            +
                # rubocop:enable CyclomaticComplexity
         
     | 
| 
       253 
271 
     | 
    
         | 
| 
       254 
272 
     | 
    
         
             
                def add_tag_filter(options, filter_type, tag_name, value=true)
         
     | 
| 
       255 
273 
     | 
    
         
             
                  (options[filter_type] ||= {})[tag_name] = value
         
     | 
| 
         @@ -57,9 +57,9 @@ RSpec.configure do |config| 
     | 
|
| 
       57 
57 
     | 
    
         | 
| 
       58 
58 
     | 
    
         
             
              # Limits the available syntax to the non-monkey patched syntax that is
         
     | 
| 
       59 
59 
     | 
    
         
             
              # recommended. For more details, see:
         
     | 
| 
       60 
     | 
    
         
            -
              #   - http:// 
     | 
| 
      
 60 
     | 
    
         
            +
              #   - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
         
     | 
| 
       61 
61 
     | 
    
         
             
              #   - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
         
     | 
| 
       62 
     | 
    
         
            -
              #   - http:// 
     | 
| 
      
 62 
     | 
    
         
            +
              #   - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
         
     | 
| 
       63 
63 
     | 
    
         
             
              config.disable_monkey_patching!
         
     | 
| 
       64 
64 
     | 
    
         | 
| 
       65 
65 
     | 
    
         
             
              # This setting enables warnings. It's recommended, but in some cases may
         
     | 
    
        data/lib/rspec/core/rake_task.rb
    CHANGED
    
    | 
         @@ -1,7 +1,16 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'rake'
         
     | 
| 
       2 
2 
     | 
    
         
             
            require 'rake/tasklib'
         
     | 
| 
       3 
     | 
    
         
            -
            require 'rspec/support 
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'rspec/support'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            RSpec::Support.require_rspec_support "ruby_features"
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            # :nocov:
         
     | 
| 
      
 8 
     | 
    
         
            +
            unless RSpec::Support.respond_to?(:require_rspec_core)
         
     | 
| 
      
 9 
     | 
    
         
            +
              RSpec::Support.define_optimized_require_for_rspec(:core) { |f| require_relative "../#{f}" }
         
     | 
| 
      
 10 
     | 
    
         
            +
            end
         
     | 
| 
      
 11 
     | 
    
         
            +
            # :nocov:
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            RSpec::Support.require_rspec_core "shell_escape"
         
     | 
| 
       5 
14 
     | 
    
         | 
| 
       6 
15 
     | 
    
         
             
            module RSpec
         
     | 
| 
       7 
16 
     | 
    
         
             
              module Core
         
     | 
| 
         @@ -91,7 +100,7 @@ module RSpec 
     | 
|
| 
       91 
100 
     | 
    
         | 
| 
       92 
101 
     | 
    
         
             
                  def file_inclusion_specification
         
     | 
| 
       93 
102 
     | 
    
         
             
                    if ENV['SPEC']
         
     | 
| 
       94 
     | 
    
         
            -
                      FileList[ 
     | 
| 
      
 103 
     | 
    
         
            +
                      FileList[ENV['SPEC']].sort
         
     | 
| 
       95 
104 
     | 
    
         
             
                    elsif String === pattern && !File.exist?(pattern)
         
     | 
| 
       96 
105 
     | 
    
         
             
                      "--pattern #{escape pattern}"
         
     | 
| 
       97 
106 
     | 
    
         
             
                    else
         
     | 
    
        data/lib/rspec/core/reporter.rb
    CHANGED
    
    | 
         @@ -8,7 +8,7 @@ module RSpec::Core 
     | 
|
| 
       8 
8 
     | 
    
         
             
                    :close, :deprecation, :deprecation_summary, :dump_failures, :dump_pending,
         
     | 
| 
       9 
9 
     | 
    
         
             
                    :dump_profile, :dump_summary, :example_failed, :example_group_finished,
         
     | 
| 
       10 
10 
     | 
    
         
             
                    :example_group_started, :example_passed, :example_pending, :example_started,
         
     | 
| 
       11 
     | 
    
         
            -
                    :message, :seed, :start, :start_dump, :stop
         
     | 
| 
      
 11 
     | 
    
         
            +
                    :message, :seed, :start, :start_dump, :stop, :example_finished
         
     | 
| 
       12 
12 
     | 
    
         
             
                  ])
         
     | 
| 
       13 
13 
     | 
    
         | 
| 
       14 
14 
     | 
    
         
             
                def initialize(configuration)
         
     | 
| 
         @@ -124,6 +124,11 @@ module RSpec::Core 
     | 
|
| 
       124 
124 
     | 
    
         
             
                  notify :example_started, Notifications::ExampleNotification.for(example)
         
     | 
| 
       125 
125 
     | 
    
         
             
                end
         
     | 
| 
       126 
126 
     | 
    
         | 
| 
      
 127 
     | 
    
         
            +
                # @private
         
     | 
| 
      
 128 
     | 
    
         
            +
                def example_finished(example)
         
     | 
| 
      
 129 
     | 
    
         
            +
                  notify :example_finished, Notifications::ExampleNotification.for(example)
         
     | 
| 
      
 130 
     | 
    
         
            +
                end
         
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
       127 
132 
     | 
    
         
             
                # @private
         
     | 
| 
       128 
133 
     | 
    
         
             
                def example_passed(example)
         
     | 
| 
       129 
134 
     | 
    
         
             
                  notify :example_passed, Notifications::ExampleNotification.for(example)
         
     | 
| 
         @@ -192,6 +197,17 @@ module RSpec::Core 
     | 
|
| 
       192 
197 
     | 
    
         
             
                  exit!(exit_status)
         
     | 
| 
       193 
198 
     | 
    
         
             
                end
         
     | 
| 
       194 
199 
     | 
    
         | 
| 
      
 200 
     | 
    
         
            +
                # @private
         
     | 
| 
      
 201 
     | 
    
         
            +
                def fail_fast_limit_met?
         
     | 
| 
      
 202 
     | 
    
         
            +
                  return false unless (fail_fast = @configuration.fail_fast)
         
     | 
| 
      
 203 
     | 
    
         
            +
             
     | 
| 
      
 204 
     | 
    
         
            +
                  if fail_fast == true
         
     | 
| 
      
 205 
     | 
    
         
            +
                    @failed_examples.any?
         
     | 
| 
      
 206 
     | 
    
         
            +
                  else
         
     | 
| 
      
 207 
     | 
    
         
            +
                    fail_fast <= @failed_examples.size
         
     | 
| 
      
 208 
     | 
    
         
            +
                  end
         
     | 
| 
      
 209 
     | 
    
         
            +
                end
         
     | 
| 
      
 210 
     | 
    
         
            +
             
     | 
| 
       195 
211 
     | 
    
         
             
              private
         
     | 
| 
       196 
212 
     | 
    
         | 
| 
       197 
213 
     | 
    
         
             
                def close
         
     | 
| 
         @@ -201,7 +217,7 @@ module RSpec::Core 
     | 
|
| 
       201 
217 
     | 
    
         
             
                def mute_profile_output?
         
     | 
| 
       202 
218 
     | 
    
         
             
                  # Don't print out profiled info if there are failures and `--fail-fast` is
         
     | 
| 
       203 
219 
     | 
    
         
             
                  # used, it just clutters the output.
         
     | 
| 
       204 
     | 
    
         
            -
                  !@configuration.profile_examples? ||  
     | 
| 
      
 220 
     | 
    
         
            +
                  !@configuration.profile_examples? || fail_fast_limit_met?
         
     | 
| 
       205 
221 
     | 
    
         
             
                end
         
     | 
| 
       206 
222 
     | 
    
         | 
| 
       207 
223 
     | 
    
         
             
                def seed_used?
         
     | 
| 
         @@ -96,6 +96,7 @@ module RSpec 
     | 
|
| 
       96 
96 
     | 
    
         
             
                  # Shared examples top level DSL.
         
     | 
| 
       97 
97 
     | 
    
         
             
                  module TopLevelDSL
         
     | 
| 
       98 
98 
     | 
    
         
             
                    # @private
         
     | 
| 
      
 99 
     | 
    
         
            +
                    # rubocop:disable Lint/NestedMethodDefinition
         
     | 
| 
       99 
100 
     | 
    
         
             
                    def self.definitions
         
     | 
| 
       100 
101 
     | 
    
         
             
                      proc do
         
     | 
| 
       101 
102 
     | 
    
         
             
                        def shared_examples(name, *args, &block)
         
     | 
| 
         @@ -105,6 +106,7 @@ module RSpec 
     | 
|
| 
       105 
106 
     | 
    
         
             
                        alias shared_examples_for shared_examples
         
     | 
| 
       106 
107 
     | 
    
         
             
                      end
         
     | 
| 
       107 
108 
     | 
    
         
             
                    end
         
     | 
| 
      
 109 
     | 
    
         
            +
                    # rubocop:enable Lint/NestedMethodDefinition
         
     | 
| 
       108 
110 
     | 
    
         | 
| 
       109 
111 
     | 
    
         
             
                    # @private
         
     | 
| 
       110 
112 
     | 
    
         
             
                    def self.exposed_globally?
         
     | 
| 
         @@ -0,0 +1,76 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            RSpec::Support.require_rspec_core 'source/node'
         
     | 
| 
      
 2 
     | 
    
         
            +
            RSpec::Support.require_rspec_core 'source/syntax_highlighter'
         
     | 
| 
      
 3 
     | 
    
         
            +
            RSpec::Support.require_rspec_core 'source/token'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module RSpec
         
     | 
| 
      
 6 
     | 
    
         
            +
              module Core
         
     | 
| 
      
 7 
     | 
    
         
            +
                # @private
         
     | 
| 
      
 8 
     | 
    
         
            +
                # Represents a Ruby source file and provides access to AST and tokens.
         
     | 
| 
      
 9 
     | 
    
         
            +
                class Source
         
     | 
| 
      
 10 
     | 
    
         
            +
                  attr_reader :source, :path
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def self.from_file(path)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    source = File.read(path)
         
     | 
| 
      
 14 
     | 
    
         
            +
                    new(source, path)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  def initialize(source_string, path=nil)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    @source = source_string
         
     | 
| 
      
 19 
     | 
    
         
            +
                    @path = path ? File.expand_path(path) : '(string)'
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  def lines
         
     | 
| 
      
 23 
     | 
    
         
            +
                    @lines ||= source.split("\n")
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  def ast
         
     | 
| 
      
 27 
     | 
    
         
            +
                    @ast ||= begin
         
     | 
| 
      
 28 
     | 
    
         
            +
                      require 'ripper'
         
     | 
| 
      
 29 
     | 
    
         
            +
                      sexp = Ripper.sexp(source)
         
     | 
| 
      
 30 
     | 
    
         
            +
                      raise SyntaxError unless sexp
         
     | 
| 
      
 31 
     | 
    
         
            +
                      Node.new(sexp)
         
     | 
| 
      
 32 
     | 
    
         
            +
                    end
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  def tokens
         
     | 
| 
      
 36 
     | 
    
         
            +
                    @tokens ||= begin
         
     | 
| 
      
 37 
     | 
    
         
            +
                      require 'ripper'
         
     | 
| 
      
 38 
     | 
    
         
            +
                      tokens = Ripper.lex(source)
         
     | 
| 
      
 39 
     | 
    
         
            +
                      Token.tokens_from_ripper_tokens(tokens)
         
     | 
| 
      
 40 
     | 
    
         
            +
                    end
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                  def nodes_by_line_number
         
     | 
| 
      
 44 
     | 
    
         
            +
                    @nodes_by_line_number ||= begin
         
     | 
| 
      
 45 
     | 
    
         
            +
                      nodes_by_line_number = ast.select(&:location).group_by { |node| node.location.line }
         
     | 
| 
      
 46 
     | 
    
         
            +
                      Hash.new { |hash, key| hash[key] = [] }.merge(nodes_by_line_number)
         
     | 
| 
      
 47 
     | 
    
         
            +
                    end
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                  def tokens_by_line_number
         
     | 
| 
      
 51 
     | 
    
         
            +
                    @tokens_by_line_number ||= begin
         
     | 
| 
      
 52 
     | 
    
         
            +
                      nodes_by_line_number = tokens.group_by { |token| token.location.line }
         
     | 
| 
      
 53 
     | 
    
         
            +
                      Hash.new { |hash, key| hash[key] = [] }.merge(nodes_by_line_number)
         
     | 
| 
      
 54 
     | 
    
         
            +
                    end
         
     | 
| 
      
 55 
     | 
    
         
            +
                  end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                  def inspect
         
     | 
| 
      
 58 
     | 
    
         
            +
                    "#<#{self.class} #{path}>"
         
     | 
| 
      
 59 
     | 
    
         
            +
                  end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                  # @private
         
     | 
| 
      
 62 
     | 
    
         
            +
                  class Cache
         
     | 
| 
      
 63 
     | 
    
         
            +
                    attr_reader :syntax_highlighter
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                    def initialize(configuration)
         
     | 
| 
      
 66 
     | 
    
         
            +
                      @sources_by_path = {}
         
     | 
| 
      
 67 
     | 
    
         
            +
                      @syntax_highlighter = SyntaxHighlighter.new(configuration)
         
     | 
| 
      
 68 
     | 
    
         
            +
                    end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                    def source_from_file(path)
         
     | 
| 
      
 71 
     | 
    
         
            +
                      @sources_by_path[path] ||= Source.from_file(path)
         
     | 
| 
      
 72 
     | 
    
         
            +
                    end
         
     | 
| 
      
 73 
     | 
    
         
            +
                  end
         
     | 
| 
      
 74 
     | 
    
         
            +
                end
         
     | 
| 
      
 75 
     | 
    
         
            +
              end
         
     | 
| 
      
 76 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,13 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module RSpec
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Core
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Source
         
     | 
| 
      
 4 
     | 
    
         
            +
                  # @private
         
     | 
| 
      
 5 
     | 
    
         
            +
                  # Represents a source location of node or token.
         
     | 
| 
      
 6 
     | 
    
         
            +
                  Location = Struct.new(:line, :column) do
         
     | 
| 
      
 7 
     | 
    
         
            +
                    def self.location?(array)
         
     | 
| 
      
 8 
     | 
    
         
            +
                      array.is_a?(Array) && array.size == 2 && array.all? { |e| e.is_a?(Integer) }
         
     | 
| 
      
 9 
     | 
    
         
            +
                    end
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
                end
         
     | 
| 
      
 12 
     | 
    
         
            +
              end
         
     | 
| 
      
 13 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,93 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            RSpec::Support.require_rspec_core "source/location"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module RSpec
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Core
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Source
         
     | 
| 
      
 6 
     | 
    
         
            +
                  # @private
         
     | 
| 
      
 7 
     | 
    
         
            +
                  # A wrapper for Ripper AST node which is generated with `Ripper.sexp`.
         
     | 
| 
      
 8 
     | 
    
         
            +
                  class Node
         
     | 
| 
      
 9 
     | 
    
         
            +
                    include Enumerable
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                    attr_reader :sexp, :parent
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                    def self.sexp?(array)
         
     | 
| 
      
 14 
     | 
    
         
            +
                      array.is_a?(Array) && array.first.is_a?(Symbol)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                    def initialize(ripper_sexp, parent=nil)
         
     | 
| 
      
 18 
     | 
    
         
            +
                      @sexp = ripper_sexp.freeze
         
     | 
| 
      
 19 
     | 
    
         
            +
                      @parent = parent
         
     | 
| 
      
 20 
     | 
    
         
            +
                    end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                    def type
         
     | 
| 
      
 23 
     | 
    
         
            +
                      sexp[0]
         
     | 
| 
      
 24 
     | 
    
         
            +
                    end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                    def args
         
     | 
| 
      
 27 
     | 
    
         
            +
                      @args ||= raw_args.map do |raw_arg|
         
     | 
| 
      
 28 
     | 
    
         
            +
                        if Node.sexp?(raw_arg)
         
     | 
| 
      
 29 
     | 
    
         
            +
                          Node.new(raw_arg, self)
         
     | 
| 
      
 30 
     | 
    
         
            +
                        elsif Location.location?(raw_arg)
         
     | 
| 
      
 31 
     | 
    
         
            +
                          Location.new(*raw_arg)
         
     | 
| 
      
 32 
     | 
    
         
            +
                        elsif raw_arg.is_a?(Array)
         
     | 
| 
      
 33 
     | 
    
         
            +
                          GroupNode.new(raw_arg, self)
         
     | 
| 
      
 34 
     | 
    
         
            +
                        else
         
     | 
| 
      
 35 
     | 
    
         
            +
                          raw_arg
         
     | 
| 
      
 36 
     | 
    
         
            +
                        end
         
     | 
| 
      
 37 
     | 
    
         
            +
                      end.freeze
         
     | 
| 
      
 38 
     | 
    
         
            +
                    end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                    def children
         
     | 
| 
      
 41 
     | 
    
         
            +
                      @children ||= args.select { |arg| arg.is_a?(Node) }.freeze
         
     | 
| 
      
 42 
     | 
    
         
            +
                    end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                    def location
         
     | 
| 
      
 45 
     | 
    
         
            +
                      @location ||= args.find { |arg| arg.is_a?(Location) }
         
     | 
| 
      
 46 
     | 
    
         
            +
                    end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                    def each(&block)
         
     | 
| 
      
 49 
     | 
    
         
            +
                      return to_enum(__method__) unless block_given?
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                      yield self
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                      children.each do |child|
         
     | 
| 
      
 54 
     | 
    
         
            +
                        child.each(&block)
         
     | 
| 
      
 55 
     | 
    
         
            +
                      end
         
     | 
| 
      
 56 
     | 
    
         
            +
                    end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                    def each_ancestor
         
     | 
| 
      
 59 
     | 
    
         
            +
                      return to_enum(__method__) unless block_given?
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                      current_node = self
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                      while (current_node = current_node.parent)
         
     | 
| 
      
 64 
     | 
    
         
            +
                        yield current_node
         
     | 
| 
      
 65 
     | 
    
         
            +
                      end
         
     | 
| 
      
 66 
     | 
    
         
            +
                    end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                    def inspect
         
     | 
| 
      
 69 
     | 
    
         
            +
                      "#<#{self.class} #{type}>"
         
     | 
| 
      
 70 
     | 
    
         
            +
                    end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                  private
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                    def raw_args
         
     | 
| 
      
 75 
     | 
    
         
            +
                      sexp[1..-1] || []
         
     | 
| 
      
 76 
     | 
    
         
            +
                    end
         
     | 
| 
      
 77 
     | 
    
         
            +
                  end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                  # @private
         
     | 
| 
      
 80 
     | 
    
         
            +
                  class GroupNode < Node
         
     | 
| 
      
 81 
     | 
    
         
            +
                    def type
         
     | 
| 
      
 82 
     | 
    
         
            +
                      :group
         
     | 
| 
      
 83 
     | 
    
         
            +
                    end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                  private
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                    def raw_args
         
     | 
| 
      
 88 
     | 
    
         
            +
                      sexp
         
     | 
| 
      
 89 
     | 
    
         
            +
                    end
         
     | 
| 
      
 90 
     | 
    
         
            +
                  end
         
     | 
| 
      
 91 
     | 
    
         
            +
                end
         
     | 
| 
      
 92 
     | 
    
         
            +
              end
         
     | 
| 
      
 93 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,71 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module RSpec
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Core
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Source
         
     | 
| 
      
 4 
     | 
    
         
            +
                  # @private
         
     | 
| 
      
 5 
     | 
    
         
            +
                  # Provides terminal syntax highlighting of code snippets
         
     | 
| 
      
 6 
     | 
    
         
            +
                  # when coderay is available.
         
     | 
| 
      
 7 
     | 
    
         
            +
                  class SyntaxHighlighter
         
     | 
| 
      
 8 
     | 
    
         
            +
                    def initialize(configuration)
         
     | 
| 
      
 9 
     | 
    
         
            +
                      @configuration = configuration
         
     | 
| 
      
 10 
     | 
    
         
            +
                    end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                    def highlight(lines)
         
     | 
| 
      
 13 
     | 
    
         
            +
                      implementation.highlight_syntax(lines)
         
     | 
| 
      
 14 
     | 
    
         
            +
                    end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  private
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                    if RSpec::Support::OS.windows?
         
     | 
| 
      
 19 
     | 
    
         
            +
                      # :nocov:
         
     | 
| 
      
 20 
     | 
    
         
            +
                      def implementation
         
     | 
| 
      
 21 
     | 
    
         
            +
                        WindowsImplementation
         
     | 
| 
      
 22 
     | 
    
         
            +
                      end
         
     | 
| 
      
 23 
     | 
    
         
            +
                      # :nocov:
         
     | 
| 
      
 24 
     | 
    
         
            +
                    else
         
     | 
| 
      
 25 
     | 
    
         
            +
                      def implementation
         
     | 
| 
      
 26 
     | 
    
         
            +
                        return color_enabled_implementation if @configuration.color_enabled?
         
     | 
| 
      
 27 
     | 
    
         
            +
                        NoSyntaxHighlightingImplementation
         
     | 
| 
      
 28 
     | 
    
         
            +
                      end
         
     | 
| 
      
 29 
     | 
    
         
            +
                    end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                    def color_enabled_implementation
         
     | 
| 
      
 32 
     | 
    
         
            +
                      @color_enabled_implementation ||= begin
         
     | 
| 
      
 33 
     | 
    
         
            +
                        ::Kernel.require 'coderay'
         
     | 
| 
      
 34 
     | 
    
         
            +
                        CodeRayImplementation
         
     | 
| 
      
 35 
     | 
    
         
            +
                      rescue LoadError
         
     | 
| 
      
 36 
     | 
    
         
            +
                        NoSyntaxHighlightingImplementation
         
     | 
| 
      
 37 
     | 
    
         
            +
                      end
         
     | 
| 
      
 38 
     | 
    
         
            +
                    end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                    # @private
         
     | 
| 
      
 41 
     | 
    
         
            +
                    module CodeRayImplementation
         
     | 
| 
      
 42 
     | 
    
         
            +
                      RESET_CODE = "\e[0m"
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                      def self.highlight_syntax(lines)
         
     | 
| 
      
 45 
     | 
    
         
            +
                        highlighted = begin
         
     | 
| 
      
 46 
     | 
    
         
            +
                          CodeRay.encode(lines.join("\n"), :ruby, :terminal)
         
     | 
| 
      
 47 
     | 
    
         
            +
                        rescue Support::AllExceptionsExceptOnesWeMustNotRescue
         
     | 
| 
      
 48 
     | 
    
         
            +
                          return lines
         
     | 
| 
      
 49 
     | 
    
         
            +
                        end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                        highlighted.split("\n").map do |line|
         
     | 
| 
      
 52 
     | 
    
         
            +
                          line.sub(/\S/) { |char| char.insert(0, RESET_CODE) }
         
     | 
| 
      
 53 
     | 
    
         
            +
                        end
         
     | 
| 
      
 54 
     | 
    
         
            +
                      end
         
     | 
| 
      
 55 
     | 
    
         
            +
                    end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                    # @private
         
     | 
| 
      
 58 
     | 
    
         
            +
                    module NoSyntaxHighlightingImplementation
         
     | 
| 
      
 59 
     | 
    
         
            +
                      def self.highlight_syntax(lines)
         
     | 
| 
      
 60 
     | 
    
         
            +
                        lines
         
     | 
| 
      
 61 
     | 
    
         
            +
                      end
         
     | 
| 
      
 62 
     | 
    
         
            +
                    end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                    # @private
         
     | 
| 
      
 65 
     | 
    
         
            +
                    # Not sure why, but our code above (and/or coderay itself) does not work
         
     | 
| 
      
 66 
     | 
    
         
            +
                    # on Windows, so we disable the feature on Windows.
         
     | 
| 
      
 67 
     | 
    
         
            +
                    WindowsImplementation = NoSyntaxHighlightingImplementation
         
     | 
| 
      
 68 
     | 
    
         
            +
                  end
         
     | 
| 
      
 69 
     | 
    
         
            +
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
              end
         
     | 
| 
      
 71 
     | 
    
         
            +
            end
         
     |