dry-auto_inject 1.1.0 → 1.2.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 +4 -4
- data/CHANGELOG.md +109 -85
- data/LICENSE +1 -1
- data/README.md +12 -13
- data/config/default.yml +21 -0
- data/dry-auto_inject.gemspec +20 -16
- data/lib/dry/auto_inject/method_parameters.rb +17 -10
- data/lib/dry/auto_inject/strategies/kwargs.rb +15 -9
- data/lib/dry/auto_inject/version.rb +1 -1
- data/lib/dry/auto_inject.rb +2 -1
- data/lib/dry-auto_inject.rb +6 -0
- data/lib/rubocop/cop/dry_auto_inject/dependency_order.rb +126 -0
- data/lib/rubocop/cop/dry_auto_inject/mixin.rb +163 -0
- data/lib/rubocop/cop/dry_auto_inject/redundant_alias.rb +68 -0
- data/lib/rubocop/dry-auto_inject.rb +3 -0
- data/lib/rubocop/dry_auto_inject/plugin.rb +34 -0
- data/lib/rubocop/dry_auto_inject.rb +5 -0
- metadata +62 -13
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e2aaa8535a986a0617f12d76b7315a9e67af171d5016b2e5a246633b6573fb97
|
|
4
|
+
data.tar.gz: d237b98ba264c303ea6f7956068cc7927a7cf7fa0eac5f3f58a05759a5d7f358
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 85719f454e9a02bf7de8cdf9ecdda0a78f641b0a15e92bae2a8d386f1f06bbe263f6cd13029c2aeba9b5266638f045e37cbfed24a979aa289bb2d0a5980724f5
|
|
7
|
+
data.tar.gz: e150f90bf7123352337c409efb54618a2c6bd560d10e19b8bbe575bf67665f3a9febd23fb3a2427c89f8b168e9b32795b7fd4e8749cde19847992875b3c4f46b
|
data/CHANGELOG.md
CHANGED
|
@@ -1,110 +1,149 @@
|
|
|
1
|
-
|
|
1
|
+
# Changelog
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Break Versioning](https://www.taoensso.com/break-versioning).
|
|
7
|
+
|
|
8
|
+
## [1.2.0] - 2026-05-19
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Ship a `DryAutoInject/DependencyOrder` rubocop cop that enforces a configurable
|
|
13
|
+
order for dependencies inside `Import[...]` calls. Non-aliased deps are
|
|
14
|
+
emitted first, then aliased ones; within each section, deps are grouped by
|
|
15
|
+
the configured `Order` patterns and sorted alphabetically inside a group.
|
|
16
|
+
Supported pattern forms: `'*'` (catch-all, at most one and implicitly
|
|
17
|
+
appended), `'prefix.*'`, `/regex/flags`, or an exact path. The cop also
|
|
18
|
+
autocorrects. (@flash-gordon in #96)
|
|
19
|
+
|
|
20
|
+
Enable it from your `.rubocop.yml` using RuboCop's plugin system
|
|
21
|
+
(requires RuboCop 1.72+):
|
|
22
|
+
|
|
23
|
+
```yaml
|
|
24
|
+
plugins:
|
|
25
|
+
- dry-auto_inject
|
|
26
|
+
|
|
27
|
+
DryAutoInject/DependencyOrder:
|
|
28
|
+
Enabled: true
|
|
29
|
+
InjectorModules: # Default is [Import, *::Import, Deps, *::Deps]
|
|
30
|
+
- Deps # exact constant
|
|
31
|
+
- "*::Deps" # match any namespace ending in `::Deps`
|
|
32
|
+
Order:
|
|
33
|
+
- "web.*"
|
|
34
|
+
- "*"
|
|
35
|
+
- "core.*"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
- Ship a `DryAutoInject/RedundantAlias` rubocop cop that flags
|
|
39
|
+
`Import[foo: 'some.path.foo']`-style imports where the alias matches the
|
|
40
|
+
last segment of the path, since dry-auto_inject already derives the
|
|
41
|
+
dependency key from that segment. The cop autocorrects by promoting
|
|
42
|
+
redundant aliases to non-aliased deps, preserving the original quoting.
|
|
43
|
+
(@flash-gordon in #98)
|
|
5
44
|
|
|
6
45
|
### Fixed
|
|
7
46
|
|
|
8
|
-
-
|
|
47
|
+
- Ancestor parameter detection for smart kwarg forwarding is no longer obscured by injections in a parent class. (@alassek in #97)
|
|
9
48
|
|
|
49
|
+
### Changed
|
|
10
50
|
|
|
11
|
-
|
|
51
|
+
- Update minimum Ruby version to 3.3. (@timriley)
|
|
12
52
|
|
|
13
|
-
|
|
53
|
+
[Unreleased]: https://github.com/dry-rb/dry-auto_inject/compare/v1.1.0...main
|
|
14
54
|
|
|
55
|
+
## [1.1.0] - 2025-01-07
|
|
15
56
|
|
|
16
57
|
### Fixed
|
|
17
58
|
|
|
18
|
-
- Update
|
|
59
|
+
- Update minimal ruby version to 3.1. (@flash-gordon)
|
|
19
60
|
|
|
61
|
+
[1.1.0]: https://github.com/dry-rb/dry-auto_inject/compare/v1.0.1...v1.1.0
|
|
20
62
|
|
|
21
|
-
[
|
|
63
|
+
## [1.0.1] - 2023-02-13
|
|
22
64
|
|
|
23
|
-
|
|
65
|
+
### Fixed
|
|
24
66
|
|
|
67
|
+
- Update passthrough parameters list to support ruby 3.2.1. (@hieuk09 in #88)
|
|
25
68
|
|
|
26
|
-
|
|
69
|
+
[1.0.1]: https://github.com/dry-rb/dry-auto_inject/compare/v1.0.0...v1.0.1
|
|
27
70
|
|
|
28
|
-
|
|
29
|
-
- This version uses zeitwerk for autoloading (@flash-gordon)
|
|
71
|
+
## [1.0.0] - 2022-11-18
|
|
30
72
|
|
|
31
|
-
|
|
73
|
+
### Changed
|
|
74
|
+
|
|
75
|
+
- This version is compatible with recently released dry-rb dependencies. (@flash-gordon)
|
|
76
|
+
- This version uses zeitwerk for autoloading. (@flash-gordon)
|
|
32
77
|
|
|
33
|
-
|
|
78
|
+
[1.0.0]: https://github.com/dry-rb/dry-auto_inject/compare/v0.9.0...v1.0.0
|
|
34
79
|
|
|
80
|
+
## [0.9.0] - 2022-01-26
|
|
35
81
|
|
|
36
82
|
### Changed
|
|
37
83
|
|
|
38
84
|
- [BREAKING] Support for ... was changed, now constructors with such signature are not considered
|
|
39
|
-
as pass-through because they can forward arguments to another method (flash-gordon in
|
|
40
|
-
|
|
85
|
+
as pass-through because they can forward arguments to another method. (@flash-gordon in #78)
|
|
41
86
|
- [BREAKING] Support for 2.6 was dropped
|
|
42
87
|
|
|
43
|
-
[
|
|
44
|
-
|
|
45
|
-
## 0.8.0 2021-06-06
|
|
88
|
+
[0.9.0]: https://github.com/dry-rb/dry-auto_inject/compare/v0.8.0...v0.9.0
|
|
46
89
|
|
|
90
|
+
## [0.8.0] - 2021-06-06
|
|
47
91
|
|
|
48
92
|
### Added
|
|
49
93
|
|
|
50
|
-
- Support For `...` passthrough-args (@ytaben)
|
|
94
|
+
- Support For `...` passthrough-args. (@ytaben)
|
|
51
95
|
|
|
52
96
|
### Fixed
|
|
53
97
|
|
|
54
|
-
- Constructors with kwargs strategy properly forward blocks to super (mintyfresh in
|
|
98
|
+
- Constructors with kwargs strategy properly forward blocks to super. (@mintyfresh in #68)
|
|
55
99
|
|
|
56
100
|
### Changed
|
|
57
101
|
|
|
58
102
|
- [BREAKING] Support for 2.4 and 2.5 was dropped
|
|
59
103
|
|
|
60
|
-
[
|
|
61
|
-
|
|
62
|
-
## 0.7.0 2019-12-28
|
|
104
|
+
[0.8.0]: https://github.com/dry-rb/dry-auto_inject/compare/v0.7.0...v0.8.0
|
|
63
105
|
|
|
106
|
+
## [0.7.0] - 2019-12-28
|
|
64
107
|
|
|
65
108
|
### Fixed
|
|
66
109
|
|
|
67
|
-
- Keyword warnings issued by Ruby 2.7 in certain contexts (flash-gordon)
|
|
110
|
+
- Keyword warnings issued by Ruby 2.7 in certain contexts. (@flash-gordon)
|
|
68
111
|
|
|
69
112
|
### Changed
|
|
70
113
|
|
|
71
114
|
- [BREAKING] Support for 2.3 was dropped
|
|
72
115
|
|
|
73
|
-
[
|
|
74
|
-
|
|
75
|
-
## 0.6.1 2019-04-16
|
|
116
|
+
[0.7.0]: https://github.com/dry-rb/dry-auto_inject/compare/v0.6.1...v0.7.0
|
|
76
117
|
|
|
118
|
+
## [0.6.1] - 2019-04-16
|
|
77
119
|
|
|
78
120
|
### Fixed
|
|
79
121
|
|
|
80
|
-
- Allow explicit injection of falsey values (timriley in
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
[Compare v0.6.0...v0.6.1](https://github.com/dry-rb/dry-auto_inject/compare/v0.6.0...v0.6.1)
|
|
122
|
+
- Allow explicit injection of falsey values. (@timriley in #58)
|
|
84
123
|
|
|
85
|
-
|
|
124
|
+
[0.6.1]: https://github.com/dry-rb/dry-auto_inject/compare/v0.6.0...v0.6.1
|
|
86
125
|
|
|
126
|
+
## [0.6.0] - 2018-11-29
|
|
87
127
|
|
|
88
128
|
### Added
|
|
89
129
|
|
|
90
|
-
- Enhanced support for integrating with existing constructors. The kwargs strategy will now pass dependencies up to the next constructor if it accepts an arbitrary number of arguments with `*args`. Note that this change may break existing code though we think it's unlikely to happen. If something doesn't work for you please report and we'll try to sort it out (flash-gordon + timriley in
|
|
130
|
+
- Enhanced support for integrating with existing constructors. The kwargs strategy will now pass dependencies up to the next constructor if it accepts an arbitrary number of arguments with `*args`. Note that this change may break existing code though we think it's unlikely to happen. If something doesn't work for you please report and we'll try to sort it out. (@flash-gordon + @timriley in #48)
|
|
91
131
|
|
|
92
132
|
### Fixed
|
|
93
133
|
|
|
94
|
-
- A couple of regressions were fixed along the way, see [#46](https://github.com/dry-rb/dry-auto_inject/issues/46) and [#49](https://github.com/dry-rb/dry-auto_inject/issues/49) (flash-gordon + timriley in
|
|
134
|
+
- A couple of regressions were fixed along the way, see [#46](https://github.com/dry-rb/dry-auto_inject/issues/46) and [#49](https://github.com/dry-rb/dry-auto_inject/issues/49). (@flash-gordon + @timriley in #48)
|
|
95
135
|
|
|
96
136
|
### Changed
|
|
97
137
|
|
|
98
138
|
- [BREAKING] 0.6.0 supports Ruby 2.3 and above. If you're on 2.3 keep in mind its EOL is scheduled at the end of March, 2019
|
|
99
139
|
|
|
100
|
-
[
|
|
101
|
-
|
|
102
|
-
## 0.5.0 2018-11-09
|
|
140
|
+
[0.6.0]: https://github.com/dry-rb/dry-auto_inject/compare/v0.5.0...v0.6.0
|
|
103
141
|
|
|
142
|
+
## [0.5.0] - 2018-11-09
|
|
104
143
|
|
|
105
144
|
### Changed
|
|
106
145
|
|
|
107
|
-
- Only assign `nil` dependency instance variables from generated `#initialize` if the instance variable has not been previously defined. This improves compatibility with objects initialized in non-conventional ways (see example below) (timriley in
|
|
146
|
+
- Only assign `nil` dependency instance variables from generated `#initialize` if the instance variable has not been previously defined. This improves compatibility with objects initialized in non-conventional ways (see example below). (@timriley in #47)
|
|
108
147
|
|
|
109
148
|
```ruby
|
|
110
149
|
module SomeFramework
|
|
@@ -136,72 +175,61 @@ as pass-through because they can forward arguments to another method (flash-gord
|
|
|
136
175
|
end
|
|
137
176
|
```
|
|
138
177
|
|
|
139
|
-
[
|
|
140
|
-
|
|
141
|
-
## 0.4.6 2018-03-27
|
|
178
|
+
[0.5.0]: https://github.com/dry-rb/dry-auto_inject/compare/v0.4.6...v0.5.0
|
|
142
179
|
|
|
180
|
+
## [0.4.6] - 2018-03-27
|
|
143
181
|
|
|
144
182
|
### Changed
|
|
145
183
|
|
|
146
|
-
- In injector-generated `#initialize` methods, set dependency instance variables before calling `super
|
|
184
|
+
- In injector-generated `#initialize` methods, set dependency instance variables before calling `super`. (@timriley)
|
|
147
185
|
|
|
148
|
-
[
|
|
149
|
-
|
|
150
|
-
## 0.4.5 2018-01-02
|
|
186
|
+
[0.4.6]: https://github.com/dry-rb/dry-auto_inject/compare/v0.4.5...v0.4.6
|
|
151
187
|
|
|
188
|
+
## [0.4.5] - 2018-01-02
|
|
152
189
|
|
|
153
190
|
### Added
|
|
154
191
|
|
|
155
|
-
- Improved handling of kwargs being passed to #initialize’s super method (timriley)
|
|
156
|
-
|
|
192
|
+
- Improved handling of kwargs being passed to #initialize’s super method. (@timriley)
|
|
157
193
|
|
|
158
|
-
[
|
|
159
|
-
|
|
160
|
-
## 0.4.4 2017-09-14
|
|
194
|
+
[0.4.5]: https://github.com/dry-rb/dry-auto_inject/compare/v0.4.4...v0.4.5
|
|
161
195
|
|
|
196
|
+
## [0.4.4] - 2017-09-14
|
|
162
197
|
|
|
163
198
|
### Added
|
|
164
199
|
|
|
165
|
-
- Determine name for dependencies by splitting identifiers on any invalid local variable name characters (e.g. "/", "?", "!"), instead of splitting on dots only (raventid in
|
|
166
|
-
|
|
200
|
+
- Determine name for dependencies by splitting identifiers on any invalid local variable name characters (e.g. "/", "?", "!"), instead of splitting on dots only. (@raventid in #39)
|
|
167
201
|
|
|
168
|
-
[
|
|
169
|
-
|
|
170
|
-
## 0.4.3 2017-05-27
|
|
202
|
+
[0.4.4]: https://github.com/dry-rb/dry-auto_inject/compare/v0.4.3...v0.4.4
|
|
171
203
|
|
|
204
|
+
## [0.4.3] - 2017-05-27
|
|
172
205
|
|
|
173
206
|
### Added
|
|
174
207
|
|
|
175
|
-
- Push sequential arguments along with keywords in the kwargs strategy (hbda + vladra in
|
|
176
|
-
|
|
208
|
+
- Push sequential arguments along with keywords in the kwargs strategy. (@hbda + @vladra in #32)
|
|
177
209
|
|
|
178
|
-
[
|
|
179
|
-
|
|
180
|
-
## 0.4.2 2016-10-10
|
|
210
|
+
[0.4.3]: https://github.com/dry-rb/dry-auto_inject/compare/v0.4.2...v0.4.3
|
|
181
211
|
|
|
212
|
+
## [0.4.2] - 2016-10-10
|
|
182
213
|
|
|
183
214
|
### Fixed
|
|
184
215
|
|
|
185
|
-
- Fixed issue where injectors for different containers could not be used on different classes in an inheritance hierarchy (timriley in
|
|
186
|
-
|
|
216
|
+
- Fixed issue where injectors for different containers could not be used on different classes in an inheritance hierarchy. (@timriley in #31)
|
|
187
217
|
|
|
188
|
-
[
|
|
189
|
-
|
|
190
|
-
## 0.4.1 2016-08-14
|
|
218
|
+
[0.4.2]: https://github.com/dry-rb/dry-auto_inject/compare/v0.4.1...v0.4.2
|
|
191
219
|
|
|
220
|
+
## [0.4.1] - 2016-08-14
|
|
192
221
|
|
|
193
222
|
### Changed
|
|
194
223
|
|
|
195
|
-
- Loosened version dependency on dry-container (AMHOL)
|
|
196
|
-
|
|
197
|
-
[Compare v0.4.0...v0.4.1](https://github.com/dry-rb/dry-auto_inject/compare/v0.4.0...v0.4.1)
|
|
224
|
+
- Loosened version dependency on dry-container. (@AMHOL)
|
|
198
225
|
|
|
199
|
-
|
|
226
|
+
[0.4.1]: https://github.com/dry-rb/dry-auto_inject/compare/v0.4.0...v0.4.1
|
|
200
227
|
|
|
228
|
+
## [0.4.0] - 2016-07-26
|
|
201
229
|
|
|
202
230
|
### Added
|
|
203
231
|
|
|
204
|
-
- Support for strategy chaining, which is helpful in opting for alternatives to an application's normal strategy (timriley in
|
|
232
|
+
- Support for strategy chaining, which is helpful in opting for alternatives to an application's normal strategy. (@timriley in #25)
|
|
205
233
|
|
|
206
234
|
```ruby
|
|
207
235
|
# Define the application's injector with a non-default
|
|
@@ -220,16 +248,15 @@ as pass-through because they can forward arguments to another method (flash-gord
|
|
|
220
248
|
|
|
221
249
|
### Fixed
|
|
222
250
|
|
|
223
|
-
- Fixed issue with kwargs injectors used at multiple points in a class inheritance heirarchy (flash-gordon in
|
|
251
|
+
- Fixed issue with kwargs injectors used at multiple points in a class inheritance heirarchy. (@flash-gordon in #27)
|
|
224
252
|
|
|
225
253
|
### Changed
|
|
226
254
|
|
|
227
|
-
- Use a `BasicObject`-based environment for the injector builder API instead of the previous `define_singleton_method`-based approach, which had negative performance characteristics (timriley in
|
|
255
|
+
- Use a `BasicObject`-based environment for the injector builder API instead of the previous `define_singleton_method`-based approach, which had negative performance characteristics. (@timriley in #26)
|
|
228
256
|
|
|
229
|
-
[
|
|
230
|
-
|
|
231
|
-
## 0.3.0, 2016-06-02
|
|
257
|
+
[0.4.0]: https://github.com/dry-rb/dry-auto_inject/compare/v0.3.0...v0.4.0
|
|
232
258
|
|
|
259
|
+
## [0.3.0] - 2016-06-02
|
|
233
260
|
|
|
234
261
|
### Added
|
|
235
262
|
|
|
@@ -314,25 +341,22 @@ as pass-through because they can forward arguments to another method (flash-gord
|
|
|
314
341
|
- `kwargs` is the new default injection strategy
|
|
315
342
|
- Rubinius support is not available for the `kwargs` strategy (see [#18](https://github.com/dry-rb/dry-auto_inject/issues/18))
|
|
316
343
|
|
|
317
|
-
[
|
|
318
|
-
|
|
319
|
-
## 0.2.0 2016-02-09
|
|
344
|
+
[0.3.0]: https://github.com/dry-rb/dry-auto_inject/compare/v0.2.0...v0.3.0
|
|
320
345
|
|
|
346
|
+
## [0.2.0] - 2016-02-09
|
|
321
347
|
|
|
322
348
|
### Added
|
|
323
349
|
|
|
324
|
-
- Support for hashes as constructor arguments via `Import.hash` interface (solnic)
|
|
350
|
+
- Support for hashes as constructor arguments via `Import.hash` interface. (@solnic)
|
|
325
351
|
|
|
352
|
+
[0.2.0]: https://github.com/dry-rb/dry-auto_inject/compare/v0.1.0...v0.2.0
|
|
326
353
|
|
|
327
|
-
[
|
|
328
|
-
|
|
329
|
-
## 0.1.0 2015-11-12
|
|
354
|
+
## [0.1.0] - 2015-11-12
|
|
330
355
|
|
|
331
356
|
Changed interface from `Dry::AutoInject.new { container(some_container) }` to
|
|
332
357
|
|
|
358
|
+
[0.1.0]: https://github.com/dry-rb/dry-auto_inject/compare/v0.0.1...v0.1.0
|
|
333
359
|
|
|
334
|
-
[
|
|
335
|
-
|
|
336
|
-
## 0.0.1 2015-08-20
|
|
360
|
+
## [0.0.1] - 2015-08-20
|
|
337
361
|
|
|
338
362
|
First public release \o/
|
data/LICENSE
CHANGED
data/README.md
CHANGED
|
@@ -1,23 +1,22 @@
|
|
|
1
|
-
<!---
|
|
1
|
+
<!--- This file is synced from hanakai-rb/repo-sync -->
|
|
2
2
|
|
|
3
|
-
[gem]: https://rubygems.org/gems/dry-auto_inject
|
|
4
3
|
[actions]: https://github.com/dry-rb/dry-auto_inject/actions
|
|
4
|
+
[chat]: https://discord.gg/naQApPAsZB
|
|
5
|
+
[forum]: https://discourse.hanamirb.org
|
|
6
|
+
[rubygem]: https://rubygems.org/gems/dry-auto_inject
|
|
5
7
|
|
|
6
|
-
# dry-auto_inject [][
|
|
8
|
+
# dry-auto_inject [][rubygem] [][actions]
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
* [User documentation](https://dry-rb.org/gems/dry-auto_inject)
|
|
11
|
-
* [API documentation](http://rubydoc.info/gems/dry-auto_inject)
|
|
12
|
-
* [Forum](https://discourse.dry-rb.org)
|
|
13
|
-
|
|
14
|
-
## Supported Ruby versions
|
|
10
|
+
[][forum]
|
|
11
|
+
[][chat]
|
|
15
12
|
|
|
16
|
-
|
|
13
|
+
## Links
|
|
17
14
|
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
- [User documentation](https://dry-rb.org/gems/dry-auto_inject)
|
|
16
|
+
- [API documentation](http://rubydoc.info/gems/dry-auto_inject)
|
|
17
|
+
- [Forum](https://discourse.dry-rb.org)
|
|
20
18
|
|
|
21
19
|
## License
|
|
22
20
|
|
|
23
21
|
See `LICENSE` file.
|
|
22
|
+
|
data/config/default.yml
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
DryAutoInject/DependencyOrder:
|
|
2
|
+
Description: 'Enforces a configurable order for dry-auto_inject `Import[...]` dependencies.'
|
|
3
|
+
Enabled: true
|
|
4
|
+
VersionAdded: '1.2'
|
|
5
|
+
InjectorModules:
|
|
6
|
+
- 'Import'
|
|
7
|
+
- '*::Import'
|
|
8
|
+
- 'Deps'
|
|
9
|
+
- '*::Deps'
|
|
10
|
+
Order:
|
|
11
|
+
- '*'
|
|
12
|
+
|
|
13
|
+
DryAutoInject/RedundantAlias:
|
|
14
|
+
Description: 'Flags dry-auto_inject imports whose hash key matches the last segment of the path.'
|
|
15
|
+
Enabled: true
|
|
16
|
+
VersionAdded: '1.2'
|
|
17
|
+
InjectorModules:
|
|
18
|
+
- 'Import'
|
|
19
|
+
- '*::Import'
|
|
20
|
+
- 'Deps'
|
|
21
|
+
- '*::Deps'
|
data/dry-auto_inject.gemspec
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
#
|
|
3
|
+
# This file is synced from hanakai-rb/repo-sync. To update it, edit repo-sync.yml.
|
|
4
4
|
|
|
5
5
|
lib = File.expand_path("lib", __dir__)
|
|
6
6
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
@@ -8,29 +8,33 @@ require "dry/auto_inject/version"
|
|
|
8
8
|
|
|
9
9
|
Gem::Specification.new do |spec|
|
|
10
10
|
spec.name = "dry-auto_inject"
|
|
11
|
-
spec.authors = ["
|
|
12
|
-
spec.email = ["
|
|
11
|
+
spec.authors = ["Hanakai team"]
|
|
12
|
+
spec.email = ["info@hanakai.org"]
|
|
13
13
|
spec.license = "MIT"
|
|
14
14
|
spec.version = Dry::AutoInject::VERSION.dup
|
|
15
15
|
|
|
16
16
|
spec.summary = "Container-agnostic automatic constructor injection"
|
|
17
17
|
spec.description = spec.summary
|
|
18
18
|
spec.homepage = "https://dry-rb.org/gems/dry-auto_inject"
|
|
19
|
-
spec.files = Dir["CHANGELOG.md", "LICENSE", "README.md", "dry-auto_inject.gemspec",
|
|
20
|
-
|
|
21
|
-
spec.
|
|
22
|
-
spec.executables = []
|
|
19
|
+
spec.files = Dir["CHANGELOG.md", "LICENSE", "README.md", "dry-auto_inject.gemspec", "lib/**/*", "config/**/*"]
|
|
20
|
+
spec.bindir = "exe"
|
|
21
|
+
spec.executables = Dir["exe/*"].map { |f| File.basename(f) }
|
|
23
22
|
spec.require_paths = ["lib"]
|
|
24
23
|
|
|
25
|
-
spec.
|
|
26
|
-
spec.metadata["changelog_uri"] = "https://github.com/dry-rb/dry-auto_inject/blob/main/CHANGELOG.md"
|
|
27
|
-
spec.metadata["source_code_uri"] = "https://github.com/dry-rb/dry-auto_inject"
|
|
28
|
-
spec.metadata["bug_tracker_uri"] = "https://github.com/dry-rb/dry-auto_inject/issues"
|
|
29
|
-
spec.metadata["rubygems_mfa_required"] = "true"
|
|
24
|
+
spec.extra_rdoc_files = ["README.md", "CHANGELOG.md", "LICENSE"]
|
|
30
25
|
|
|
31
|
-
spec.
|
|
26
|
+
spec.metadata["changelog_uri"] = "https://github.com/dry-rb/dry-auto_inject/blob/main/CHANGELOG.md"
|
|
27
|
+
spec.metadata["source_code_uri"] = "https://github.com/dry-rb/dry-auto_inject"
|
|
28
|
+
spec.metadata["bug_tracker_uri"] = "https://github.com/dry-rb/dry-auto_inject/issues"
|
|
29
|
+
spec.metadata["funding_uri"] = "https://github.com/sponsors/hanami"
|
|
30
|
+
spec.metadata["default_lint_roller_plugin"] = "RuboCop::DryAutoInject::Plugin"
|
|
32
31
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
spec.
|
|
32
|
+
spec.required_ruby_version = ">= 3.3"
|
|
33
|
+
|
|
34
|
+
spec.add_runtime_dependency "dry-core", "~> 1.1"
|
|
35
|
+
spec.add_runtime_dependency "zeitwerk", "~> 2.6"
|
|
36
|
+
spec.add_development_dependency "bundler"
|
|
37
|
+
spec.add_development_dependency "rake"
|
|
38
|
+
spec.add_development_dependency "rspec"
|
|
36
39
|
end
|
|
40
|
+
|
|
@@ -1,18 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "set"
|
|
4
|
-
|
|
5
3
|
module Dry
|
|
6
4
|
module AutoInject
|
|
7
5
|
# @api private
|
|
8
6
|
class MethodParameters
|
|
9
|
-
PASS_THROUGH = [
|
|
10
|
-
[%i[rest]],
|
|
11
|
-
[%i[rest], %i[keyrest]],
|
|
12
|
-
[%i[rest *]],
|
|
13
|
-
[%i[rest *], %i[keyrest **]]
|
|
14
|
-
].freeze
|
|
15
|
-
|
|
16
7
|
def self.of(obj, name)
|
|
17
8
|
::Enumerator.new do |y|
|
|
18
9
|
begin
|
|
@@ -61,7 +52,23 @@ module Dry
|
|
|
61
52
|
|
|
62
53
|
def length = parameters.length
|
|
63
54
|
|
|
64
|
-
def pass_through?
|
|
55
|
+
def pass_through?
|
|
56
|
+
return false if parameters.empty?
|
|
57
|
+
return true if parameters.any? { |param| param in [:keyrest, :__auto_inject_kwargs__] }
|
|
58
|
+
|
|
59
|
+
parameters.all? do |param|
|
|
60
|
+
case param
|
|
61
|
+
in [:rest, :*] | [:keyrest, :**]
|
|
62
|
+
true
|
|
63
|
+
in [:rest | :req | :opt | :keyrest | :keyreq | :key | :block, _]
|
|
64
|
+
false
|
|
65
|
+
in [:nokey]
|
|
66
|
+
false
|
|
67
|
+
else
|
|
68
|
+
true
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
65
72
|
|
|
66
73
|
EMPTY = new([])
|
|
67
74
|
end
|
|
@@ -23,8 +23,10 @@ module Dry
|
|
|
23
23
|
|
|
24
24
|
def define_initialize(klass)
|
|
25
25
|
super_parameters = MethodParameters.of(klass, :initialize).each do |ps|
|
|
26
|
-
# Look upwards past
|
|
27
|
-
#
|
|
26
|
+
# Look upwards past methods that only forward arguments, stopping at the
|
|
27
|
+
# first instance of explicit parameters. So `foo(**kwargs)` is
|
|
28
|
+
# skipped, but `foo(bar:, **kwargs)` is not. `foo(...)` is used by ROM as
|
|
29
|
+
# a delegation pattern, so it is not skipped.
|
|
28
30
|
break ps unless ps.pass_through?
|
|
29
31
|
end
|
|
30
32
|
|
|
@@ -37,15 +39,18 @@ module Dry
|
|
|
37
39
|
self
|
|
38
40
|
end
|
|
39
41
|
|
|
42
|
+
# rubocop:disable Lint/UnderscorePrefixedVariableName
|
|
40
43
|
def define_initialize_with_keywords(super_parameters)
|
|
41
44
|
assign_dependencies = method(:assign_dependencies)
|
|
42
45
|
slice_kwargs = method(:slice_kwargs)
|
|
43
46
|
|
|
44
47
|
instance_mod.class_exec do
|
|
45
|
-
|
|
46
|
-
|
|
48
|
+
# The choice of `__auto_inject_kwargs__` here is intentional, and used
|
|
49
|
+
# by MethodParameters#pass_through? to detect an injected initialize.
|
|
50
|
+
define_method :initialize do |**__auto_inject_kwargs__, &block|
|
|
51
|
+
assign_dependencies.(__auto_inject_kwargs__, self)
|
|
47
52
|
|
|
48
|
-
super_kwargs = slice_kwargs.(
|
|
53
|
+
super_kwargs = slice_kwargs.(__auto_inject_kwargs__, super_parameters)
|
|
49
54
|
|
|
50
55
|
if super_kwargs.any?
|
|
51
56
|
super(**super_kwargs, &block)
|
|
@@ -61,13 +66,13 @@ module Dry
|
|
|
61
66
|
slice_kwargs = method(:slice_kwargs)
|
|
62
67
|
|
|
63
68
|
instance_mod.class_exec do
|
|
64
|
-
define_method :initialize do |*args, **
|
|
65
|
-
assign_dependencies.(
|
|
69
|
+
define_method :initialize do |*args, **__auto_inject_kwargs__, &block|
|
|
70
|
+
assign_dependencies.(__auto_inject_kwargs__, self)
|
|
66
71
|
|
|
67
72
|
if super_parameters.splat?
|
|
68
|
-
super(*args, **
|
|
73
|
+
super(*args, **__auto_inject_kwargs__, &block)
|
|
69
74
|
else
|
|
70
|
-
super_kwargs = slice_kwargs.(
|
|
75
|
+
super_kwargs = slice_kwargs.(__auto_inject_kwargs__, super_parameters)
|
|
71
76
|
|
|
72
77
|
if super_kwargs.any?
|
|
73
78
|
super(*args, **super_kwargs, &block)
|
|
@@ -78,6 +83,7 @@ module Dry
|
|
|
78
83
|
end
|
|
79
84
|
end
|
|
80
85
|
end
|
|
86
|
+
# rubocop:enable Lint/UnderscorePrefixedVariableName
|
|
81
87
|
|
|
82
88
|
def assign_dependencies(kwargs, destination)
|
|
83
89
|
dependency_map.names.each do |name|
|
data/lib/dry/auto_inject.rb
CHANGED
data/lib/dry-auto_inject.rb
CHANGED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "mixin"
|
|
4
|
+
|
|
5
|
+
module RuboCop
|
|
6
|
+
module Cop
|
|
7
|
+
module DryAutoInject
|
|
8
|
+
# Enforces a configurable order for dry-auto_inject `Import[...]` deps.
|
|
9
|
+
#
|
|
10
|
+
# Non-aliased deps are emitted first, then aliased deps. Within each
|
|
11
|
+
# section, deps are grouped by matching the configured `Order` patterns
|
|
12
|
+
# and sorted alphabetically inside a group. Each pattern can be:
|
|
13
|
+
#
|
|
14
|
+
# - `'*'` — catch-all (at most one; implicitly appended)
|
|
15
|
+
# - `'prefix.*'` — prefix wildcard (matches `prefix` and `prefix.*`)
|
|
16
|
+
# - `'/regex/flags'` — regex matched against the dep path
|
|
17
|
+
# - otherwise — exact path match
|
|
18
|
+
#
|
|
19
|
+
# If `Order` is empty or omits `'*'`, a catch-all `'*'` group is appended
|
|
20
|
+
# implicitly so unmatched deps still have a home.
|
|
21
|
+
#
|
|
22
|
+
# Specific patterns take priority over the `*` catch-all regardless of
|
|
23
|
+
# their position in `Order`.
|
|
24
|
+
#
|
|
25
|
+
# @example Order: ['web.*', '*', 'core.*']
|
|
26
|
+
# # bad
|
|
27
|
+
# include Import[
|
|
28
|
+
# 'core.db',
|
|
29
|
+
# 'web.router',
|
|
30
|
+
# ]
|
|
31
|
+
#
|
|
32
|
+
# # good
|
|
33
|
+
# include Import[
|
|
34
|
+
# 'web.router',
|
|
35
|
+
# 'core.db',
|
|
36
|
+
# ]
|
|
37
|
+
#
|
|
38
|
+
# @example Order: ['/\A[^.]+\z/', '*'] — group dotless deps first
|
|
39
|
+
# include Import[
|
|
40
|
+
# 'logger',
|
|
41
|
+
# 'core.db',
|
|
42
|
+
# ]
|
|
43
|
+
class DependencyOrder < Base
|
|
44
|
+
extend AutoCorrector
|
|
45
|
+
include Mixin
|
|
46
|
+
|
|
47
|
+
MSG = "Dependencies are not in the configured order."
|
|
48
|
+
|
|
49
|
+
def initialize(config = nil, options = nil)
|
|
50
|
+
super
|
|
51
|
+
@parsed_order = build_parsed_order
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def on_send(node)
|
|
55
|
+
return unless injector_call?(node)
|
|
56
|
+
|
|
57
|
+
deps = parse_injector_deps(node)
|
|
58
|
+
return if deps.nil?
|
|
59
|
+
|
|
60
|
+
order = parsed_order
|
|
61
|
+
current = deps[:non_aliased] + deps[:aliased]
|
|
62
|
+
sorted = [deps[:non_aliased], deps[:aliased]].flat_map { |group|
|
|
63
|
+
group_and_sort(group, order) { |d| d[:path] }
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return if current == sorted
|
|
67
|
+
|
|
68
|
+
add_offense(node, message: MSG) do |corrector|
|
|
69
|
+
replace_injector_content(corrector, node, sorted)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
|
|
75
|
+
attr_reader :parsed_order
|
|
76
|
+
|
|
77
|
+
def build_parsed_order
|
|
78
|
+
raw = Array(cop_config["Order"]).dup
|
|
79
|
+
|
|
80
|
+
if raw.count("*") > 1
|
|
81
|
+
raise "#{self.class.badge}: `Order` may contain at most one '*' entry " \
|
|
82
|
+
"(got #{raw.inspect})"
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
raw << "*" unless raw.include?("*")
|
|
86
|
+
raw.each { |pat| validate_regex_pattern!(pat) if pat.start_with?("/") }
|
|
87
|
+
raw
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def validate_regex_pattern!(pat)
|
|
91
|
+
return if parse_regex_entry(pat)
|
|
92
|
+
|
|
93
|
+
raise "#{self.class.badge}: invalid regex in `Order` entry #{pat.inspect}"
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def group_and_sort(deps, order, &)
|
|
97
|
+
groups = ::Hash.new { |h, k| h[k] = [] }
|
|
98
|
+
|
|
99
|
+
# Specific patterns take priority over the `*` catch-all regardless
|
|
100
|
+
# of their position in `Order`.
|
|
101
|
+
specific_patterns = order.reject { |p| p == "*" }
|
|
102
|
+
|
|
103
|
+
deps.each do |d|
|
|
104
|
+
pat = specific_patterns.find { |p| match_pattern?(d[:path], p) } || "*"
|
|
105
|
+
groups[pat] << d
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
order.flat_map { |p| groups[p].sort_by(&) }
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def match_pattern?(path, pattern)
|
|
112
|
+
return true if pattern == "*"
|
|
113
|
+
|
|
114
|
+
if pattern.start_with?("/")
|
|
115
|
+
parse_regex_entry(pattern)&.match?(path)
|
|
116
|
+
elsif pattern.end_with?(".*")
|
|
117
|
+
prefix = pattern[...-2]
|
|
118
|
+
path == prefix || path.start_with?("#{prefix}.")
|
|
119
|
+
else
|
|
120
|
+
path == pattern
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "dry/core"
|
|
4
|
+
|
|
5
|
+
module RuboCop
|
|
6
|
+
module Cop
|
|
7
|
+
module DryAutoInject
|
|
8
|
+
# Shared helpers for cops that inspect `Import[...]`-style calls produced
|
|
9
|
+
# by dry-auto_inject.
|
|
10
|
+
module Mixin
|
|
11
|
+
include ::Dry::Core::Constants
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def injector_call?(node)
|
|
16
|
+
return false unless node.send_type?
|
|
17
|
+
return false unless node.method?(:[])
|
|
18
|
+
|
|
19
|
+
receiver = node.receiver
|
|
20
|
+
return false unless receiver&.const_type?
|
|
21
|
+
|
|
22
|
+
match_injector_module?(receiver)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def match_injector_module?(const_node)
|
|
26
|
+
full = const_fullname(const_node)
|
|
27
|
+
clean = full.sub(/\A::/, "")
|
|
28
|
+
|
|
29
|
+
Array(cop_config["InjectorModules"]).any? do |entry|
|
|
30
|
+
match_injector_entry?(entry.to_s, full, clean)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Entry formats:
|
|
35
|
+
# - `/pattern/flags` — regex literal, matched against `clean`
|
|
36
|
+
# - `*::Name` — last segment match with any prefix (incl. empty)
|
|
37
|
+
# - otherwise — exact match on the full or leading-`::`-stripped path
|
|
38
|
+
def match_injector_entry?(entry, full, clean)
|
|
39
|
+
if entry.start_with?("/")
|
|
40
|
+
regex = parse_regex_entry(entry)
|
|
41
|
+
return false unless regex
|
|
42
|
+
|
|
43
|
+
regex.match?(clean)
|
|
44
|
+
elsif entry.start_with?("*::")
|
|
45
|
+
suffix = entry[3..]
|
|
46
|
+
clean == suffix || clean.end_with?("::#{suffix}")
|
|
47
|
+
else
|
|
48
|
+
entry == full || entry == clean
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Returns a Regexp for a `/pattern/flags` literal, or nil if the
|
|
53
|
+
# string is not a regex literal or the pattern is invalid.
|
|
54
|
+
def parse_regex_entry(str)
|
|
55
|
+
m = str.match(%r{\A/(.*)/([imx]*)\z}m)
|
|
56
|
+
return nil unless m
|
|
57
|
+
|
|
58
|
+
opts = 0
|
|
59
|
+
opts |= ::Regexp::IGNORECASE if m[2].include?("i")
|
|
60
|
+
opts |= ::Regexp::MULTILINE if m[2].include?("m")
|
|
61
|
+
opts |= ::Regexp::EXTENDED if m[2].include?("x")
|
|
62
|
+
::Regexp.new(m[1], opts)
|
|
63
|
+
rescue ::RegexpError
|
|
64
|
+
nil
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def const_fullname(const_node)
|
|
68
|
+
parts = []
|
|
69
|
+
current = const_node
|
|
70
|
+
|
|
71
|
+
while current
|
|
72
|
+
if current.const_type?
|
|
73
|
+
parts.unshift(current.children[1].to_s)
|
|
74
|
+
current = current.children[0]
|
|
75
|
+
elsif current.cbase_type?
|
|
76
|
+
parts.unshift("")
|
|
77
|
+
current = nil
|
|
78
|
+
else
|
|
79
|
+
return ""
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
parts.join("::")
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Parses the arguments of an `Import[...]` call into a structured form.
|
|
87
|
+
# Returns nil if any argument is not a plain string or symbol-keyed/string-valued pair.
|
|
88
|
+
def parse_injector_deps(node)
|
|
89
|
+
args = node.arguments
|
|
90
|
+
return nil if args.empty?
|
|
91
|
+
|
|
92
|
+
hash_arg = args.last if args.last.hash_type?
|
|
93
|
+
string_nodes = hash_arg ? args[...-1] : args
|
|
94
|
+
|
|
95
|
+
non_aliased = parse_non_aliased_deps(string_nodes)
|
|
96
|
+
aliased = parse_aliased_deps(hash_arg)
|
|
97
|
+
return nil if non_aliased.nil? || aliased.nil?
|
|
98
|
+
|
|
99
|
+
{non_aliased:, aliased:}
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def parse_non_aliased_deps(nodes)
|
|
103
|
+
return nil unless nodes.all?(&:str_type?)
|
|
104
|
+
|
|
105
|
+
nodes.map { |arg| {node: arg, alias: nil, path: arg.value} }
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def parse_aliased_deps(hash_arg)
|
|
109
|
+
return EMPTY_ARRAY unless hash_arg
|
|
110
|
+
return nil unless hash_arg.pairs.all? { |p| p.key.sym_type? && p.value.str_type? }
|
|
111
|
+
|
|
112
|
+
hash_arg.pairs.map { |p| {node: p, alias: p.key.value.to_s, path: p.value.value} }
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def format_dep(dep)
|
|
116
|
+
node = dep[:node]
|
|
117
|
+
if dep[:alias]
|
|
118
|
+
"#{dep[:alias]}: #{node.value.source}"
|
|
119
|
+
else
|
|
120
|
+
node.source
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def line_indent_col(node)
|
|
125
|
+
line = node.source_range.source_line
|
|
126
|
+
line.index(/\S/) || node.source_range.column
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def item_indent_spaces(node)
|
|
130
|
+
args = node.arguments
|
|
131
|
+
|
|
132
|
+
if args.any? && args.first.source_range.line > node.source_range.line
|
|
133
|
+
indent(args.first.source_range.column)
|
|
134
|
+
else
|
|
135
|
+
indent(line_indent_col(node) + 2)
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def indent(width)
|
|
140
|
+
" " * width
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def render_deps(node, deps)
|
|
144
|
+
if node.multiline?
|
|
145
|
+
inner_indent = item_indent_spaces(node)
|
|
146
|
+
close_indent = indent(line_indent_col(node))
|
|
147
|
+
lines = deps.map { |d| "#{inner_indent}#{format_dep(d)}," }
|
|
148
|
+
"\n#{lines.join("\n")}\n#{close_indent}"
|
|
149
|
+
else
|
|
150
|
+
deps.map { |d| format_dep(d) }.join(", ")
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def replace_injector_content(corrector, node, deps)
|
|
155
|
+
selector = node.loc.selector
|
|
156
|
+
return unless selector&.source&.start_with?("[")
|
|
157
|
+
|
|
158
|
+
corrector.replace(selector.adjust(begin_pos: 1, end_pos: -1), render_deps(node, deps))
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "mixin"
|
|
4
|
+
|
|
5
|
+
module RuboCop
|
|
6
|
+
module Cop
|
|
7
|
+
module DryAutoInject
|
|
8
|
+
# Flags dry-auto_inject imports whose hash key matches the last segment
|
|
9
|
+
# of the path, since dry-auto_inject already derives the dependency name
|
|
10
|
+
# from that segment.
|
|
11
|
+
#
|
|
12
|
+
# @example
|
|
13
|
+
# # bad
|
|
14
|
+
# include Import[foo: 'some.path.foo']
|
|
15
|
+
#
|
|
16
|
+
# # good
|
|
17
|
+
# include Import['some.path.foo']
|
|
18
|
+
class RedundantAlias < Base
|
|
19
|
+
extend AutoCorrector
|
|
20
|
+
include Mixin
|
|
21
|
+
|
|
22
|
+
MSG =
|
|
23
|
+
"Redundant alias `%<alias_name>s:` — dependency key is derived from " \
|
|
24
|
+
"the last segment of `'%<path>s'`."
|
|
25
|
+
|
|
26
|
+
def on_send(node)
|
|
27
|
+
return unless injector_call?(node)
|
|
28
|
+
|
|
29
|
+
deps = parse_injector_deps(node)
|
|
30
|
+
return if deps.nil?
|
|
31
|
+
|
|
32
|
+
redundant = deps[:aliased].select { |d| d[:alias] == d[:path].split(".").last }
|
|
33
|
+
return if redundant.empty?
|
|
34
|
+
|
|
35
|
+
canonical = promote_redundant_aliases(deps)
|
|
36
|
+
|
|
37
|
+
redundant.each_with_index do |dep, i|
|
|
38
|
+
add_offense(
|
|
39
|
+
dep[:node],
|
|
40
|
+
message: format(MSG, alias_name: dep[:alias], path: dep[:path])
|
|
41
|
+
) do |corrector|
|
|
42
|
+
next unless i.zero?
|
|
43
|
+
|
|
44
|
+
replace_injector_content(corrector, node, canonical)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
def promote_redundant_aliases(deps)
|
|
52
|
+
non_aliased = deps[:non_aliased].dup
|
|
53
|
+
aliased = []
|
|
54
|
+
|
|
55
|
+
deps[:aliased].each do |d|
|
|
56
|
+
if d[:alias] == d[:path].split(".").last
|
|
57
|
+
non_aliased << {node: d[:node].value, alias: nil, path: d[:path]}
|
|
58
|
+
else
|
|
59
|
+
aliased << d
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
non_aliased + aliased
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "lint_roller"
|
|
4
|
+
|
|
5
|
+
require "dry/auto_inject/version"
|
|
6
|
+
|
|
7
|
+
module RuboCop
|
|
8
|
+
module DryAutoInject
|
|
9
|
+
class Plugin < ::LintRoller::Plugin
|
|
10
|
+
def about
|
|
11
|
+
::LintRoller::About.new(
|
|
12
|
+
name: "dry-auto_inject",
|
|
13
|
+
version: ::Dry::AutoInject::VERSION,
|
|
14
|
+
homepage: "https://hanakai.org/learn/dry/dry-auto_inject",
|
|
15
|
+
description: "RuboCop cops for enforcing dry-auto_inject conventions."
|
|
16
|
+
)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def supported?(context)
|
|
20
|
+
context.engine == :rubocop
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def rules(_context)
|
|
24
|
+
project_root = ::Pathname.new(__dir__).join("../../..")
|
|
25
|
+
|
|
26
|
+
::LintRoller::Rules.new(
|
|
27
|
+
type: :path,
|
|
28
|
+
config_format: :rubocop,
|
|
29
|
+
value: project_root.join("config", "default.yml")
|
|
30
|
+
)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dry-auto_inject
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
|
-
-
|
|
8
|
-
|
|
9
|
-
bindir: bin
|
|
7
|
+
- Hanakai team
|
|
8
|
+
bindir: exe
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: dry-core
|
|
@@ -38,16 +37,62 @@ dependencies:
|
|
|
38
37
|
- - "~>"
|
|
39
38
|
- !ruby/object:Gem::Version
|
|
40
39
|
version: '2.6'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: bundler
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '0'
|
|
47
|
+
type: :development
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: rake
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0'
|
|
61
|
+
type: :development
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '0'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: rspec
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - ">="
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '0'
|
|
75
|
+
type: :development
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - ">="
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '0'
|
|
41
82
|
description: Container-agnostic automatic constructor injection
|
|
42
83
|
email:
|
|
43
|
-
-
|
|
84
|
+
- info@hanakai.org
|
|
44
85
|
executables: []
|
|
45
86
|
extensions: []
|
|
46
|
-
extra_rdoc_files:
|
|
87
|
+
extra_rdoc_files:
|
|
88
|
+
- CHANGELOG.md
|
|
89
|
+
- LICENSE
|
|
90
|
+
- README.md
|
|
47
91
|
files:
|
|
48
92
|
- CHANGELOG.md
|
|
49
93
|
- LICENSE
|
|
50
94
|
- README.md
|
|
95
|
+
- config/default.yml
|
|
51
96
|
- dry-auto_inject.gemspec
|
|
52
97
|
- lib/dry-auto_inject.rb
|
|
53
98
|
- lib/dry/auto_inject.rb
|
|
@@ -61,16 +106,21 @@ files:
|
|
|
61
106
|
- lib/dry/auto_inject/strategies/hash.rb
|
|
62
107
|
- lib/dry/auto_inject/strategies/kwargs.rb
|
|
63
108
|
- lib/dry/auto_inject/version.rb
|
|
109
|
+
- lib/rubocop/cop/dry_auto_inject/dependency_order.rb
|
|
110
|
+
- lib/rubocop/cop/dry_auto_inject/mixin.rb
|
|
111
|
+
- lib/rubocop/cop/dry_auto_inject/redundant_alias.rb
|
|
112
|
+
- lib/rubocop/dry-auto_inject.rb
|
|
113
|
+
- lib/rubocop/dry_auto_inject.rb
|
|
114
|
+
- lib/rubocop/dry_auto_inject/plugin.rb
|
|
64
115
|
homepage: https://dry-rb.org/gems/dry-auto_inject
|
|
65
116
|
licenses:
|
|
66
117
|
- MIT
|
|
67
118
|
metadata:
|
|
68
|
-
allowed_push_host: https://rubygems.org
|
|
69
119
|
changelog_uri: https://github.com/dry-rb/dry-auto_inject/blob/main/CHANGELOG.md
|
|
70
120
|
source_code_uri: https://github.com/dry-rb/dry-auto_inject
|
|
71
121
|
bug_tracker_uri: https://github.com/dry-rb/dry-auto_inject/issues
|
|
72
|
-
|
|
73
|
-
|
|
122
|
+
funding_uri: https://github.com/sponsors/hanami
|
|
123
|
+
default_lint_roller_plugin: RuboCop::DryAutoInject::Plugin
|
|
74
124
|
rdoc_options: []
|
|
75
125
|
require_paths:
|
|
76
126
|
- lib
|
|
@@ -78,15 +128,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
78
128
|
requirements:
|
|
79
129
|
- - ">="
|
|
80
130
|
- !ruby/object:Gem::Version
|
|
81
|
-
version: '3.
|
|
131
|
+
version: '3.3'
|
|
82
132
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
83
133
|
requirements:
|
|
84
134
|
- - ">="
|
|
85
135
|
- !ruby/object:Gem::Version
|
|
86
136
|
version: '0'
|
|
87
137
|
requirements: []
|
|
88
|
-
rubygems_version: 3.
|
|
89
|
-
signing_key:
|
|
138
|
+
rubygems_version: 3.6.9
|
|
90
139
|
specification_version: 4
|
|
91
140
|
summary: Container-agnostic automatic constructor injection
|
|
92
141
|
test_files: []
|