rubocop-crystal 0.0.2 → 0.0.4
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 +4 -4
- data/.github/workflows/rspec.yml +16 -0
- data/.github/workflows/rubocop.yml +16 -0
- data/.github/workflows/test.yml +1 -1
- data/.rspec +1 -0
- data/.rubocop.yml +37 -0
- data/CHANGELOG.md +26 -0
- data/README.md +6 -2
- data/config/default.yml +36 -1
- data/lib/rubocop/cop/crystal/enumerable_reduce.rb +58 -0
- data/lib/rubocop/cop/crystal/enumerable_size.rb +31 -0
- data/lib/rubocop/cop/crystal/file_extension.rb +1 -0
- data/lib/rubocop/cop/crystal/file_read_lines.rb +115 -0
- data/lib/rubocop/cop/crystal/interpolation_in_single_quotes.rb +3 -2
- data/lib/rubocop/cop/crystal/method_name_starting_with_uppercase_letter.rb +30 -0
- data/lib/rubocop/cop/crystal/method_returning_char.rb +54 -0
- data/lib/rubocop/cop/crystal/require_at_top_level.rb +35 -0
- data/lib/rubocop/cop/crystal/require_relative.rb +6 -5
- data/lib/rubocop/cop/crystal_cops.rb +6 -0
- data/lib/rubocop/crystal/plugin.rb +28 -0
- data/lib/rubocop-crystal.rb +1 -3
- data/rubocop-crystal.gemspec +5 -2
- data/spec/rubocop/cop/crystal/enumerable_reduce_spec.rb +101 -0
- data/spec/rubocop/cop/crystal/enumerable_size_spec.rb +64 -0
- data/spec/rubocop/cop/crystal/file_read_lines_spec.rb +156 -0
- data/spec/rubocop/cop/crystal/interpolation_in_single_quotes_spec.rb +30 -0
- data/spec/rubocop/cop/crystal/method_name_starting_with_uppercase_letter_spec.rb +35 -0
- data/spec/rubocop/cop/crystal/method_returning_char_spec.rb +150 -0
- data/spec/rubocop/cop/crystal/require_at_top_level_spec.rb +42 -0
- data/spec/rubocop/cop/crystal/require_relative_spec.rb +51 -0
- data/spec/spec_helper.rb +12 -0
- data/test/string.rb +55 -0
- metadata +41 -11
- data/lib/rubocop/crystal/inject.rb +0 -15
@@ -0,0 +1,101 @@
|
|
1
|
+
RSpec.describe RuboCop::Cop::Crystal::EnumerableReduce, :config do
|
2
|
+
it 'registers an offense when .inject is used with a block and no initial value' do
|
3
|
+
expect_offense(<<~RUBY)
|
4
|
+
x.inject { |r,v| r + v }
|
5
|
+
^^^^^^ Crystal has .reduce instead of .inject
|
6
|
+
RUBY
|
7
|
+
|
8
|
+
expect_correction(<<~RUBY)
|
9
|
+
x.reduce { |r,v| r + v }
|
10
|
+
RUBY
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'registers an offense when &.inject is used with a block and no initial value' do
|
14
|
+
expect_offense(<<~RUBY)
|
15
|
+
x&.inject { |r,v| r + v }
|
16
|
+
^^^^^^ Crystal has .reduce instead of .inject
|
17
|
+
RUBY
|
18
|
+
|
19
|
+
expect_correction(<<~RUBY)
|
20
|
+
x&.reduce { |r,v| r + v }
|
21
|
+
RUBY
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'registers an offense when .inject is used with a block and an initial value' do
|
25
|
+
expect_offense(<<~RUBY)
|
26
|
+
x.inject(y) { |r,v| r + v }
|
27
|
+
^^^^^^ Crystal has .reduce instead of .inject
|
28
|
+
RUBY
|
29
|
+
|
30
|
+
expect_correction(<<~RUBY)
|
31
|
+
x.reduce(y) { |r,v| r + v }
|
32
|
+
RUBY
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'registers an offense when .inject is used with a reducer function and no initial value' do
|
36
|
+
expect_offense(<<~RUBY)
|
37
|
+
x.inject(:+)
|
38
|
+
^^^^^^ Crystal has .reduce instead of .inject
|
39
|
+
RUBY
|
40
|
+
|
41
|
+
expect_correction(<<~RUBY)
|
42
|
+
x.reduce { |r,v| r.+(v) }
|
43
|
+
RUBY
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'registers an offense when .inject is used with a reducer function and an initial value' do
|
47
|
+
expect_offense(<<~RUBY)
|
48
|
+
x.inject(4, :+)
|
49
|
+
^^^^^^ Crystal has .reduce instead of .inject
|
50
|
+
RUBY
|
51
|
+
|
52
|
+
expect_correction(<<~RUBY)
|
53
|
+
x.reduce(4) { |r,v| r.+(v) }
|
54
|
+
RUBY
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'registers an offense when .reduce is used with a reducer function and no initial value' do
|
58
|
+
expect_offense(<<~RUBY)
|
59
|
+
x.reduce(:prepend)
|
60
|
+
^^^^^^ Crystal has .reduce instead of .inject
|
61
|
+
RUBY
|
62
|
+
|
63
|
+
expect_correction(<<~RUBY)
|
64
|
+
x.reduce { |r,v| r.prepend(v) }
|
65
|
+
RUBY
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'registers an offense when &.reduce is used with a reducer function and no initial value' do
|
69
|
+
expect_offense(<<~RUBY)
|
70
|
+
x&.reduce(:prepend)
|
71
|
+
^^^^^^ Crystal has .reduce instead of .inject
|
72
|
+
RUBY
|
73
|
+
|
74
|
+
expect_correction(<<~RUBY)
|
75
|
+
x&.reduce { |r,v| r.prepend(v) }
|
76
|
+
RUBY
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'registers an offense when .reduce is used with a reducer function and an initial value' do
|
80
|
+
expect_offense(<<~RUBY)
|
81
|
+
x.reduce("foo", :prepend)
|
82
|
+
^^^^^^ Crystal has .reduce instead of .inject
|
83
|
+
RUBY
|
84
|
+
|
85
|
+
expect_correction(<<~RUBY)
|
86
|
+
x.reduce("foo") { |r,v| r.prepend(v) }
|
87
|
+
RUBY
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'does not register an offense when .reduce is used with a block and no initial value' do
|
91
|
+
expect_no_offenses(<<~RUBY)
|
92
|
+
x.reduce { |r,v| r + v }
|
93
|
+
RUBY
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'does not register an offense when &.reduce is used with a block and no initial value' do
|
97
|
+
expect_no_offenses(<<~RUBY)
|
98
|
+
x&.reduce { |r,v| r + v }
|
99
|
+
RUBY
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
RSpec.describe RuboCop::Cop::Crystal::EnumerableSize, :config do
|
2
|
+
it 'registers an offense when .length is used' do
|
3
|
+
expect_offense(<<~RUBY)
|
4
|
+
x.length
|
5
|
+
^^^^^^ Crystal does not have the .length or .count methods as aliases to .size
|
6
|
+
RUBY
|
7
|
+
|
8
|
+
expect_correction(<<~RUBY)
|
9
|
+
x.size
|
10
|
+
RUBY
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'registers an offense when &.length is used' do
|
14
|
+
expect_offense(<<~RUBY)
|
15
|
+
x&.length
|
16
|
+
^^^^^^ Crystal does not have the .length or .count methods as aliases to .size
|
17
|
+
RUBY
|
18
|
+
|
19
|
+
expect_correction(<<~RUBY)
|
20
|
+
x&.size
|
21
|
+
RUBY
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'registers an offense when .count is used with no argument and no block' do
|
25
|
+
expect_offense(<<~RUBY)
|
26
|
+
x.count
|
27
|
+
^^^^^ Crystal does not have the .length or .count methods as aliases to .size
|
28
|
+
RUBY
|
29
|
+
|
30
|
+
expect_correction(<<~RUBY)
|
31
|
+
x.size
|
32
|
+
RUBY
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'does not register an offense when .count is used with an argument and no block' do
|
36
|
+
expect_no_offenses(<<~RUBY)
|
37
|
+
x.count(y)
|
38
|
+
RUBY
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'does not register an offense when &.count is used with an argument and no block' do
|
42
|
+
expect_no_offenses(<<~RUBY)
|
43
|
+
x&.count(y)
|
44
|
+
RUBY
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'does not register an offense when .count is used with a block and no argument' do
|
48
|
+
expect_no_offenses(<<~RUBY)
|
49
|
+
x.count {|e| e > 2 }
|
50
|
+
RUBY
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'does not register an offense when .count is used with an argument and a block' do
|
54
|
+
expect_no_offenses(<<~RUBY)
|
55
|
+
x.count(y) {|e| e > 2 }
|
56
|
+
RUBY
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'does not register an offense when .size is used' do
|
60
|
+
expect_no_offenses(<<~RUBY)
|
61
|
+
x.size
|
62
|
+
RUBY
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
RSpec.describe RuboCop::Cop::Crystal::FileReadLines, :config do
|
2
|
+
it 'registers an offense when File.readlines is used with a path argument' do
|
3
|
+
expect_offense(<<~RUBY)
|
4
|
+
File.readlines("foo")
|
5
|
+
^^^^^^^^^ Ruby has IO.readlines, while Crystal has File.read_lines and IO.each_line
|
6
|
+
RUBY
|
7
|
+
|
8
|
+
expect_correction(<<~RUBY)
|
9
|
+
File.read_lines("foo", chomp: false)
|
10
|
+
RUBY
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'registers an offense when IO.readlines is used with a path argument' do
|
14
|
+
expect_offense(<<~RUBY)
|
15
|
+
IO.readlines("foo")
|
16
|
+
^^^^^^^^^ Ruby has IO.readlines, while Crystal has File.read_lines and IO.each_line
|
17
|
+
RUBY
|
18
|
+
|
19
|
+
expect_correction(<<~RUBY)
|
20
|
+
File.read_lines("foo", chomp: false)
|
21
|
+
RUBY
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'registers an offense when File.readlines is used with a path argument and chomp: false' do
|
25
|
+
expect_offense(<<~RUBY)
|
26
|
+
File.readlines("foo", chomp: false)
|
27
|
+
^^^^^^^^^ Ruby has IO.readlines, while Crystal has File.read_lines and IO.each_line
|
28
|
+
RUBY
|
29
|
+
|
30
|
+
expect_correction(<<~RUBY)
|
31
|
+
File.read_lines("foo", chomp: false)
|
32
|
+
RUBY
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'registers an offense when File.readlines is used with a path argument and chomp: true' do
|
36
|
+
expect_offense(<<~RUBY)
|
37
|
+
File.readlines("foo", chomp: true)
|
38
|
+
^^^^^^^^^ Ruby has IO.readlines, while Crystal has File.read_lines and IO.each_line
|
39
|
+
RUBY
|
40
|
+
|
41
|
+
expect_correction(<<~RUBY)
|
42
|
+
File.read_lines("foo", chomp: true)
|
43
|
+
RUBY
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'registers an offense when File.readlines is used with a path and a single-character separator argument' do
|
47
|
+
expect_offense(<<~RUBY)
|
48
|
+
File.readlines("foo", "a")
|
49
|
+
^^^^^^^^^ Ruby has IO.readlines, while Crystal has File.read_lines and IO.each_line
|
50
|
+
RUBY
|
51
|
+
|
52
|
+
expect_correction(<<~RUBY)
|
53
|
+
File.open("foo").each_line("a").to_a
|
54
|
+
RUBY
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'registers an offense when File.readlines is used with a path and a multi-character separator argument' do
|
58
|
+
expect_offense(<<~RUBY)
|
59
|
+
File.readlines("foo", "quz")
|
60
|
+
^^^^^^^^^ Ruby has IO.readlines, while Crystal has File.read_lines and IO.each_line
|
61
|
+
RUBY
|
62
|
+
|
63
|
+
expect_correction(<<~RUBY)
|
64
|
+
File.open("foo").each_line("quz").to_a
|
65
|
+
RUBY
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'registers an offense when File.readlines is used with a path and a nil separator argument' do
|
69
|
+
expect_offense(<<~RUBY)
|
70
|
+
File.readlines("foo", nil)
|
71
|
+
^^^^^^^^^ Ruby has IO.readlines, while Crystal has File.read_lines and IO.each_line
|
72
|
+
RUBY
|
73
|
+
|
74
|
+
expect_correction(<<~RUBY)
|
75
|
+
[File.open("foo").each_line(chomp: false).to_a.join]
|
76
|
+
RUBY
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'registers an offense when File.readlines is used with a path and an empty string separator argument' do
|
80
|
+
expect_offense(<<~RUBY)
|
81
|
+
File.readlines("foo", "")
|
82
|
+
^^^^^^^^^ Ruby has IO.readlines, while Crystal has File.read_lines and IO.each_line
|
83
|
+
RUBY
|
84
|
+
|
85
|
+
expect_correction(<<~'RUBY')
|
86
|
+
File.open("foo").each_line("\n").to_a.join.split(/\n{2,}/).reject { |e| e.empty? }.reverse.map_with_index {|e, i| i == 0 ? e : "#{e}\n\n" }.reverse
|
87
|
+
RUBY
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'registers an offense when File.readlines is used with a path and a limiter argument' do
|
91
|
+
expect_offense(<<~RUBY)
|
92
|
+
File.readlines("foo", 2)
|
93
|
+
^^^^^^^^^ Ruby has IO.readlines, while Crystal has File.read_lines and IO.each_line
|
94
|
+
RUBY
|
95
|
+
|
96
|
+
expect_correction(<<~RUBY)
|
97
|
+
File.open("foo").each_line(2).to_a
|
98
|
+
RUBY
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'registers an offense when File.readlines is used with a path, single-character separator, and limiter argument' do
|
102
|
+
expect_offense(<<~RUBY)
|
103
|
+
File.readlines("foo", "b", 3)
|
104
|
+
^^^^^^^^^ Ruby has IO.readlines, while Crystal has File.read_lines and IO.each_line
|
105
|
+
RUBY
|
106
|
+
|
107
|
+
expect_correction(<<~RUBY)
|
108
|
+
File.open("foo").each_line("b", 3).to_a
|
109
|
+
RUBY
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'registers an offense when File.readlines is used with a path, multi-character separator, and limiter argument' do
|
113
|
+
expect_offense(<<~RUBY)
|
114
|
+
File.readlines("foo", "quz", 3)
|
115
|
+
^^^^^^^^^ Ruby has IO.readlines, while Crystal has File.read_lines and IO.each_line
|
116
|
+
RUBY
|
117
|
+
|
118
|
+
expect_correction(<<~RUBY)
|
119
|
+
File.open("foo").each_line("quz", 3).to_a
|
120
|
+
RUBY
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'registers an offense when .readlines is used on a File object' do
|
124
|
+
expect_offense(<<~RUBY)
|
125
|
+
File.open("foo").readlines
|
126
|
+
^^^^^^^^^ Ruby has IO.readlines, while Crystal has File.read_lines and IO.each_line
|
127
|
+
RUBY
|
128
|
+
|
129
|
+
expect_correction(<<~RUBY)
|
130
|
+
File.open("foo").each_line.to_a
|
131
|
+
RUBY
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'registers an offense when .readlines is used on a chained File object' do
|
135
|
+
expect_offense(<<~RUBY)
|
136
|
+
File.new(File.expand_path("foo", "bar")).readlines
|
137
|
+
^^^^^^^^^ Ruby has IO.readlines, while Crystal has File.read_lines and IO.each_line
|
138
|
+
RUBY
|
139
|
+
|
140
|
+
expect_correction(<<~RUBY)
|
141
|
+
File.new(File.expand_path("foo", "bar")).each_line.to_a
|
142
|
+
RUBY
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'does not register an offense when .readlines is used from a non File/IO class' do
|
146
|
+
expect_no_offenses(<<~RUBY)
|
147
|
+
Bar.readlines("foo")
|
148
|
+
RUBY
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'does not register an offense when .readlines is used on a non File/IO object' do
|
152
|
+
expect_no_offenses(<<~RUBY)
|
153
|
+
Bar.open("foo").readlines
|
154
|
+
RUBY
|
155
|
+
end
|
156
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
RSpec.describe RuboCop::Cop::Crystal::InterpolationInSingleQuotes, :config do
|
2
|
+
it 'does not register an offense when a non-interpolated string is in double quotes' do
|
3
|
+
expect_no_offenses(<<~RUBY)
|
4
|
+
"foo"
|
5
|
+
RUBY
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'does not register an offense when an interpolated string is in double quotes' do
|
9
|
+
expect_no_offenses(<<~'RUBY')
|
10
|
+
"foo #{bar}"
|
11
|
+
RUBY
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'does not register an offense when a non-interpolated string is in single quotes' do
|
15
|
+
expect_no_offenses(<<~RUBY)
|
16
|
+
'foo'
|
17
|
+
RUBY
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'registers an offense when an interpolated string is in single quotes' do
|
21
|
+
expect_offense(<<~'RUBY')
|
22
|
+
'foo #{bar}'
|
23
|
+
^^^^^^^^^^^^ Crystal does not support the use of single-quote deliminated strings to avoid interpolation.
|
24
|
+
RUBY
|
25
|
+
|
26
|
+
expect_correction(<<~'RUBY')
|
27
|
+
%q(foo #{bar})
|
28
|
+
RUBY
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
RSpec.describe RuboCop::Cop::Crystal::MethodNameStartingWithUppercaseLetter, :config do
|
2
|
+
it 'registers an offense when the first letter of a method name is capitalized' do
|
3
|
+
expect_offense(<<~RUBY)
|
4
|
+
def Foo
|
5
|
+
^^^ Method names must start with a lowercase letter in Crystal.
|
6
|
+
bar
|
7
|
+
end
|
8
|
+
RUBY
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'registers an offense when all the letters of a method name are capitalized' do
|
12
|
+
expect_offense(<<~RUBY)
|
13
|
+
def FOO
|
14
|
+
^^^ Method names must start with a lowercase letter in Crystal.
|
15
|
+
bar
|
16
|
+
end
|
17
|
+
RUBY
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'does not register an offense when the first letter of a method name is lowercase' do
|
21
|
+
expect_no_offenses(<<~RUBY)
|
22
|
+
def foo
|
23
|
+
bar
|
24
|
+
end
|
25
|
+
RUBY
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'does not register an offense when the first letter of a method name is lowercase regardless of the rest of the method name' do
|
29
|
+
expect_no_offenses(<<~RUBY)
|
30
|
+
def fOO
|
31
|
+
bar
|
32
|
+
end
|
33
|
+
RUBY
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
RSpec.describe RuboCop::Cop::Crystal::MethodReturningChar, :config do
|
2
|
+
it 'registers an offense when .chars is used without converting the elements of the array to strings' do
|
3
|
+
expect_offense(<<~RUBY)
|
4
|
+
x.chars
|
5
|
+
^^^^^ In Crystal, this method returns the Char type instead of a 1-character string.
|
6
|
+
RUBY
|
7
|
+
|
8
|
+
expect_correction(<<~RUBY)
|
9
|
+
x.chars.map { |c| c.to_s }
|
10
|
+
RUBY
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'registers an offense when &.chars is used without converting the elements of the array to strings' do
|
14
|
+
expect_offense(<<~RUBY)
|
15
|
+
x&.chars
|
16
|
+
^^^^^ In Crystal, this method returns the Char type instead of a 1-character string.
|
17
|
+
RUBY
|
18
|
+
|
19
|
+
expect_correction(<<~RUBY)
|
20
|
+
x&.chars.map { |c| c.to_s }
|
21
|
+
RUBY
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'registers an offense when .chars is used in a chain ending in a block without converting the elements of the array to strings' do
|
25
|
+
expect_offense(<<~RUBY)
|
26
|
+
x.chars.each { |c| puts c}
|
27
|
+
^^^^^ In Crystal, this method returns the Char type instead of a 1-character string.
|
28
|
+
RUBY
|
29
|
+
|
30
|
+
expect_correction(<<~RUBY)
|
31
|
+
x.chars.map { |c| c.to_s }.each { |c| puts c}
|
32
|
+
RUBY
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'registers an offense when .chars is used on a string literal in a chain ending in a block without converting the elements of the array to strings' do
|
36
|
+
expect_offense(<<~RUBY)
|
37
|
+
"foo".chars.each { |c| puts c}
|
38
|
+
^^^^^ In Crystal, this method returns the Char type instead of a 1-character string.
|
39
|
+
RUBY
|
40
|
+
|
41
|
+
expect_correction(<<~RUBY)
|
42
|
+
"foo".chars.map { |c| c.to_s }.each { |c| puts c}
|
43
|
+
RUBY
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'registers an offense when .chars is used on a variable in a chain ending in a block without converting the elements of the array to strings' do
|
47
|
+
expect_offense(<<~RUBY)
|
48
|
+
x = "foo"
|
49
|
+
x.chars.each { |c| puts c}
|
50
|
+
^^^^^ In Crystal, this method returns the Char type instead of a 1-character string.
|
51
|
+
RUBY
|
52
|
+
|
53
|
+
expect_correction(<<~RUBY)
|
54
|
+
x = "foo"
|
55
|
+
x.chars.map { |c| c.to_s }.each { |c| puts c}
|
56
|
+
RUBY
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'registers an offense when .each_char is used without converting the character to a string' do
|
60
|
+
expect_offense(<<~RUBY)
|
61
|
+
x.each_char { |c| puts c }
|
62
|
+
^^^^^^^^^ In Crystal, this method returns the Char type instead of a 1-character string.
|
63
|
+
RUBY
|
64
|
+
|
65
|
+
expect_correction(<<~RUBY)
|
66
|
+
x.each_char { |c| puts c.to_s }
|
67
|
+
RUBY
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'registers an offense when .each_char with a multiline block is used without converting each instance of the character to a string' do
|
71
|
+
expect_offense(<<~RUBY)
|
72
|
+
x.each_char do |c|
|
73
|
+
^^^^^^^^^ In Crystal, this method returns the Char type instead of a 1-character string.
|
74
|
+
puts foo if c == y
|
75
|
+
bar
|
76
|
+
z << c
|
77
|
+
end
|
78
|
+
RUBY
|
79
|
+
|
80
|
+
expect_correction(<<~RUBY)
|
81
|
+
x.each_char do |c|
|
82
|
+
puts foo if c.to_s == y
|
83
|
+
bar
|
84
|
+
z << c.to_s
|
85
|
+
end
|
86
|
+
RUBY
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'does not register an an offense when .chars is used with converting the elements of the array to strings' do
|
90
|
+
expect_no_offenses(<<~RUBY)
|
91
|
+
x.chars.map { |c| c.to_s }
|
92
|
+
RUBY
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'does not register an an offense when &.chars is used with converting the elements of the array to strings' do
|
96
|
+
expect_no_offenses(<<~RUBY)
|
97
|
+
x&.chars.map { |c| c.to_s }
|
98
|
+
RUBY
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'does not register an offense when .chars is used in a chain ending in a block with converting the elements of the array to strings' do
|
102
|
+
expect_no_offenses(<<~RUBY)
|
103
|
+
x.chars.map { |c| c.to_s }.each { |c| puts c}
|
104
|
+
RUBY
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'does not register an offense when .chars is used on a string literal in a chain ending in a block with converting the elements of the array to strings' do
|
108
|
+
expect_no_offenses(<<~RUBY)
|
109
|
+
"foo".chars.map { |c| c.to_s }.each { |c| puts c}
|
110
|
+
RUBY
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'does not register an offense when .chars is used on a variable in a chain ending in a block with converting the elements of the array to strings' do
|
114
|
+
expect_no_offenses(<<~RUBY)
|
115
|
+
x = "foo"
|
116
|
+
x.chars.map { |c| c.to_s }.each { |c| puts c}
|
117
|
+
RUBY
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'does not register an offense when .each_char is used with converting the character to a string' do
|
121
|
+
expect_no_offenses(<<~RUBY)
|
122
|
+
x.each_char { |c| puts c.to_s }
|
123
|
+
RUBY
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'does not register an offense when .each_char with a multiline block is used with converting each instance of the character to a string' do
|
127
|
+
expect_no_offenses(<<~RUBY)
|
128
|
+
x.each_char do |c|
|
129
|
+
puts foo if c.to_s == y
|
130
|
+
bar
|
131
|
+
z << c.to_s
|
132
|
+
end
|
133
|
+
RUBY
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'does not register an offense when .each_char is used with no instances of the character' do
|
137
|
+
expect_no_offenses(<<~RUBY)
|
138
|
+
x.each_char { |c| puts x }
|
139
|
+
RUBY
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'does not register an offense when .each_char with a multiline block is used with no instances of the character' do
|
143
|
+
expect_no_offenses(<<~RUBY)
|
144
|
+
x.each_char do |c|
|
145
|
+
puts x
|
146
|
+
foo if y == z
|
147
|
+
end
|
148
|
+
RUBY
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
RSpec.describe RuboCop::Cop::Crystal::RequireAtTopLevel, :config do
|
2
|
+
it 'registers an offense when require is inside a function' do
|
3
|
+
expect_offense(<<~RUBY)
|
4
|
+
def foo
|
5
|
+
require 'bar'
|
6
|
+
^^^^^^^^^^^^^ Crystal does not allow require anywhere other than the top level.
|
7
|
+
end
|
8
|
+
RUBY
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'registers an offense when require is inside a class' do
|
12
|
+
expect_offense(<<~RUBY)
|
13
|
+
class Foo
|
14
|
+
require 'bar'
|
15
|
+
^^^^^^^^^^^^^ Crystal does not allow require anywhere other than the top level.
|
16
|
+
end
|
17
|
+
RUBY
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'registers an offense when require is inside a module' do
|
21
|
+
expect_offense(<<~RUBY)
|
22
|
+
module Foo
|
23
|
+
require 'bar'
|
24
|
+
^^^^^^^^^^^^^ Crystal does not allow require anywhere other than the top level.
|
25
|
+
end
|
26
|
+
RUBY
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'does not register an offense when require is at the top level' do
|
30
|
+
expect_no_offenses(<<~RUBY)
|
31
|
+
require 'bar'
|
32
|
+
RUBY
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'does not register an offense when a funciton does not contain require' do
|
36
|
+
expect_no_offenses(<<~RUBY)
|
37
|
+
def foo
|
38
|
+
bar
|
39
|
+
end
|
40
|
+
RUBY
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
RSpec.describe RuboCop::Cop::Crystal::RequireRelative, :config do
|
2
|
+
it 'registers an offense when requiring a file in the same directory' do
|
3
|
+
expect_offense(<<~RUBY)
|
4
|
+
require_relative 'foo'
|
5
|
+
^^^^^^^^^^^^^^^^^^^^^^ Crystal does not support require_relative.
|
6
|
+
RUBY
|
7
|
+
|
8
|
+
expect_correction(<<~RUBY)
|
9
|
+
require './foo'
|
10
|
+
RUBY
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'registers an offense when requiring a file path starting with ./' do
|
14
|
+
expect_offense(<<~RUBY)
|
15
|
+
require_relative './foo'
|
16
|
+
^^^^^^^^^^^^^^^^^^^^^^^^ Crystal does not support require_relative.
|
17
|
+
RUBY
|
18
|
+
|
19
|
+
expect_correction(<<~RUBY)
|
20
|
+
require './foo'
|
21
|
+
RUBY
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'registers an offense when requiring a file path starting with ../' do
|
25
|
+
expect_offense(<<~RUBY)
|
26
|
+
require_relative '../foo'
|
27
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^ Crystal does not support require_relative.
|
28
|
+
RUBY
|
29
|
+
|
30
|
+
expect_correction(<<~RUBY)
|
31
|
+
require '../foo'
|
32
|
+
RUBY
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'registers an offense when requiring a file path starting with /' do
|
36
|
+
expect_offense(<<~RUBY)
|
37
|
+
require_relative '/foo'
|
38
|
+
^^^^^^^^^^^^^^^^^^^^^^^ Crystal does not support require_relative.
|
39
|
+
RUBY
|
40
|
+
|
41
|
+
expect_correction(<<~RUBY)
|
42
|
+
require '/foo'
|
43
|
+
RUBY
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'does not register an offense on non-relative requires' do
|
47
|
+
expect_no_offenses(<<~RUBY)
|
48
|
+
require '../foo'
|
49
|
+
RUBY
|
50
|
+
end
|
51
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'rubocop-crystal'
|
2
|
+
require 'rubocop/rspec/support'
|
3
|
+
|
4
|
+
RSpec.configure do |config|
|
5
|
+
config.disable_monkey_patching!
|
6
|
+
config.raise_errors_for_deprecations!
|
7
|
+
config.raise_on_warning = true
|
8
|
+
config.fail_if_no_examples = true
|
9
|
+
|
10
|
+
config.order = :random
|
11
|
+
Kernel.srand config.seed
|
12
|
+
end
|