rubocop-crystal 0.0.2 → 0.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3beb9db336ee0d664fdd093775a9c14dc9512c8ec84be250ec177a6763b4924d
4
- data.tar.gz: 015acc39018447fef5d62304bf91dddab3b66faa795149f00b3e447de6db5990
3
+ metadata.gz: bbaf055e01ff70c7c189f9b6a73c94bf6ffbc50d7c0a335103177b5b8b52fb4a
4
+ data.tar.gz: ff97d8c93dd042f6dc9288a4adc97dc975c953fda4cc3e4c4af3b7ca7b8fb795
5
5
  SHA512:
6
- metadata.gz: 2077733fe1bc6189b71854a249601f8294366a2d86cd013822bb6ec9fd1371e9229ad6622dc169426ae35c75b1f65e26f5308538a749e2b02fb7239ac99a087e
7
- data.tar.gz: ea546caea1eeb127c946df8c97ec77ba7e5572db33c63402bba1ad4ffeeaca05d19d402d6c6a96aa37d4641f2aeda11d95a8f26a2e6b1c18a473961b8468d221
6
+ metadata.gz: 479c9f1a1c18e2147ebbbc22e8c4aa77d683e5601653d3ddbfa565ba7bee08d94aef3b92e1fabe41afcd5250a529a0a36672623db22a4206e840a40176d7fa4e
7
+ data.tar.gz: 262807664ebcfa6e7ae82af586e2c1535378184bfc20cb722932d62a6e6f75465acbd6781b79720a5cfec94460dea4ed31d55080f5192b1203b23c15ccf5b34a
@@ -0,0 +1,16 @@
1
+ name: RSpec
2
+ on: [push, pull_request]
3
+ jobs:
4
+ test:
5
+ runs-on: ubuntu-latest
6
+ steps:
7
+ - name: Download source
8
+ uses: actions/checkout@v4
9
+ - name: Install Ruby
10
+ uses: ruby/setup-ruby@v1
11
+ with:
12
+ ruby-version: '3.1.2'
13
+ - name: Install dependencies
14
+ run: gem install rspec rubocop
15
+ - name: Run spec
16
+ run: rspec
@@ -0,0 +1,16 @@
1
+ name: Rubocop
2
+ on: [push, pull_request]
3
+ jobs:
4
+ test:
5
+ runs-on: ubuntu-latest
6
+ steps:
7
+ - name: Download source
8
+ uses: actions/checkout@v4
9
+ - name: Install Ruby
10
+ uses: ruby/setup-ruby@v1
11
+ with:
12
+ ruby-version: '3.1.2'
13
+ - name: Install rubocop
14
+ run: gem install rubocop
15
+ - name: Run rubocop
16
+ run: rubocop
@@ -21,6 +21,6 @@ jobs:
21
21
  gem build rubocop-crystal
22
22
  gem install rubocop-crystal
23
23
  - name: Convert test files
24
- run: rubocop --require rubocop-crystal --fail-level fatal -A test
24
+ run: rubocop --plugin rubocop-crystal -c config/default.yml --fail-level fatal -A test
25
25
  - name: Run tests (Crystal)
26
26
  run: crystal run test/string.cr
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,36 @@
1
+ plugins:
2
+ - rubocop-internal_affairs
3
+
4
+ AllCops:
5
+ NewCops: enable
6
+ Exclude:
7
+ - 'test/*'
8
+
9
+ Gemspec/RequireMFA:
10
+ Enabled: false
11
+
12
+ # TODO: Find out what ruby version we actually require and then remove this.
13
+ Gemspec/RequiredRubyVersion:
14
+ Enabled: false
15
+
16
+ InternalAffairs/OnSendWithoutOnCSend:
17
+ Exclude:
18
+ - 'lib/rubocop/cop/crystal/require_relative.rb'
19
+
20
+ Layout/LineLength:
21
+ Enabled: false
22
+
23
+ Metrics:
24
+ Enabled: false
25
+
26
+ Naming/FileName:
27
+ Enabled: false
28
+
29
+ Style/Documentation:
30
+ Enabled: False
31
+
32
+ Style/FrozenStringLiteralComment:
33
+ Enabled: False
34
+
35
+ Style/MutableConstant:
36
+ Enabled: False
data/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ## 0.0.3 (2025-04-28)
2
+
3
+ ### New features
4
+
5
+ * Enable Style/BlockComments cop ([@zopolis4][])
6
+ * Enable Style/WhileUntilDo cop ([@zopolis4][])
7
+ * Add Crystal/MethodNameStartingWithUppercaseLetter cop ([@zopolis4][])
8
+
9
+ ### Changes
10
+
11
+ * Convert to Rubocop plugin ([@zopolis4][])
12
+
1
13
  ## 0.0.2 (2024-08-01)
