packwerk 1.0.2 → 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/.github/workflows/ci.yml +14 -5
- data/.ruby-version +1 -1
- data/Gemfile +1 -1
- data/Gemfile.lock +129 -111
- data/README.md +8 -1
- data/USAGE.md +39 -17
- data/dev.yml +1 -1
- data/exe/packwerk +1 -1
- data/gemfiles/Gemfile-rails-6-0 +22 -0
- data/lib/packwerk.rb +73 -34
- data/lib/packwerk/application_load_paths.rb +3 -2
- data/lib/packwerk/application_validator.rb +85 -69
- data/lib/packwerk/association_inspector.rb +23 -11
- data/lib/packwerk/checker.rb +4 -7
- data/lib/packwerk/cli.rb +36 -93
- data/lib/packwerk/configuration.rb +10 -2
- data/lib/packwerk/const_node_inspector.rb +13 -14
- data/lib/packwerk/constant_discovery.rb +2 -0
- data/lib/packwerk/constant_name_inspector.rb +0 -1
- data/lib/packwerk/dependency_checker.rb +12 -17
- data/lib/packwerk/deprecated_references.rb +25 -8
- data/lib/packwerk/file_processor.rb +0 -4
- data/lib/packwerk/formatters/offenses_formatter.rb +43 -0
- data/lib/packwerk/formatters/progress_formatter.rb +9 -4
- data/lib/packwerk/generators/configuration_file.rb +0 -1
- data/lib/packwerk/inflector.rb +0 -2
- data/lib/packwerk/node.rb +9 -2
- data/lib/packwerk/node_processor.rb +15 -32
- data/lib/packwerk/node_processor_factory.rb +0 -5
- data/lib/packwerk/node_visitor.rb +1 -4
- data/lib/packwerk/offense.rb +2 -8
- data/lib/packwerk/offense_collection.rb +84 -0
- data/lib/packwerk/offenses_formatter.rb +15 -0
- data/lib/packwerk/output_style.rb +20 -0
- data/lib/packwerk/output_styles/coloured.rb +29 -0
- data/lib/packwerk/output_styles/plain.rb +26 -0
- data/lib/packwerk/package.rb +8 -0
- data/lib/packwerk/package_set.rb +8 -5
- data/lib/packwerk/parse_run.rb +104 -0
- data/lib/packwerk/parsed_constant_definitions.rb +2 -4
- data/lib/packwerk/parsers.rb +0 -2
- data/lib/packwerk/parsers/erb.rb +4 -2
- data/lib/packwerk/parsers/factory.rb +10 -3
- data/lib/packwerk/privacy_checker.rb +22 -17
- data/lib/packwerk/reference_extractor.rb +0 -8
- data/lib/packwerk/reference_offense.rb +49 -0
- data/lib/packwerk/result.rb +9 -0
- data/lib/packwerk/run_context.rb +4 -20
- data/lib/packwerk/sanity_checker.rb +1 -3
- data/lib/packwerk/spring_command.rb +1 -1
- data/lib/packwerk/version.rb +1 -1
- data/lib/packwerk/violation_type.rb +0 -2
- data/library.yml +1 -1
- data/packwerk.gemspec +1 -0
- data/service.yml +1 -4
- data/shipit.rubygems.yml +5 -1
- data/sorbet/rbi/gems/{actioncable@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → actioncable@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +56 -36
- data/sorbet/rbi/gems/{actionmailbox@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → actionmailbox@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +25 -28
- data/sorbet/rbi/gems/{actionmailer@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → actionmailer@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +43 -24
- data/sorbet/rbi/gems/{actionpack@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → actionpack@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +382 -284
- data/sorbet/rbi/gems/{actiontext@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → actiontext@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +76 -40
- data/sorbet/rbi/gems/{actionview@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → actionview@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +206 -195
- data/sorbet/rbi/gems/{activejob@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → activejob@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +64 -75
- data/sorbet/rbi/gems/{activemodel@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → activemodel@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +103 -56
- data/sorbet/rbi/gems/{activerecord@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → activerecord@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +1250 -898
- data/sorbet/rbi/gems/{activestorage@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → activestorage@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +92 -120
- data/sorbet/rbi/gems/{activesupport@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → activesupport@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +292 -193
- data/sorbet/rbi/gems/{ast@2.4.1.rbi → ast@2.4.2.rbi} +2 -1
- data/sorbet/rbi/gems/{better_html@1.0.15.rbi → better_html@1.0.16.rbi} +2 -2
- data/sorbet/rbi/gems/{concurrent-ruby@1.1.6.rbi → concurrent-ruby@1.1.8.rbi} +12 -9
- data/sorbet/rbi/gems/{erubi@1.9.0.rbi → erubi@1.10.0.rbi} +3 -1
- data/sorbet/rbi/gems/{i18n@1.8.2.rbi → i18n@1.8.10.rbi} +19 -52
- data/sorbet/rbi/gems/{loofah@2.5.0.rbi → loofah@2.9.0.rbi} +3 -1
- data/sorbet/rbi/gems/marcel@1.0.0.rbi +70 -0
- data/sorbet/rbi/gems/{mini_mime@1.0.2.rbi → mini_mime@1.0.3.rbi} +6 -6
- data/sorbet/rbi/gems/{mini_portile2@2.4.0.rbi → minitest-focus@1.2.1.rbi} +2 -2
- data/sorbet/rbi/gems/{minitest@5.14.0.rbi → minitest@5.14.4.rbi} +31 -29
- data/sorbet/rbi/gems/{mocha@1.11.2.rbi → mocha@1.12.0.rbi} +25 -36
- data/sorbet/rbi/gems/{nio4r@2.5.2.rbi → nio4r@2.5.7.rbi} +21 -20
- data/sorbet/rbi/gems/{nokogiri@1.10.9.rbi → nokogiri@1.11.2.rbi} +193 -154
- data/sorbet/rbi/gems/parallel@1.20.1.rbi +117 -0
- data/sorbet/rbi/gems/parlour@6.0.0.rbi +1272 -0
- data/sorbet/rbi/gems/{parser@2.7.1.4.rbi → parser@3.0.0.0.rbi} +287 -174
- data/sorbet/rbi/gems/{pry@0.13.1.rbi → pry@0.14.0.rbi} +1 -1
- data/sorbet/rbi/gems/racc@1.5.2.rbi +57 -0
- data/sorbet/rbi/gems/{rack@2.2.2.rbi → rack@2.2.3.rbi} +23 -35
- data/sorbet/rbi/gems/{rails@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → rails@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +1 -1
- data/sorbet/rbi/gems/{railties@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → railties@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +132 -121
- data/sorbet/rbi/gems/{rake@13.0.1.rbi → rake@13.0.3.rbi} +16 -20
- data/sorbet/rbi/gems/{parallel@1.19.1.rbi → regexp_parser@2.1.1.rbi} +2 -2
- data/sorbet/rbi/gems/rubocop-ast@1.4.1.rbi +8 -0
- data/sorbet/rbi/gems/{rubocop-performance@1.5.2.rbi → rubocop-performance@1.10.2.rbi} +1 -1
- data/sorbet/rbi/gems/{rubocop-shopify@1.0.2.rbi → rubocop-shopify@2.0.1.rbi} +1 -1
- data/sorbet/rbi/gems/{rubocop-sorbet@0.3.7.rbi → rubocop-sorbet@0.6.1.rbi} +1 -1
- data/sorbet/rbi/gems/{rubocop@0.82.0.rbi → rubocop@1.12.0.rbi} +1 -1
- data/sorbet/rbi/gems/{ruby-progressbar@1.10.1.rbi → ruby-progressbar@1.11.0.rbi} +1 -1
- data/sorbet/rbi/gems/spoom@1.1.0.rbi +1061 -0
- data/sorbet/rbi/gems/{spring@2.1.0.rbi → spring@2.1.1.rbi} +7 -7
- data/sorbet/rbi/gems/{sprockets-rails@3.2.1.rbi → sprockets-rails@3.2.2.rbi} +88 -68
- data/sorbet/rbi/gems/{sprockets@4.0.0.rbi → sprockets@4.0.2.rbi} +8 -7
- data/sorbet/rbi/gems/{tapioca@0.4.5.rbi → tapioca@0.4.19.rbi} +109 -24
- data/sorbet/rbi/gems/{thor@1.0.1.rbi → thor@1.1.0.rbi} +16 -15
- data/sorbet/rbi/gems/{tzinfo@2.0.2.rbi → tzinfo@2.0.4.rbi} +21 -2
- data/sorbet/rbi/gems/{unicode-display_width@1.7.0.rbi → unicode-display_width@2.0.0.rbi} +1 -1
- data/sorbet/rbi/gems/{websocket-driver@0.7.1.rbi → websocket-driver@0.7.3.rbi} +29 -29
- data/sorbet/rbi/gems/{websocket-extensions@0.1.4.rbi → websocket-extensions@0.1.5.rbi} +2 -2
- data/sorbet/rbi/gems/zeitwerk@2.4.2.rbi +177 -0
- data/sorbet/tapioca/require.rb +1 -0
- metadata +78 -57
- data/lib/packwerk/checking_deprecated_references.rb +0 -40
- data/lib/packwerk/output_styles.rb +0 -41
- data/lib/packwerk/reference_lister.rb +0 -23
- data/lib/packwerk/updating_deprecated_references.rb +0 -51
- data/sorbet/rbi/gems/jaro_winkler@1.5.4.rbi +0 -8
- data/sorbet/rbi/gems/marcel@0.3.3.rbi +0 -30
- data/sorbet/rbi/gems/mimemagic@0.3.5.rbi +0 -47
- data/sorbet/rbi/gems/parlour@4.0.1.rbi +0 -561
- data/sorbet/rbi/gems/spoom@1.0.4.rbi +0 -418
- data/sorbet/rbi/gems/zeitwerk@2.3.0.rbi +0 -8
@@ -0,0 +1,43 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Packwerk
|
5
|
+
module Formatters
|
6
|
+
class OffensesFormatter
|
7
|
+
include Packwerk::OffensesFormatter
|
8
|
+
|
9
|
+
extend T::Sig
|
10
|
+
|
11
|
+
sig { params(style: OutputStyle).void }
|
12
|
+
def initialize(style: OutputStyles::Plain.new)
|
13
|
+
@style = style
|
14
|
+
end
|
15
|
+
|
16
|
+
sig { override.params(offenses: T::Array[T.nilable(Offense)]).returns(String) }
|
17
|
+
def show_offenses(offenses)
|
18
|
+
return "No offenses detected 🎉" if offenses.empty?
|
19
|
+
|
20
|
+
<<~EOS
|
21
|
+
#{offenses_list(offenses)}
|
22
|
+
#{offenses_summary(offenses)}
|
23
|
+
EOS
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
sig { params(offenses: T::Array[T.nilable(Offense)]).returns(String) }
|
29
|
+
def offenses_list(offenses)
|
30
|
+
offenses
|
31
|
+
.compact
|
32
|
+
.map { |offense| offense.to_s(@style) }
|
33
|
+
.join("\n")
|
34
|
+
end
|
35
|
+
|
36
|
+
sig { params(offenses: T::Array[T.nilable(Offense)]).returns(String) }
|
37
|
+
def offenses_summary(offenses)
|
38
|
+
offenses_string = Inflector.default.pluralize("offense", offenses.length)
|
39
|
+
"#{offenses.length} #{offenses_string} detected"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -3,13 +3,13 @@
|
|
3
3
|
|
4
4
|
require "benchmark"
|
5
5
|
|
6
|
-
require "packwerk/inflector"
|
7
|
-
require "packwerk/output_styles"
|
8
|
-
|
9
6
|
module Packwerk
|
10
7
|
module Formatters
|
11
8
|
class ProgressFormatter
|
12
|
-
|
9
|
+
extend T::Sig
|
10
|
+
|
11
|
+
sig { params(out: T.any(StringIO, IO), style: OutputStyle).void }
|
12
|
+
def initialize(out, style: OutputStyles::Plain.new)
|
13
13
|
@out = out
|
14
14
|
@style = style
|
15
15
|
end
|
@@ -41,6 +41,11 @@ module Packwerk
|
|
41
41
|
@out.puts
|
42
42
|
@out.puts("📦 Finished in #{execution_time.round(2)} seconds")
|
43
43
|
end
|
44
|
+
|
45
|
+
def interrupted
|
46
|
+
@out.puts
|
47
|
+
@out.puts("Manually interrupted. Violations caught so far are listed below:")
|
48
|
+
end
|
44
49
|
end
|
45
50
|
end
|
46
51
|
end
|
data/lib/packwerk/inflector.rb
CHANGED
data/lib/packwerk/node.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# typed: true
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require "parser"
|
4
5
|
require "parser/ast/node"
|
5
6
|
|
6
7
|
module Packwerk
|
@@ -9,6 +10,8 @@ module Packwerk
|
|
9
10
|
Location = Struct.new(:line, :column)
|
10
11
|
|
11
12
|
class << self
|
13
|
+
extend T::Sig
|
14
|
+
|
12
15
|
def class_or_module_name(class_or_module_node)
|
13
16
|
case type_of(class_or_module_node)
|
14
17
|
when CLASS, MODULE
|
@@ -27,7 +30,7 @@ module Packwerk
|
|
27
30
|
case type_of(constant_node)
|
28
31
|
when CONSTANT_ROOT_NAMESPACE
|
29
32
|
""
|
30
|
-
when CONSTANT, CONSTANT_ASSIGNMENT
|
33
|
+
when CONSTANT, CONSTANT_ASSIGNMENT, SELF
|
31
34
|
# (const nil :Foo)
|
32
35
|
# "Foo"
|
33
36
|
# (const (cbase) :Foo)
|
@@ -40,6 +43,8 @@ module Packwerk
|
|
40
43
|
# "::Foo = 1"
|
41
44
|
# (casgn (lvar :a) :Foo (int 1))
|
42
45
|
# "a::Foo = 1"
|
46
|
+
# (casgn (self) :Foo (int 1))
|
47
|
+
# "self::Foo = 1"
|
43
48
|
namespace, name = constant_node.children
|
44
49
|
if namespace
|
45
50
|
[constant_name(namespace), name].join("::")
|
@@ -176,6 +181,7 @@ module Packwerk
|
|
176
181
|
class_node.children[1]
|
177
182
|
end
|
178
183
|
|
184
|
+
sig { params(ancestors: T::Array[AST::Node]).returns(String) }
|
179
185
|
def parent_module_name(ancestors:)
|
180
186
|
definitions = ancestors
|
181
187
|
.select { |n| [CLASS, MODULE, CONSTANT_ASSIGNMENT, BLOCK].include?(type_of(n)) }
|
@@ -204,12 +210,13 @@ module Packwerk
|
|
204
210
|
HASH_PAIR = :pair
|
205
211
|
METHOD_CALL = :send
|
206
212
|
MODULE = :module
|
213
|
+
SELF = :self
|
207
214
|
STRING = :str
|
208
215
|
SYMBOL = :sym
|
209
216
|
|
210
217
|
private_constant(
|
211
218
|
:BLOCK, :CLASS, :CONSTANT, :CONSTANT_ASSIGNMENT, :CONSTANT_ROOT_NAMESPACE, :HASH, :HASH_PAIR, :METHOD_CALL,
|
212
|
-
:MODULE, :STRING, :SYMBOL,
|
219
|
+
:MODULE, :SELF, :STRING, :SYMBOL,
|
213
220
|
)
|
214
221
|
|
215
222
|
def type_of(node)
|
@@ -1,11 +1,6 @@
|
|
1
1
|
# typed: true
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require "packwerk/node"
|
5
|
-
require "packwerk/offense"
|
6
|
-
require "packwerk/checker"
|
7
|
-
require "packwerk/reference_lister"
|
8
|
-
|
9
4
|
module Packwerk
|
10
5
|
class NodeProcessor
|
11
6
|
extend T::Sig
|
@@ -13,48 +8,36 @@ module Packwerk
|
|
13
8
|
sig do
|
14
9
|
params(
|
15
10
|
reference_extractor: ReferenceExtractor,
|
16
|
-
reference_lister: ReferenceLister,
|
17
11
|
filename: String,
|
18
12
|
checkers: T::Array[Checker]
|
19
13
|
).void
|
20
14
|
end
|
21
|
-
def initialize(reference_extractor:,
|
15
|
+
def initialize(reference_extractor:, filename:, checkers:)
|
22
16
|
@reference_extractor = reference_extractor
|
23
|
-
@reference_lister = reference_lister
|
24
17
|
@filename = filename
|
25
18
|
@checkers = checkers
|
26
19
|
end
|
27
20
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
21
|
+
sig { params(node: Parser::AST::Node, ancestors: T::Array[Parser::AST::Node]).returns(T::Array[Offense]) }
|
22
|
+
def call(node, ancestors)
|
23
|
+
return [] unless Node.method_call?(node) || Node.constant?(node)
|
24
|
+
reference = @reference_extractor.reference_from_node(node, ancestors: ancestors, file_path: @filename)
|
25
|
+
check_reference(reference, node)
|
33
26
|
end
|
34
27
|
|
35
28
|
private
|
36
29
|
|
37
30
|
def check_reference(reference, node)
|
38
|
-
return
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
Inference details: this is a reference to #{constant.name} which seems to be defined in #{constant.location}.
|
48
|
-
To receive help interpreting or resolving this error message, see: https://github.com/Shopify/packwerk/blob/main/TROUBLESHOOT.md#Troubleshooting-violations
|
49
|
-
EOS
|
50
|
-
)
|
51
|
-
end
|
52
|
-
|
53
|
-
def failed_check(reference)
|
54
|
-
failing_checker = @checkers.find do |checker|
|
55
|
-
checker.invalid_reference?(reference, @reference_lister)
|
31
|
+
return [] unless reference
|
32
|
+
@checkers.each_with_object([]) do |checker, violations|
|
33
|
+
next unless checker.invalid_reference?(reference)
|
34
|
+
offense = Packwerk::ReferenceOffense.new(
|
35
|
+
location: Node.location(node),
|
36
|
+
reference: reference,
|
37
|
+
violation_type: checker.violation_type
|
38
|
+
)
|
39
|
+
violations << offense
|
56
40
|
end
|
57
|
-
failing_checker&.message_for(reference)
|
58
41
|
end
|
59
42
|
end
|
60
43
|
end
|
@@ -1,15 +1,11 @@
|
|
1
1
|
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require "packwerk/constant_name_inspector"
|
5
|
-
require "packwerk/checker"
|
6
|
-
|
7
4
|
module Packwerk
|
8
5
|
class NodeProcessorFactory < T::Struct
|
9
6
|
extend T::Sig
|
10
7
|
|
11
8
|
const :root_path, String
|
12
|
-
const :reference_lister, ReferenceLister
|
13
9
|
const :context_provider, Packwerk::ConstantDiscovery
|
14
10
|
const :constant_name_inspectors, T::Array[ConstantNameInspector]
|
15
11
|
const :checkers, T::Array[Checker]
|
@@ -18,7 +14,6 @@ module Packwerk
|
|
18
14
|
def for(filename:, node:)
|
19
15
|
::Packwerk::NodeProcessor.new(
|
20
16
|
reference_extractor: reference_extractor(node: node),
|
21
|
-
reference_lister: reference_lister,
|
22
17
|
filename: filename,
|
23
18
|
checkers: checkers,
|
24
19
|
)
|
@@ -1,8 +1,6 @@
|
|
1
1
|
# typed: false
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require "packwerk/node"
|
5
|
-
|
6
4
|
module Packwerk
|
7
5
|
class NodeVisitor
|
8
6
|
def initialize(node_processor:)
|
@@ -10,8 +8,7 @@ module Packwerk
|
|
10
8
|
end
|
11
9
|
|
12
10
|
def visit(node, ancestors:, result:)
|
13
|
-
|
14
|
-
result << offense if offense
|
11
|
+
result.concat(@node_processor.call(node, ancestors))
|
15
12
|
|
16
13
|
child_ancestors = [node] + ancestors
|
17
14
|
Node.each_child(node) do |child|
|
data/lib/packwerk/offense.rb
CHANGED
@@ -2,9 +2,6 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require "parser/source/map"
|
5
|
-
require "sorbet-runtime"
|
6
|
-
|
7
|
-
require "packwerk/output_styles"
|
8
5
|
|
9
6
|
module Packwerk
|
10
7
|
class Offense
|
@@ -23,11 +20,8 @@ module Packwerk
|
|
23
20
|
@message = message
|
24
21
|
end
|
25
22
|
|
26
|
-
sig
|
27
|
-
|
28
|
-
.returns(String)
|
29
|
-
end
|
30
|
-
def to_s(style = OutputStyles::Plain)
|
23
|
+
sig { params(style: OutputStyle).returns(String) }
|
24
|
+
def to_s(style = OutputStyles::Plain.new)
|
31
25
|
if location
|
32
26
|
<<~EOS
|
33
27
|
#{style.filename}#{file}#{style.reset}:#{location.line}:#{location.column}
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Packwerk
|
5
|
+
class OffenseCollection
|
6
|
+
extend T::Sig
|
7
|
+
extend T::Helpers
|
8
|
+
|
9
|
+
sig do
|
10
|
+
params(
|
11
|
+
root_path: String,
|
12
|
+
deprecated_references: T::Hash[Packwerk::Package, Packwerk::DeprecatedReferences]
|
13
|
+
).void
|
14
|
+
end
|
15
|
+
def initialize(root_path, deprecated_references = {})
|
16
|
+
@root_path = root_path
|
17
|
+
@deprecated_references = T.let(deprecated_references, T::Hash[Packwerk::Package, Packwerk::DeprecatedReferences])
|
18
|
+
@new_violations = T.let([], T::Array[Packwerk::ReferenceOffense])
|
19
|
+
@errors = T.let([], T::Array[Packwerk::Offense])
|
20
|
+
end
|
21
|
+
|
22
|
+
sig { returns(T::Array[Packwerk::ReferenceOffense]) }
|
23
|
+
attr_reader :new_violations
|
24
|
+
|
25
|
+
sig { returns(T::Array[Packwerk::Offense]) }
|
26
|
+
attr_reader :errors
|
27
|
+
|
28
|
+
sig do
|
29
|
+
params(offense: Packwerk::Offense)
|
30
|
+
.returns(T::Boolean)
|
31
|
+
end
|
32
|
+
def listed?(offense)
|
33
|
+
return false unless offense.is_a?(ReferenceOffense)
|
34
|
+
reference = offense.reference
|
35
|
+
deprecated_references_for(reference.source_package).listed?(reference, violation_type: offense.violation_type)
|
36
|
+
end
|
37
|
+
|
38
|
+
sig do
|
39
|
+
params(offense: Packwerk::Offense).void
|
40
|
+
end
|
41
|
+
def add_offense(offense)
|
42
|
+
unless offense.is_a?(ReferenceOffense)
|
43
|
+
@errors << offense
|
44
|
+
return
|
45
|
+
end
|
46
|
+
deprecated_references = deprecated_references_for(offense.reference.source_package)
|
47
|
+
unless deprecated_references.add_entries(offense.reference, offense.violation_type)
|
48
|
+
new_violations << offense
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
sig { returns(T::Boolean) }
|
53
|
+
def stale_violations?
|
54
|
+
@deprecated_references.values.any?(&:stale_violations?)
|
55
|
+
end
|
56
|
+
|
57
|
+
sig { void }
|
58
|
+
def dump_deprecated_references_files
|
59
|
+
@deprecated_references.each do |_, deprecated_references_file|
|
60
|
+
deprecated_references_file.dump
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
sig { returns(T::Array[Packwerk::Offense]) }
|
65
|
+
def outstanding_offenses
|
66
|
+
errors + new_violations
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
sig { params(package: Packwerk::Package).returns(Packwerk::DeprecatedReferences) }
|
72
|
+
def deprecated_references_for(package)
|
73
|
+
@deprecated_references[package] ||= Packwerk::DeprecatedReferences.new(
|
74
|
+
package,
|
75
|
+
deprecated_references_file_for(package),
|
76
|
+
)
|
77
|
+
end
|
78
|
+
|
79
|
+
sig { params(package: Packwerk::Package).returns(String) }
|
80
|
+
def deprecated_references_file_for(package)
|
81
|
+
File.join(@root_path, package.name, "deprecated_references.yml")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Packwerk
|
5
|
+
module OffensesFormatter
|
6
|
+
extend T::Sig
|
7
|
+
extend T::Helpers
|
8
|
+
|
9
|
+
interface!
|
10
|
+
|
11
|
+
sig { abstract.params(offenses: T::Array[T.nilable(Offense)]).returns(String) }
|
12
|
+
def show_offenses(offenses)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Packwerk
|
5
|
+
module OutputStyle
|
6
|
+
extend T::Sig
|
7
|
+
extend T::Helpers
|
8
|
+
|
9
|
+
interface!
|
10
|
+
|
11
|
+
sig { abstract.returns(String) }
|
12
|
+
def reset; end
|
13
|
+
|
14
|
+
sig { abstract.returns(String) }
|
15
|
+
def filename; end
|
16
|
+
|
17
|
+
sig { abstract.returns(String) }
|
18
|
+
def error; end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Packwerk
|
5
|
+
module OutputStyles
|
6
|
+
# See https://en.wikipedia.org/wiki/ANSI_escape_code#3/4_bit for ANSI escape colour codes
|
7
|
+
class Coloured
|
8
|
+
extend T::Sig
|
9
|
+
include OutputStyle
|
10
|
+
|
11
|
+
sig { override.returns(String) }
|
12
|
+
def reset
|
13
|
+
"\033[m"
|
14
|
+
end
|
15
|
+
|
16
|
+
sig { override.returns(String) }
|
17
|
+
def filename
|
18
|
+
# 36 is foreground cyan
|
19
|
+
"\033[36m"
|
20
|
+
end
|
21
|
+
|
22
|
+
sig { override.returns(String) }
|
23
|
+
def error
|
24
|
+
# 31 is foreground red
|
25
|
+
"\033[31m"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|