packwerk 3.2.3 → 3.3.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/exe/packwerk +0 -4
- data/lib/packwerk/application_validator.rb +11 -10
- data/lib/packwerk/association_inspector.rb +21 -32
- data/lib/packwerk/cache.rb +43 -36
- data/lib/packwerk/checker.rb +24 -26
- data/lib/packwerk/cli.rb +13 -20
- data/lib/packwerk/commands/base_command.rb +20 -26
- data/lib/packwerk/commands/check_command.rb +8 -8
- data/lib/packwerk/commands/help_command.rb +3 -4
- data/lib/packwerk/commands/init_command.rb +2 -3
- data/lib/packwerk/commands/lazy_loaded_entry.rb +5 -7
- data/lib/packwerk/commands/update_todo_command.rb +3 -3
- data/lib/packwerk/commands/uses_parse_run.rb +20 -26
- data/lib/packwerk/commands/validate_command.rb +6 -7
- data/lib/packwerk/commands/version_command.rb +2 -3
- data/lib/packwerk/commands.rb +5 -8
- data/lib/packwerk/configuration.rb +29 -43
- data/lib/packwerk/const_node_inspector.rb +5 -9
- data/lib/packwerk/constant_context.rb +0 -2
- data/lib/packwerk/constant_discovery.rb +3 -16
- data/lib/packwerk/constant_name_inspector.rb +4 -11
- data/lib/packwerk/extension_loader.rb +1 -2
- data/lib/packwerk/file_processor.rb +20 -25
- data/lib/packwerk/files_for_processing.rb +13 -29
- data/lib/packwerk/formatters/default_offenses_formatter.rb +14 -12
- data/lib/packwerk/formatters/progress_formatter.rb +10 -12
- data/lib/packwerk/generators/configuration_file.rb +5 -9
- data/lib/packwerk/generators/root_package.rb +3 -7
- data/lib/packwerk/graph.rb +1 -7
- data/lib/packwerk/node_helpers.rb +32 -38
- data/lib/packwerk/node_processor.rb +2 -14
- data/lib/packwerk/node_processor_factory.rb +13 -7
- data/lib/packwerk/node_visitor.rb +2 -10
- data/lib/packwerk/offense.rb +6 -12
- data/lib/packwerk/offense_collection.rb +22 -35
- data/lib/packwerk/offenses_formatter.rb +27 -34
- data/lib/packwerk/output_style.rb +10 -11
- data/lib/packwerk/output_styles/coloured.rb +6 -4
- data/lib/packwerk/output_styles/plain.rb +6 -4
- data/lib/packwerk/package.rb +15 -16
- data/lib/packwerk/package_set.rb +15 -25
- data/lib/packwerk/package_todo.rb +21 -30
- data/lib/packwerk/parse_run.rb +10 -37
- data/lib/packwerk/parsed_constant_definitions.rb +10 -24
- data/lib/packwerk/parsers/erb.rb +11 -22
- data/lib/packwerk/parsers/factory.rb +9 -9
- data/lib/packwerk/parsers/parser_interface.rb +5 -10
- data/lib/packwerk/parsers/ruby.rb +9 -14
- data/lib/packwerk/parsers.rb +2 -4
- data/lib/packwerk/rails_load_paths.rb +6 -11
- data/lib/packwerk/reference_checking/checkers/dependency_checker.rb +10 -15
- data/lib/packwerk/reference_checking/reference_checker.rb +2 -8
- data/lib/packwerk/reference_extractor.rb +22 -55
- data/lib/packwerk/reference_offense.rb +5 -15
- data/lib/packwerk/run_context.rb +28 -39
- data/lib/packwerk/spring_command.rb +4 -7
- data/lib/packwerk/validator/result.rb +12 -5
- data/lib/packwerk/validator.rb +23 -33
- data/lib/packwerk/validators/dependency_validator.rb +9 -10
- data/lib/packwerk/version.rb +1 -1
- data/lib/packwerk.rb +0 -1
- data/sorbet/config +2 -0
- data/sorbet/rbi/gems/prism@1.9.0.rbi +43359 -0
- data/sorbet/rbi/shims/packwerk/reference.rbi +5 -12
- data/sorbet/rbi/shims/packwerk/unresolved_reference.rbi +5 -12
- data/sorbet/rbi/shims/parser.rbi +1 -1
- metadata +18 -19
- data/lib/packwerk/disable_sorbet.rb +0 -41
- data/sorbet/rbi/gems/prism@0.27.0.rbi +0 -36983
|
@@ -4,20 +4,12 @@
|
|
|
4
4
|
module Packwerk
|
|
5
5
|
# Visits all nodes of an AST, processing them using a given node processor.
|
|
6
6
|
class NodeVisitor
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
sig { params(node_processor: NodeProcessor).void }
|
|
7
|
+
#: (node_processor: NodeProcessor) -> void
|
|
10
8
|
def initialize(node_processor:)
|
|
11
9
|
@node_processor = node_processor
|
|
12
10
|
end
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
params(
|
|
16
|
-
node: Parser::AST::Node,
|
|
17
|
-
ancestors: T::Array[Parser::AST::Node],
|
|
18
|
-
result: T::Array[UnresolvedReference],
|
|
19
|
-
).void
|
|
20
|
-
end
|
|
12
|
+
#: (Parser::AST::Node node, ancestors: Array[Parser::AST::Node], result: Array[UnresolvedReference]) -> void
|
|
21
13
|
def visit(node, ancestors:, result:)
|
|
22
14
|
reference = @node_processor.call(node, ancestors)
|
|
23
15
|
result << reference if reference
|
data/lib/packwerk/offense.rb
CHANGED
|
@@ -1,33 +1,27 @@
|
|
|
1
1
|
# typed: strict
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
-
require "parser
|
|
4
|
+
require "parser"
|
|
5
5
|
|
|
6
6
|
module Packwerk
|
|
7
7
|
class Offense
|
|
8
|
-
|
|
9
|
-
extend T::Helpers
|
|
10
|
-
|
|
11
|
-
sig { returns(T.nilable(Node::Location)) }
|
|
8
|
+
#: Node::Location?
|
|
12
9
|
attr_reader :location
|
|
13
10
|
|
|
14
|
-
|
|
11
|
+
#: String
|
|
15
12
|
attr_reader :file
|
|
16
13
|
|
|
17
|
-
|
|
14
|
+
#: String
|
|
18
15
|
attr_reader :message
|
|
19
16
|
|
|
20
|
-
|
|
21
|
-
params(file: String, message: String, location: T.nilable(Node::Location))
|
|
22
|
-
.void
|
|
23
|
-
end
|
|
17
|
+
#: (file: String, message: String, ?location: Node::Location?) -> void
|
|
24
18
|
def initialize(file:, message:, location: nil)
|
|
25
19
|
@location = location
|
|
26
20
|
@file = file
|
|
27
21
|
@message = message
|
|
28
22
|
end
|
|
29
23
|
|
|
30
|
-
|
|
24
|
+
#: (?OutputStyle style) -> String
|
|
31
25
|
def to_s(style = OutputStyles::Plain.new)
|
|
32
26
|
location = self.location
|
|
33
27
|
if location
|
|
@@ -5,50 +5,37 @@ require "pathname"
|
|
|
5
5
|
|
|
6
6
|
module Packwerk
|
|
7
7
|
class OffenseCollection
|
|
8
|
-
|
|
9
|
-
extend T::Helpers
|
|
10
|
-
|
|
11
|
-
sig do
|
|
12
|
-
params(
|
|
13
|
-
root_path: String,
|
|
14
|
-
package_todos: T::Hash[Packwerk::Package, Packwerk::PackageTodo]
|
|
15
|
-
).void
|
|
16
|
-
end
|
|
8
|
+
#: (String root_path, ?Hash[Packwerk::Package, Packwerk::PackageTodo] package_todos) -> void
|
|
17
9
|
def initialize(root_path, package_todos = {})
|
|
18
10
|
@root_path = root_path
|
|
19
|
-
@package_todos =
|
|
20
|
-
@new_violations =
|
|
21
|
-
@strict_mode_violations =
|
|
22
|
-
@errors =
|
|
11
|
+
@package_todos = package_todos #: Hash[Packwerk::Package, Packwerk::PackageTodo]
|
|
12
|
+
@new_violations = [] #: Array[Packwerk::ReferenceOffense]
|
|
13
|
+
@strict_mode_violations = [] #: Array[Packwerk::ReferenceOffense]
|
|
14
|
+
@errors = [] #: Array[Packwerk::Offense]
|
|
23
15
|
end
|
|
24
16
|
|
|
25
|
-
|
|
17
|
+
#: Array[Packwerk::ReferenceOffense]
|
|
26
18
|
attr_reader :new_violations
|
|
27
19
|
|
|
28
|
-
|
|
20
|
+
#: Array[Packwerk::Offense]
|
|
29
21
|
attr_reader :errors
|
|
30
22
|
|
|
31
|
-
|
|
23
|
+
#: Array[Packwerk::ReferenceOffense]
|
|
32
24
|
attr_reader :strict_mode_violations
|
|
33
25
|
|
|
34
|
-
|
|
35
|
-
params(offense: Packwerk::Offense)
|
|
36
|
-
.returns(T::Boolean)
|
|
37
|
-
end
|
|
26
|
+
#: (Packwerk::Offense offense) -> bool
|
|
38
27
|
def listed?(offense)
|
|
39
28
|
return false unless offense.is_a?(ReferenceOffense)
|
|
40
29
|
|
|
41
30
|
already_listed?(offense)
|
|
42
31
|
end
|
|
43
32
|
|
|
44
|
-
|
|
33
|
+
#: (Array[Offense] offenses) -> void
|
|
45
34
|
def add_offenses(offenses)
|
|
46
35
|
offenses.each { |offense| add_offense(offense) }
|
|
47
36
|
end
|
|
48
37
|
|
|
49
|
-
|
|
50
|
-
params(offense: Packwerk::Offense).void
|
|
51
|
-
end
|
|
38
|
+
#: (Packwerk::Offense offense) -> void
|
|
52
39
|
def add_offense(offense)
|
|
53
40
|
unless offense.is_a?(ReferenceOffense)
|
|
54
41
|
@errors << offense
|
|
@@ -67,50 +54,50 @@ module Packwerk
|
|
|
67
54
|
end
|
|
68
55
|
end
|
|
69
56
|
|
|
70
|
-
|
|
57
|
+
#: (Set[String] for_files) -> bool
|
|
71
58
|
def stale_violations?(for_files)
|
|
72
59
|
@package_todos.values.any? do |package_todo|
|
|
73
60
|
package_todo.stale_violations?(for_files)
|
|
74
61
|
end
|
|
75
62
|
end
|
|
76
63
|
|
|
77
|
-
|
|
64
|
+
#: (Packwerk::PackageSet package_set) -> void
|
|
78
65
|
def persist_package_todo_files(package_set)
|
|
79
66
|
dump_package_todo_files
|
|
80
67
|
cleanup_extra_package_todo_files(package_set)
|
|
81
68
|
end
|
|
82
69
|
|
|
83
|
-
|
|
70
|
+
#: -> Array[Packwerk::Offense]
|
|
84
71
|
def outstanding_offenses
|
|
85
72
|
errors + new_violations
|
|
86
73
|
end
|
|
87
74
|
|
|
88
|
-
|
|
75
|
+
#: -> Array[Packwerk::ReferenceOffense]
|
|
89
76
|
def unlisted_strict_mode_violations
|
|
90
77
|
strict_mode_violations.reject { |offense| already_listed?(offense) }
|
|
91
78
|
end
|
|
92
79
|
|
|
93
80
|
private
|
|
94
81
|
|
|
95
|
-
|
|
82
|
+
#: (ReferenceOffense offense) -> bool
|
|
96
83
|
def already_listed?(offense)
|
|
97
84
|
package_todo_for(offense.reference.package).listed?(offense.reference,
|
|
98
85
|
violation_type: offense.violation_type)
|
|
99
86
|
end
|
|
100
87
|
|
|
101
|
-
|
|
88
|
+
#: (ReferenceOffense offense) -> bool
|
|
102
89
|
def add_to_package_todo(offense)
|
|
103
90
|
package_todo_for(offense.reference.package).add_entries(offense.reference,
|
|
104
91
|
offense.violation_type)
|
|
105
92
|
end
|
|
106
93
|
|
|
107
|
-
|
|
94
|
+
#: (ReferenceOffense offense) -> bool
|
|
108
95
|
def strict_mode_violation?(offense)
|
|
109
96
|
checker = Checker.find(offense.violation_type)
|
|
110
97
|
checker.strict_mode_violation?(offense)
|
|
111
98
|
end
|
|
112
99
|
|
|
113
|
-
|
|
100
|
+
#: (Packwerk::PackageSet package_set) -> void
|
|
114
101
|
def cleanup_extra_package_todo_files(package_set)
|
|
115
102
|
packages_without_todos = (package_set.packages.values - @package_todos.keys)
|
|
116
103
|
|
|
@@ -122,12 +109,12 @@ module Packwerk
|
|
|
122
109
|
end
|
|
123
110
|
end
|
|
124
111
|
|
|
125
|
-
|
|
112
|
+
#: -> void
|
|
126
113
|
def dump_package_todo_files
|
|
127
114
|
@package_todos.each_value(&:dump)
|
|
128
115
|
end
|
|
129
116
|
|
|
130
|
-
|
|
117
|
+
#: (Packwerk::Package package) -> Packwerk::PackageTodo
|
|
131
118
|
def package_todo_for(package)
|
|
132
119
|
@package_todos[package] ||= Packwerk::PackageTodo.new(
|
|
133
120
|
package,
|
|
@@ -135,7 +122,7 @@ module Packwerk
|
|
|
135
122
|
)
|
|
136
123
|
end
|
|
137
124
|
|
|
138
|
-
|
|
125
|
+
#: (Packwerk::Package package) -> String
|
|
139
126
|
def package_todo_file_for(package)
|
|
140
127
|
File.join(@root_path, package.name, "package_todo.yml")
|
|
141
128
|
end
|
|
@@ -2,84 +2,77 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
module Packwerk
|
|
5
|
+
# @abstract
|
|
5
6
|
module OffensesFormatter
|
|
6
|
-
extend T::Sig
|
|
7
|
-
extend T::Helpers
|
|
8
|
-
|
|
9
|
-
abstract!
|
|
10
|
-
|
|
11
7
|
class DuplicateFormatterError < StandardError
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
sig { params(identifier: String).void }
|
|
8
|
+
#: (String identifier) -> void
|
|
15
9
|
def initialize(identifier)
|
|
16
10
|
super("Cannot have multiple identifiers with the same key (`#{identifier}`)")
|
|
17
11
|
end
|
|
18
12
|
end
|
|
19
13
|
|
|
20
14
|
class << self
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
sig { params(base: T::Class[T.anything]).void }
|
|
15
|
+
#: (Class[top] base) -> void
|
|
24
16
|
def included(base)
|
|
25
17
|
offenses_formatters << base
|
|
26
18
|
end
|
|
27
19
|
|
|
28
|
-
|
|
20
|
+
#: -> Array[OffensesFormatter]
|
|
29
21
|
def all
|
|
30
22
|
load_defaults
|
|
31
|
-
|
|
23
|
+
offenses_formatters.map(&:new) #: as Array[OffensesFormatter]
|
|
32
24
|
end
|
|
33
25
|
|
|
34
|
-
|
|
26
|
+
#: (String identifier) -> OffensesFormatter
|
|
35
27
|
def find(identifier)
|
|
36
28
|
formatter_by_identifier(identifier)
|
|
37
29
|
end
|
|
38
30
|
|
|
39
31
|
private
|
|
40
32
|
|
|
41
|
-
|
|
33
|
+
#: -> void
|
|
42
34
|
def load_defaults
|
|
43
35
|
require("packwerk/formatters/default_offenses_formatter")
|
|
44
36
|
end
|
|
45
37
|
|
|
46
|
-
|
|
38
|
+
#: -> Array[Class[top]]
|
|
47
39
|
def offenses_formatters
|
|
48
|
-
@offenses_formatters ||=
|
|
40
|
+
@offenses_formatters ||= [] #: Array[Class[top]]?
|
|
49
41
|
end
|
|
50
42
|
|
|
51
|
-
|
|
43
|
+
#: (String name) -> OffensesFormatter
|
|
52
44
|
def formatter_by_identifier(name)
|
|
53
|
-
@formatter_by_identifier ||=
|
|
45
|
+
@formatter_by_identifier ||= nil #: Hash[String, OffensesFormatter?]?
|
|
54
46
|
@formatter_by_identifier ||= begin
|
|
55
|
-
index =
|
|
47
|
+
index = {} #: Hash[String, OffensesFormatter?]
|
|
56
48
|
OffensesFormatter.all.each do |formatter|
|
|
57
49
|
identifier = formatter.identifier
|
|
58
50
|
raise DuplicateFormatterError, identifier if index.key?(identifier)
|
|
59
51
|
|
|
60
52
|
index[identifier] = formatter
|
|
61
53
|
end
|
|
62
|
-
|
|
54
|
+
index #: Hash[String, OffensesFormatter?]?
|
|
63
55
|
end
|
|
64
56
|
|
|
65
|
-
|
|
57
|
+
formatter_by_identifier = @formatter_by_identifier #: as !nil
|
|
58
|
+
formatter_by_identifier[name] #: as !nil
|
|
66
59
|
end
|
|
67
60
|
end
|
|
68
61
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
62
|
+
# @abstract
|
|
63
|
+
#: (Array[Offense?] offenses) -> String
|
|
64
|
+
def show_offenses(offenses) = raise NotImplementedError, "Abstract method called"
|
|
72
65
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
66
|
+
# @abstract
|
|
67
|
+
#: (OffenseCollection offense_collection, Set[String] for_files) -> String
|
|
68
|
+
def show_stale_violations(offense_collection, for_files) = raise NotImplementedError, "Abstract method called"
|
|
76
69
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
70
|
+
# @abstract
|
|
71
|
+
#: -> String
|
|
72
|
+
def identifier = raise NotImplementedError, "Abstract method called"
|
|
80
73
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
74
|
+
# @abstract
|
|
75
|
+
#: (Array[ReferenceOffense] strict_mode_violations) -> String
|
|
76
|
+
def show_strict_mode_violations(strict_mode_violations) = raise NotImplementedError, "Abstract method called"
|
|
84
77
|
end
|
|
85
78
|
end
|
|
@@ -2,19 +2,18 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
module Packwerk
|
|
5
|
+
# @interface
|
|
5
6
|
module OutputStyle
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
# @abstract
|
|
8
|
+
#: -> String
|
|
9
|
+
def reset = raise NotImplementedError, "Abstract method called"
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
# @abstract
|
|
12
|
+
#: -> String
|
|
13
|
+
def filename = raise NotImplementedError, "Abstract method called"
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
sig { abstract.returns(String) }
|
|
15
|
-
def filename; end
|
|
16
|
-
|
|
17
|
-
sig { abstract.returns(String) }
|
|
18
|
-
def error; end
|
|
15
|
+
# @abstract
|
|
16
|
+
#: -> String
|
|
17
|
+
def error = raise NotImplementedError, "Abstract method called"
|
|
19
18
|
end
|
|
20
19
|
end
|
|
@@ -5,21 +5,23 @@ module Packwerk
|
|
|
5
5
|
module OutputStyles
|
|
6
6
|
# See https://en.wikipedia.org/wiki/ANSI_escape_code#3/4_bit for ANSI escape colour codes
|
|
7
7
|
class Coloured
|
|
8
|
-
extend T::Sig
|
|
9
8
|
include OutputStyle
|
|
10
9
|
|
|
11
|
-
|
|
10
|
+
# @override
|
|
11
|
+
#: -> String
|
|
12
12
|
def reset
|
|
13
13
|
"\033[m"
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
# @override
|
|
17
|
+
#: -> String
|
|
17
18
|
def filename
|
|
18
19
|
# 36 is foreground cyan
|
|
19
20
|
"\033[36m"
|
|
20
21
|
end
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
# @override
|
|
24
|
+
#: -> String
|
|
23
25
|
def error
|
|
24
26
|
# 31 is foreground red
|
|
25
27
|
"\033[31m"
|
|
@@ -4,20 +4,22 @@
|
|
|
4
4
|
module Packwerk
|
|
5
5
|
module OutputStyles
|
|
6
6
|
class Plain
|
|
7
|
-
extend T::Sig
|
|
8
7
|
include OutputStyle
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
# @override
|
|
10
|
+
#: -> String
|
|
11
11
|
def reset
|
|
12
12
|
""
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
# @override
|
|
16
|
+
#: -> String
|
|
16
17
|
def filename
|
|
17
18
|
""
|
|
18
19
|
end
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
# @override
|
|
22
|
+
#: -> String
|
|
21
23
|
def error
|
|
22
24
|
""
|
|
23
25
|
end
|
data/lib/packwerk/package.rb
CHANGED
|
@@ -6,68 +6,67 @@ module Packwerk
|
|
|
6
6
|
# The package contains all constants defined in files in this folder and all subfolders that are not packages
|
|
7
7
|
# themselves.
|
|
8
8
|
class Package
|
|
9
|
-
extend T::Sig
|
|
10
9
|
include Comparable
|
|
11
10
|
|
|
12
11
|
ROOT_PACKAGE_NAME = "."
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
#: String
|
|
15
14
|
attr_reader :name
|
|
16
15
|
|
|
17
|
-
|
|
16
|
+
#: Array[String]
|
|
18
17
|
attr_reader :dependencies
|
|
19
18
|
|
|
20
|
-
|
|
19
|
+
#: Hash[untyped, untyped]
|
|
21
20
|
attr_reader :config
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
#: (name: String, ?config: Hash[String, untyped]?) -> void
|
|
24
23
|
def initialize(name:, config: nil)
|
|
25
24
|
@name = name
|
|
26
|
-
@config =
|
|
27
|
-
@dependencies =
|
|
28
|
-
@public_path =
|
|
25
|
+
@config = config || {} #: Hash[String, untyped]
|
|
26
|
+
@dependencies = Array(@config["dependencies"]).freeze #: Array[String]
|
|
27
|
+
@public_path = nil #: String?
|
|
29
28
|
end
|
|
30
29
|
|
|
31
|
-
|
|
30
|
+
#: -> bool
|
|
32
31
|
def enforce_dependencies?
|
|
33
32
|
[true, "strict"].include?(@config["enforce_dependencies"])
|
|
34
33
|
end
|
|
35
34
|
|
|
36
|
-
|
|
35
|
+
#: (Package package) -> bool
|
|
37
36
|
def dependency?(package)
|
|
38
37
|
@dependencies.include?(package.name)
|
|
39
38
|
end
|
|
40
39
|
|
|
41
|
-
|
|
40
|
+
#: (String path) -> bool
|
|
42
41
|
def package_path?(path)
|
|
43
42
|
return true if root?
|
|
44
43
|
|
|
45
44
|
path.start_with?(@name + "/")
|
|
46
45
|
end
|
|
47
46
|
|
|
48
|
-
|
|
47
|
+
#: (untyped other) -> Integer?
|
|
49
48
|
def <=>(other)
|
|
50
49
|
return nil unless other.is_a?(self.class)
|
|
51
50
|
|
|
52
51
|
name <=> other.name
|
|
53
52
|
end
|
|
54
53
|
|
|
55
|
-
|
|
54
|
+
#: (untyped other) -> bool
|
|
56
55
|
def eql?(other)
|
|
57
56
|
self == other
|
|
58
57
|
end
|
|
59
58
|
|
|
60
|
-
|
|
59
|
+
#: -> Integer
|
|
61
60
|
def hash
|
|
62
61
|
name.hash
|
|
63
62
|
end
|
|
64
63
|
|
|
65
|
-
|
|
64
|
+
#: -> String
|
|
66
65
|
def to_s
|
|
67
66
|
name
|
|
68
67
|
end
|
|
69
68
|
|
|
70
|
-
|
|
69
|
+
#: -> bool
|
|
71
70
|
def root?
|
|
72
71
|
@name == ROOT_PACKAGE_NAME
|
|
73
72
|
end
|
data/lib/packwerk/package_set.rb
CHANGED
|
@@ -5,22 +5,17 @@ require "pathname"
|
|
|
5
5
|
require "bundler"
|
|
6
6
|
|
|
7
7
|
module Packwerk
|
|
8
|
-
|
|
8
|
+
#: type path_spec = String | Array[String]
|
|
9
9
|
|
|
10
10
|
# A set of {Packwerk::Package}s as well as methods to parse packages from the filesystem.
|
|
11
|
+
#: [Elem = Package]
|
|
11
12
|
class PackageSet
|
|
12
|
-
extend T::Sig
|
|
13
|
-
extend T::Generic
|
|
14
13
|
include Enumerable
|
|
15
14
|
|
|
16
|
-
Elem = type_member { { fixed: Package } }
|
|
17
|
-
|
|
18
15
|
PACKAGE_CONFIG_FILENAME = "package.yml"
|
|
19
16
|
|
|
20
17
|
class << self
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
sig { params(root_path: String, package_pathspec: T.nilable(PathSpec)).returns(PackageSet) }
|
|
18
|
+
#: (String root_path, ?package_pathspec: path_spec?) -> PackageSet
|
|
24
19
|
def load_all_from(root_path, package_pathspec: nil)
|
|
25
20
|
package_paths = package_paths(root_path, package_pathspec || "**")
|
|
26
21
|
|
|
@@ -34,13 +29,7 @@ module Packwerk
|
|
|
34
29
|
new(packages)
|
|
35
30
|
end
|
|
36
31
|
|
|
37
|
-
|
|
38
|
-
params(
|
|
39
|
-
root_path: String,
|
|
40
|
-
package_pathspec: PathSpec,
|
|
41
|
-
exclude_pathspec: T.nilable(PathSpec)
|
|
42
|
-
).returns(T::Array[Pathname])
|
|
43
|
-
end
|
|
32
|
+
#: (String root_path, path_spec package_pathspec, ?path_spec? exclude_pathspec) -> Array[Pathname]
|
|
44
33
|
def package_paths(root_path, package_pathspec, exclude_pathspec = [])
|
|
45
34
|
exclude_pathspec = Array(exclude_pathspec).dup
|
|
46
35
|
.push(Bundler.bundle_path.join("**").to_s)
|
|
@@ -57,14 +46,14 @@ module Packwerk
|
|
|
57
46
|
|
|
58
47
|
private
|
|
59
48
|
|
|
60
|
-
|
|
49
|
+
#: (Array[Package] packages) -> void
|
|
61
50
|
def create_root_package_if_none_in(packages)
|
|
62
51
|
return if packages.any?(&:root?)
|
|
63
52
|
|
|
64
53
|
packages << Package.new(name: Package::ROOT_PACKAGE_NAME, config: nil)
|
|
65
54
|
end
|
|
66
55
|
|
|
67
|
-
|
|
56
|
+
#: (Array[String] globs, Pathname path) -> bool
|
|
68
57
|
def exclude_path?(globs, path)
|
|
69
58
|
globs.any? do |glob|
|
|
70
59
|
path.realpath.fnmatch(glob, File::FNM_EXTGLOB)
|
|
@@ -72,32 +61,33 @@ module Packwerk
|
|
|
72
61
|
end
|
|
73
62
|
end
|
|
74
63
|
|
|
75
|
-
|
|
64
|
+
#: Hash[String, Package]
|
|
76
65
|
attr_reader :packages
|
|
77
66
|
|
|
78
|
-
|
|
67
|
+
#: (Array[Package] packages) -> void
|
|
79
68
|
def initialize(packages)
|
|
80
69
|
# We want to match more specific paths first
|
|
81
70
|
sorted_packages = packages.sort_by { |package| -package.name.length }
|
|
82
71
|
packages = sorted_packages.each_with_object({}) { |package, hash| hash[package.name] = package }
|
|
83
|
-
@packages =
|
|
84
|
-
@package_from_path =
|
|
72
|
+
@packages = packages #: Hash[String, Package]
|
|
73
|
+
@package_from_path = {} #: Hash[String, Package?]
|
|
85
74
|
end
|
|
86
75
|
|
|
87
|
-
|
|
76
|
+
# @override
|
|
77
|
+
#: { (Package arg0) -> untyped } -> untyped
|
|
88
78
|
def each(&blk)
|
|
89
79
|
packages.values.each(&blk)
|
|
90
80
|
end
|
|
91
81
|
|
|
92
|
-
|
|
82
|
+
#: (String name) -> Package?
|
|
93
83
|
def fetch(name)
|
|
94
84
|
packages[name]
|
|
95
85
|
end
|
|
96
86
|
|
|
97
|
-
|
|
87
|
+
#: ((Pathname | String) file_path) -> Package
|
|
98
88
|
def package_from_path(file_path)
|
|
99
89
|
path_string = file_path.to_s
|
|
100
|
-
@package_from_path[path_string] ||=
|
|
90
|
+
@package_from_path[path_string] ||= packages.values.find { |package| package.package_path?(path_string) } #: as !nil
|
|
101
91
|
end
|
|
102
92
|
end
|
|
103
93
|
end
|