packwerk 2.2.2 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|