packwerk 1.1.3 → 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/Gemfile.lock +6 -5
- data/USAGE.md +17 -16
- data/lib/packwerk.rb +72 -36
- data/lib/packwerk/application_validator.rb +0 -5
- data/lib/packwerk/association_inspector.rb +0 -3
- data/lib/packwerk/checker.rb +2 -8
- data/lib/packwerk/cli.rb +22 -77
- data/lib/packwerk/configuration.rb +5 -0
- data/lib/packwerk/const_node_inspector.rb +0 -2
- data/lib/packwerk/constant_discovery.rb +2 -0
- data/lib/packwerk/constant_name_inspector.rb +0 -1
- data/lib/packwerk/dependency_checker.rb +2 -15
- data/lib/packwerk/deprecated_references.rb +3 -9
- data/lib/packwerk/file_processor.rb +0 -4
- data/lib/packwerk/formatters/offenses_formatter.rb +3 -8
- data/lib/packwerk/formatters/progress_formatter.rb +5 -4
- data/lib/packwerk/generators/configuration_file.rb +0 -1
- data/lib/packwerk/inflector.rb +0 -2
- data/lib/packwerk/node.rb +1 -0
- data/lib/packwerk/node_processor.rb +14 -32
- data/lib/packwerk/node_processor_factory.rb +0 -5
- data/lib/packwerk/node_visitor.rb +1 -4
- data/lib/packwerk/offense.rb +0 -4
- data/lib/packwerk/offense_collection.rb +84 -0
- data/lib/packwerk/offenses_formatter.rb +15 -0
- data/lib/packwerk/package.rb +8 -0
- data/lib/packwerk/package_set.rb +0 -2
- data/lib/packwerk/parse_run.rb +104 -0
- data/lib/packwerk/parsed_constant_definitions.rb +0 -2
- data/lib/packwerk/parsers.rb +0 -2
- data/lib/packwerk/parsers/erb.rb +0 -2
- data/lib/packwerk/parsers/factory.rb +0 -2
- data/lib/packwerk/privacy_checker.rb +2 -15
- 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 -21
- data/lib/packwerk/sanity_checker.rb +0 -2
- data/lib/packwerk/version.rb +1 -1
- data/lib/packwerk/violation_type.rb +0 -2
- data/packwerk.gemspec +1 -0
- data/service.yml +1 -4
- data/sorbet/rbi/gems/parallel@1.20.1.rbi +111 -2
- data/sorbet/tapioca/require.rb +1 -0
- metadata +22 -12
- data/lib/packwerk/cache_deprecated_references.rb +0 -55
- data/lib/packwerk/checking_deprecated_references.rb +0 -43
- data/lib/packwerk/commands/detect_stale_violations_command.rb +0 -60
- data/lib/packwerk/commands/offense_progress_marker.rb +0 -24
- data/lib/packwerk/commands/result.rb +0 -13
- data/lib/packwerk/commands/update_deprecations_command.rb +0 -81
- data/lib/packwerk/detect_stale_deprecated_references.rb +0 -14
- data/lib/packwerk/reference_lister.rb +0 -23
- data/lib/packwerk/updating_deprecated_references.rb +0 -14
@@ -1,9 +1,6 @@
|
|
1
1
|
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require "packwerk/violation_type"
|
5
|
-
require "packwerk/checker"
|
6
|
-
|
7
4
|
module Packwerk
|
8
5
|
class DependencyChecker
|
9
6
|
extend T::Sig
|
@@ -16,24 +13,14 @@ module Packwerk
|
|
16
13
|
|
17
14
|
sig do
|
18
15
|
override
|
19
|
-
.params(reference: Packwerk::Reference
|
16
|
+
.params(reference: Packwerk::Reference)
|
20
17
|
.returns(T::Boolean)
|
21
18
|
end
|
22
|
-
def invalid_reference?(reference
|
19
|
+
def invalid_reference?(reference)
|
23
20
|
return false unless reference.source_package
|
24
21
|
return false unless reference.source_package.enforce_dependencies?
|
25
22
|
return false if reference.source_package.dependency?(reference.constant.package)
|
26
|
-
return false if reference_lister.listed?(reference, violation_type: violation_type)
|
27
23
|
true
|
28
24
|
end
|
29
|
-
|
30
|
-
sig { override.params(reference: Packwerk::Reference).returns(String) }
|
31
|
-
def message_for(reference)
|
32
|
-
"Dependency violation: #{reference.constant.name} belongs to '#{reference.constant.package}', but " \
|
33
|
-
"'#{reference.source_package}' does not specify a dependency on " \
|
34
|
-
"'#{reference.constant.package}'.\n" \
|
35
|
-
"Are we missing an abstraction?\n" \
|
36
|
-
"Is the code making the reference, and the referenced constant, in the right packages?\n"
|
37
|
-
end
|
38
25
|
end
|
39
26
|
end
|
@@ -1,17 +1,11 @@
|
|
1
1
|
# typed: true
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require "sorbet-runtime"
|
5
4
|
require "yaml"
|
6
5
|
|
7
|
-
require "packwerk/reference"
|
8
|
-
require "packwerk/reference_lister"
|
9
|
-
require "packwerk/violation_type"
|
10
|
-
|
11
6
|
module Packwerk
|
12
7
|
class DeprecatedReferences
|
13
8
|
extend T::Sig
|
14
|
-
include ReferenceLister
|
15
9
|
|
16
10
|
sig { params(package: Packwerk::Package, filepath: String).void }
|
17
11
|
def initialize(package, filepath)
|
@@ -23,7 +17,6 @@ module Packwerk
|
|
23
17
|
sig do
|
24
18
|
params(reference: Packwerk::Reference, violation_type: ViolationType)
|
25
19
|
.returns(T::Boolean)
|
26
|
-
.override
|
27
20
|
end
|
28
21
|
def listed?(reference, violation_type:)
|
29
22
|
violated_constants_found = deprecated_references.dig(reference.constant.package.name, reference.constant.name)
|
@@ -35,18 +28,19 @@ module Packwerk
|
|
35
28
|
violated_constants_found.fetch("violations", []).include?(violation_type.serialize)
|
36
29
|
end
|
37
30
|
|
38
|
-
sig { params(reference: Packwerk::Reference, violation_type:
|
31
|
+
sig { params(reference: Packwerk::Reference, violation_type: Packwerk::ViolationType).returns(T::Boolean) }
|
39
32
|
def add_entries(reference, violation_type)
|
40
33
|
package_violations = @new_entries.fetch(reference.constant.package.name, {})
|
41
34
|
entries_for_file = package_violations[reference.constant.name] ||= {}
|
42
35
|
|
43
36
|
entries_for_file["violations"] ||= []
|
44
|
-
entries_for_file["violations"] << violation_type
|
37
|
+
entries_for_file["violations"] << violation_type.serialize
|
45
38
|
|
46
39
|
entries_for_file["files"] ||= []
|
47
40
|
entries_for_file["files"] << reference.relative_path.to_s
|
48
41
|
|
49
42
|
@new_entries[reference.constant.package.name] = package_violations
|
43
|
+
listed?(reference, violation_type: violation_type)
|
50
44
|
end
|
51
45
|
|
52
46
|
sig { returns(T::Boolean) }
|
@@ -1,16 +1,11 @@
|
|
1
1
|
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require "benchmark"
|
5
|
-
require "sorbet-runtime"
|
6
|
-
|
7
|
-
require "packwerk/inflector"
|
8
|
-
require "packwerk/output_style"
|
9
|
-
require "packwerk/output_styles/plain"
|
10
|
-
|
11
4
|
module Packwerk
|
12
5
|
module Formatters
|
13
6
|
class OffensesFormatter
|
7
|
+
include Packwerk::OffensesFormatter
|
8
|
+
|
14
9
|
extend T::Sig
|
15
10
|
|
16
11
|
sig { params(style: OutputStyle).void }
|
@@ -18,7 +13,7 @@ module Packwerk
|
|
18
13
|
@style = style
|
19
14
|
end
|
20
15
|
|
21
|
-
sig { params(offenses: T::Array[T.nilable(Offense)]).returns(String) }
|
16
|
+
sig { override.params(offenses: T::Array[T.nilable(Offense)]).returns(String) }
|
22
17
|
def show_offenses(offenses)
|
23
18
|
return "No offenses detected 🎉" if offenses.empty?
|
24
19
|
|
@@ -3,10 +3,6 @@
|
|
3
3
|
|
4
4
|
require "benchmark"
|
5
5
|
|
6
|
-
require "packwerk/inflector"
|
7
|
-
require "packwerk/output_style"
|
8
|
-
require "packwerk/output_styles/plain"
|
9
|
-
|
10
6
|
module Packwerk
|
11
7
|
module Formatters
|
12
8
|
class ProgressFormatter
|
@@ -45,6 +41,11 @@ module Packwerk
|
|
45
41
|
@out.puts
|
46
42
|
@out.puts("📦 Finished in #{execution_time.round(2)} seconds")
|
47
43
|
end
|
44
|
+
|
45
|
+
def interrupted
|
46
|
+
@out.puts
|
47
|
+
@out.puts("Manually interrupted. Violations caught so far are listed below:")
|
48
|
+
end
|
48
49
|
end
|
49
50
|
end
|
50
51
|
end
|
data/lib/packwerk/inflector.rb
CHANGED
data/lib/packwerk/node.rb
CHANGED
@@ -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,49 +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
|
-
sig { params(node: Parser::AST::Node, ancestors: T::Array[Parser::AST::Node]).returns(T
|
21
|
+
sig { params(node: Parser::AST::Node, ancestors: T::Array[Parser::AST::Node]).returns(T::Array[Offense]) }
|
29
22
|
def call(node, ancestors)
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
end
|
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)
|
34
26
|
end
|
35
27
|
|
36
28
|
private
|
37
29
|
|
38
30
|
def check_reference(reference, node)
|
39
|
-
return
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
Inference details: this is a reference to #{constant.name} which seems to be defined in #{constant.location}.
|
49
|
-
To receive help interpreting or resolving this error message, see: https://github.com/Shopify/packwerk/blob/main/TROUBLESHOOT.md#Troubleshooting-violations
|
50
|
-
EOS
|
51
|
-
)
|
52
|
-
end
|
53
|
-
|
54
|
-
def failed_check(reference)
|
55
|
-
failing_checker = @checkers.find do |checker|
|
56
|
-
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
|
57
40
|
end
|
58
|
-
failing_checker&.message_for(reference)
|
59
41
|
end
|
60
42
|
end
|
61
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
@@ -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
|
data/lib/packwerk/package.rb
CHANGED