rspec-core 3.6.0.beta2 → 3.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cedf9914463a5f8470ddb33bef491f31615a7b63
4
- data.tar.gz: 8eecab50a480c797c96f53932f955643f23db6eb
3
+ metadata.gz: 33bf2ee1c5d02653b19cece430ba75ac28668df0
4
+ data.tar.gz: 5c3e3a2f628543125d4bc02ffff6ee05135e4d1e
5
5
  SHA512:
6
- metadata.gz: a162b44414bcbd3ac23ee749f456976c10858bc84b8703a4ef63f370fcf8a691b7366ef8a9d0d2e15f7cecea6f38ce78379da1a25be1f75bf09ea9e913aa4939
7
- data.tar.gz: f9a9b8815b6a42d5da60f033443dbf145b025058a6ec327c8a16fde556c83a753b1ed2bfd54ae85e02772fa54e8d7169c7323e034622b52ffbd9e3eab0826841
6
+ metadata.gz: ca2f7dea70f81dad661b79e61b7b4142989368fddca025d8741a97d5d36037bf598c4dff28a37c4a25bc5116520aa49ace6fbd4cc16b1f7b49bc8f5ef1956435
7
+ data.tar.gz: 8d104339ba402be5aec231e5d16e6fcad61cd9b81554593f71f87393b0638f6be590fdbdab06c54b1f981ef9f576eff8db302e32026d8ecabaebb9710d219ba9
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -1,3 +1,31 @@
1
+ ### 3.6.0 / 2017-05-04
2
+ [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.6.0.beta2...v3.6.0)
3
+
4
+ Enhancements:
5
+
6
+ * Add seed information to JSON formatter output. (#2388, Mitsutaka Mimura)
7
+ * Include example id in the JSON formatter output. (#2369, Xavier Shay)
8
+ * Respect changes to `config.output_stream` after formatters have been
9
+ setup. (#2401, #2419, Ilya Lavrov)
10
+
11
+ Bug Fixes:
12
+
13
+ * Delay formatter loading until the last minute to allow accessing the reporter
14
+ without triggering formatter setup. (Jon Rowe, #2243)
15
+ * Ensure context hook failures running before an example can access the
16
+ reporter. (Jon Jensen, #2387)
17
+ * Multiple fixes to allow using the runner multiple times within the same
18
+ process: `RSpec.clear_examples` resets the formatter and no longer clears
19
+ shared examples, and streams can be used across multiple runs rather than
20
+ being closed after the first. (#2368, Xavier Shay)
21
+ * Prevent unexpected `example_group_finished` notifications causing an error.
22
+ (#2396, VTJamie)
23
+ * Fix bugs where `config.when_first_matching_example_defined` hooks would fire
24
+ multiple times in some cases. (Yuji Nakayama, #2400)
25
+ * Default `last_run_status` to "unknown" when the `status` field in the
26
+ persistence file contains an unrecognized value. (#2360, matrinox)
27
+ * Prevent `let` from defining an `initialize` method. (#2414, Jon Rowe)
28
+
1
29
  ### 3.6.0.beta2 / 2016-12-12
2
30
  [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.6.0.beta1...v3.6.0.beta2)
3
31
 
@@ -69,7 +69,7 @@ module RSpec
69
69
  # same process.
70
70
  def self.clear_examples
71
71
  world.reset
72
- configuration.reporter.reset
72
+ configuration.reset_reporter
73
73
  configuration.start_time = ::RSpec::Core::Time.now
74
74
  configuration.reset_filters
75
75
  end
@@ -1,6 +1,7 @@
1
1
  RSpec::Support.require_rspec_core "backtrace_formatter"
2
2
  RSpec::Support.require_rspec_core "ruby_project"
3
3
  RSpec::Support.require_rspec_core "formatters/deprecation_formatter"
4
+ RSpec::Support.require_rspec_core "output_wrapper"
4
5
 
5
6
  module RSpec
6
7
  module Core
@@ -141,7 +142,7 @@ module RSpec
141
142
 
142
143
  # Determines where deprecation warnings are printed.
143
144
  # Defaults to `$stderr`.
144
- # @return [IO, String] IO to write to or filename to write to
145
+ # @return [IO, String] IO or filename to write to
145
146
  define_reader :deprecation_stream
146
147
 
147
148
  # Determines where deprecation warnings are printed.
@@ -218,7 +219,7 @@ module RSpec
218
219
  define_reader :output_stream
219
220
 
220
221
  # Set the output stream for reporter.
221
- # @attr value [IO] value for output, defaults to $stdout
222
+ # @attr value [IO, String] IO to write to or filename to write to, defaults to $stdout
222
223
  def output_stream=(value)
223
224
  if @reporter && !value.equal?(@output_stream)
224
225
  warn "RSpec's reporter has already been initialized with " \
@@ -227,6 +228,7 @@ module RSpec
227
228
  "it to take effect. (Called from #{CallerFilter.first_non_rspec_line})"
228
229
  else
229
230
  @output_stream = value
231
+ output_wrapper.output = @output_stream
230
232
  end
231
233
  end
232
234
 
@@ -480,8 +482,14 @@ module RSpec
480
482
  # @private
481
483
  def reset
482
484
  @spec_files_loaded = false
485
+ reset_reporter
486
+ end
487
+
488
+ # @private
489
+ def reset_reporter
483
490
  @reporter = nil
484
491
  @formatter_loader = nil
492
+ @output_wrapper = nil
485
493
  end
486
494
 
487
495
  # @private
@@ -864,7 +872,7 @@ module RSpec
864
872
  # Adds a formatter to the set RSpec will use for this run.
865
873
  #
866
874
  # @see RSpec::Core::Formatters::Protocol
867
- def add_formatter(formatter, output=output_stream)
875
+ def add_formatter(formatter, output=output_wrapper)
868
876
  formatter_loader.add(formatter, output)
869
877
  end
870
878
  alias_method :formatter=, :add_formatter
@@ -930,7 +938,7 @@ module RSpec
930
938
  @reporter_buffer || @reporter ||=
931
939
  begin
932
940
  @reporter_buffer = DeprecationReporterBuffer.new
933
- formatter_loader.setup_default output_stream, deprecation_stream
941
+ formatter_loader.prepare_default output_wrapper, deprecation_stream
934
942
  @reporter_buffer.play_onto(formatter_loader.reporter)
935
943
  @reporter_buffer = nil
936
944
  formatter_loader.reporter
@@ -974,7 +982,9 @@ module RSpec
974
982
  if (path = example_status_persistence_file_path)
975
983
  begin
976
984
  ExampleStatusPersister.load_from(path).inject(statuses) do |hash, example|
977
- hash[example.fetch(:example_id)] = example.fetch(:status)
985
+ status = example[:status]
986
+ status = UNKNOWN_STATUS unless VALID_STATUSES.include?(status)
987
+ hash[example.fetch(:example_id)] = status
978
988
  hash
979
989
  end
980
990
  rescue SystemCallError => e
@@ -994,6 +1004,15 @@ module RSpec
994
1004
  # @private
995
1005
  FAILED_STATUS = "failed".freeze
996
1006
 
1007
+ # @private
1008
+ PASSED_STATUS = "passed".freeze
1009
+
1010
+ # @private
1011
+ PENDING_STATUS = "pending".freeze
1012
+
1013
+ # @private
1014
+ VALID_STATUSES = [UNKNOWN_STATUS, FAILED_STATUS, PASSED_STATUS, PENDING_STATUS]
1015
+
997
1016
  # @private
998
1017
  def spec_files_with_failures
999
1018
  @spec_files_with_failures ||= last_run_statuses.inject(Set.new) do |files, (id, status)|
@@ -1698,7 +1717,7 @@ module RSpec
1698
1717
  # mocks.patch_marshal_to_support_partial_doubles = false
1699
1718
  # end
1700
1719
  #
1701
- # config.mock_with :rspec do |expectations|
1720
+ # config.expect_with :rspec do |expectations|
1702
1721
  # expectations.syntax = :expect
1703
1722
  # end
1704
1723
  # end
@@ -1761,7 +1780,7 @@ module RSpec
1761
1780
  return unless example_or_group_meta.key?(:example_group)
1762
1781
 
1763
1782
  # Ensure the callback only fires once.
1764
- @derived_metadata_blocks.items_for(specified_meta).delete(callback)
1783
+ @derived_metadata_blocks.delete(callback, specified_meta)
1765
1784
 
1766
1785
  block.call
1767
1786
  end
@@ -2039,6 +2058,10 @@ module RSpec
2039
2058
  )
2040
2059
  end
2041
2060
 
2061
+ def output_wrapper
2062
+ @output_wrapper ||= OutputWrapper.new(output_stream)
2063
+ end
2064
+
2042
2065
  def output_to_tty?(output=output_stream)
2043
2066
  output.respond_to?(:tty?) && output.tty?
2044
2067
  end
@@ -186,8 +186,10 @@ module RSpec
186
186
  def global_options_file
187
187
  File.join(File.expand_path("~"), ".rspec")
188
188
  rescue ArgumentError
189
+ # :nocov:
189
190
  RSpec.warning "Unable to find ~/.rspec because the HOME environment variable is not set"
190
191
  nil
192
+ # :nocov:
191
193
  end
192
194
  end
193
195
  end
@@ -260,7 +260,11 @@ module RSpec
260
260
  'Expected example to fail since it is pending, but it passed.',
261
261
  [location]
262
262
  end
263
- rescue Pending::SkipDeclaredInExample
263
+ rescue Pending::SkipDeclaredInExample => _
264
+ # The "=> _" is normally useless but on JRuby it is a workaround
265
+ # for a bug that prevents us from getting backtraces:
266
+ # https://github.com/jruby/jruby/issues/4467
267
+ #
264
268
  # no-op, required metadata has already been set by the `skip`
265
269
  # method.
266
270
  rescue AllExceptionsExcludingDangerousOnesOnRubiesThatAllowIt => e
@@ -465,22 +469,22 @@ module RSpec
465
469
 
466
470
  if @exception
467
471
  execution_result.exception = @exception
468
- record_finished :failed
472
+ record_finished :failed, reporter
469
473
  reporter.example_failed self
470
474
  false
471
475
  elsif pending_message
472
476
  execution_result.pending_message = pending_message
473
- record_finished :pending
477
+ record_finished :pending, reporter
474
478
  reporter.example_pending self
475
479
  true
476
480
  else
477
- record_finished :passed
481
+ record_finished :passed, reporter
478
482
  reporter.example_passed self
479
483
  true
480
484
  end
481
485
  end
482
486
 
483
- def record_finished(status)
487
+ def record_finished(status, reporter)
484
488
  execution_result.record_finished(status, clock.now)
485
489
  reporter.example_finished(self)
486
490
  end
@@ -115,6 +115,11 @@ module RSpec::Core::Formatters
115
115
  # @return [String] the default formatter to setup, defaults to `progress`
116
116
  attr_accessor :default_formatter
117
117
 
118
+ # @private
119
+ def prepare_default(output_stream, deprecation_stream)
120
+ reporter.prepare_default(self, output_stream, deprecation_stream)
121
+ end
122
+
118
123
  # @private
119
124
  def setup_default(output_stream, deprecation_stream)
120
125
  add default_formatter, output_stream if @formatters.empty?
@@ -140,7 +145,7 @@ module RSpec::Core::Formatters
140
145
  def add(formatter_to_use, *paths)
141
146
  formatter_class = find_formatter(formatter_to_use)
142
147
 
143
- args = paths.map { |p| p.respond_to?(:puts) ? p : file_at(p) }
148
+ args = paths.map { |p| p.respond_to?(:puts) ? p : open_stream(p) }
144
149
 
145
150
  if !Loader.formatters[formatter_class].nil?
146
151
  formatter = formatter_class.new(*args)
@@ -247,9 +252,14 @@ module RSpec::Core::Formatters
247
252
  word
248
253
  end
249
254
 
250
- def file_at(path)
251
- RSpec::Support::DirectoryMaker.mkdir_p(File.dirname(path))
252
- File.new(path, 'w')
255
+ def open_stream(path_or_wrapper)
256
+ if RSpec::Core::OutputWrapper === path_or_wrapper
257
+ path_or_wrapper.output = open_stream(path_or_wrapper.output)
258
+ path_or_wrapper
259
+ else
260
+ RSpec::Support::DirectoryMaker.mkdir_p(File.dirname(path_or_wrapper))
261
+ File.new(path_or_wrapper, 'w')
262
+ end
253
263
  end
254
264
  end
255
265
  end
@@ -57,18 +57,17 @@ module RSpec
57
57
 
58
58
  # @api public
59
59
  #
60
- # Invoked at the very end, `close` allows the formatter to clean
61
- # up resources, e.g. open streams, etc.
60
+ # Invoked at the end of a suite run. Allows the formatter to do any
61
+ # tidying up, but be aware that formatter output streams may be used
62
+ # elsewhere so don't actually close them.
62
63
  #
63
64
  # @param _notification [NullNotification] (Ignored)
64
65
  def close(_notification)
65
- return unless IO === output
66
66
  return if output.closed?
67
67
 
68
68
  output.puts
69
69
 
70
70
  output.flush
71
- output.close unless output == $stdout
72
71
  end
73
72
  end
74
73
  end
@@ -22,7 +22,7 @@ module RSpec
22
22
  end
23
23
 
24
24
  def example_group_finished(_notification)
25
- @group_level -= 1
25
+ @group_level -= 1 if @group_level > 0
26
26
  end
27
27
 
28
28
  def example_passed(passed)
@@ -1,6 +1,7 @@
1
1
  # encoding: utf-8
2
2
  RSpec::Support.require_rspec_core "formatters/console_codes"
3
3
  RSpec::Support.require_rspec_core "formatters/snippet_extractor"
4
+ RSpec::Support.require_rspec_core 'formatters/syntax_highlighter'
4
5
  RSpec::Support.require_rspec_support "encoded_string"
5
6
 
6
7
  module RSpec
@@ -215,7 +216,7 @@ module RSpec
215
216
  file_path, line_number = file_and_line_number[1..2]
216
217
  max_line_count = RSpec.configuration.max_displayed_failure_line_count
217
218
  lines = SnippetExtractor.extract_expression_lines_at(file_path, line_number.to_i, max_line_count)
218
- RSpec.world.source_cache.syntax_highlighter.highlight(lines)
219
+ RSpec.world.syntax_highlighter.highlight(lines)
219
220
  rescue SnippetExtractor::NoSuchFileError
220
221
  ["Unable to find #{file_path} to read failed line"]
221
222
  rescue SnippetExtractor::NoSuchLineError
@@ -279,7 +280,7 @@ module RSpec
279
280
  :description => "#{@example.full_description} FIXED",
280
281
  :message_color => RSpec.configuration.fixed_color,
281
282
  :failure_lines => [
282
- "Expected pending '#{@execution_result.pending_message}' to fail. No Error was raised."
283
+ "Expected pending '#{@execution_result.pending_message}' to fail. No error was raised."
283
284
  ]
284
285
  }
285
286
  elsif @execution_result.status == :pending
@@ -24,8 +24,8 @@ module RSpec
24
24
  @@converter = NullConverter
25
25
  begin
26
26
  require 'coderay'
27
- RSpec::Support.require_rspec_core 'source/syntax_highlighter'
28
- RSpec::Core::Source::SyntaxHighlighter.attempt_to_add_rspec_terms_to_coderay_keywords
27
+ RSpec::Support.require_rspec_core 'formatters/syntax_highlighter'
28
+ RSpec::Core::Formatters::SyntaxHighlighter.attempt_to_add_rspec_terms_to_coderay_keywords
29
29
  @@converter = CoderayConverter
30
30
  # rubocop:disable Lint/HandleExceptions
31
31
  rescue LoadError
@@ -6,7 +6,7 @@ module RSpec
6
6
  module Formatters
7
7
  # @private
8
8
  class JsonFormatter < BaseFormatter
9
- Formatters.register self, :message, :dump_summary, :dump_profile, :stop, :close
9
+ Formatters.register self, :message, :dump_summary, :dump_profile, :stop, :seed, :close
10
10
 
11
11
  attr_reader :output_hash
12
12
 
@@ -46,9 +46,13 @@ module RSpec
46
46
  end
47
47
  end
48
48
 
49
+ def seed(notification)
50
+ return unless notification.seed_used?
51
+ @output_hash[:seed] = notification.seed
52
+ end
53
+
49
54
  def close(_notification)
50
55
  output.write @output_hash.to_json
51
- output.close if IO === output && output != $stdout
52
56
  end
53
57
 
54
58
  def dump_profile(profile)
@@ -81,6 +85,7 @@ module RSpec
81
85
 
82
86
  def format_example(example)
83
87
  {
88
+ :id => example.id,
84
89
  :description => example.description,
85
90
  :full_description => example.full_description,
86
91
  :status => example.execution_result.status.to_s,
@@ -171,8 +171,9 @@ module RSpec
171
171
  # @api public
172
172
  # @group Suite Notifications
173
173
  #
174
- # Invoked at the very end, `close` allows the formatter to clean
175
- # up resources, e.g. open streams, etc.
174
+ # Invoked at the end of a suite run. Allows the formatter to do any
175
+ # tidying up, but be aware that formatter output streams may be used
176
+ # elsewhere so don't actually close them.
176
177
  #
177
178
  # @param notification [Notifications::NullNotification]
178
179
  end
@@ -1,5 +1,3 @@
1
- RSpec::Support.require_rspec_core "source"
2
-
3
1
  module RSpec
4
2
  module Core
5
3
  module Formatters
@@ -17,7 +15,7 @@ module RSpec
17
15
 
18
16
  def self.source_from_file(path)
19
17
  raise NoSuchFileError unless File.exist?(path)
20
- RSpec.world.source_cache.source_from_file(path)
18
+ RSpec.world.source_from_file(path)
21
19
  end
22
20
 
23
21
  if RSpec::Support::RubyFeatures.ripper_supported?
@@ -1,6 +1,6 @@
1
1
  module RSpec
2
2
  module Core
3
- class Source
3
+ module Formatters
4
4
  # @private
5
5
  # Provides terminal syntax highlighting of code snippets
6
6
  # when coderay is available.
@@ -285,6 +285,9 @@ EOS
285
285
  # We have to pass the block directly to `define_method` to
286
286
  # allow it to use method constructs like `super` and `return`.
287
287
  raise "#let or #subject called without a block" if block.nil?
288
+ raise(
289
+ "#let or #subject called with a reserved name #initialize"
290
+ ) if :initialize == name
288
291
  MemoizedHelpers.module_for(self).__send__(:define_method, name, &block)
289
292
 
290
293
  # Apply the memoization. The method has been defined in an ancestor
@@ -111,6 +111,10 @@ module RSpec
111
111
  @items_and_filters.unshift [item, metadata]
112
112
  end
113
113
 
114
+ def delete(item, metadata)
115
+ @items_and_filters.delete [item, metadata]
116
+ end
117
+
114
118
  def items_for(request_meta)
115
119
  @items_and_filters.each_with_object([]) do |(item, item_meta), to_return|
116
120
  to_return << item if item_meta.empty? ||
@@ -167,6 +171,11 @@ module RSpec
167
171
  handle_mutation(metadata)
168
172
  end
169
173
 
174
+ def delete(item, metadata)
175
+ super
176
+ reconstruct_caches
177
+ end
178
+
170
179
  def items_for(metadata)
171
180
  # The filtering of `metadata` to `applicable_metadata` is the key thing
172
181
  # that makes the memoization actually useful in practice, since each
@@ -191,6 +200,14 @@ module RSpec
191
200
 
192
201
  private
193
202
 
203
+ def reconstruct_caches
204
+ @applicable_keys.clear
205
+ @proc_keys.clear
206
+ @items_and_filters.each do |_item, metadata|
207
+ handle_mutation(metadata)
208
+ end
209
+ end
210
+
194
211
  def handle_mutation(metadata)
195
212
  @applicable_keys.merge(metadata.keys)
196
213
  @proc_keys.merge(proc_keys_from metadata)
@@ -336,7 +336,7 @@ module RSpec::Core
336
336
  # specific colors.
337
337
  # @return [String] A colorized results line.
338
338
  def colorized_totals_line(colorizer=::RSpec::Core::Formatters::ConsoleCodes)
339
- if failure_count > 0
339
+ if failure_count > 0 || errors_outside_of_examples_count > 0
340
340
  colorizer.wrap(totals_line, RSpec.configuration.failure_color)
341
341
  elsif pending_count > 0
342
342
  colorizer.wrap(totals_line, RSpec.configuration.pending_color)
@@ -0,0 +1,29 @@
1
+ module RSpec
2
+ module Core
3
+ # @private
4
+ class OutputWrapper
5
+ # @private
6
+ attr_accessor :output
7
+
8
+ # @private
9
+ def initialize(output)
10
+ @output = output
11
+ end
12
+
13
+ def respond_to?(name, priv=false)
14
+ output.respond_to?(name, priv)
15
+ end
16
+
17
+ def method_missing(name, *args, &block)
18
+ output.send(name, *args, &block)
19
+ end
20
+
21
+ # Redirect calls for IO interface methods
22
+ IO.instance_methods(false).each do |method|
23
+ define_method(method) do |*args, &block|
24
+ output.send(method, *args, &block)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -12,9 +12,6 @@
12
12
  # the additional setup, and require it from the spec files that actually need
13
13
  # it.
14
14
  #
15
- # The `.rspec` file also contains a few flags that are not defaults but that
16
- # users commonly want.
17
- #
18
15
  # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
19
16
  RSpec.configure do |config|
20
17
  # rspec-expectations config goes here. You can use an alternate
@@ -19,19 +19,13 @@ module RSpec::Core
19
19
  @pending_examples = []
20
20
  @duration = @start = @load_time = nil
21
21
  @non_example_exception_count = 0
22
+ @setup_default = lambda {}
23
+ @setup = false
22
24
  end
23
25
 
24
26
  # @private
25
27
  attr_reader :examples, :failed_examples, :pending_examples
26
28
 
27
- # @private
28
- def reset
29
- @examples = []
30
- @failed_examples = []
31
- @pending_examples = []
32
- @profiler = Profiler.new if defined?(@profiler)
33
- end
34
-
35
29
  # @private
36
30
  def setup_profiler
37
31
  @profiler = Profiler.new
@@ -52,6 +46,13 @@ module RSpec::Core
52
46
  true
53
47
  end
54
48
 
49
+ # @private
50
+ def prepare_default(loader, output_stream, deprecation_stream)
51
+ @setup_default = lambda do
52
+ loader.setup_default output_stream, deprecation_stream
53
+ end
54
+ end
55
+
55
56
  # @private
56
57
  def registered_listeners(notification)
57
58
  @listeners[notification].to_a
@@ -200,6 +201,7 @@ module RSpec::Core
200
201
 
201
202
  # @private
202
203
  def notify(event, notification)
204
+ ensure_listeners_ready
203
205
  registered_listeners(event).each do |formatter|
204
206
  formatter.__send__(event, notification)
205
207
  end
@@ -225,6 +227,13 @@ module RSpec::Core
225
227
 
226
228
  private
227
229
 
230
+ def ensure_listeners_ready
231
+ return if @setup
232
+
233
+ @setup_default.call
234
+ @setup = true
235
+ end
236
+
228
237
  def close
229
238
  notify :close, Notifications::NullNotification
230
239
  end
@@ -44,6 +44,11 @@ module RSpec
44
44
  end
45
45
  self
46
46
  end
47
+
48
+ def clear
49
+ @values.clear
50
+ self
51
+ end
47
52
  end
48
53
  end
49
54
  end
@@ -64,11 +64,6 @@ module RSpec
64
64
  # group; any example group or example with matching metadata will
65
65
  # automatically include this shared example group.
66
66
  # @param block The block to be eval'd
67
- # @overload shared_examples(metadata, &block)
68
- # @param metadata [Array<Symbol>, Hash] metadata to attach to this
69
- # group; any example group or example with matching metadata will
70
- # automatically include this shared example group.
71
- # @param block The block to be eval'd
72
67
  #
73
68
  # Stores the block for later use. The block will be evaluated
74
69
  # in the context of an example group via `include_examples`,
@@ -3,7 +3,7 @@ module RSpec
3
3
  # Version information for RSpec Core.
4
4
  module Version
5
5
  # Current version of RSpec Core, in semantic versioning format.
6
- STRING = '3.6.0.beta2'
6
+ STRING = '3.6.0'
7
7
  end
8
8
  end
9
9
  end
@@ -40,7 +40,8 @@ module RSpec
40
40
  def reset
41
41
  RSpec::ExampleGroups.remove_all_constants
42
42
  example_groups.clear
43
- @shared_example_group_registry = nil
43
+ @sources_by_path.clear if defined?(@sources_by_path)
44
+ @syntax_highlighter = nil
44
45
  end
45
46
 
46
47
  # @private
@@ -129,11 +130,18 @@ module RSpec
129
130
  end
130
131
 
131
132
  # @private
132
- def source_cache
133
- @source_cache ||= begin
134
- RSpec::Support.require_rspec_core "source"
135
- Source::Cache.new(@configuration)
133
+ def source_from_file(path)
134
+ unless defined?(@sources_by_path)
135
+ RSpec::Support.require_rspec_support 'source'
136
+ @sources_by_path = {}
136
137
  end
138
+
139
+ @sources_by_path[path] ||= Support::Source.from_file(path)
140
+ end
141
+
142
+ # @private
143
+ def syntax_highlighter
144
+ @syntax_highlighter ||= Formatters::SyntaxHighlighter.new(@configuration)
137
145
  end
138
146
 
139
147
  # @api private
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.6.0.beta2
4
+ version: 3.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steven Baker
@@ -46,22 +46,22 @@ cert_chain:
46
46
  ZsVDj6a7lH3cNqtWXZxrb2wO38qV5AkYj8SQK7Hj3/Yui9myUX3crr+PdetazSqQ
47
47
  F3MdtaDehhjC
48
48
  -----END CERTIFICATE-----
49
- date: 2016-12-12 00:00:00.000000000 Z
49
+ date: 2017-05-04 00:00:00.000000000 Z
50
50
  dependencies:
51
51
  - !ruby/object:Gem::Dependency
52
52
  name: rspec-support
53
53
  requirement: !ruby/object:Gem::Requirement
54
54
  requirements:
55
- - - '='
55
+ - - "~>"
56
56
  - !ruby/object:Gem::Version
57
- version: 3.6.0.beta2
57
+ version: 3.6.0
58
58
  type: :runtime
59
59
  prerelease: false
60
60
  version_requirements: !ruby/object:Gem::Requirement
61
61
  requirements:
62
- - - '='
62
+ - - "~>"
63
63
  - !ruby/object:Gem::Version
64
- version: 3.6.0.beta2
64
+ version: 3.6.0
65
65
  - !ruby/object:Gem::Dependency
66
66
  name: cucumber
67
67
  requirement: !ruby/object:Gem::Requirement
@@ -222,6 +222,7 @@ files:
222
222
  - lib/rspec/core/formatters/progress_formatter.rb
223
223
  - lib/rspec/core/formatters/protocol.rb
224
224
  - lib/rspec/core/formatters/snippet_extractor.rb
225
+ - lib/rspec/core/formatters/syntax_highlighter.rb
225
226
  - lib/rspec/core/hooks.rb
226
227
  - lib/rspec/core/invocations.rb
227
228
  - lib/rspec/core/memoized_helpers.rb
@@ -236,6 +237,7 @@ files:
236
237
  - lib/rspec/core/notifications.rb
237
238
  - lib/rspec/core/option_parser.rb
238
239
  - lib/rspec/core/ordering.rb
240
+ - lib/rspec/core/output_wrapper.rb
239
241
  - lib/rspec/core/pending.rb
240
242
  - lib/rspec/core/profiler.rb
241
243
  - lib/rspec/core/project_initializer.rb
@@ -250,11 +252,6 @@ files:
250
252
  - lib/rspec/core/shared_context.rb
251
253
  - lib/rspec/core/shared_example_group.rb
252
254
  - lib/rspec/core/shell_escape.rb
253
- - lib/rspec/core/source.rb
254
- - lib/rspec/core/source/location.rb
255
- - lib/rspec/core/source/node.rb
256
- - lib/rspec/core/source/syntax_highlighter.rb
257
- - lib/rspec/core/source/token.rb
258
255
  - lib/rspec/core/test_unit_assertions_adapter.rb
259
256
  - lib/rspec/core/version.rb
260
257
  - lib/rspec/core/warnings.rb
@@ -275,14 +272,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
275
272
  version: 1.8.7
276
273
  required_rubygems_version: !ruby/object:Gem::Requirement
277
274
  requirements:
278
- - - ">"
275
+ - - ">="
279
276
  - !ruby/object:Gem::Version
280
- version: 1.3.1
277
+ version: '0'
281
278
  requirements: []
282
279
  rubyforge_project:
283
- rubygems_version: 2.5.1
280
+ rubygems_version: 2.4.5.2
284
281
  signing_key:
285
282
  specification_version: 4
286
- summary: rspec-core-3.6.0.beta2
283
+ summary: rspec-core-3.6.0
287
284
  test_files: []
288
285
  has_rdoc:
metadata.gz.sig CHANGED
Binary file
@@ -1,86 +0,0 @@
1
- RSpec::Support.require_rspec_support "encoded_string"
2
- RSpec::Support.require_rspec_core 'source/node'
3
- RSpec::Support.require_rspec_core 'source/syntax_highlighter'
4
- RSpec::Support.require_rspec_core 'source/token'
5
-
6
- module RSpec
7
- module Core
8
- # @private
9
- # Represents a Ruby source file and provides access to AST and tokens.
10
- class Source
11
- attr_reader :source, :path
12
-
13
- def self.from_file(path)
14
- source = File.read(path)
15
- new(source, path)
16
- end
17
-
18
- if String.method_defined?(:encoding)
19
- def initialize(source_string, path=nil)
20
- @source = RSpec::Support::EncodedString.new(source_string, Encoding.default_external)
21
- @path = path ? File.expand_path(path) : '(string)'
22
- end
23
- else # for 1.8.7
24
- # :nocov:
25
- def initialize(source_string, path=nil)
26
- @source = RSpec::Support::EncodedString.new(source_string)
27
- @path = path ? File.expand_path(path) : '(string)'
28
- end
29
- # :nocov:
30
- end
31
-
32
- def lines
33
- @lines ||= source.split("\n")
34
- end
35
-
36
- def ast
37
- @ast ||= begin
38
- require 'ripper'
39
- sexp = Ripper.sexp(source)
40
- raise SyntaxError unless sexp
41
- Node.new(sexp)
42
- end
43
- end
44
-
45
- def tokens
46
- @tokens ||= begin
47
- require 'ripper'
48
- tokens = Ripper.lex(source)
49
- Token.tokens_from_ripper_tokens(tokens)
50
- end
51
- end
52
-
53
- def nodes_by_line_number
54
- @nodes_by_line_number ||= begin
55
- nodes_by_line_number = ast.select(&:location).group_by { |node| node.location.line }
56
- Hash.new { |hash, key| hash[key] = [] }.merge(nodes_by_line_number)
57
- end
58
- end
59
-
60
- def tokens_by_line_number
61
- @tokens_by_line_number ||= begin
62
- nodes_by_line_number = tokens.group_by { |token| token.location.line }
63
- Hash.new { |hash, key| hash[key] = [] }.merge(nodes_by_line_number)
64
- end
65
- end
66
-
67
- def inspect
68
- "#<#{self.class} #{path}>"
69
- end
70
-
71
- # @private
72
- class Cache
73
- attr_reader :syntax_highlighter
74
-
75
- def initialize(configuration)
76
- @sources_by_path = {}
77
- @syntax_highlighter = SyntaxHighlighter.new(configuration)
78
- end
79
-
80
- def source_from_file(path)
81
- @sources_by_path[path] ||= Source.from_file(path)
82
- end
83
- end
84
- end
85
- end
86
- end
@@ -1,13 +0,0 @@
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
@@ -1,93 +0,0 @@
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
@@ -1,87 +0,0 @@
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 token which is generated with `Ripper.lex`.
8
- class Token
9
- CLOSING_TYPES_BY_OPENING_TYPE = {
10
- :on_lbracket => :on_rbracket,
11
- :on_lparen => :on_rparen,
12
- :on_lbrace => :on_rbrace,
13
- :on_heredoc_beg => :on_heredoc_end
14
- }.freeze
15
-
16
- CLOSING_KEYWORDS_BY_OPENING_KEYWORD = {
17
- 'def' => 'end',
18
- 'do' => 'end',
19
- }.freeze
20
-
21
- attr_reader :token
22
-
23
- def self.tokens_from_ripper_tokens(ripper_tokens)
24
- ripper_tokens.map { |ripper_token| new(ripper_token) }.freeze
25
- end
26
-
27
- def initialize(ripper_token)
28
- @token = ripper_token.freeze
29
- end
30
-
31
- def location
32
- @location ||= Location.new(*token[0])
33
- end
34
-
35
- def type
36
- token[1]
37
- end
38
-
39
- def string
40
- token[2]
41
- end
42
-
43
- def ==(other)
44
- token == other.token
45
- end
46
-
47
- alias_method :eql?, :==
48
-
49
- def inspect
50
- "#<#{self.class} #{type} #{string.inspect}>"
51
- end
52
-
53
- def keyword?
54
- type == :on_kw
55
- end
56
-
57
- def opening?
58
- opening_delimiter? || opening_keyword?
59
- end
60
-
61
- def closed_by?(other)
62
- closed_by_delimiter?(other) || closed_by_keyword?(other)
63
- end
64
-
65
- private
66
-
67
- def opening_delimiter?
68
- CLOSING_TYPES_BY_OPENING_TYPE.key?(type)
69
- end
70
-
71
- def opening_keyword?
72
- return false unless keyword?
73
- CLOSING_KEYWORDS_BY_OPENING_KEYWORD.key?(string)
74
- end
75
-
76
- def closed_by_delimiter?(other)
77
- other.type == CLOSING_TYPES_BY_OPENING_TYPE[type]
78
- end
79
-
80
- def closed_by_keyword?(other)
81
- return false unless other.keyword?
82
- other.string == CLOSING_KEYWORDS_BY_OPENING_KEYWORD[string]
83
- end
84
- end
85
- end
86
- end
87
- end