1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
#!/usr/bin/env ruby
# Removes old version guards in ruby/spec.
# Run it from the ruby/spec repository root.
# The argument is the new minimum supported version.
#
# cd spec
# ../mspec/tool/remove_old_guards.rb <ruby-version>
#
# where <ruby-version> is a version guard with which should be removed
#
# Example:
# tool/remove_old_guards.rb 3.1
#
# As a result guards like
# ruby_version_is "3.1" do
# # ...
# end
#
# will be removed.
def dedent(line)
if line.start_with?(" ")
line[2..-1]
else
line
end
end
def each_spec_file(&block)
Dir["*/**/*.rb"].each(&block)
end
def remove_guards(guard, keep)
each_spec_file do |file|
contents = File.binread(file)
if contents =~ guard
puts file
lines = contents.lines.to_a
while first = lines.find_index { |line| line =~ guard }
comment = first
while comment > 0 and lines[comment-1] =~ /^(\s*)#/
comment -= 1
end
indent = lines[first][/^(\s*)/, 1].length
last = (first+1...lines.size).find { |i|
space = lines[i][/^(\s*)end$/, 1] and space.length == indent
}
raise file unless last
if keep
lines[comment..last] = lines[first+1..last-1].map { |l| dedent(l) }
else
if comment > 0 and lines[comment-1] == "\n"
comment -= 1
elsif lines[last+1] == "\n"
last += 1
end
lines[comment..last] = []
end
end
File.binwrite file, lines.join
end
end
end
def remove_empty_files
each_spec_file do |file|
unless file.include?("fixtures/")
lines = File.readlines(file)
if lines.all? { |line| line.chomp.empty? or line.start_with?('require', '#') }
puts "Removing empty file #{file}"
File.delete(file)
end
end
end
end
def remove_unused_shared_specs
shared_groups = {}
# Dir["**/shared/**/*.rb"].each do |shared|
each_spec_file do |shared|
next if File.basename(shared) == 'constants.rb'
contents = File.binread(shared)
found = false
contents.scan(/^\s*describe (:[\w_?]+), shared: true do$/) {
shared_groups[$1] = 0
found = true
}
if !found and shared.include?('shared/') and !shared.include?('fixtures/') and !shared.end_with?('/constants.rb')
puts "no shared describe in #{shared} ?"
end
end
each_spec_file do |file|
contents = File.binread(file)
contents.scan(/(?:it_behaves_like|it_should_behave_like) (:[\w_?]+)[,\s]/) do
puts $1 unless shared_groups.key?($1)
shared_groups[$1] += 1
end
end
shared_groups.each_pair do |group, value|
if value == 0
puts "Shared describe #{group} seems unused"
elsif value == 1
puts "Shared describe #{group} seems used only once" if $VERBOSE
end
end
end
def search(regexp)
each_spec_file do |file|
contents = File.binread(file)
if contents =~ regexp
puts file
contents.each_line do |line|
if line =~ regexp
puts line
end
end
end
end
end
abort "usage: #{$0} <ruby-version>" if ARGV.empty?
version = Regexp.escape(ARGV.fetch(0))
version += "(?:\\.0)?" if version.count(".") < 2
remove_guards(/ruby_version_is (["'])#{version}\1 do/, true)
remove_guards(/ruby_version_is (["'])[0-9.]*\1 *... *(["'])#{version}\2 do/, false)
remove_guards(/ruby_bug ["']#\d+["'], (["'])[0-9.]*\1 *... *(["'])#{version}\2 do/, true)
remove_empty_files
remove_unused_shared_specs
puts "Search:"
search(/(["'])#{version}\1/)
search(/^\s*#.+#{version}/)
|