2
14
 
3
15
  ### New features
data/README.md CHANGED
@@ -38,5 +38,9 @@ gem install rubocop-crystal
38
38
  ## Usage
39
39
 
40
40
  ```
41
- rubocop --require rubocop-crystal
41
+ rubocop --plugin rubocop-crystal
42
42
  ```
43
+
44
+ Note that there are some differences between Ruby and Crystal that can be automatically resolved, while some (at least for now) require manual intervention.
45
+
46
+ If you wish to only process the autocorrectable offenses, add `--disable-uncorrectable`, while reporting only the offenses requiring manual intervention is waiting on rubocop/rubocop#13275.
data/config/default.yml CHANGED
@@ -9,6 +9,10 @@ Crystal/InterpolationInSingleQuotes:
9
9
  Description: "This cop uses %q in place of ' if the enclosed string would be affected by interpolation."
10
10
  Enabled: true
11
11
 
12
+ Crystal/MethodNameStartingWithUppercaseLetter:
13
+ Description: 'This cop detects method names that start with uppercase letters.'
14
+ Enabled: true
15
+
12
16
  Crystal/RequireRelative:
13
17
  Description: 'This cop replaces require_relative with require while maintaining behavior.'
14
18
  Enabled: true
@@ -16,9 +20,15 @@ Crystal/RequireRelative:
16
20
  Lint/ImplicitStringConcatenation:
17
21
  Enabled: true
18
22
 
23
+ Style/BlockComments:
24
+ Enabled: true
25
+
26
+ Style/MethodDefParentheses:
27
+ Enabled: true
28
+
19
29
  Style/StringLiterals:
20
30
  Enabled: true
21
31
  EnforcedStyle: double_quotes
22
32
 
23
- Style/MethodDefParentheses:
33
+ Style/WhileUntilDo:
24
34
  Enabled: true
@@ -23,10 +23,10 @@ module RuboCop
23
23
  return unless node.source.start_with?("'")
24
24
  # Replace the single quotes deliminating the string with double quotes, and check if the resulting ast is still the same.
25
25
  # If it is, the string doesn't have any interpolation to avoid, and we're done here.
26
- return if node == parse('"' + node.source[1..-2] + '"').ast
26
+ return if node == parse("\"#{node.source[1..-2]}\"").ast
27
27
 
28
28
  add_offense(node) do |corrector|
29
- corrector.replace(node, '%q(' + node.source[1..-2] + ')')
29
+ corrector.replace(node, "%q(#{node.source[1..-2]})")
30
30
  end
31
31
  end
32
32
  end
@@ -0,0 +1,30 @@
1
+ module RuboCop
2
+ module Cop
3
+ module Crystal
4
+ # Method names cannot start with uppercase letters in Crystal:
5
+ # https://crystal-lang.org/reference/latest/syntax_and_semantics/methods_and_instance_variables.html
6
+ # ^ "Method names begin with a lowercase letter and, as a convention, only use lowercase letters, underscores and numbers."
7
+ #
8
+ # @example
9
+ # # bad
10
+ # def Foo(bar)
11
+ # qux
12
+ # end
13
+ # Foo(bar)
14
+ #
15
+ # # good
16
+ # def foo(bar)
17
+ # qux
18
+ # end
19
+ # foo(bar)
20
+ #
21
+ class MethodNameStartingWithUppercaseLetter < Base
22
+ MSG = 'Method names must start with a lowecase letter in Crystal.'
23
+
24
+ def on_def(node)
25
+ add_offense(node.loc.name) if node.method_name.to_s.chr.capitalize!.nil?
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -24,11 +24,11 @@ module RuboCop
24
24
 
