packwerk 1.4.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5d150d89ede62e601246e2ff0290ecda4aab883a7c8b8be02feb86760ad26b72
4
- data.tar.gz: 33b088b3387b8fdfe694967f20529fb8795dec8572dc9e036cb4979402f19c5b
3
+ metadata.gz: a473db2c54adea132ca7e61a51072b570d7e37b7d63c021259eef3cc7625177b
4
+ data.tar.gz: 1b8486e61969621fac562d2fb6ebe47dcf6f71fcd13f6d18524337a3ed831ac2
5
5
  SHA512:
6
- metadata.gz: 102154447670b85dc4e0825dcdf1ec11cd0fd291ffc1c7230b98da2208b0a39c38d2c8726a33226aeea68082e16a24917db7ad3380c871b9b02b0d76c8ac69fc
7
- data.tar.gz: 666e3745e9167028e5d3901d74400848c87c1b8a64a7487d3e4bfe13916e2902990633db7c448057b8106fd4b6b5c5de08c697c88151a305c92d34259266448f
6
+ metadata.gz: 8c05f0ce6e8b398a87e98453c721d00707628918ce8455600c1cb00fb2cb9c68efc6bea373323e889d36fc3658ff45db3508b0e6386b876da58ca50cdb53ab9f
7
+ data.tar.gz: 51586b68f489ff1f32df06338d05a64cab753da56c11575b3c5c8fa55019e9a8527e0a20c54c8695e1432307227d26c10f01b0d6c610e41c55d84296be000bd8
data/CHANGELOG.md ADDED
@@ -0,0 +1 @@
1
+ See https://github.com/Shopify/packwerk/releases.
data/Gemfile.lock CHANGED
@@ -87,7 +87,7 @@ GIT
87
87
  PATH
88
88
  remote: .
89
89
  specs:
90
- packwerk (1.4.0)
90
+ packwerk (2.0.0)
91
91
  activesupport (>= 5.2)
92
92
  ast
93
93
  better_html
