Skip to content
This repository was archived by the owner on Nov 30, 2024. It is now read-only.

Commit 81e33d4

Browse files
committed
Merge pull request #245 from rspec/ripper-support-detection
Add RubyFeatures.ripper_supported?
2 parents 36abad6 + ea46730 commit 81e33d4

File tree

6 files changed

+209
-0
lines changed

6 files changed

+209
-0
lines changed

Changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ Enhancements:
44

55
* Improve formatting of `Delegator` based objects (e.g. `SimpleDelgator`) in
66
failure messages and diffs. (Andrew Horner, #215)
7+
* Add `ComparableVersion`. (Yuji Nakayama, #245)
8+
* Add `Ripper` support detection. (Yuji Nakayama, #245)
79

810
Bug Fixes:
911

benchmarks/ripper.rb

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
require 'benchmark/ips'
2+
require 'ripper'
3+
4+
ruby_version = defined?(JRUBY_VERSION) ? JRUBY_VERSION : RUBY_VERSION
5+
puts "#{RUBY_ENGINE} #{ruby_version}"
6+
7+
source = File.read(__FILE__)
8+
9+
Benchmark.ips do |x|
10+
x.report("Ripper") do
11+
Ripper.sexp(source)
12+
Ripper.lex(source)
13+
end
14+
end
15+
16+
__END__
17+
18+
ruby 1.9.3
19+
Calculating -------------------------------------
20+
Ripper 284.000 i/100ms
21+
22+
ruby 2.2.3
23+
Calculating -------------------------------------
24+
Ripper 320.000 i/100ms
25+
26+
jruby 1.7.5
27+
Calculating -------------------------------------
28+
Ripper 24.000 i/100ms
29+
30+
jruby 1.7.13
31+
Calculating -------------------------------------
32+
Ripper 25.000 i/100ms
33+
34+
jruby 1.7.14
35+
Calculating -------------------------------------
36+
Ripper 239.000 i/100ms
37+
38+
jruby 1.7.22
39+
Calculating -------------------------------------
40+
Ripper 231.000 i/100ms
41+
42+
jruby 9.0.1.0
43+
Calculating -------------------------------------
44+
Ripper 218.000 i/100ms
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
module RSpec
2+
module Support
3+
# @private
4+
class ComparableVersion
5+
include Comparable
6+
7+
attr_reader :string
8+
9+
def initialize(string)
10+
@string = string
11+
end
12+
13+
def <=>(other)
14+
other = self.class.new(other) unless other.is_a?(self.class)
15+
16+
return 0 if string == other.string
17+
18+
longer_segment_count = [self, other].map { |version| version.segments.count }.max
19+
20+
longer_segment_count.times do |index|
21+
self_segment = segments[index] || 0
22+
other_segment = other.segments[index] || 0
23+
24+
if self_segment.class == other_segment.class
25+
result = self_segment <=> other_segment
26+
return result unless result == 0
27+
else
28+
return self_segment.is_a?(String) ? -1 : 1
29+
end
30+
end
31+
32+
0
33+
end
34+
35+
def segments
36+
@segments ||= string.scan(/[a-z]+|\d+/i).map do |segment|
37+
if segment =~ /\A\d+\z/
38+
segment.to_i
39+
else
40+
segment
41+
end
42+
end
43+
end
44+
end
45+
end
46+
end

lib/rspec/support/ruby_features.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
require 'rbconfig'
2+
RSpec::Support.require_rspec_support "comparable_version"
23

34
module RSpec
45
module Support
@@ -65,6 +66,24 @@ def supports_exception_cause?
6566
end
6667
end
6768

69+
ripper_requirements = [ComparableVersion.new(RUBY_VERSION) >= '1.9.2']
70+
71+
if Ruby.jruby?
72+
ripper_requirements.push(ComparableVersion.new(JRUBY_VERSION) >= '1.7.5')
73+
# Ripper on JRuby 9.0.0.0.rc1 or later reports wrong line number.
74+
ripper_requirements.push(ComparableVersion.new(JRUBY_VERSION) < '9.0.0.0.rc1')
75+
end
76+
77+
if ripper_requirements.all?
78+
def ripper_supported?
79+
true
80+
end
81+
else
82+
def ripper_supported?
83+
false
84+
end
85+
end
86+
6887
if Ruby.mri?
6988
def kw_args_supported?
7089
RUBY_VERSION >= '2.0.0'
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
require 'rspec/support/comparable_version'
2+
3+
module RSpec::Support
4+
describe ComparableVersion do
5+
describe '#<=>' do
6+
[
7+
['1.2.3', '1.2.3', 0],
8+
['1.2.4', '1.2.3', 1],
9+
['1.3.0', '1.2.3', 1],
10+
['1.2.3', '1.2.4', -1],
11+
['1.2.3', '1.3.0', -1],
12+
['1.2.10', '1.2.3', 1],
13+
['1.2.3', '1.2.10', -1],
14+
['1.2.3.0', '1.2.3', 0],
15+
['1.2.3', '1.2.3.0', 0],
16+
['1.2.3.1', '1.2.3', 1],
17+
['1.2.3.1', '1.2.3.0', 1],
18+
['1.2.3', '1.2.3.1', -1],
19+
['1.2.3.0', '1.2.3.1', -1],
20+
['1.2.3.rc1', '1.2.3', -1],
21+
['1.2.3.rc1', '1.2.3.rc2', -1],
22+
['1.2.3.rc2', '1.2.3.rc10', -1],
23+
['1.2.3.alpha2', '1.2.3.beta1', -1],
24+
['1.2.3', '1.2.3.rc1', 1],
25+
['1.2.3.rc2', '1.2.3.rc1', 1],
26+
['1.2.3.rc10', '1.2.3.rc2', 1],
27+
['1.2.3.beta1', '1.2.3.alpha2', 1]
28+
].each do |subject_string, other_string, expected|
29+
context "with #{subject_string.inspect} and #{other_string.inspect}" do
30+
subject do
31+
ComparableVersion.new(subject_string) <=> ComparableVersion.new(other_string)
32+
end
33+
34+
it { should eq(expected) }
35+
end
36+
end
37+
end
38+
end
39+
end

spec/rspec/support/ruby_features_spec.rb

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,65 @@ module Support
8181
expect(RubyFeatures.caller_locations_supported?).to eq(RUBY_VERSION >= '2.0.0')
8282
end
8383
end
84+
85+
describe "#ripper_supported?" do
86+
it 'does not load Ripper' do
87+
expect { RubyFeatures.ripper_supported? }.not_to change { defined?(::Ripper) }
88+
end
89+
90+
describe 'Ripper' do
91+
let(:line_number) do
92+
token = tokens.first
93+
location = token.first
94+
location.first
95+
end
96+
97+
let(:tokens) do
98+
require 'ripper'
99+
::Ripper.lex('foo')
100+
end
101+
102+
if Ruby.mri?
103+
context 'on MRI' do
104+
context '1.8.x', :if => RUBY_VERSION.start_with?('1.8.') do
105+
it 'is not supported' do
106+
expect { tokens }.to raise_error(LoadError)
107+
end
108+
end
109+
110+
context '1.9.x or later', :if => RUBY_VERSION >= '1.9' do
111+
it 'is supported' do
112+
expect(line_number).to eq(1)
113+
end
114+
end
115+
end
116+
end
117+
118+
if Ruby.jruby?
119+
context 'on JRuby' do
120+
context '1.7.x', :if => JRUBY_VERSION.start_with?('1.7.') do
121+
context 'in 1.8 mode', :if => RUBY_VERSION.start_with?('1.8.') do
122+
it 'is not supported' do
123+
expect { tokens }.to raise_error(NameError)
124+
end
125+
end
126+
127+
context 'in non 1.8 mode', :unless => RUBY_VERSION.start_with?('1.8.') do
128+
it 'is supported' do
129+
expect(line_number).to eq(1)
130+
end
131+
end
132+
end
133+
134+
context '9.x.x.x', :if => JRUBY_VERSION.start_with?('9.') do
135+
it 'reports wrong line number' do
136+
expect(line_number).to eq(2)
137+
end
138+
end
139+
end
140+
end
141+
end
142+
end
84143
end
85144
end
86145
end

0 commit comments

Comments
 (0)