25
25
  def on_send(node)
26
26
  add_offense(node) do |corrector|
27
- if node.first_argument.value.start_with?('.', '/')
28
- require_value = node.first_argument.value
29
- else
30
- require_value = "./#{node.first_argument.value}"
31
- end
27
+ require_value = if node.first_argument.value.start_with?('.', '/')
28
+ node.first_argument.value
29
+ else
30
+ "./#{node.first_argument.value}"
31
+ end
32
32
  corrector.replace(node, "require '#{require_value}'")
33
33
  end
34
34
  end
@@ -1,3 +1,4 @@
1
1
  require_relative 'crystal/file_extension'
2
2
  require_relative 'crystal/interpolation_in_single_quotes'
3
+ require_relative 'crystal/method_name_starting_with_uppercase_letter'
3
4
  require_relative 'crystal/require_relative'
@@ -0,0 +1,28 @@
1
+ require 'lint_roller'
2
+
3
+ module RuboCop
4
+ module Crystal
5
+ class Plugin < LintRoller::Plugin
6
+ def about
7
+ LintRoller::About.new(
8
+ name: 'rubocop-crystal',
9
+ version: '0.0.3',
10
+ homepage: 'https://github.com/Zopolis4/rubocop-crystal',
11
+ description: 'A RuboCop extension for converting Ruby to Crystal.'
12
+ )
13
+ end
14
+
15
+ def supported?(context)
16
+ context.engine == :rubocop
17
+ end
18
+
19
+ def rules(_context)
20
+ LintRoller::Rules.new(
21
+ type: :path,
22
+ config_format: :rubocop,
23
+ value: Pathname.new(__dir__).join('../../../config/default.yml')
24
+ )
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,8 +1,6 @@
1
1
  require 'rubocop'
2
2
 
3
3
  require_relative 'rubocop/crystal'
4
- require_relative 'rubocop/crystal/inject'
5
-
6
- RuboCop::Crystal::Inject.defaults!
4
+ require_relative 'rubocop/crystal/plugin'
7
5
 
8
6
  require_relative 'rubocop/cop/crystal_cops'
@@ -1,14 +1,17 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = 'rubocop-crystal'
3
3
  spec.summary = 'A RuboCop extension for converting Ruby to Crystal.'
4
- spec.version = '0.0.2'
4
+ spec.version = '0.0.3'
5
5
  spec.license = 'GPL-3.0-or-later'
6
6
  spec.author = 'Zopolis4'
7
7
  spec.email = 'creatorsmithmdt@gmail.com'
8
8
  spec.homepage = 'https://github.com/Zopolis4/rubocop-crystal'
9
9
 
10
+ spec.metadata['default_lint_roller_plugin'] = 'RuboCop::Crystal::Plugin'
11
+
10
12
  spec.files = `git ls-files`.split("\n")
11
13
  spec.require_paths = ['lib']
12
14
 
13
- spec.add_dependency 'rubocop', '>= 1.65.1'
15
+ spec.add_dependency 'lint_roller'
16
+ spec.add_dependency 'rubocop', '>= 1.72.1'
14
17
  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 lowecase 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 lowecase 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,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
data/test/string.rb CHANGED
@@ -1,5 +1,11 @@
1
1
  require_relative 'harness'
2
2
 
3
+ =begin
4
+ The Alternative Instruction Set is a relatively unknown 32-bit RISC ISA.
5
+ It is found inside certain VIA C3 CPUs, and is responsible for emulating x86 instructions.
6
+ This isn't relevant in the slightest, but I had to put something in this commment, and I think it's cool.
7
+ =end
8
+
3
9
  Test.assert_equal 'foo', "foo"
4
10
  Test.assert_equal 'foo'"bar", "foobar"
5
11
  Test.assert_equal "foobar", "foo" + 'bar'
@@ -18,3 +24,15 @@ Test.assert_equal "#{foo}""bar", 'bar' + "bar"
18
24
  Test.assert_unequal '#{1 + 1}', '2'
19
25
 
20
26
  Test.assert_equal '#{foo}'"bar", '#{foo}bar'