data/README.md CHANGED
@@ -35,8 +35,6 @@ Watch a [1-minute video demo](https://www.youtube.com/watch?v=NwqlyBAxVpQ&featur
35
35
  gem 'packwerk'
36
36
  ```
37
37
 
38
- _Note: Packwerk has to be grouped in production environment within the Gemfile if your Rails app has custom inflections._
39
-
40
38
  2. Install the gem
41
39
 
42
40
  Execute:
data/UPGRADING.md ADDED
@@ -0,0 +1,54 @@
1
+ # Upgrading from 1.x to 2.0
2
+
3
+ With Packwerk 2.0, we made a few changes to simplify the setup. Updating will require removing some previously necessary files and configuration.
4
+
5
+ ## Gem group
6
+
7
+ Because packwerk is no longer involved in specifying the application's inflections, it doesn't have to live in the `production` group in your `Gemfile` anymore. We recommend moving it to the `development` group.
8
+
9
+ ## Removing application config caches
10
+
11
+ ### Load paths
12
+ We no longer require the `load_paths` key in `packwerk.yml`. You can simply delete the load_paths key as it will not be read anymore. Instead, Packwerk will ask Rails for load paths. If you're using spring, make sure to properly set up spring (see [USAGE.md](USAGE.md#setting-up-spring)) to keep packwerk fast.
13
+
14
+ ### Inflections
15
+ We no longer require a custom `inflections.yml` file. Instead, you'll want to revert BACK to using the `inflections.rb` initializer as you would have done prior to adopting packwerk. To do this, you'll want to convert back to using the plain [ActiveSupport Inflections API](https://api.rubyonrails.org/classes/ActiveSupport/Inflector/Inflections.html).
16
+
17
+
18
+ Given the following example `inflections.yml`, here is an example `inflections.rb` that would follow. Tip: if you're using git, you can run `git log config/inflections.yml`, find the first commit that introduced `inflections.yml`, find the COMMIT_SHA, and then run `git show COMMIT_SHA` to see what your inflections file looked like before (note that you may have changed `inflections.yml` since then, though).
19
+
20
+ `config/inflections.yml`
21
+ ```yml
22
+ # List your inflections in this file instead of `inflections.rb`
23
+ # See steps to set up custom inflections:
24
+ # https://github.com/Shopify/packwerk/blob/main/USAGE.md#Inflections
25
+
26
+ acronym:
27
+ - 'HTML'
28
+ - 'API'
29
+
30
+ singular:
31
+ - ['oxen', 'oxen']
32
+
33
+ irregular:
34
+ - ['person', 'people']
35
+
36
+ uncountable:
37
+ - 'fish'
38
+ - 'sheep'
39
+ ```
40
+
41
+ `config/initializers/inflections.rb`
42
+ ```ruby
43
+ ActiveSupport::Inflector.inflections(:en) do |inflect|
44
+ inflect.acronym('HTML')
45
+ inflect.acronym('API')
46
+
47
+ inflect.singular('oxen', 'oxen')
48
+
49
+ inflect.irregular('person', 'people')
50
+
51
+ inflect.uncountable('fish')
52
+ inflect.uncountable('sheep')
53
+ end
54
+ ```
data/USAGE.md CHANGED
@@ -9,7 +9,6 @@
9
9
  * [Setting up Spring](#setting-up-spring)
10
10
  * [Configuring Packwerk](#configuring-packwerk)
11
11
  * [Using a custom ERB parser](#using-a-custom-erb-parser)
12
- * [Inflections](#inflections)
13
12
  * [Validating the package system](#validating-the-package-system)
14
13
  * [Defining packages](#defining-packages)
15
14
  * [Package metadata](#package-metadata)
@@ -57,7 +56,6 @@ Here is a list of files generated:
57
56
  |-----------------------------|--------------|------------|
58
57
  | Packwerk configuration | packwerk.yml | See [Setting up the configuration file](#Setting-up-the-configuration-file) |
59
58
  | Root package | package.yml | A package for the root folder |
60
- | Custom inflections | config/inflections.yml | A custom inflections file is only required if you have custom inflections in `inflections.rb`, see [Inflections](#Inflections) |
61
59
 
62
60
  After that, you may begin creating packages for your application. See [Defining packages](#Defining-packages)
63
61
 
@@ -77,7 +75,6 @@ Packwerk reads from the `packwerk.yml` configuration file in the root directory.
77
75
  | include | **/*.{rb,rake,erb} | list of patterns for folder paths to include |
78
76
  | exclude | {bin,node_modules,script,tmp,vendor}/**/* | list of patterns for folder paths to exclude |
79
77
  | package_paths | **/ | a single pattern or a list of patterns to find package configuration files, see: [Defining packages](#Defining-packages) |
80
- | load_paths | All application autoload paths | list of load paths |
81
78
  | custom_associations | N/A | list of custom associations, if any |
82
79
  | parallel | true | when true, fork code parsing out to subprocesses |
83
80
 
@@ -103,45 +100,6 @@ end
103
100
  Packwerk::Parsers::Factory.instance.erb_parser_class = CustomParser
104
101
  ```
105
102
 
106
- ### Inflections
107
-
108
- Packwerk requires custom inflections to be defined in `inflections.yml` instead of the traditional `inflections.rb`. This is because Packwerk accounts for custom inflections, such as acronyms, when resolving constants. Additionally, Packwerk interprets Active Record associations as references to constants. For example, `has_many :birds` is a reference to the `Bird` constant.
109
-
110
- In order to make your custom inflections compatible with Active Support and Packwerk, you must create a `config/inflections.yml` file and point `ActiveSupport::Inflector` to that file.
111
-
112
- In `inflections.rb`, add:
113
-
114
- ```rb
115
- require "packwerk/inflections/custom"
116
-
117
- ActiveSupport::Inflector.inflections do |inflect|
118
- # please add all custom inflections in the file below.
119
- Packwerk::Inflections::Custom.new(
120
- Rails.root.join("config", "inflections.yml")
121
- ).apply_to(inflect)
122
- end
123
- ```
124
-
125
- _Note: Packwerk has to be grouped in production environment within the Gemfile if you have custom inflections._
126
-
127
- Next, move your existing custom inflections into `config/inflections.yml`:
128
-
129
- ```yaml
130
- acronym:
131
- - 'GraphQL'
132
- - 'MRuby'
133
- - 'TOS'
134
- irregular:
135
- - ['analysis', 'analyses']
136
- - ['reserve', 'reserves']
137
- uncountable:
138
- - 'payment_details'
139
- singular:
140
- - [!ruby/regexp /status$/, 'status']
141
- ```
142
-
143
- Any new inflectors should be added to `config/inflections.yml`.
144
-
145
103
  ## Validating the package system
146
104
 
147
105
  There are some criteria that an application must meet in order to have a valid package system. These criteria include having a valid autoload path cache, package definition files, and application folder structure. The dependency graph within the package system also has to be acyclic.
@@ -1,7 +1,6 @@
1
1
  # typed: true
2
2
  # frozen_string_literal: true
3
3
 
4
- require "active_support/inflector/inflections"
5
4
  require "constant_resolver"
6
5
  require "pathname"
7
6
  require "yaml"
@@ -14,19 +13,15 @@ module Packwerk
14
13
  @config_file_path = config_file_path
15
14
  @configuration = configuration
16
15
  @environment = environment
17
-
18
- @application_load_paths = ApplicationLoadPaths.extract_relevant_paths(configuration.root_path, environment)
19
16
  end
20
17
 
21
18
  Result = Struct.new(:ok?, :error_value)
22
19
 
23
20
  def check_all
24
21
  results = [
25
- check_autoload_path_cache,
26
22
  check_package_manifests_for_privacy,
27
23
  check_package_manifest_syntax,
28
24
  check_application_structure,
29
- check_inflection_file,
30
25
  check_acyclic_graph,
31
26
  check_package_manifest_paths,
32
27
  check_valid_package_dependencies,
@@ -36,21 +31,6 @@ module Packwerk
36
31
  merge_results(results)
37
32
  end
38
33
 
39
- def check_autoload_path_cache
40
- expected = Set.new(@application_load_paths)
41
- actual = Set.new(@configuration.load_paths)
42
- if expected == actual
43
- Result.new(true)
44
- else
45
- Result.new(
46
- false,
47
- "Load path cache in #{@config_file_path} incorrect!\n"\
48
- "Paths missing from file:\n#{format_yaml_strings(expected - actual)}\n"\
49
- "Extraneous load paths in file:\n#{format_yaml_strings(actual - expected)}"
50
- )
51
- end
52
- end
53
-
54
34
  def check_package_manifests_for_privacy
55
35
  privacy_settings = package_manifests_settings_for("enforce_privacy")
56
36
 
@@ -142,39 +122,6 @@ module Packwerk
142
122
  end
143
123
  end
144
124
 
145
- def check_inflection_file
146
- inflections_file = @configuration.inflections_file
147
-
148
- application_inflections = ActiveSupport::Inflector.inflections
149
- packwerk_inflections = Packwerk::Inflector.from_file(inflections_file).inflections
150
-
151
- results = %i(plurals singulars uncountables humans acronyms).map do |type|
152
- expected = application_inflections.public_send(type).to_set
153
- actual = packwerk_inflections.public_send(type).to_set
154
-
155
- if expected == actual
156
- Result.new(true)
157
- else
158
- missing_msg = unless (expected - actual).empty?
159
- "Expected #{type} to be specified in file: #{expected - actual}"
160
- end
161
- extraneous_msg = unless (actual - expected).empty?
162
- "Extraneous #{type} was specified in file: #{actual - expected}"
163
- end
164
- Result.new(
165
- false,
166
- [missing_msg, extraneous_msg].join("\n")
167
- )
168
- end
169
- end
170
-
171
- merge_results(
172
- results,
173
- separator: "\n",
174
- errors_headline: "Inflections specified in #{inflections_file} don't line up with application!\n"
175
- )
176
- end
177
-
178
125
  def check_acyclic_graph
179
126
  edges = package_set.flat_map do |package|
180
127
  package.dependencies.map { |dependency| [package, package_set.fetch(dependency)] }
@@ -19,7 +19,7 @@ module Packwerk
19
19
  CustomAssociations
20
20
  )
21
21
 
22
- sig { params(inflector: Inflector, custom_associations: CustomAssociations).void }
22
+ sig { params(inflector: T.class_of(ActiveSupport::Inflector), custom_associations: CustomAssociations).void }
23
23
  def initialize(inflector:, custom_associations: Set.new)
24
24
  @inflector = inflector
25
25
  @associations = T.let(RAILS_ASSOCIATIONS + custom_associations, CustomAssociations)
data/lib/packwerk/cli.rb CHANGED
@@ -53,8 +53,6 @@ module Packwerk
53
53
  output_result(parse_run(args).check)
54
54
  when "detect-stale-violations"
55
55
  output_result(parse_run(args).detect_stale_violations)
56
- when "update"
57
- update(args)
58
56
  when "update-deprecations"
59
57
  output_result(parse_run(args).update_deprecations)
60
58
  when "validate"
@@ -88,14 +86,13 @@ module Packwerk
88
86
 
89
87
  def generate_configs
90
88
  configuration_file = Packwerk::Generators::ConfigurationFile.generate(
91
- load_paths: Packwerk::ApplicationLoadPaths.extract_relevant_paths(@configuration.root_path, @environment),
92
89
  root: @configuration.root_path,
93
90
  out: @out
94
91
  )
95
- inflections_file = Packwerk::Generators::InflectionsFile.generate(root: @configuration.root_path, out: @out)
92
+
96
93
  root_package = Packwerk::Generators::RootPackage.generate(root: @configuration.root_path, out: @out)
97
94
 
98
- success = configuration_file && inflections_file && root_package
95
+ success = configuration_file && root_package
99
96
 
100
97
  result = if success
101
98
  <<~EOS
@@ -115,11 +112,6 @@ module Packwerk
115
112
  success
116
113
  end
117
114
 
118
- def update(paths)
119
- warn("`packwerk update` is deprecated in favor of `packwerk update-deprecations`.")
120
- output_result(parse_run(paths).update_deprecations)
121
- end
122
-
123
115
  def output_result(result)
124
116
  @out.puts
125
117
  @out.puts(result.message)
@@ -139,11 +131,6 @@ module Packwerk
139
131
 
140
132
  def validate(_paths)
141
133
  @progress_formatter.started_validation do
142
- checker = Packwerk::ApplicationValidator.new(
143
- config_file_path: @configuration.config_path,
144
- configuration: @configuration,
145
- environment: @environment,
146
- )
147
134
  result = checker.check_all
148
135
 
149
136
  list_validation_errors(result)
@@ -152,6 +139,14 @@ module Packwerk
152
139
  end
153
140
  end
154
141
 
142
+ def checker
143
+ Packwerk::ApplicationValidator.new(
144
+ config_file_path: @configuration.config_path,
145
+ configuration: @configuration,
146
+ environment: @environment,
147
+ )
148
+ end
149
+
155
150
  def list_validation_errors(result)
156
151
  @out.puts
157
152
  if result.ok?
@@ -34,24 +34,54 @@ module Packwerk
34
34
  DEFAULT_EXCLUDE_GLOBS = ["{bin,node_modules,script,tmp,vendor}/**/*"]
35
35
 
36
36
  attr_reader(
37
- :include, :exclude, :root_path, :package_paths, :custom_associations, :load_paths, :inflections_file,
38
- :config_path,
37
+ :include, :exclude, :root_path, :package_paths, :custom_associations, :config_path
39
38
  )
40
39
 
41
40
  def initialize(configs = {}, config_path: nil)
41
+ if configs["load_paths"]
42
+ warning = <<~WARNING
43
+ DEPRECATION WARNING: The 'load_paths' key in `packwerk.yml` is deprecated.
44
+ This value is no longer cached, and you can remove the key from `packwerk.yml`.
45
+ WARNING
46
+
47
+ warn(warning)
48
+ end
49
+
50
+ inflection_file = File.expand_path(configs["inflections_file"] || "config/inflections.yml", @root_path)
51
+ if configs["inflections_file"]
52
+ warning = <<~WARNING
53
+ DEPRECATION WARNING: The 'inflections_file' key in `packwerk.yml` is deprecated.
54
+ This value is no longer cached, and you can remove the key from `packwerk.yml`.
55
+ You can also delete #{configs["inflections_file"]}.
56
+ WARNING
57
+
58
+ warn(warning)
59
+ end
60
+
61
+ if Pathname.new(inflection_file).exist?
62
+ warning = <<~WARNING
63
+ DEPRECATION WARNING: Inflections YMLs in packwerk are now deprecated.
64
+ This value is no longer cached, and you can now delete #{inflection_file}
65
+ WARNING
66
+
67
+ warn(warning)
68
+ end
69
+
42
70
  @include = configs["include"] || DEFAULT_INCLUDE_GLOBS
43
71
  @exclude = configs["exclude"] || DEFAULT_EXCLUDE_GLOBS
44
72
  root = config_path ? File.dirname(config_path) : "."
45
73
  @root_path = File.expand_path(root)
46
74
  @package_paths = configs["package_paths"] || "**/"
47
75
  @custom_associations = configs["custom_associations"] || []
48
- @load_paths = (configs["load_paths"] || []).uniq
49
- @inflections_file = File.expand_path(configs["inflections_file"] || "config/inflections.yml", @root_path)
50
76
  @parallel = configs.key?("parallel") ? configs["parallel"] : true
51
77
 
52
78
  @config_path = config_path
53
79
  end
54
80
 
81
+ def load_paths
82
+ @load_paths ||= ApplicationLoadPaths.extract_relevant_paths(@root_path, "test")
83
+ end
84
+
55
85
  def parallel?
56
86
  @parallel
57
87
  end
@@ -45,7 +45,7 @@ module Packwerk
45
45
  begin
46
46
  constant = @resolver.resolve(const_name, current_namespace_path: current_namespace_path)
47
47
  rescue ConstantResolver::Error => e
48
- raise(ConstantResolver::Error, e.message + "\n Make sure autoload paths are added to the config file.")
48
+ raise(ConstantResolver::Error, e.message)
49
49
  end
50
50
 
51
51
  return unless constant
@@ -44,7 +44,7 @@ module Packwerk
44
44
 
45
45
  sig { params(offenses: T::Array[T.nilable(Offense)]).returns(String) }
46
46
  def offenses_summary(offenses)
47
- offenses_string = Inflector.default.pluralize("offense", offenses.length)
47
+ offenses_string = "offense".pluralize(offenses.length)
48
48
  "#{offenses.length} #{offenses_string} detected"
49
49
  end
50
50
  end
@@ -16,7 +16,7 @@ module Packwerk
16
16
 
17
17
  def started(target_files)
18
18
  files_size = target_files.size
19
- files_string = Inflector.default.pluralize("file", files_size)
19
+ files_string = "file".pluralize(files_size)
20
20
  @out.puts("📦 Packwerk is inspecting #{files_size} #{files_string}")
21
21
  end
22
22
 
@@ -11,18 +11,15 @@ module Packwerk
11
11
  CONFIGURATION_TEMPLATE_FILE_PATH = "templates/packwerk.yml.erb"
12
12
 
13
13
  class << self
14
- def generate(load_paths:, root:, out:)
15
- new(load_paths: load_paths, root: root, out: out).generate
14
+ def generate(root:, out:)
15
+ new(root: root, out: out).generate
16
16
  end
17
17
  end
18
18
 
19
- sig { params(load_paths: T::Array[String], root: String, out: T.any(StringIO, IO)).void }
20
- def initialize(load_paths:, root:, out: $stdout)
21
- @load_paths = load_paths
19
+ sig { params(root: String, out: T.any(StringIO, IO)).void }
20
+ def initialize(root:, out: $stdout)
22
21
  @root = root
23
22
  @out = out
24
-
25
- set_template_variables
26
23
  end
27
24
 
28
25
  sig { returns(T::Boolean) }
@@ -43,18 +40,6 @@ module Packwerk
43
40
 
44
41
  private
45
42
 
46
- def set_template_variables
47
- @load_paths_formatted = if @load_paths.empty?
48
- "# load_paths:\n# - 'app/models'\n"
49
- else
50
- @load_paths.map { |path| "- #{path}\n" }.join
51
- end
52
-
53
- @load_paths_comment = unless @load_paths.empty?
54
- "# These load paths were auto generated by Packwerk.\nload_paths:\n"
55
- end
56
- end
57
-
58
43
  def render
59
44
  ERB.new(template, trim_mode: "-").result(binding)
60
45
  end
@@ -12,12 +12,6 @@
12
12
  # Patterns to find package configuration files
13
13
  # package_paths: "**/"
14
14
 
15
- # List of application load paths
16
- <%= @load_paths_comment -%>
17
- <%= @load_paths_formatted %>
18
15
  # List of custom associations, if any
19
16
  # custom_associations:
20
17
  # - "cache_belongs_to"
21
-
22
- # Location of inflections file
23
- # inflections_file: "config/inflections.yml"
@@ -24,7 +24,7 @@ module Packwerk
24
24
 
25
25
  class << self
26
26
  def from_configuration(configuration)
27
- inflector = ::Packwerk::Inflector.from_file(configuration.inflections_file)
27
+ inflector = ActiveSupport::Inflector
28
28
  new(
29
29
  root_path: configuration.root_path,
30
30
  load_paths: configuration.load_paths,
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Packwerk
5
- VERSION = "1.4.0"
5
+ VERSION = "2.0.0"
6
6
  end
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
 
@@ -21,7 +24,6 @@ module Packwerk
21
24
  autoload :FileProcessor
22
25
  autoload :FilesForProcessing
23
26
  autoload :Graph
24
- autoload :Inflector
25
27
  autoload :Node
26
28
  autoload :NodeProcessor
27
29
  autoload :NodeProcessorFactory
@@ -42,13 +44,6 @@ module Packwerk
42
44
  autoload :Version
43
45
  autoload :ViolationType
44
46
 
45
- module Inflections
46
- extend ActiveSupport::Autoload
47
-
48
- autoload :Custom
49
- autoload :Default
50
- end
51
-
52
47
  module OutputStyles
53
48
  extend ActiveSupport::Autoload
54
49
 
@@ -71,7 +66,6 @@ module Packwerk
71
66
  extend ActiveSupport::Autoload
72
67
 
73
68
  autoload :ConfigurationFile
74
- autoload :InflectionsFile
75
69
  autoload :RootPackage
76
70
  end
77
71
 
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.4.0
4
+ version: 2.0.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-11-24 00:00:00.000000000 Z
11
+ date: 2021-12-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -195,6 +195,7 @@ files:
195
195
  - ".gitignore"
196
196
  - ".rubocop.yml"
197
197
  - ".ruby-version"
198
+ - CHANGELOG.md
198
199
  - CODEOWNERS
199
200
  - CODE_OF_CONDUCT.md
200
201
  - CONTRIBUTING.md
@@ -204,6 +205,7 @@ files:
204
205
  - README.md
205
206
  - Rakefile
206
207
  - TROUBLESHOOT.md
208
+ - UPGRADING.md
207
209
  - USAGE.md
208
210
  - bin/console
209
211
  - bin/m
@@ -231,15 +233,10 @@ files:
231
233
  - lib/packwerk/formatters/offenses_formatter.rb
232
234
  - lib/packwerk/formatters/progress_formatter.rb
233
235
  - lib/packwerk/generators/configuration_file.rb
234
- - lib/packwerk/generators/inflections_file.rb
235
236
  - lib/packwerk/generators/root_package.rb
236
- - lib/packwerk/generators/templates/inflections.yml
237
237
  - lib/packwerk/generators/templates/package.yml
238
238
  - lib/packwerk/generators/templates/packwerk.yml.erb
239
239
  - lib/packwerk/graph.rb
240
- - lib/packwerk/inflections/custom.rb
241
- - lib/packwerk/inflections/default.rb
242
- - lib/packwerk/inflector.rb
243
240
  - lib/packwerk/node.rb
244
241
  - lib/packwerk/node_processor.rb
245
242
  - lib/packwerk/node_processor_factory.rb
@@ -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,49 +0,0 @@
1
- # typed: true
2
- # frozen_string_literal: true
3
-
4
- require "active_support/inflector"
5
-
6
- module Packwerk
7
- # A custom inflector used, among other things, to map between constant names and file names.
8
- class Inflector
9
- class << self
10
- extend T::Sig
11
-
12
- def default
13
- @default ||= new(custom_inflector: Inflections::Custom.new)
14
- end
15
-
16
- sig { params(inflections_file: String).returns(::Packwerk::Inflector) }
17
- def from_file(inflections_file)
18
- new(custom_inflector: Inflections::Custom.new(inflections_file))
19
- end
20
- end
21
-
22
- extend T::Sig
23
- include ::ActiveSupport::Inflector # For #camelize, #classify, #pluralize, #singularize
24
-
25
- sig do
26
- params(
27
- custom_inflector: Inflections::Custom
28
- ).void
29
- end
30
- def initialize(custom_inflector:)
31
- @inflections = ::ActiveSupport::Inflector::Inflections.new
32
-
33
- Inflections::Default.apply_to(@inflections)
34
- custom_inflector.apply_to(@inflections)
35
- end
36
-
37
- def pluralize(word, count = nil)
38
- if count == 1
39
- singularize(word)
40
- else
41
- super(word)
42
- end
43
- end
44
-
45
- def inflections(_ = nil)
46
- @inflections
47
- end
48
- end
49
- end