packwerk 1.3.1 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1 -0
  3. data/Gemfile.lock +12 -9
  4. data/README.md +9 -3
  5. data/TROUBLESHOOT.md +3 -3
  6. data/UPGRADING.md +54 -0
  7. data/USAGE.md +32 -51
  8. data/exe/packwerk +7 -1
  9. data/lib/packwerk/application_load_paths.rb +1 -0
  10. data/lib/packwerk/application_validator.rb +17 -59
  11. data/lib/packwerk/association_inspector.rb +1 -1
  12. data/lib/packwerk/cache.rb +168 -0
  13. data/lib/packwerk/cli.rb +37 -20
  14. data/lib/packwerk/configuration.rb +40 -5
  15. data/lib/packwerk/const_node_inspector.rb +3 -2
  16. data/lib/packwerk/constant_discovery.rb +4 -4
  17. data/lib/packwerk/constant_name_inspector.rb +1 -1
  18. data/lib/packwerk/deprecated_references.rb +18 -6
  19. data/lib/packwerk/file_processor.rb +53 -14
  20. data/lib/packwerk/files_for_processing.rb +15 -4
  21. data/lib/packwerk/formatters/offenses_formatter.rb +1 -1
  22. data/lib/packwerk/formatters/progress_formatter.rb +1 -1
  23. data/lib/packwerk/generators/configuration_file.rb +4 -19
  24. data/lib/packwerk/generators/templates/package.yml +1 -1
  25. data/lib/packwerk/generators/templates/packwerk.yml.erb +5 -5
  26. data/lib/packwerk/graph.rb +2 -0
  27. data/lib/packwerk/node.rb +2 -0
  28. data/lib/packwerk/node_processor.rb +10 -22
  29. data/lib/packwerk/node_processor_factory.rb +0 -3
  30. data/lib/packwerk/node_visitor.rb +7 -2
  31. data/lib/packwerk/package.rb +25 -4
  32. data/lib/packwerk/package_set.rb +44 -8
  33. data/lib/packwerk/parsed_constant_definitions.rb +5 -4
  34. data/lib/packwerk/reference.rb +2 -1
  35. data/lib/packwerk/reference_checking/checkers/checker.rb +21 -0
  36. data/lib/packwerk/reference_checking/checkers/dependency_checker.rb +31 -0
  37. data/lib/packwerk/reference_checking/checkers/privacy_checker.rb +58 -0
  38. data/lib/packwerk/reference_checking/reference_checker.rb +33 -0
  39. data/lib/packwerk/reference_extractor.rb +66 -19
  40. data/lib/packwerk/reference_offense.rb +1 -0
  41. data/lib/packwerk/run_context.rb +32 -11
  42. data/lib/packwerk/sanity_checker.rb +1 -1
  43. data/lib/packwerk/spring_command.rb +28 -0
  44. data/lib/packwerk/unresolved_reference.rb +10 -0
  45. data/lib/packwerk/version.rb +1 -1
  46. data/lib/packwerk/violation_type.rb +1 -1
  47. data/lib/packwerk.rb +19 -12
  48. data/packwerk.gemspec +4 -1
  49. data/service.yml +0 -2
  50. data/sorbet/rbi/gems/psych@3.3.2.rbi +24 -0
  51. metadata +41 -11
  52. data/lib/packwerk/checker.rb +0 -17
  53. data/lib/packwerk/dependency_checker.rb +0 -26
  54. data/lib/packwerk/generators/inflections_file.rb +0 -43
  55. data/lib/packwerk/generators/templates/inflections.yml +0 -6
  56. data/lib/packwerk/inflections/custom.rb +0 -33
  57. data/lib/packwerk/inflections/default.rb +0 -73
  58. data/lib/packwerk/inflector.rb +0 -48
  59. data/lib/packwerk/privacy_checker.rb +0 -53
@@ -4,6 +4,7 @@
4
4
  require "constant_resolver"
5
5
 
6
6
  module Packwerk
7
+ # Holds the context of a Packwerk run across multiple files.
7
8
  class RunContext
8
9
  extend T::Sig
9
10
 
@@ -17,19 +18,23 @@ module Packwerk
17
18
  )
18
19
 