27
+
28
+ i = 3
29
+
30
+ while i > 0 do
31
+ i -= 1
32
+ end
33
+ Test.assert_equal 0, i
34
+
35
+ until i > 3 do
36
+ i += 1
37
+ end
38
+ Test.assert_equal 4, i
metadata CHANGED
@@ -1,37 +1,53 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-crystal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zopolis4
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-08-01 00:00:00.000000000 Z
10
+ date: 2025-04-28 00:00:00.000000000 Z
12
11
  dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: lint_roller
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '0'
13
26
  - !ruby/object:Gem::Dependency
14
27
  name: rubocop
15
28
  requirement: !ruby/object:Gem::Requirement
16
29
  requirements:
17
30
  - - ">="
18
31
  - !ruby/object:Gem::Version
19
- version: 1.65.1
32
+ version: 1.72.1
20
33
  type: :runtime
21
34
  prerelease: false
22
35
  version_requirements: !ruby/object:Gem::Requirement
23
36
  requirements:
24
37
  - - ">="
25
38
  - !ruby/object:Gem::Version
26
- version: 1.65.1
27
- description:
39
+ version: 1.72.1
28
40
  email: creatorsmithmdt@gmail.com
29
41
  executables: []
30
42
  extensions: []
31
43
  extra_rdoc_files: []
32
44
  files:
45
+ - ".github/workflows/rspec.yml"
46
+ - ".github/workflows/rubocop.yml"
33
47
  - ".github/workflows/test.yml"
34
48
  - ".gitignore"
49
+ - ".rspec"
50
+ - ".rubocop.yml"
35
51
  - CHANGELOG.md
36
52
  - LICENSE
37
53
  - README.md
@@ -39,18 +55,23 @@ files:
39
55
  - lib/rubocop-crystal.rb
40
56
  - lib/rubocop/cop/crystal/file_extension.rb
41
57
  - lib/rubocop/cop/crystal/interpolation_in_single_quotes.rb
58
+ - lib/rubocop/cop/crystal/method_name_starting_with_uppercase_letter.rb
42
59
  - lib/rubocop/cop/crystal/require_relative.rb
43
60
  - lib/rubocop/cop/crystal_cops.rb
44
61
  - lib/rubocop/crystal.rb
45
- - lib/rubocop/crystal/inject.rb
62
+ - lib/rubocop/crystal/plugin.rb
46
63
  - rubocop-crystal.gemspec
64
+ - spec/rubocop/cop/crystal/interpolation_in_single_quotes_spec.rb
65
+ - spec/rubocop/cop/crystal/method_name_starting_with_uppercase_letter_spec.rb
66
+ - spec/rubocop/cop/crystal/require_relative_spec.rb
67
+ - spec/spec_helper.rb
47
68
  - test/harness.rb
48
69
  - test/string.rb
49
70
  homepage: https://github.com/Zopolis4/rubocop-crystal
50
71
  licenses:
51
72
  - GPL-3.0-or-later
52
- metadata: {}
53
- post_install_message:
73
+ metadata:
74
+ default_lint_roller_plugin: RuboCop::Crystal::Plugin
54
75
  rdoc_options: []
55
76
  require_paths:
56
77
  - lib
@@ -65,8 +86,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
65
86
  - !ruby/object:Gem::Version
66
87
  version: '0'
67
88
  requirements: []
68
- rubygems_version: 3.4.20
69
- signing_key:
89
+ rubygems_version: 3.6.5
70
90
  specification_version: 4
71
91
  summary: A RuboCop extension for converting Ruby to Crystal.
72
92
  test_files: []
@@ -1,15 +0,0 @@
1
- module RuboCop
2
- module Crystal
3
- # Because RuboCop doesn't yet support plugins, we have to monkey patch in a bit of our configuration.
4
- module Inject
5
- def self.defaults!
6
- path = CONFIG_DEFAULT.to_s
7
- hash = ConfigLoader.send(:load_yaml_configuration, path)
8
- config = Config.new(hash, path).tap(&:make_excludes_absolute)
9
- puts "configuration from #{path}" if ConfigLoader.debug?
10
- config = ConfigLoader.merge_with_default(config, path)
11
- ConfigLoader.instance_variable_set(:@default_configuration, config)
12
- end
13
- end
14
- end
15
- end