rspec-core 3.6.0.beta2 → 3.6.0

Sign up to get free protection for your applications and to get access to all the features.
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