rspec-support 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: a7fcfff9285fcfb448dbb76d0b30871c0d60f59e
4
- data.tar.gz: 56752014cf41733a30d156dd4e6166317deb3e15
3
+ metadata.gz: a39471f0a21ffe1247f79c44e1e2975452335c0d
4
+ data.tar.gz: a0b069a829099dc903dc988dd2dfaa640e8492a7
5
5
  SHA512:
6
- metadata.gz: e855bdc6915f139f0743b1f1dac1251411f389b00c8f61f12676ee5da459fb194e1bfde2546416b13528018d7ff4affd1c9e149fcba45f3ac09f7c30867e5c0e
7
- data.tar.gz: 2e0b5cab4de91471beadad27058fdceb2f8607ee801cd1fe86d7347fe1e3f20028f628e1578da0c8f72049ef249fa36a7445ad1f8a6ba39036da90bf15e466c1
6
+ metadata.gz: 89338ce6b89473bd3bd5aa5d1d8d37270d144799f222bed8a2261d8e07d84aaafdfeedb4f18e58e1270583919e61ff9c5b5af4383adf9c872184cd83b7965947
7
+ data.tar.gz: acd5ecc188371e729570a9d9d82fba8bb57a8ba220ad5aed7d3bafb612e4e185b07c47305612b75d3736831de260234bc9a880fd555790351c3a24aec7d1bafa
checksums.yaml.gz.sig CHANGED
Binary file
data.tar.gz.sig CHANGED
Binary file
data/Changelog.md CHANGED
@@ -1,7 +1,14 @@
1
+ ### 3.6.0 / 2017-05-04
2
+ [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.6.0.beta2...3.6.0)
3
+
4
+ Enhancements:
5
+
6
+ * Import `Source` classes from rspec-core. (Yuji Nakayama, #315)
7
+
1
8
  ### 3.6.0.beta2 / 2016-12-12
2
9
  [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.6.0.beta1...v3.6.0.beta2)
3
10
 
4
- No user-facinc changes.
11
+ No user-facing changes.
5
12
 
6
13
  ### 3.6.0.beta1 / 2016-10-09
7
14
  [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.5.0...v3.6.0.beta1)
@@ -243,7 +243,12 @@ module RSpec
243
243
  DescribableMatcherInspector,
244
244
  DelegatorInspector,
245
245
  InspectableObjectInspector
246
- ]
246
+ ].tap do |classes|
247
+ # 2.4 has improved BigDecimal formatting so we do not need
248
+ # to provide our own.
249
+ # https://github.com/ruby/bigdecimal/pull/42
250
+ classes.delete(BigDecimalInspector) if RUBY_VERSION >= '2.4'
251
+ end
247
252
 
248
253
  private
249
254
 
@@ -28,6 +28,10 @@ module RSpec
28
28
  RUBY_PLATFORM == 'java'
29
29
  end
30
30
 
31
+ def jruby_version
32
+ @jruby_version ||= ComparableVersion.new(JRUBY_VERSION)
33
+ end
34
+
31
35
  def jruby_9000?
32
36
  jruby? && JRUBY_VERSION >= '9.0.0.0'
33
37
  end
@@ -75,9 +79,10 @@ module RSpec
75
79
  ripper_requirements.push(false) if Ruby.rbx?
76
80
 
77
81
  if Ruby.jruby?
78
- ripper_requirements.push(ComparableVersion.new(JRUBY_VERSION) >= '1.7.5')
79
- # Ripper on JRuby 9.0.0.0.rc1 or later reports wrong line number.
80
- ripper_requirements.push(ComparableVersion.new(JRUBY_VERSION) < '9.0.0.0.rc1')
82
+ ripper_requirements.push(Ruby.jruby_version >= '1.7.5')
83
+ # Ripper on JRuby 9.0.0.0.rc1 or later reports wrong line number
84
+ # or cannot parse source including `:if`.
85
+ ripper_requirements.push(Ruby.jruby_version < '9.0.0.0.rc1')
81
86
  end
82
87
 
83
88
  if ripper_requirements.all?
