packwerk 2.2.2 → 3.0.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 +2 -5
- data/.ruby-version +1 -1
- data/Gemfile +0 -1
- data/Gemfile.lock +5 -95
- data/README.md +2 -7
- data/RESOLVING_VIOLATIONS.md +7 -7
- data/TROUBLESHOOT.md +1 -23
- data/USAGE.md +149 -59
- data/dev.yml +1 -1
- data/exe/packwerk +1 -0
- data/gemfiles/Gemfile-rails-6-1 +1 -1
- data/lib/packwerk/application_validator.rb +54 -285
- data/lib/packwerk/association_inspector.rb +2 -0
- data/lib/packwerk/cache.rb +6 -5
- data/lib/packwerk/checker.rb +54 -0
- data/lib/packwerk/cli/result.rb +11 -0
- data/lib/packwerk/cli.rb +56 -31
- data/lib/packwerk/configuration.rb +61 -40
- data/lib/packwerk/const_node_inspector.rb +2 -0
- data/lib/packwerk/constant_context.rb +8 -0
- data/lib/packwerk/constant_discovery.rb +5 -6
- data/lib/packwerk/constant_name_inspector.rb +2 -0
- data/lib/packwerk/disable_sorbet.rb +41 -0
- data/lib/packwerk/extension_loader.rb +24 -0
- data/lib/packwerk/file_processor.rb +3 -1
- data/lib/packwerk/files_for_processing.rb +25 -12
- data/lib/packwerk/formatters/default_offenses_formatter.rb +77 -0
- data/lib/packwerk/formatters/progress_formatter.rb +31 -12
- data/lib/packwerk/generators/configuration_file.rb +7 -2
- data/lib/packwerk/generators/root_package.rb +5 -1
- data/lib/packwerk/generators/templates/package.yml +0 -10
- data/lib/packwerk/graph.rb +10 -2
- data/lib/packwerk/node.rb +1 -1
- data/lib/packwerk/node_helpers.rb +14 -7
- data/lib/packwerk/node_processor.rb +2 -0
- data/lib/packwerk/node_processor_factory.rb +6 -4
- data/lib/packwerk/node_visitor.rb +10 -1
- data/lib/packwerk/offense_collection.rb +43 -23
- data/lib/packwerk/offenses_formatter.rb +59 -2
- data/lib/packwerk/package.rb +7 -35
- data/lib/packwerk/package_set.rb +1 -1
- data/lib/packwerk/{deprecated_references.rb → package_todo.rb} +29 -13
- data/lib/packwerk/parse_run.rb +29 -36
- data/lib/packwerk/parsed_constant_definitions.rb +28 -5
- data/lib/packwerk/parsers/erb.rb +23 -4
- data/lib/packwerk/parsers/factory.rb +11 -2
- data/lib/packwerk/parsers/parser_interface.rb +1 -1
- data/lib/packwerk/parsers/ruby.rb +13 -3
- data/lib/packwerk/parsers.rb +6 -2
- data/lib/packwerk/{application_load_paths.rb → rails_load_paths.rb} +6 -4
- data/lib/packwerk/reference.rb +7 -1
- data/lib/packwerk/reference_checking/checkers/dependency_checker.rb +29 -6
- data/lib/packwerk/reference_checking/reference_checker.rb +1 -1
- data/lib/packwerk/reference_extractor.rb +24 -12
- data/lib/packwerk/reference_offense.rb +2 -2
- data/lib/packwerk/run_context.rb +7 -10
- data/lib/packwerk/spring_command.rb +11 -2
- data/lib/packwerk/unresolved_reference.rb +9 -1
- data/lib/packwerk/validator/result.rb +18 -0
- data/lib/packwerk/validator.rb +90 -0
- data/lib/packwerk/validators/dependency_validator.rb +154 -0
- data/lib/packwerk/version.rb +1 -1
- data/lib/packwerk.rb +64 -26
- data/packwerk.gemspec +4 -2
- data/sorbet/rbi/gems/{zeitwerk@2.6.0.rbi → zeitwerk@2.6.4.rbi} +291 -228
- data/sorbet/rbi/shims/minitest/test.rb +8 -0
- data/sorbet/rbi/shims/packwerk/reference.rbi +33 -0
- data/sorbet/rbi/shims/packwerk/unresolved_reference.rbi +33 -0
- data/sorbet/rbi/shims/parser.rbi +13 -0
- metadata +35 -16
- data/lib/packwerk/formatters/offenses_formatter.rb +0 -52
- data/lib/packwerk/reference_checking/checkers/checker.rb +0 -34
- data/lib/packwerk/reference_checking/checkers/privacy_checker.rb +0 -76
- data/lib/packwerk/result.rb +0 -9
- data/lib/packwerk/sanity_checker.rb +0 -8
- data/lib/packwerk/violation_type.rb +0 -11
- data/sorbet/rbi/gems/html_tokenizer@0.0.7.rbi +0 -46
- data/sorbet/rbi/gems/mini_portile2@2.8.0.rbi +0 -8
@@ -6,12 +6,12 @@ module Packwerk
|
|
6
6
|
extend T::Sig
|
7
7
|
|
8
8
|
const :root_path, String
|
9
|
-
const :context_provider,
|
9
|
+
const :context_provider, ConstantDiscovery
|
10
10
|
const :constant_name_inspectors, T::Array[ConstantNameInspector]
|
11
11
|
|
12
12
|
sig { params(relative_file: String, node: AST::Node).returns(NodeProcessor) }
|
13
13
|
def for(relative_file:, node:)
|
14
|
-
|
14
|
+
NodeProcessor.new(
|
15
15
|
reference_extractor: reference_extractor(node: node),
|
16
16
|
relative_file: relative_file,
|
17
17
|
)
|
@@ -19,13 +19,15 @@ module Packwerk
|
|
19
19
|
|
20
20
|
private
|
21
21
|
|
22
|
-
sig { params(node: AST::Node).returns(
|
22
|
+
sig { params(node: AST::Node).returns(ReferenceExtractor) }
|
23
23
|
def reference_extractor(node:)
|
24
|
-
|
24
|
+
ReferenceExtractor.new(
|
25
25
|
constant_name_inspectors: constant_name_inspectors,
|
26
26
|
root_node: node,
|
27
27
|
root_path: root_path,
|
28
28
|
)
|
29
29
|
end
|
30
30
|
end
|
31
|
+
|
32
|
+
private_constant :NodeProcessorFactory
|
31
33
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module Packwerk
|
@@ -11,6 +11,13 @@ module Packwerk
|
|
11
11
|
@node_processor = node_processor
|
12
12
|
end
|
13
13
|
|
14
|
+
sig do
|
15
|
+
params(
|
16
|
+
node: Parser::AST::Node,
|
17
|
+
ancestors: T::Array[Parser::AST::Node],
|
18
|
+
result: T::Array[UnresolvedReference],
|
19
|
+
).void
|
20
|
+
end
|
14
21
|
def visit(node, ancestors:, result:)
|
15
22
|
reference = @node_processor.call(node, ancestors)
|
16
23
|
result << reference if reference
|
@@ -21,4 +28,6 @@ module Packwerk
|
|
21
28
|
end
|
22
29
|
end
|
23
30
|
end
|
31
|
+
|
32
|
+
private_constant :NodeVisitor
|
24
33
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require "pathname"
|
5
|
+
|
4
6
|
module Packwerk
|
5
7
|
class OffenseCollection
|
6
8
|
extend T::Sig
|
@@ -9,13 +11,14 @@ module Packwerk
|
|
9
11
|
sig do
|
10
12
|
params(
|
11
13
|
root_path: String,
|
12
|
-
|
14
|
+
package_todo: T::Hash[Packwerk::Package, Packwerk::PackageTodo]
|
13
15
|
).void
|
14
16
|
end
|
15
|
-
def initialize(root_path,
|
17
|
+
def initialize(root_path, package_todo = {})
|
16
18
|
@root_path = root_path
|
17
|
-
@
|
19
|
+
@package_todo = T.let(package_todo, T::Hash[Packwerk::Package, Packwerk::PackageTodo])
|
18
20
|
@new_violations = T.let([], T::Array[Packwerk::ReferenceOffense])
|
21
|
+
@strict_mode_violations = T.let([], T::Array[Packwerk::ReferenceOffense])
|
19
22
|
@errors = T.let([], T::Array[Packwerk::Offense])
|
20
23
|
end
|
21
24
|
|
@@ -25,6 +28,9 @@ module Packwerk
|
|
25
28
|
sig { returns(T::Array[Packwerk::Offense]) }
|
26
29
|
attr_reader :errors
|
27
30
|
|
31
|
+
sig { returns(T::Array[Packwerk::ReferenceOffense]) }
|
32
|
+
attr_reader :strict_mode_violations
|
33
|
+
|
28
34
|
sig do
|
29
35
|
params(offense: Packwerk::Offense)
|
30
36
|
.returns(T::Boolean)
|
@@ -33,7 +39,7 @@ module Packwerk
|
|
33
39
|
return false unless offense.is_a?(ReferenceOffense)
|
34
40
|
|
35
41
|
reference = offense.reference
|
36
|
-
|
42
|
+
package_todo_for(reference.package).listed?(reference, violation_type: offense.violation_type)
|
37
43
|
end
|
38
44
|
|
39
45
|
sig do
|
@@ -44,23 +50,25 @@ module Packwerk
|
|
44
50
|
@errors << offense
|
45
51
|
return
|
46
52
|
end
|
47
|
-
|
48
|
-
|
53
|
+
|
54
|
+
if !already_listed?(offense)
|
49
55
|
new_violations << offense
|
56
|
+
elsif strict_mode_violation?(offense)
|
57
|
+
strict_mode_violations << offense
|
50
58
|
end
|
51
59
|
end
|
52
60
|
|
53
61
|
sig { params(for_files: T::Set[String]).returns(T::Boolean) }
|
54
62
|
def stale_violations?(for_files)
|
55
|
-
@
|
56
|
-
|
63
|
+
@package_todo.values.any? do |package_todo|
|
64
|
+
package_todo.stale_violations?(for_files)
|
57
65
|
end
|
58
66
|
end
|
59
67
|
|
60
68
|
sig { params(package_set: Packwerk::PackageSet).void }
|
61
|
-
def
|
62
|
-
|
63
|
-
|
69
|
+
def persist_package_todo_files(package_set)
|
70
|
+
dump_package_todo_files
|
71
|
+
cleanup_extra_package_todo_files(package_set)
|
64
72
|
end
|
65
73
|
|
66
74
|
sig { returns(T::Array[Packwerk::Offense]) }
|
@@ -70,34 +78,46 @@ module Packwerk
|
|
70
78
|
|
71
79
|
private
|
72
80
|
|
81
|
+
sig { params(offense: ReferenceOffense).returns(T::Boolean) }
|
82
|
+
def already_listed?(offense)
|
83
|
+
package_todo_for(offense.reference.package).add_entries(offense.reference,
|
84
|
+
offense.violation_type)
|
85
|
+
end
|
86
|
+
|
87
|
+
sig { params(offense: ReferenceOffense).returns(T::Boolean) }
|
88
|
+
def strict_mode_violation?(offense)
|
89
|
+
checker = Checker.find(offense.violation_type)
|
90
|
+
checker.strict_mode_violation?(offense)
|
91
|
+
end
|
92
|
+
|
73
93
|
sig { params(package_set: Packwerk::PackageSet).void }
|
74
|
-
def
|
75
|
-
packages_without_todos = (package_set.packages.values - @
|
94
|
+
def cleanup_extra_package_todo_files(package_set)
|
95
|
+
packages_without_todos = (package_set.packages.values - @package_todo.keys)
|
76
96
|
|
77
97
|
packages_without_todos.each do |package|
|
78
|
-
Packwerk::
|
98
|
+
Packwerk::PackageTodo.new(
|
79
99
|
package,
|
80
|
-
|
100
|
+
package_todo_file_for(package),
|
81
101
|
).delete_if_exists
|
82
102
|
end
|
83
103
|
end
|
84
104
|
|
85
105
|
sig { void }
|
86
|
-
def
|
87
|
-
@
|
106
|
+
def dump_package_todo_files
|
107
|
+
@package_todo.each_value(&:dump)
|
88
108
|
end
|
89
109
|
|
90
|
-
sig { params(package: Packwerk::Package).returns(Packwerk::
|
91
|
-
def
|
92
|
-
@
|
110
|
+
sig { params(package: Packwerk::Package).returns(Packwerk::PackageTodo) }
|
111
|
+
def package_todo_for(package)
|
112
|
+
@package_todo[package] ||= Packwerk::PackageTodo.new(
|
93
113
|
package,
|
94
|
-
|
114
|
+
package_todo_file_for(package),
|
95
115
|
)
|
96
116
|
end
|
97
117
|
|
98
118
|
sig { params(package: Packwerk::Package).returns(String) }
|
99
|
-
def
|
100
|
-
File.join(@root_path, package.name, "
|
119
|
+
def package_todo_file_for(package)
|
120
|
+
File.join(@root_path, package.name, "package_todo.yml")
|
101
121
|
end
|
102
122
|
end
|
103
123
|
end
|
@@ -6,14 +6,71 @@ module Packwerk
|
|
6
6
|
extend T::Sig
|
7
7
|
extend T::Helpers
|
8
8
|
|
9
|
-
|
9
|
+
abstract!
|
10
|
+
|
11
|
+
class DuplicateFormatterError < StandardError
|
12
|
+
extend T::Sig
|
13
|
+
|
14
|
+
sig { params(identifier: String).void }
|
15
|
+
def initialize(identifier)
|
16
|
+
super("Cannot have multiple identifiers with the same key (`#{identifier}`)")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class << self
|
21
|
+
extend T::Sig
|
22
|
+
|
23
|
+
sig { params(base: Class).void }
|
24
|
+
def included(base)
|
25
|
+
@offenses_formatters ||= T.let(@offenses_formatters, T.nilable(T::Array[Class]))
|
26
|
+
@offenses_formatters ||= []
|
27
|
+
@offenses_formatters << base
|
28
|
+
end
|
29
|
+
|
30
|
+
sig { returns(T::Array[OffensesFormatter]) }
|
31
|
+
def all
|
32
|
+
T.unsafe(@offenses_formatters).map(&:new)
|
33
|
+
end
|
34
|
+
|
35
|
+
sig { params(identifier: String).returns(OffensesFormatter) }
|
36
|
+
def find(identifier)
|
37
|
+
formatter_by_identifier(identifier)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
sig { params(name: String).returns(OffensesFormatter) }
|
43
|
+
def formatter_by_identifier(name)
|
44
|
+
@formatter_by_identifier ||= T.let(nil, T.nilable(T::Hash[String, T.nilable(OffensesFormatter)]))
|
45
|
+
@formatter_by_identifier ||= begin
|
46
|
+
index = T.let({}, T::Hash[String, T.nilable(OffensesFormatter)])
|
47
|
+
OffensesFormatter.all.each do |formatter|
|
48
|
+
identifier = formatter.identifier
|
49
|
+
raise DuplicateFormatterError, identifier if index.key?(identifier)
|
50
|
+
|
51
|
+
index[identifier] = formatter
|
52
|
+
end
|
53
|
+
T.let(index, T.nilable(T::Hash[String, T.nilable(OffensesFormatter)]))
|
54
|
+
end
|
55
|
+
|
56
|
+
T.must(T.must(@formatter_by_identifier)[name])
|
57
|
+
end
|
58
|
+
end
|
10
59
|
|
11
60
|
sig { abstract.params(offenses: T::Array[T.nilable(Offense)]).returns(String) }
|
12
61
|
def show_offenses(offenses)
|
13
62
|
end
|
14
63
|
|
15
|
-
sig { abstract.params(offense_collection:
|
64
|
+
sig { abstract.params(offense_collection: OffenseCollection, for_files: T::Set[String]).returns(String) }
|
16
65
|
def show_stale_violations(offense_collection, for_files)
|
17
66
|
end
|
67
|
+
|
68
|
+
sig { abstract.returns(String) }
|
69
|
+
def identifier
|
70
|
+
end
|
71
|
+
|
72
|
+
sig { abstract.params(strict_mode_violations: T::Array[ReferenceOffense]).returns(String) }
|
73
|
+
def show_strict_mode_violations(strict_mode_violations)
|
74
|
+
end
|
18
75
|
end
|
19
76
|
end
|
data/lib/packwerk/package.rb
CHANGED
@@ -17,22 +17,20 @@ module Packwerk
|
|
17
17
|
sig { returns(T::Array[String]) }
|
18
18
|
attr_reader :dependencies
|
19
19
|
|
20
|
-
sig {
|
21
|
-
|
20
|
+
sig { returns(T::Hash[T.untyped, T.untyped]) }
|
21
|
+
attr_reader :config
|
22
|
+
|
23
|
+
sig { params(name: String, config: T.nilable(T::Hash[String, T.untyped])).void }
|
24
|
+
def initialize(name:, config: nil)
|
22
25
|
@name = name
|
23
|
-
@config = T.let(config || {}, T::Hash[
|
26
|
+
@config = T.let(config || {}, T::Hash[String, T.untyped])
|
24
27
|
@dependencies = T.let(Array(@config["dependencies"]).freeze, T::Array[String])
|
25
28
|
@public_path = T.let(nil, T.nilable(String))
|
26
29
|
end
|
27
30
|
|
28
|
-
sig { returns(T.nilable(T.any(T::Boolean, T::Array[String]))) }
|
29
|
-
def enforce_privacy
|
30
|
-
@config["enforce_privacy"]
|
31
|
-
end
|
32
|
-
|
33
31
|
sig { returns(T::Boolean) }
|
34
32
|
def enforce_dependencies?
|
35
|
-
@config["enforce_dependencies"]
|
33
|
+
[true, "strict"].include?(@config["enforce_dependencies"])
|
36
34
|
end
|
37
35
|
|
38
36
|
sig { params(package: Package).returns(T::Boolean) }
|
@@ -47,32 +45,6 @@ module Packwerk
|
|
47
45
|
path.start_with?(@name)
|
48
46
|
end
|
49
47
|
|
50
|
-
sig { returns(String) }
|
51
|
-
def public_path
|
52
|
-
@public_path ||= begin
|
53
|
-
unprefixed_public_path = user_defined_public_path || "app/public/"
|
54
|
-
|
55
|
-
if root?
|
56
|
-
unprefixed_public_path
|
57
|
-
else
|
58
|
-
File.join(@name, unprefixed_public_path)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
sig { params(path: String).returns(T::Boolean) }
|
64
|
-
def public_path?(path)
|
65
|
-
path.start_with?(public_path)
|
66
|
-
end
|
67
|
-
|
68
|
-
sig { returns(T.nilable(String)) }
|
69
|
-
def user_defined_public_path
|
70
|
-
return unless @config["public_path"]
|
71
|
-
return @config["public_path"] if @config["public_path"].end_with?("/")
|
72
|
-
|
73
|
-
@config["public_path"] + "/"
|
74
|
-
end
|
75
|
-
|
76
48
|
sig { params(other: T.untyped).returns(T.nilable(Integer)) }
|
77
49
|
def <=>(other)
|
78
50
|
return nil unless other.is_a?(self.class)
|
data/lib/packwerk/package_set.rb
CHANGED
@@ -26,7 +26,7 @@ module Packwerk
|
|
26
26
|
|
27
27
|
packages = package_paths.map do |path|
|
28
28
|
root_relative = path.dirname.relative_path_from(root_path)
|
29
|
-
Package.new(name: root_relative.to_s, config: YAML.load_file(path))
|
29
|
+
Package.new(name: root_relative.to_s, config: YAML.load_file(path, fallback: nil))
|
30
30
|
end
|
31
31
|
|
32
32
|
create_root_package_if_none_in(packages)
|
@@ -4,7 +4,7 @@
|
|
4
4
|
require "yaml"
|
5
5
|
|
6
6
|
module Packwerk
|
7
|
-
class
|
7
|
+
class PackageTodo
|
8
8
|
extend T::Sig
|
9
9
|
|
10
10
|
EntriesType = T.type_alias do
|
@@ -16,30 +16,32 @@ module Packwerk
|
|
16
16
|
@package = package
|
17
17
|
@filepath = filepath
|
18
18
|
@new_entries = T.let({}, EntriesType)
|
19
|
-
@
|
19
|
+
@todo_list = T.let(nil, T.nilable(EntriesType))
|
20
20
|
end
|
21
21
|
|
22
22
|
sig do
|
23
|
-
params(reference: Packwerk::Reference, violation_type:
|
23
|
+
params(reference: Packwerk::Reference, violation_type: String)
|
24
24
|
.returns(T::Boolean)
|
25
25
|
end
|
26
26
|
def listed?(reference, violation_type:)
|
27
|
-
violated_constants_found =
|
27
|
+
violated_constants_found = todo_list.dig(reference.constant.package.name, reference.constant.name)
|
28
28
|
return false unless violated_constants_found
|
29
29
|
|
30
30
|
violated_constant_in_file = violated_constants_found.fetch("files", []).include?(reference.relative_path)
|
31
31
|
return false unless violated_constant_in_file
|
32
32
|
|
33
|
-
violated_constants_found.fetch("violations", []).include?(violation_type
|
33
|
+
violated_constants_found.fetch("violations", []).include?(violation_type)
|
34
34
|
end
|
35
35
|
|
36
|
-
sig
|
36
|
+
sig do
|
37
|
+
params(reference: Packwerk::Reference, violation_type: String).returns(T::Boolean)
|
38
|
+
end
|
37
39
|
def add_entries(reference, violation_type)
|
38
40
|
package_violations = @new_entries.fetch(reference.constant.package.name, {})
|
39
41
|
entries_for_constant = package_violations[reference.constant.name] ||= {}
|
40
42
|
|
41
43
|
entries_for_constant["violations"] ||= []
|
42
|
-
entries_for_constant["violations"] << violation_type
|
44
|
+
entries_for_constant["violations"] << violation_type
|
43
45
|
|
44
46
|
entries_for_constant["files"] ||= []
|
45
47
|
entries_for_constant["files"] << reference.relative_path.to_s
|
@@ -52,7 +54,7 @@ module Packwerk
|
|
52
54
|
def stale_violations?(for_files)
|
53
55
|
prepare_entries_for_dump
|
54
56
|
|
55
|
-
|
57
|
+
todo_list.any? do |package, package_violations|
|
56
58
|
package_violations_for_files = {}
|
57
59
|
package_violations.each do |constant_name, entries_for_constant|
|
58
60
|
entries_for_files = for_files & entries_for_constant["files"]
|
@@ -64,11 +66,17 @@ module Packwerk
|
|
64
66
|
}
|
65
67
|
end
|
66
68
|
|
67
|
-
|
69
|
+
# We `next false` because if we cannot find existing violations for `for_files` within
|
70
|
+
# the `package_todo.yml` file, then there are no violations that
|
71
|
+
# can be considered stale.
|
72
|
+
next false if package_violations_for_files.empty?
|
68
73
|
|
69
74
|
package_violations_for_files.any? do |constant_name, entries_for_constant|
|
70
75
|
new_entries_violation_types = @new_entries.dig(package, constant_name, "violations")
|
71
|
-
|
76
|
+
# If there are no NEW entries that match the old entries `for_files`,
|
77
|
+
# @new_entries is from the list of violations we get when we check this file.
|
78
|
+
# If this list is empty, we also must have stale violations.
|
79
|
+
next true if new_entries_violation_types.nil?
|
72
80
|
|
73
81
|
if entries_for_constant["violations"].all? { |type| new_entries_violation_types.include?(type) }
|
74
82
|
stale_violations =
|
@@ -83,6 +91,8 @@ module Packwerk
|
|
83
91
|
|
84
92
|
sig { void }
|
85
93
|
def dump
|
94
|
+
delete_old_deprecated_references
|
95
|
+
|
86
96
|
if @new_entries.empty?
|
87
97
|
delete_if_exists
|
88
98
|
else
|
@@ -93,7 +103,7 @@ module Packwerk
|
|
93
103
|
#
|
94
104
|
# You can regenerate this file using the following command:
|
95
105
|
#
|
96
|
-
# bin/packwerk update-
|
106
|
+
# bin/packwerk update-todo #{@package.name}
|
97
107
|
MESSAGE
|
98
108
|
File.open(@filepath, "w") do |f|
|
99
109
|
f.write(message)
|
@@ -109,6 +119,12 @@ module Packwerk
|
|
109
119
|
|
110
120
|
private
|
111
121
|
|
122
|
+
sig { void }
|
123
|
+
def delete_old_deprecated_references
|
124
|
+
deprecated_references_filepath = File.join(File.dirname(@filepath), "deprecated_references.yml")
|
125
|
+
File.delete(deprecated_references_filepath) if File.exist?(deprecated_references_filepath)
|
126
|
+
end
|
127
|
+
|
112
128
|
sig { returns(EntriesType) }
|
113
129
|
def prepare_entries_for_dump
|
114
130
|
@new_entries.each do |package_name, package_violations|
|
@@ -123,8 +139,8 @@ module Packwerk
|
|
123
139
|
end
|
124
140
|
|
125
141
|
sig { returns(EntriesType) }
|
126
|
-
def
|
127
|
-
@
|
142
|
+
def todo_list
|
143
|
+
@todo_list ||= if File.exist?(@filepath)
|
128
144
|
load_yaml(@filepath)
|
129
145
|
else
|
130
146
|
{}
|
data/lib/packwerk/parse_run.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require "benchmark"
|
5
4
|
require "parallel"
|
6
5
|
|
7
6
|
module Packwerk
|
@@ -16,77 +15,71 @@ module Packwerk
|
|
16
15
|
params(
|
17
16
|
relative_file_set: FilesForProcessing::RelativeFileSet,
|
18
17
|
configuration: Configuration,
|
18
|
+
file_set_specified: T::Boolean,
|
19
|
+
offenses_formatter: T.nilable(OffensesFormatter),
|
19
20
|
progress_formatter: Formatters::ProgressFormatter,
|
20
|
-
offenses_formatter: OffensesFormatter,
|
21
21
|
).void
|
22
22
|
end
|
23
23
|
def initialize(
|
24
24
|
relative_file_set:,
|
25
25
|
configuration:,
|
26
|
-
|
27
|
-
offenses_formatter:
|
26
|
+
file_set_specified: false,
|
27
|
+
offenses_formatter: nil,
|
28
|
+
progress_formatter: Formatters::ProgressFormatter.new(StringIO.new)
|
28
29
|
)
|
30
|
+
|
29
31
|
@configuration = configuration
|
30
32
|
@progress_formatter = progress_formatter
|
31
|
-
@offenses_formatter = offenses_formatter
|
33
|
+
@offenses_formatter = T.let(offenses_formatter || configuration.offenses_formatter, Packwerk::OffensesFormatter)
|
32
34
|
@relative_file_set = relative_file_set
|
35
|
+
@file_set_specified = file_set_specified
|
33
36
|
end
|
34
37
|
|
35
|
-
sig { returns(Result) }
|
36
|
-
def
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
run_context = Packwerk::RunContext.from_configuration(@configuration)
|
43
|
-
offense_collection = find_offenses(run_context)
|
38
|
+
sig { returns(Cli::Result) }
|
39
|
+
def update_todo
|
40
|
+
if @file_set_specified
|
41
|
+
message = <<~MSG.squish
|
42
|
+
⚠️ update-todo must be called without any file arguments.
|
43
|
+
MSG
|
44
44
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
Result.new(message: message, status: result_status)
|
49
|
-
end
|
45
|
+
return Cli::Result.new(message: message, status: false)
|
46
|
+
end
|
50
47
|
|
51
|
-
|
52
|
-
def update_deprecations
|
53
|
-
run_context = Packwerk::RunContext.from_configuration(@configuration)
|
48
|
+
run_context = RunContext.from_configuration(@configuration)
|
54
49
|
offense_collection = find_offenses(run_context)
|
55
|
-
offense_collection.
|
50
|
+
offense_collection.persist_package_todo_files(run_context.package_set)
|
56
51
|
|
57
52
|
message = <<~EOS
|
58
53
|
#{@offenses_formatter.show_offenses(offense_collection.errors)}
|
59
|
-
✅ `
|
54
|
+
✅ `package_todo.yml` has been updated.
|
60
55
|
EOS
|
61
56
|
|
62
|
-
Result.new(message: message, status: offense_collection.errors.empty?)
|
57
|
+
Cli::Result.new(message: message, status: offense_collection.errors.empty?)
|
63
58
|
end
|
64
59
|
|
65
|
-
sig { returns(Result) }
|
60
|
+
sig { returns(Cli::Result) }
|
66
61
|
def check
|
67
|
-
run_context =
|
62
|
+
run_context = RunContext.from_configuration(@configuration)
|
68
63
|
offense_collection = find_offenses(run_context, show_errors: true)
|
69
64
|
|
70
65
|
messages = [
|
71
66
|
@offenses_formatter.show_offenses(offense_collection.outstanding_offenses),
|
72
67
|
@offenses_formatter.show_stale_violations(offense_collection, @relative_file_set),
|
68
|
+
@offenses_formatter.show_strict_mode_violations(offense_collection.strict_mode_violations),
|
73
69
|
]
|
74
70
|
|
75
71
|
result_status = offense_collection.outstanding_offenses.empty? &&
|
76
|
-
!offense_collection.stale_violations?(@relative_file_set)
|
72
|
+
!offense_collection.stale_violations?(@relative_file_set) && offense_collection.strict_mode_violations.empty?
|
77
73
|
|
78
|
-
Result.new(message: messages.join("\n") + "\n", status: result_status)
|
74
|
+
Cli::Result.new(message: messages.select(&:present?).join("\n") + "\n", status: result_status)
|
79
75
|
end
|
80
76
|
|
81
77
|
private
|
82
78
|
|
83
|
-
sig { params(run_context:
|
79
|
+
sig { params(run_context: RunContext, show_errors: T::Boolean).returns(OffenseCollection) }
|
84
80
|
def find_offenses(run_context, show_errors: false)
|
85
81
|
offense_collection = OffenseCollection.new(@configuration.root_path)
|
86
|
-
@progress_formatter.started(@relative_file_set)
|
87
|
-
|
88
82
|
all_offenses = T.let([], T::Array[Offense])
|
89
|
-
|
90
83
|
process_file = T.let(->(relative_file) do
|
91
84
|
run_context.process_file(relative_file: relative_file).tap do |offenses|
|
92
85
|
failed = show_errors && offenses.any? { |offense| !offense_collection.listed?(offense) }
|
@@ -94,7 +87,7 @@ module Packwerk
|
|
94
87
|
end
|
95
88
|
end, ProcessFileProc)
|
96
89
|
|
97
|
-
|
90
|
+
@progress_formatter.started_inspection(@relative_file_set) do
|
98
91
|
all_offenses = if @configuration.parallel?
|
99
92
|
Parallel.flat_map(@relative_file_set, &process_file)
|
100
93
|
else
|
@@ -102,8 +95,6 @@ module Packwerk
|
|
102
95
|
end
|
103
96
|
end
|
104
97
|
|
105
|
-
@progress_formatter.finished(execution_time)
|
106
|
-
|
107
98
|
all_offenses.each { |offense| offense_collection.add_offense(offense) }
|
108
99
|
offense_collection
|
109
100
|
end
|
@@ -132,4 +123,6 @@ module Packwerk
|
|
132
123
|
end
|
133
124
|
end
|
134
125
|
end
|
126
|
+
|
127
|
+
private_constant :ParseRun
|
135
128
|
end
|