19
20
  DEFAULT_CHECKERS = [
20
- ::Packwerk::DependencyChecker,
21
- ::Packwerk::PrivacyChecker,
21
+ ::Packwerk::ReferenceChecking::Checkers::DependencyChecker,
22
+ ::Packwerk::ReferenceChecking::Checkers::PrivacyChecker,
22
23
  ]
23
24
 
24
25
  class << self
25
26
  def from_configuration(configuration)
26
- inflector = ::Packwerk::Inflector.from_file(configuration.inflections_file)
27
+ inflector = ActiveSupport::Inflector
28
+
27
29
  new(
28
30
  root_path: configuration.root_path,
29
31
  load_paths: configuration.load_paths,
30
32
  package_paths: configuration.package_paths,
31
33
  inflector: inflector,
32
- custom_associations: configuration.custom_associations
34
+ custom_associations: configuration.custom_associations,
35
+ cache_enabled: configuration.cache_enabled?,
36
+ cache_directory: configuration.cache_directory,
37
+ config_path: configuration.config_path,
33
38
  )
34
39
  end
35
40
  end
@@ -40,7 +45,10 @@ module Packwerk
40
45
  package_paths: nil,
41
46
  inflector: nil,
42
47
  custom_associations: [],
43
- checker_classes: DEFAULT_CHECKERS
48
+ checker_classes: DEFAULT_CHECKERS,
49
+ cache_enabled: false,
50
+ cache_directory: nil,
51
+ config_path: nil
44
52
  )
45
53
  @root_path = root_path
46
54
  @load_paths = load_paths
@@ -48,25 +56,33 @@ module Packwerk
48
56
  @inflector = inflector
49
57
  @custom_associations = custom_associations
50
58
  @checker_classes = checker_classes
59
+ @cache_enabled = cache_enabled
60
+ @cache_directory = cache_directory
61
+ @config_path = config_path
51
62
  end
52
63
 
53
- sig { params(file: String).returns(T::Array[T.nilable(::Packwerk::Offense)]) }
64
+ sig { params(file: String).returns(T::Array[Packwerk::Offense]) }
54
65
  def process_file(file:)
55
- file_processor.call(file)
66
+ unresolved_references_and_offenses = file_processor.call(file)
67
+ references_and_offenses = ReferenceExtractor.get_fully_qualified_references_and_offenses_from(
68
+ unresolved_references_and_offenses,
69
+ context_provider
70
+ )
71
+ reference_checker = ReferenceChecking::ReferenceChecker.new(checkers)
72
+ references_and_offenses.flat_map { |reference| reference_checker.call(reference) }
56
73
  end
57
74
 
58
75
  private
59
76
 
60
77
  sig { returns(FileProcessor) }
61
78
  def file_processor
62
- @file_processor ||= FileProcessor.new(node_processor_factory: node_processor_factory)
79
+ @file_processor ||= FileProcessor.new(node_processor_factory: node_processor_factory, cache: cache)
63
80
  end
64
81
 
65
82
  sig { returns(NodeProcessorFactory) }
66
83
  def node_processor_factory
67
84
  NodeProcessorFactory.new(
68
85
  context_provider: context_provider,
69
- checkers: checkers,
70
86
  root_path: root_path,
71
87
  constant_name_inspectors: constant_name_inspectors
72
88
  )
@@ -74,7 +90,7 @@ module Packwerk
74
90
 
75
91
  sig { returns(ConstantDiscovery) }
76
92
  def context_provider
77
- ::Packwerk::ConstantDiscovery.new(
93
+ @context_provider ||= ::Packwerk::ConstantDiscovery.new(
78
94
  constant_resolver: resolver,
79
95
  packages: package_set
80
96
  )
@@ -89,12 +105,17 @@ module Packwerk
89
105
  )
90
106
  end
91
107
 
108
+ sig { returns(Cache) }
109
+ def cache
110
+ @cache ||= Cache.new(enable_cache: @cache_enabled, cache_directory: @cache_directory, config_path: @config_path)
111
+ end
112
+
92
113
  sig { returns(PackageSet) }
93
114
  def package_set
94
115
  ::Packwerk::PackageSet.load_all_from(root_path, package_pathspec: package_paths)
95
116
  end
96
117
 