@@ -0,0 +1,75 @@
1
+ RSpec::Support.require_rspec_support 'encoded_string'
2
+ RSpec::Support.require_rspec_support 'ruby_features'
3
+
4
+ module RSpec
5
+ module Support
6
+ # @private
7
+ # Represents a Ruby source file and provides access to AST and tokens.
8
+ class Source
9
+ attr_reader :source, :path
10
+
11
+ def self.from_file(path)
12
+ source = File.read(path)
13
+ new(source, path)
14
+ end
15
+
16
+ if String.method_defined?(:encoding)
17
+ def initialize(source_string, path=nil)
18
+ @source = RSpec::Support::EncodedString.new(source_string, Encoding.default_external)
19
+ @path = path ? File.expand_path(path) : '(string)'
20
+ end
21
+ else # for 1.8.7
22
+ # :nocov:
23
+ def initialize(source_string, path=nil)
24
+ @source = RSpec::Support::EncodedString.new(source_string)
25
+ @path = path ? File.expand_path(path) : '(string)'
26
+ end
27
+ # :nocov:
28
+ end
29
+
30
+ def lines
31
+ @lines ||= source.split("\n")
32
+ end
33
+
34
+ def inspect
35
+ "#<#{self.class} #{path}>"
36
+ end
37
+
38
+ if RSpec::Support::RubyFeatures.ripper_supported?
39
+ RSpec::Support.require_rspec_support 'source/node'
40
+ RSpec::Support.require_rspec_support 'source/token'
41
+
42
+ def ast
43
+ @ast ||= begin
44
+ require 'ripper'
45
+ sexp = Ripper.sexp(source)
46
+ raise SyntaxError unless sexp
47
+ Node.new(sexp)
48
+ end
49
+ end
50
+
51
+ def tokens
52
+ @tokens ||= begin
53
+ require 'ripper'
54
+ tokens = Ripper.lex(source)
55
+ Token.tokens_from_ripper_tokens(tokens)
56
+ end
57
+ end
58
+
59
+ def nodes_by_line_number
60
+ @nodes_by_line_number ||= begin
61
+ nodes_by_line_number = ast.select(&:location).group_by { |node| node.location.line }
62
+ Hash.new { |hash, key| hash[key] = [] }.merge(nodes_by_line_number)
63
+ end
64
+ end
65
+
66
+ def tokens_by_line_number
67
+ @tokens_by_line_number ||= begin
68
+ nodes_by_line_number = tokens.group_by { |token| token.location.line }
69
+ Hash.new { |hash, key| hash[key] = [] }.merge(nodes_by_line_number)
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,21 @@
1
+ module RSpec
2
+ module Support
3
+ class Source
4
+ # @private
5
+ # Represents a source location of node or token.
6
+ Location = Struct.new(:line, :column) do
7
+ include Comparable
8
+
9
+ def self.location?(array)
10
+ array.is_a?(Array) && array.size == 2 && array.all? { |e| e.is_a?(Integer) }
11
+ end
12
+
13
+ def <=>(other)
14
+ line_comparison = (line <=> other.line)
15
+ return line_comparison unless line_comparison == 0
16
+ column <=> other.column
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,107 @@
1
+ RSpec::Support.require_rspec_support 'source/location'
2
+
3
+ module RSpec
4
+ module Support
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
+ ExpressionSequenceNode.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
+ # Basically `Ripper.sexp` generates arrays whose first element is a symbol (type of sexp),
81
+ # but it exceptionally generates typeless arrays for expression sequence:
82
+ #
83
+ # Ripper.sexp('foo; bar')
84
+ # => [
85
+ # :program,
86
+ # [ # Typeless array
87
+ # [:vcall, [:@ident, "foo", [1, 0]]],
88
+ # [:vcall, [:@ident, "bar", [1, 5]]]
89
+ # ]
90
+ # ]
91
+ #
92
+ # We wrap typeless arrays in this pseudo type node
93
+ # so that it can be handled in the same way as other type node.
94
+ class ExpressionSequenceNode < Node
95
+ def type
96
+ :_expression_sequence
97
+ end
98
+
99
+ private
100
+
101
+ def raw_args
102
+ sexp
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,87 @@
1
+ RSpec::Support.require_rspec_support 'source/location'
2
+
3
+ module RSpec
4
+ module Support
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
@@ -3,40 +3,57 @@ module RSpec
3
3
  module InSubProcess
4
4
  if Process.respond_to?(:fork) && !(Ruby.jruby? && RUBY_VERSION == '1.8.7')
5
5
 
6
+ UnmarshableObject = Struct.new(:error)
7
+
6
8
  # Useful as a way to isolate a global change to a subprocess.
7
9
 
8
10
  # rubocop:disable MethodLength
9
11
  def in_sub_process(prevent_warnings=true)
