blob: bce9e32ba89a2e9383865789d58c16ea611a7f50 (
plain)
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
|
def contiguous_use_block(root_dir)
pattern = root_dir.join('crates', '**', '*.rs').to_s
errors = Dir.glob(pattern).sort.flat_map do |path|
relative = Pathname.new(path).relative_path_from(root_dir).to_s
find_split_use_block(path, relative)
end
return true if errors.empty?
puts 'Found blank lines splitting the leading `use` block into sections.'
puts 'All `use` statements at the top of the file must be contiguous (no blank lines between them):'
errors.each do |err|
puts " #{err}"
end
false
end
USE_START_RE = /\A(?:pub(?:\([^)]*\))?\s+)?use\b/
def find_split_use_block(path, relative)
lines = File.readlines(path)
errors = []
i = skip_preamble(lines)
return [] if i.nil?
loop do
i = consume_use_statement(lines, i)
break if i >= lines.length
blanks = []
j = i
while j < lines.length
stripped = lines[j].strip
if stripped.empty?
blanks << j
j += 1
elsif stripped.start_with?('//') || stripped.start_with?('#[')
j += 1
else
break
end
end
if j < lines.length && lines[j].strip =~ USE_START_RE
blanks.each do |bi|
errors << "#{relative}:#{bi + 1}: blank line splits the leading `use` block"
end
i = j
else
break
end
end
errors
end
def skip_preamble(lines)
lines.each_with_index do |raw, idx|
stripped = raw.strip
return idx if stripped =~ USE_START_RE
next if stripped.empty? || stripped.start_with?('//') || stripped.start_with?('#![') || stripped.start_with?('#[')
return nil
end
nil
end
def consume_use_statement(lines, start_idx)
brace_depth = 0
i = start_idx
while i < lines.length
line = lines[i]
brace_depth += line.count('{') - line.count('}')
done = brace_depth <= 0 && line.rstrip.end_with?(';')
i += 1
return i if done
end
i
end
|