97
- sig { returns(T::Array[Checker]) }
118
+ sig { returns(T::Array[ReferenceChecking::Checkers::Checker]) }
98
119
  def checkers
99
120
  checker_classes.map(&:new)
100
121
  end
@@ -1,4 +1,4 @@
1
- # typed: false
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Packwerk
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+ # typed: false
3
+
4
+ require "spring/commands"
5
+
6
+ module Packwerk
7
+ class SpringCommand
8
+ def env(*)
9
+ # Packwerk needs to run in a test environment, which has a set of autoload paths that are
10
+ # often a superset of the dev/prod paths (for example, test/support/helpers)
11
+ "test"
12
+ end
13
+
14
+ def exec_name
15
+ "packwerk"
16
+ end
17
+
18
+ def gem_name
19
+ "packwerk"
20
+ end
21
+
22
+ def call
23
+ load(Gem.bin_path(gem_name, exec_name))
24
+ end
25
+ end
26
+
27
+ Spring.register_command("packwerk", SpringCommand.new)
28
+ end
@@ -0,0 +1,10 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module Packwerk
5
+ # An unresolved reference from a file in one package to a constant that may be defined in a different package.
6
+ # Unresolved means that we know how it's referred to in the file,
7
+ # and we have enough context on that reference to figure out the fully qualified reference such that we
8
+ # can produce a Reference in a separate pass. However, we have not yet resolved it to its fully qualified version.
9
+ UnresolvedReference = Struct.new(:constant_name, :namespace_path, :relative_path, :source_location)
10
+ end
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Packwerk
5
- VERSION = "1.3.1"
5
+ VERSION = "2.1.0"
6
6
  end
@@ -1,4 +1,4 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Packwerk
data/lib/packwerk.rb CHANGED
@@ -5,6 +5,9 @@ require "sorbet-runtime"
5
5
  require "active_support"
6
6
  require "fileutils"
7
7
 
8
+ # Provides String#pluralize
9
+ require "active_support/core_ext/string"
10
+
8
11
  module Packwerk
9
12
  extend ActiveSupport::Autoload
10
13
 
@@ -12,18 +15,16 @@ module Packwerk
12
15
  autoload :ApplicationValidator
13
16
  autoload :AssociationInspector
14
17
  autoload :OffenseCollection
15
- autoload :Checker
18
+ autoload :Cache
16
19
  autoload :Cli
17
20
  autoload :Configuration
18
21
  autoload :ConstantDiscovery
19
22
  autoload :ConstantNameInspector
20
23
  autoload :ConstNodeInspector
21
- autoload :DependencyChecker
22
24
  autoload :DeprecatedReferences
23
25
  autoload :FileProcessor
24
26
  autoload :FilesForProcessing
25
27
  autoload :Graph
26
- autoload :Inflector
27
28
  autoload :Node
28
29
  autoload :NodeProcessor
29
30
  autoload :NodeProcessorFactory
@@ -36,7 +37,7 @@ module Packwerk
36
37
  autoload :ParsedConstantDefinitions
37
38
  autoload :Parsers
38
39
  autoload :ParseRun
39
- autoload :PrivacyChecker
40
+ autoload :UnresolvedReference
40
41
  autoload :Reference
41
42
  autoload :ReferenceExtractor
42
43
  autoload :ReferenceOffense
@@ -45,13 +46,6 @@ module Packwerk
45
46
  autoload :Version
46
47
  autoload :ViolationType
47
48
 
48
- module Inflections
49
- extend ActiveSupport::Autoload
50
-
51
- autoload :Custom
52
- autoload :Default
53
- end
54
-
55
49
  module OutputStyles
56
50
  extend ActiveSupport::Autoload
57
51
 
@@ -74,7 +68,20 @@ module Packwerk
74
68
  extend ActiveSupport::Autoload
75
69
 
76
70
  autoload :ConfigurationFile
77
- autoload :InflectionsFile
78
71
  autoload :RootPackage
79
72
  end
73
+
74
+ module ReferenceChecking
75
+ extend ActiveSupport::Autoload
76
+
77
+ autoload :ReferenceChecker
78
+
79
+ module Checkers
80
+ extend ActiveSupport::Autoload
81
+
82
+ autoload :Checker
83
+ autoload :DependencyChecker
84
+ autoload :PrivacyChecker
85
+ end
86
+ end
80
87
  end