10
- readme, writeme = IO.pipe
12
+ exception_reader, exception_writer = IO.pipe
13
+ result_reader, result_writer = IO.pipe
11
14
 
12
15
  pid = Process.fork do
13
- exception = nil
14
16
  warning_preventer = $stderr = RSpec::Support::StdErrSplitter.new($stderr)
15
17
 
16
18
  begin
17
- yield
19
+ result = yield
18
20
  warning_preventer.verify_no_warnings! if prevent_warnings
19
- rescue Support::AllExceptionsExceptOnesWeMustNotRescue => e
20
- exception = e
21
+ # rubocop:disable Lint/HandleExceptions
22
+ rescue Support::AllExceptionsExceptOnesWeMustNotRescue => exception
23
+ # rubocop:enable Lint/HandleExceptions
21
24
  end
22
25
 
23
- writeme.write Marshal.dump(exception)
26
+ exception_writer.write marshal_dump_with_unmarshable_object_handling(exception)
27
+ exception_reader.close
28
+ exception_writer.close
29
+
30
+ result_writer.write marshal_dump_with_unmarshable_object_handling(result)
31
+ result_reader.close
32
+ result_writer.close
24
33
 
25
- readme.close
26
- writeme.close
27
34
  exit! # prevent at_exit hooks from running (e.g. minitest)
28
35
  end
29
36
 
30
- writeme.close
37
+ exception_writer.close
38
+ result_writer.close
31
39
  Process.waitpid(pid)
32
40
 
33
- exception = Marshal.load(readme.read)
34
- readme.close
35
-
41
+ exception = Marshal.load(exception_reader.read)
42
+ exception_reader.close
36
43
  raise exception if exception
44
+
45
+ result = Marshal.load(result_reader.read)
46
+ result_reader.close
47
+ result
37
48
  end
38
49
  # rubocop:enable MethodLength
39
50
  alias :in_sub_process_if_possible :in_sub_process
51
+
52
+ def marshal_dump_with_unmarshable_object_handling(object)
53
+ Marshal.dump(object)
54
+ rescue TypeError => error
55
+ Marshal.dump(UnmarshableObject.new(error))
56
+ end
40
57
  else
41
58
  def in_sub_process(*)
42
59
  skip "This spec requires forking to work properly, " \
@@ -1,7 +1,7 @@
1
1
  module RSpec
2
2
  module Support
3
3
  module Version
4
- STRING = '3.6.0.beta2'
4
+ STRING = '3.6.0'
5
5
  end
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-support
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
  - David Chelimsky
@@ -48,7 +48,7 @@ cert_chain:
48
48
  ZsVDj6a7lH3cNqtWXZxrb2wO38qV5AkYj8SQK7Hj3/Yui9myUX3crr+PdetazSqQ
49
49
  F3MdtaDehhjC
50
50
  -----END CERTIFICATE-----
51
- date: 2016-12-12 00:00:00.000000000 Z
51
+ date: 2017-05-04 00:00:00.000000000 Z
52
52
  dependencies:
53
53
  - !ruby/object:Gem::Dependency
54
54
  name: bundler
@@ -116,6 +116,10 @@ files:
116
116
  - lib/rspec/support/recursive_const_methods.rb
117
117
  - lib/rspec/support/reentrant_mutex.rb
118
118
  - lib/rspec/support/ruby_features.rb
119
+ - lib/rspec/support/source.rb
120
+ - lib/rspec/support/source/location.rb
121
+ - lib/rspec/support/source/node.rb
122
+ - lib/rspec/support/source/token.rb
119
123
  - lib/rspec/support/spec.rb
120
124
  - lib/rspec/support/spec/deprecation_helpers.rb
121
125
  - lib/rspec/support/spec/formatting_support.rb
@@ -144,13 +148,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
144
148
  version: 1.8.7
145
149
  required_rubygems_version: !ruby/object:Gem::Requirement
146
150
  requirements:
147
- - - ">"
151
+ - - ">="
148
152
  - !ruby/object:Gem::Version
149
- version: 1.3.1
153
+ version: '0'
150
154
  requirements: []
151
155
  rubyforge_project:
152
- rubygems_version: 2.2.2
156
+ rubygems_version: 2.4.5.2
153
157
  signing_key:
154
158
  specification_version: 4
155
- summary: rspec-support-3.6.0.beta2
159
+ summary: rspec-support-3.6.0
156
160
  test_files: []
metadata.gz.sig CHANGED
Binary file