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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rspec.yml +16 -0
  3. data/.github/workflows/rubocop.yml +16 -0
  4. data/.github/workflows/test.yml +1 -1
  5. data/.rspec +1 -0
  6. data/.rubocop.yml +37 -0
  7. data/CHANGELOG.md +26 -0
  8. data/README.md +6 -2
  9. data/config/default.yml +36 -1
  10. data/lib/rubocop/cop/crystal/enumerable_reduce.rb +58 -0
  11. data/lib/rubocop/cop/crystal/enumerable_size.rb +31 -0
  12. data/lib/rubocop/cop/crystal/file_extension.rb +1 -0
  13. data/lib/rubocop/cop/crystal/file_read_lines.rb +115 -0
  14. data/lib/rubocop/cop/crystal/interpolation_in_single_quotes.rb +3 -2
  15. data/lib/rubocop/cop/crystal/method_name_starting_with_uppercase_letter.rb +30 -0
  16. data/lib/rubocop/cop/crystal/method_returning_char.rb +54 -0
  17. data/lib/rubocop/cop/crystal/require_at_top_level.rb +35 -0
  18. data/lib/rubocop/cop/crystal/require_relative.rb +6 -5
  19. data/lib/rubocop/cop/crystal_cops.rb +6 -0
  20. data/lib/rubocop/crystal/plugin.rb +28 -0
  21. data/lib/rubocop-crystal.rb +1 -3
  22. data/rubocop-crystal.gemspec +5 -2
  23. data/spec/rubocop/cop/crystal/enumerable_reduce_spec.rb +101 -0
  24. data/spec/rubocop/cop/crystal/enumerable_size_spec.rb +64 -0
  25. data/spec/rubocop/cop/crystal/file_read_lines_spec.rb +156 -0
  26. data/spec/rubocop/cop/crystal/interpolation_in_single_quotes_spec.rb +30 -0
  27. data/spec/rubocop/cop/crystal/method_name_starting_with_uppercase_letter_spec.rb +35 -0
  28. data/spec/rubocop/cop/crystal/method_returning_char_spec.rb +150 -0
  29. data/spec/rubocop/cop/crystal/require_at_top_level_spec.rb +42 -0
  30. data/spec/rubocop/cop/crystal/require_relative_spec.rb +51 -0
  31. data/spec/spec_helper.rb +12 -0
  32. data/test/string.rb +55 -0
  33. metadata +41 -11
  34. 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
@@ -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