data/packwerk.gemspec CHANGED
@@ -44,11 +44,14 @@ Gem::Specification.new do |spec|
44
44
  spec.add_dependency("constant_resolver")
45
45
  spec.add_dependency("parallel")
46
46
  spec.add_dependency("sorbet-runtime")
47
+ spec.add_dependency("bundler")
48
+ spec.add_dependency("digest")
47
49
 
48
- spec.add_development_dependency("bundler")
49
50
  spec.add_development_dependency("rake")
50
51
  spec.add_development_dependency("sorbet")
51
52
  spec.add_development_dependency("m")
53
+ # https://github.com/ruby/psych/pull/487
54
+ spec.add_development_dependency("psych", "~> 3")
52
55
 
53
56
  # For Ruby parsing
54
57
  spec.add_dependency("ast")
data/service.yml CHANGED
@@ -1,3 +1 @@
1
1
  classification: library
2
- slack_channels:
3
- - core-stewardship
@@ -0,0 +1,24 @@
1
+ # typed: true
2
+
3
+ # DO NOT EDIT MANUALLY
4
+ # This is an autogenerated file for types exported from the `psych` gem.
5
+ # Please instead update this file by running `bin/tapioca gem psych`.
6
+
7
+ ::RUBY19 = T.let(T.unsafe(nil), TrueClass)
8
+
9
+ class Object < ::BasicObject
10
+ include ::ActiveSupport::ToJsonWithActiveSupportEncoder
11
+ include ::Kernel
12
+ include ::JSON::Ext::Generator::GeneratorMethods::Object
13
+ include ::ActiveSupport::Tryable
14
+ include ::Minitest::Expectations
15
+ include ::Mocha::ParameterMatchers::InstanceMethods
16
+ include ::Mocha::Inspect::ObjectMethods
17
+ include ::Mocha::ObjectMethods
18
+
19
+ def to_yaml(options = T.unsafe(nil)); end
20
+
21
+ class << self
22
+ def yaml_tag(url); end
23
+ end
24
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: packwerk
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.1
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-07-15 00:00:00.000000000 Z
11
+ date: 2022-02-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -73,7 +73,21 @@ dependencies:
73
73
  - - ">="
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
- type: :development
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: digest
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
77
91
  prerelease: false
78
92
  version_requirements: !ruby/object:Gem::Requirement
79
93
  requirements:
@@ -122,6 +136,20 @@ dependencies:
122
136
  - - ">="
123
137
  - !ruby/object:Gem::Version
124
138
  version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: psych
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '3'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '3'
125
153
  - !ruby/object:Gem::Dependency
126
154
  name: ast
127
155
  requirement: !ruby/object:Gem::Requirement
@@ -181,6 +209,7 @@ files:
181
209
  - ".gitignore"
182
210
  - ".rubocop.yml"
183
211
  - ".ruby-version"
212
+ - CHANGELOG.md
184
213
  - CODEOWNERS
185
214
  - CODE_OF_CONDUCT.md
186
215
  - CONTRIBUTING.md
@@ -190,6 +219,7 @@ files:
190
219
  - README.md
191
220
  - Rakefile
192
221
  - TROUBLESHOOT.md
222
+ - UPGRADING.md
193
223
  - USAGE.md
194
224
  - bin/console
195
225
  - bin/m
@@ -206,28 +236,22 @@ files:
206
236
  - lib/packwerk/application_load_paths.rb
207
237
  - lib/packwerk/application_validator.rb
208
238
  - lib/packwerk/association_inspector.rb
209
- - lib/packwerk/checker.rb
239
+ - lib/packwerk/cache.rb
210
240
  - lib/packwerk/cli.rb
211
241
  - lib/packwerk/configuration.rb
212
242
  - lib/packwerk/const_node_inspector.rb
213
243
  - lib/packwerk/constant_discovery.rb
214
244
  - lib/packwerk/constant_name_inspector.rb
215
- - lib/packwerk/dependency_checker.rb
216
245
  - lib/packwerk/deprecated_references.rb
217
246
  - lib/packwerk/file_processor.rb
