rubocop-dry-import 0.1.0
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 +7 -0
- data/.rubocop_todo.yml +23 -0
- data/LICENSE.txt +21 -0
- data/README.md +85 -0
- data/Rakefile +12 -0
- data/config/default.yml +3 -0
- data/lib/rubocop/cop/dry/unused_import.rb +72 -0
- data/lib/rubocop_dry_import/version.rb +5 -0
- data/lib/rubocop_dry_import.rb +13 -0
- data/rubocop-dry-import.gemspec +34 -0
- metadata +74 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 85d7c48439ed60d9252a754f9f30c10a936d66e7005ee1786ae03c0a14999779
|
|
4
|
+
data.tar.gz: fede65640799eef6f9fc7ab33f9f0d758d9e947057c1a20789220577c3c143ca
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: a02c84254590d9b1c82bd9a2bf7e0a09e9c41047cee910ead491695bba8f615e91b075c428af636f90dde7733e414931a79989cc288f7b68403e027d7edd672b
|
|
7
|
+
data.tar.gz: 9fc2060a4c3c733a1c076b63dc9bc211ce1f32531254f2582d3d42e4dab536d8eea3d515ad8619299a1d137ee6edeb7b09279c9fac25b047d9e2bb00472ab243
|
data/.rubocop_todo.yml
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# This configuration was generated by
|
|
2
|
+
# `rubocop --auto-gen-config`
|
|
3
|
+
# on 2025-11-08 19:30:09 UTC using RuboCop version 1.81.7.
|
|
4
|
+
# The point is for the user to remove these configuration records
|
|
5
|
+
# one by one as the offenses are removed from the code base.
|
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
|
8
|
+
|
|
9
|
+
# Offense count: 1
|
|
10
|
+
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
|
|
11
|
+
Metrics/AbcSize:
|
|
12
|
+
Max: 18
|
|
13
|
+
|
|
14
|
+
# Offense count: 1
|
|
15
|
+
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
|
16
|
+
# AllowedMethods: refine
|
|
17
|
+
Metrics/BlockLength:
|
|
18
|
+
Max: 65
|
|
19
|
+
|
|
20
|
+
# Offense count: 2
|
|
21
|
+
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
|
22
|
+
Metrics/MethodLength:
|
|
23
|
+
Max: 14
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 seriousdev-gh
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# RuboCop Dry Import
|
|
2
|
+
|
|
3
|
+
A custom [RuboCop](https://github.com/rubocop/rubocop) extension that detects **unused `Import` dependencies** in classes using [dry-rb’s dependency injection](https://dry-rb.org/gems/dry-auto_inject/).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Add this line to your application's Gemfile:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
gem 'rubocop-dry-import', require: false
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
Add the extension to your `.rubocop.yml`:
|
|
16
|
+
|
|
17
|
+
```yaml
|
|
18
|
+
require:
|
|
19
|
+
- rubocop-dry-import
|
|
20
|
+
|
|
21
|
+
Dry/UnusedImport:
|
|
22
|
+
Enabled: true
|
|
23
|
+
ImportName: 'Import' # Optional, defaults to "Import"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Run RuboCop as usual:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
bundle exec rubocop
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Example
|
|
33
|
+
|
|
34
|
+
```ruby
|
|
35
|
+
class FooService
|
|
36
|
+
include Import['service_a', 'service_b']
|
|
37
|
+
|
|
38
|
+
def call
|
|
39
|
+
service_b.call
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Offense:**
|
|
45
|
+
```
|
|
46
|
+
Include Import['service_a', 'service_b']
|
|
47
|
+
^^^^^^^^^^^ Imported dependency `service_a` is not used in the class.
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Autocorrect:** Not available (yet).
|
|
51
|
+
|
|
52
|
+
## Development
|
|
53
|
+
|
|
54
|
+
Clone and setup:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
git clone https://github.com/seriousdev-gh/rubocop-dry-import
|
|
58
|
+
cd rubocop-dry-import
|
|
59
|
+
bundle install
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Run tests:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
bundle exec rspec
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Run RuboCop locally:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
bundle exec rubocop --require rubocop-dry-import path/to/file.rb
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Contributing
|
|
75
|
+
|
|
76
|
+
1. Fork the project.
|
|
77
|
+
2. Create your feature branch (`git checkout -b feature/new-cop`).
|
|
78
|
+
3. Commit your changes (`git commit -am 'Add new cop'`).
|
|
79
|
+
4. Push to the branch (`git push origin feature/new-cop`).
|
|
80
|
+
5. Open a Pull Request.
|
|
81
|
+
|
|
82
|
+
## License
|
|
83
|
+
|
|
84
|
+
This project is licensed under the [MIT License](LICENSE).
|
|
85
|
+
|
data/Rakefile
ADDED
data/config/default.yml
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Dry
|
|
6
|
+
class UnusedImport < Base
|
|
7
|
+
MSG = 'Imported dependency `%<name>s` is not used in the class.'
|
|
8
|
+
|
|
9
|
+
def_node_matcher :possible_injector_include?, <<~PATTERN
|
|
10
|
+
(send nil? :include
|
|
11
|
+
(send
|
|
12
|
+
(const nil? $_) :[] ...))
|
|
13
|
+
PATTERN
|
|
14
|
+
|
|
15
|
+
# search for method calls
|
|
16
|
+
def on_send(node)
|
|
17
|
+
# search for method calls with specific pattern `include <included_const_name>[<...>]`
|
|
18
|
+
possible_injector_include?(node) do |included_const_name|
|
|
19
|
+
next if included_const_name.to_s != injector_name
|
|
20
|
+
|
|
21
|
+
injector_call_node = node.arguments.first
|
|
22
|
+
class_node = node.parent
|
|
23
|
+
|
|
24
|
+
imported = extract_imported_methods(injector_call_node)
|
|
25
|
+
break if imported.empty?
|
|
26
|
+
|
|
27
|
+
unused = filter_unused_imported_methods(class_node, imported.dup)
|
|
28
|
+
unused.each do |name, import_node|
|
|
29
|
+
add_offense(import_node, message: format(MSG, name:))
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def injector_name
|
|
37
|
+
cop_config['InjectorName'] || 'Import'
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def extract_imported_methods(injector_call_node)
|
|
41
|
+
imported_methods = {}
|
|
42
|
+
|
|
43
|
+
injector_call_node.arguments.each do |arg|
|
|
44
|
+
case arg.type
|
|
45
|
+
when :str, :sym
|
|
46
|
+
name = arg.value.to_s.split('.').last
|
|
47
|
+
imported_methods[name.to_s] = arg
|
|
48
|
+
when :hash
|
|
49
|
+
arg.pairs.each do |pair_node|
|
|
50
|
+
name = pair_node.key.value
|
|
51
|
+
imported_methods[name.to_s] = pair_node
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
imported_methods
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def filter_unused_imported_methods(class_node, imported)
|
|
60
|
+
class_node.each_descendant(:send).each do |node|
|
|
61
|
+
break if imported.empty?
|
|
62
|
+
|
|
63
|
+
name = node.method_name.to_s
|
|
64
|
+
imported.delete(name) if imported.key?(name)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
imported
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'rubocop_dry_import/version'
|
|
4
|
+
require_relative 'rubocop/cop/dry/unused_import'
|
|
5
|
+
|
|
6
|
+
module RuboCopDryImport
|
|
7
|
+
def self.inject!
|
|
8
|
+
path = File.expand_path(__dir__)
|
|
9
|
+
RuboCop::ConfigLoader.default_configuration = RuboCop::ConfigLoader.default_configuration.merge(
|
|
10
|
+
YAML.safe_load_file(File.join(path, 'config', 'default.yml'), aliases: true)
|
|
11
|
+
)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'lib/rubocop_dry_import/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = 'rubocop-dry-import'
|
|
7
|
+
spec.version = RuboCopDryImport::VERSION
|
|
8
|
+
spec.authors = ['seriousdev-gh']
|
|
9
|
+
spec.email = ['borisdrovnin@gmail.com']
|
|
10
|
+
|
|
11
|
+
spec.summary = 'RuboCop extension that detects unused dry-rb Import dependencies.'
|
|
12
|
+
spec.description = 'rubocop-dry-import adds a RuboCop cop (Dry/UnusedImport) that warns when imported ' \
|
|
13
|
+
'dependencies via dry-rb’s Import or AutoInject are not used within the class.'
|
|
14
|
+
spec.homepage = 'https://github.com/seriousdev-gh/rubocop-dry-import'
|
|
15
|
+
spec.license = 'MIT'
|
|
16
|
+
spec.required_ruby_version = '>= 3.2.0'
|
|
17
|
+
|
|
18
|
+
spec.metadata['source_code_uri'] = spec.homepage
|
|
19
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
|
20
|
+
|
|
21
|
+
spec.files = IO.popen(%w[git ls-files -z], chdir: __dir__, err: IO::NULL) do |ls|
|
|
22
|
+
ls.readlines("\x0", chomp: true).reject do |f|
|
|
23
|
+
f.start_with?(*%w[bin/ Gemfile .gitignore .rspec spec/ .github/ example/ .rubocop.yml])
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
spec.bindir = 'exe'
|
|
28
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
|
29
|
+
spec.require_paths = ['lib']
|
|
30
|
+
|
|
31
|
+
spec.add_dependency 'rubocop', '>= 1.0', '< 2.0'
|
|
32
|
+
|
|
33
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
|
34
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: rubocop-dry-import
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- seriousdev-gh
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: rubocop
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '1.0'
|
|
19
|
+
- - "<"
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '2.0'
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
requirements:
|
|
26
|
+
- - ">="
|
|
27
|
+
- !ruby/object:Gem::Version
|
|
28
|
+
version: '1.0'
|
|
29
|
+
- - "<"
|
|
30
|
+
- !ruby/object:Gem::Version
|
|
31
|
+
version: '2.0'
|
|
32
|
+
description: rubocop-dry-import adds a RuboCop cop (Dry/UnusedImport) that warns when
|
|
33
|
+
imported dependencies via dry-rb’s Import or AutoInject are not used within the
|
|
34
|
+
class.
|
|
35
|
+
email:
|
|
36
|
+
- borisdrovnin@gmail.com
|
|
37
|
+
executables: []
|
|
38
|
+
extensions: []
|
|
39
|
+
extra_rdoc_files: []
|
|
40
|
+
files:
|
|
41
|
+
- ".rubocop_todo.yml"
|
|
42
|
+
- LICENSE.txt
|
|
43
|
+
- README.md
|
|
44
|
+
- Rakefile
|
|
45
|
+
- config/default.yml
|
|
46
|
+
- lib/rubocop/cop/dry/unused_import.rb
|
|
47
|
+
- lib/rubocop_dry_import.rb
|
|
48
|
+
- lib/rubocop_dry_import/version.rb
|
|
49
|
+
- rubocop-dry-import.gemspec
|
|
50
|
+
homepage: https://github.com/seriousdev-gh/rubocop-dry-import
|
|
51
|
+
licenses:
|
|
52
|
+
- MIT
|
|
53
|
+
metadata:
|
|
54
|
+
source_code_uri: https://github.com/seriousdev-gh/rubocop-dry-import
|
|
55
|
+
rubygems_mfa_required: 'true'
|
|
56
|
+
allowed_push_host: https://rubygems.org
|
|
57
|
+
rdoc_options: []
|
|
58
|
+
require_paths:
|
|
59
|
+
- lib
|
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
61
|
+
requirements:
|
|
62
|
+
- - ">="
|
|
63
|
+
- !ruby/object:Gem::Version
|
|
64
|
+
version: 3.2.0
|
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
66
|
+
requirements:
|
|
67
|
+
- - ">="
|
|
68
|
+
- !ruby/object:Gem::Version
|
|
69
|
+
version: '0'
|
|
70
|
+
requirements: []
|
|
71
|
+
rubygems_version: 3.7.2
|
|
72
|
+
specification_version: 4
|
|
73
|
+
summary: RuboCop extension that detects unused dry-rb Import dependencies.
|
|
74
|
+
test_files: []
|