218
247
  - lib/packwerk/files_for_processing.rb
219
248
  - lib/packwerk/formatters/offenses_formatter.rb
220
249
  - lib/packwerk/formatters/progress_formatter.rb
221
250
  - lib/packwerk/generators/configuration_file.rb
222
- - lib/packwerk/generators/inflections_file.rb
223
251
  - lib/packwerk/generators/root_package.rb
224
- - lib/packwerk/generators/templates/inflections.yml
225
252
  - lib/packwerk/generators/templates/package.yml
226
253
  - lib/packwerk/generators/templates/packwerk.yml.erb
227
254
  - lib/packwerk/graph.rb
228
- - lib/packwerk/inflections/custom.rb
229
- - lib/packwerk/inflections/default.rb
230
- - lib/packwerk/inflector.rb
231
255
  - lib/packwerk/node.rb
232
256
  - lib/packwerk/node_processor.rb
233
257
  - lib/packwerk/node_processor_factory.rb
@@ -246,13 +270,18 @@ files:
246
270
  - lib/packwerk/parsers/erb.rb
247
271
  - lib/packwerk/parsers/factory.rb
248
272
  - lib/packwerk/parsers/ruby.rb
249
- - lib/packwerk/privacy_checker.rb
250
273
  - lib/packwerk/reference.rb
274
+ - lib/packwerk/reference_checking/checkers/checker.rb
275
+ - lib/packwerk/reference_checking/checkers/dependency_checker.rb
276
+ - lib/packwerk/reference_checking/checkers/privacy_checker.rb
277
+ - lib/packwerk/reference_checking/reference_checker.rb
251
278
  - lib/packwerk/reference_extractor.rb
252
279
  - lib/packwerk/reference_offense.rb
253
280
  - lib/packwerk/result.rb
254
281
  - lib/packwerk/run_context.rb
255
282
  - lib/packwerk/sanity_checker.rb
283
+ - lib/packwerk/spring_command.rb
284
+ - lib/packwerk/unresolved_reference.rb
256
285
  - lib/packwerk/version.rb
257
286
  - lib/packwerk/violation_type.rb
258
287
  - library.yml
@@ -301,6 +330,7 @@ files:
301
330
  - sorbet/rbi/gems/parlour@6.0.0.rbi
302
331
  - sorbet/rbi/gems/parser@3.0.0.0.rbi
303
332
  - sorbet/rbi/gems/pry@0.14.0.rbi
333
+ - sorbet/rbi/gems/psych@3.3.2.rbi
304
334
  - sorbet/rbi/gems/racc@1.5.2.rbi
305
335
  - sorbet/rbi/gems/rack-test@1.1.0.rbi
306
336
  - sorbet/rbi/gems/rack@2.2.3.rbi
@@ -1,17 +0,0 @@
1
- # typed: true
2
- # frozen_string_literal: true
3
-
4
- module Packwerk
5
- module Checker
6
- extend T::Sig
7
- extend T::Helpers
8
-
9
- interface!
10
-
11
- sig { returns(ViolationType).abstract }
12
- def violation_type; end
13
-
14
- sig { params(reference: Reference).returns(T::Boolean).abstract }
15
- def invalid_reference?(reference); end
16
- end
17
- end
@@ -1,26 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- module Packwerk
5
- class DependencyChecker
6
- extend T::Sig
7
- include Checker
8
-
9
- sig { override.returns(ViolationType) }
10
- def violation_type
11
- ViolationType::Dependency
12
- end
13
-
14
- sig do
15
- override
16
- .params(reference: Packwerk::Reference)
17
- .returns(T::Boolean)
18
- end
19
- def invalid_reference?(reference)
20
- return false unless reference.source_package
21
- return false unless reference.source_package.enforce_dependencies?
22
- return false if reference.source_package.dependency?(reference.constant.package)
23
- true
24
- end
25
- end
26
- end
@@ -1,43 +0,0 @@
1
- # typed: true
2
- # frozen_string_literal: true
3
-
4
- module Packwerk
5
- module Generators
6
- class InflectionsFile
7
- extend T::Sig
8
-
9
- class << self
10
- def generate(root:, out:)
11
- new(root, out: out).generate
12
- end
13
- end
14
-
15
- def initialize(root, out: $stdout)
16
- @root = root
17
- @out = out
18
- end
19
-
20
- sig { returns(T::Boolean) }
21
- def generate
22
- ruby_inflection_file_exist = Dir.glob("#{@root}/**/inflections.rb").any?
23
- yaml_inflection_file_exist = Dir.glob("#{@root}/**/inflections.yml").any?
24
-
25
- if !ruby_inflection_file_exist || yaml_inflection_file_exist
26
- return true
27
- end
28
-
29
- @out.puts("📦 Generating `inflections.yml` file...")
30
-
31
- destination_file_path = File.join(@root, "config")
32
- FileUtils.mkdir_p(destination_file_path)
33
-
34
- source_file_path = File.join(__dir__, "/templates/inflections.yml")
35
- FileUtils.cp(source_file_path, destination_file_path)
36
-
37
- @out.puts("✅ `inflections.yml` generated in #{destination_file_path}")
38
-
39
- true
40
- end
41
- end
42
- end
43
- end
@@ -1,6 +0,0 @@
1
- # List your inflections in this file instead of `inflections.rb`
2
- # See steps to set up custom inflections:
3
- # https://github.com/Shopify/packwerk/blob/main/USAGE.md#Inflections
4
-
5
- # acronym:
6
- # - "GraphQL"
@@ -1,33 +0,0 @@
1
- # typed: true
2
- # frozen_string_literal: true
3
-
4
- require "yaml"
5
-
6
- module Packwerk
7
- module Inflections
8
- class Custom
9
- SUPPORTED_INFLECTION_METHODS = %w(acronym human irregular plural singular uncountable)
10
-
11
- attr_accessor :inflections
12
-
13
- def initialize(custom_inflection_file = nil)
14
- if custom_inflection_file && File.exist?(custom_inflection_file)
15
- @inflections = YAML.load_file(custom_inflection_file) || {}
16
-
17
- invalid_inflections = @inflections.keys - SUPPORTED_INFLECTION_METHODS
18
- raise ArgumentError, "Unsupported inflection types: #{invalid_inflections}" if invalid_inflections.any?
19
- else
20
- @inflections = []
21
- end
22
- end
23
-
24
- def apply_to(inflections_object)
25
- @inflections.each do |inflection_type, inflections|
26
- inflections.each do |inflection|
27
- inflections_object.public_send(inflection_type, *Array(inflection))
28
- end
29
- end
30
- end
31
- end
32
- end
33
- end
@@ -1,73 +0,0 @@
1
- # typed: true
2
- # frozen_string_literal: true
3
-
4
- module Packwerk
5
- module Inflections
6
- module Default
7
- class << self
8
- def apply_to(inflections_object)
9
- # copied from active_support/inflections
10
- # https://github.com/rails/rails/blob/d2ae2c3103e93783971d5356d0b3fd1b4070d6cf/activesupport/lib/active_support/inflections.rb#L12
11
- inflections_object.plural(/$/, "s")
12
- inflections_object.plural(/s$/i, "s")
13
- inflections_object.plural(/^(ax|test)is$/i, '\1es')
14
- inflections_object.plural(/(octop|vir)us$/i, '\1i')
15
- inflections_object.plural(/(octop|vir)i$/i, '\1i')
16
- inflections_object.plural(/(alias|status)$/i, '\1es')
17
- inflections_object.plural(/(bu)s$/i, '\1ses')
18
- inflections_object.plural(/(buffal|tomat)o$/i, '\1oes')
19
- inflections_object.plural(/([ti])um$/i, '\1a')
20
- inflections_object.plural(/([ti])a$/i, '\1a')
21
- inflections_object.plural(/sis$/i, "ses")
22
- inflections_object.plural(/(?:([^f])fe|([lr])f)$/i, '\1\2ves')
23
- inflections_object.plural(/(hive)$/i, '\1s')
24
- inflections_object.plural(/([^aeiouy]|qu)y$/i, '\1ies')
25
- inflections_object.plural(/(x|ch|ss|sh)$/i, '\1es')
26
- inflections_object.plural(/(matr|vert|ind)(?:ix|ex)$/i, '\1ices')
27
- inflections_object.plural(/^(m|l)ouse$/i, '\1ice')
28
- inflections_object.plural(/^(m|l)ice$/i, '\1ice')
29
- inflections_object.plural(/^(ox)$/i, '\1en')
30
- inflections_object.plural(/^(oxen)$/i, '\1')
31
- inflections_object.plural(/(quiz)$/i, '\1zes')
32
-
33
- inflections_object.singular(/s$/i, "")
34
- inflections_object.singular(/(ss)$/i, '\1')
35
- inflections_object.singular(/(n)ews$/i, '\1ews')
36
- inflections_object.singular(/([ti])a$/i, '\1um')
37
- inflections_object.singular(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(sis|ses)$/i, '\1sis')
38
- inflections_object.singular(/(^analy)(sis|ses)$/i, '\1sis')
39
- inflections_object.singular(/([^f])ves$/i, '\1fe')
40
- inflections_object.singular(/(hive)s$/i, '\1')
41
- inflections_object.singular(/(tive)s$/i, '\1')
42
- inflections_object.singular(/([lr])ves$/i, '\1f')
43
- inflections_object.singular(/([^aeiouy]|qu)ies$/i, '\1y')
44
- inflections_object.singular(/(s)eries$/i, '\1eries')
45
- inflections_object.singular(/(m)ovies$/i, '\1ovie')
46
- inflections_object.singular(/(x|ch|ss|sh)es$/i, '\1')
47
- inflections_object.singular(/^(m|l)ice$/i, '\1ouse')
48
- inflections_object.singular(/(bus)(es)?$/i, '\1')
49
- inflections_object.singular(/(o)es$/i, '\1')
50
- inflections_object.singular(/(shoe)s$/i, '\1')
51
- inflections_object.singular(/(cris|test)(is|es)$/i, '\1is')
52
- inflections_object.singular(/^(a)x[ie]s$/i, '\1xis')
53
- inflections_object.singular(/(octop|vir)(us|i)$/i, '\1us')
54
- inflections_object.singular(/(alias|status)(es)?$/i, '\1')
55
- inflections_object.singular(/^(ox)en/i, '\1')
56
- inflections_object.singular(/(vert|ind)ices$/i, '\1ex')
57
- inflections_object.singular(/(matr)ices$/i, '\1ix')
58
- inflections_object.singular(/(quiz)zes$/i, '\1')
59
- inflections_object.singular(/(database)s$/i, '\1')
60
-
61
- inflections_object.irregular("person", "people")
62
- inflections_object.irregular("man", "men")
63
- inflections_object.irregular("child", "children")
64
- inflections_object.irregular("sex", "sexes")
65
- inflections_object.irregular("move", "moves")
66
- inflections_object.irregular("zombie", "zombies")
67
-
68
- inflections_object.uncountable(%w(equipment information rice money species series fish sheep jeans police))
69
- end
70
- end
71
- end
72
- end
73
- end
@@ -1,48 +0,0 @@
1
- # typed: true
2
- # frozen_string_literal: true
3
-
4
- require "active_support/inflector"
5
-
6
- module Packwerk
7
- class Inflector
8
- class << self
9
- extend T::Sig
10
-
11
- def default
12
- @default ||= new(custom_inflector: Inflections::Custom.new)
13
- end
14
-
15
- sig { params(inflections_file: String).returns(::Packwerk::Inflector) }
16
- def from_file(inflections_file)
17
- new(custom_inflector: Inflections::Custom.new(inflections_file))
18
- end
19
- end
20
-
21
- extend T::Sig
22
- include ::ActiveSupport::Inflector # For #camelize, #classify, #pluralize, #singularize
23
-
24
- sig do
25
- params(
26
- custom_inflector: Inflections::Custom
27
- ).void
28
- end
29
- def initialize(custom_inflector:)
30
- @inflections = ::ActiveSupport::Inflector::Inflections.new
31
-
32
- Inflections::Default.apply_to(@inflections)
33
- custom_inflector.apply_to(@inflections)
34
- end
35
-
36
- def pluralize(word, count = nil)
37
- if count == 1
38
- singularize(word)
39
- else
40
- super(word)
41
- end
42
- end
43
-
44
- def inflections(_ = nil)
45
- @inflections
46
- end
47
- end
48
- end