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
|
@@ -3,53 +3,37 @@
|
|
|
3
3
|
|
|
4
4
|
module Packwerk
|
|
5
5
|
class FilesForProcessing
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
RelativeFileSet = T.type_alias { T::Set[String] }
|
|
6
|
+
#: type relative_file_set = Set[String]
|
|
9
7
|
|
|
10
8
|
class << self
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
sig do
|
|
14
|
-
params(
|
|
15
|
-
relative_file_paths: T::Array[String],
|
|
16
|
-
configuration: Configuration,
|
|
17
|
-
ignore_nested_packages: T::Boolean
|
|
18
|
-
).returns(FilesForProcessing)
|
|
19
|
-
end
|
|
9
|
+
#: (relative_file_paths: Array[String], configuration: Configuration, ?ignore_nested_packages: bool) -> FilesForProcessing
|
|
20
10
|
def fetch(relative_file_paths:, configuration:, ignore_nested_packages: false)
|
|
21
11
|
new(relative_file_paths, configuration, ignore_nested_packages)
|
|
22
12
|
end
|
|
23
13
|
end
|
|
24
14
|
|
|
25
|
-
|
|
26
|
-
params(
|
|
27
|
-
relative_file_paths: T::Array[String],
|
|
28
|
-
configuration: Configuration,
|
|
29
|
-
ignore_nested_packages: T::Boolean
|
|
30
|
-
).void
|
|
31
|
-
end
|
|
15
|
+
#: (Array[String] relative_file_paths, Configuration configuration, bool ignore_nested_packages) -> void
|
|
32
16
|
def initialize(relative_file_paths, configuration, ignore_nested_packages)
|
|
33
17
|
@relative_file_paths = relative_file_paths
|
|
34
18
|
@configuration = configuration
|
|
35
19
|
@ignore_nested_packages = ignore_nested_packages
|
|
36
|
-
@specified_files =
|
|
37
|
-
@files =
|
|
20
|
+
@specified_files = nil #: relative_file_set?
|
|
21
|
+
@files = nil #: relative_file_set?
|
|
38
22
|
end
|
|
39
23
|
|
|
40
|
-
|
|
24
|
+
#: -> relative_file_set
|
|
41
25
|
def files
|
|
42
26
|
@files ||= files_for_processing
|
|
43
27
|
end
|
|
44
28
|
|
|
45
|
-
|
|
29
|
+
#: -> bool
|
|
46
30
|
def files_specified?
|
|
47
31
|
specified_files.any?
|
|
48
32
|
end
|
|
49
33
|
|
|
50
34
|
private
|
|
51
35
|
|
|
52
|
-
|
|
36
|
+
#: -> relative_file_set
|
|
53
37
|
def files_for_processing
|
|
54
38
|
all_included_files = if specified_files.empty?
|
|
55
39
|
configured_included_files
|
|
@@ -60,7 +44,7 @@ module Packwerk
|
|
|
60
44
|
all_included_files - configured_excluded_files
|
|
61
45
|
end
|
|
62
46
|
|
|
63
|
-
|
|
47
|
+
#: -> relative_file_set
|
|
64
48
|
def specified_files
|
|
65
49
|
@specified_files ||= Set.new(
|
|
66
50
|
@relative_file_paths.map do |relative_file_path|
|
|
@@ -73,7 +57,7 @@ module Packwerk
|
|
|
73
57
|
).flatten
|
|
74
58
|
end
|
|
75
59
|
|
|
76
|
-
|
|
60
|
+
#: (String relative_file_path) -> relative_file_set
|
|
77
61
|
def specified_included_files(relative_file_path)
|
|
78
62
|
# Note, assuming include globs are always relative paths
|
|
79
63
|
relative_includes = @configuration.include
|
|
@@ -96,17 +80,17 @@ module Packwerk
|
|
|
96
80
|
Set.new(relative_files)
|
|
97
81
|
end
|
|
98
82
|
|
|
99
|
-
|
|
83
|
+
#: -> relative_file_set
|
|
100
84
|
def configured_included_files
|
|
101
85
|
relative_files_for_globs(@configuration.include)
|
|
102
86
|
end
|
|
103
87
|
|
|
104
|
-
|
|
88
|
+
#: -> relative_file_set
|
|
105
89
|
def configured_excluded_files
|
|
106
90
|
relative_files_for_globs(@configuration.exclude)
|
|
107
91
|
end
|
|
108
92
|
|
|
109
|
-
|
|
93
|
+
#: (Array[String] relative_globs) -> relative_file_set
|
|
110
94
|
def relative_files_for_globs(relative_globs)
|
|
111
95
|
Set.new(relative_globs.flat_map { |glob| Dir[glob] })
|
|
112
96
|
end
|
|
@@ -6,11 +6,10 @@ module Packwerk
|
|
|
6
6
|
class DefaultOffensesFormatter
|
|
7
7
|
include OffensesFormatter
|
|
8
8
|
|
|
9
|
-
IDENTIFIER =
|
|
9
|
+
IDENTIFIER = "default" #: String
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
sig { override.params(offenses: T::Array[T.nilable(Offense)]).returns(String) }
|
|
11
|
+
# @override
|
|
12
|
+
#: (Array[Offense?] offenses) -> String
|
|
14
13
|
def show_offenses(offenses)
|
|
15
14
|
return "No offenses detected" if offenses.empty?
|
|
16
15
|
|
|
@@ -20,7 +19,8 @@ module Packwerk
|
|
|
20
19
|
EOS
|
|
21
20
|
end
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
# @override
|
|
23
|
+
#: (OffenseCollection offense_collection, Set[String] file_set) -> String
|
|
24
24
|
def show_stale_violations(offense_collection, file_set)
|
|
25
25
|
if offense_collection.stale_violations?(file_set)
|
|
26
26
|
"There were stale violations found, please run `packwerk update-todo`"
|
|
@@ -29,12 +29,14 @@ module Packwerk
|
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
# @override
|
|
33
|
+
#: -> String
|
|
33
34
|
def identifier
|
|
34
35
|
IDENTIFIER
|
|
35
36
|
end
|
|
36
37
|
|
|
37
|
-
|
|
38
|
+
# @override
|
|
39
|
+
#: (Array[ReferenceOffense] strict_mode_violations) -> String
|
|
38
40
|
def show_strict_mode_violations(strict_mode_violations)
|
|
39
41
|
if strict_mode_violations.any?
|
|
40
42
|
strict_mode_violations.compact.map { |offense| format_strict_mode_violation(offense) }.join("\n")
|
|
@@ -45,12 +47,12 @@ module Packwerk
|
|
|
45
47
|
|
|
46
48
|
private
|
|
47
49
|
|
|
48
|
-
|
|
50
|
+
#: -> OutputStyle
|
|
49
51
|
def style
|
|
50
|
-
@style ||=
|
|
52
|
+
@style ||= Packwerk::OutputStyles::Coloured.new #: Packwerk::OutputStyles::Coloured?
|
|
51
53
|
end
|
|
52
54
|
|
|
53
|
-
|
|
55
|
+
#: (ReferenceOffense offense) -> String
|
|
54
56
|
def format_strict_mode_violation(offense)
|
|
55
57
|
reference_package = offense.reference.package
|
|
56
58
|
defining_package = offense.reference.constant.package
|
|
@@ -59,7 +61,7 @@ module Packwerk
|
|
|
59
61
|
"the enforcing package's package.yml"
|
|
60
62
|
end
|
|
61
63
|
|
|
62
|
-
|
|
64
|
+
#: (Array[Offense?] offenses) -> String
|
|
63
65
|
def offenses_list(offenses)
|
|
64
66
|
offenses
|
|
65
67
|
.compact
|
|
@@ -67,7 +69,7 @@ module Packwerk
|
|
|
67
69
|
.join("\n")
|
|
68
70
|
end
|
|
69
71
|
|
|
70
|
-
|
|
72
|
+
#: (Array[Offense?] offenses) -> String
|
|
71
73
|
def offenses_summary(offenses)
|
|
72
74
|
offenses_string = "offense".pluralize(offenses.length)
|
|
73
75
|
"#{offenses.length} #{offenses_string} detected"
|
|
@@ -6,15 +6,13 @@ require "benchmark"
|
|
|
6
6
|
module Packwerk
|
|
7
7
|
module Formatters
|
|
8
8
|
class ProgressFormatter
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
sig { params(out: T.any(StringIO, IO), style: OutputStyle).void }
|
|
9
|
+
#: ((StringIO | IO) out, ?style: OutputStyle) -> void
|
|
12
10
|
def initialize(out, style: OutputStyles::Plain.new)
|
|
13
11
|
@out = out
|
|
14
12
|
@style = style
|
|
15
13
|
end
|
|
16
14
|
|
|
17
|
-
|
|
15
|
+
#: { -> void } -> void
|
|
18
16
|
def started_validation(&block)
|
|
19
17
|
start_validation
|
|
20
18
|
|
|
@@ -22,7 +20,7 @@ module Packwerk
|
|
|
22
20
|
finished(execution_time)
|
|
23
21
|
end
|
|
24
22
|
|
|
25
|
-
|
|
23
|
+
#: (FilesForProcessing::relative_file_set target_files) { -> void } -> void
|
|
26
24
|
def started_inspection(target_files, &block)
|
|
27
25
|
start_inspection(target_files)
|
|
28
26
|
|
|
@@ -30,7 +28,7 @@ module Packwerk
|
|
|
30
28
|
finished(execution_time)
|
|
31
29
|
end
|
|
32
30
|
|
|
33
|
-
|
|
31
|
+
#: (?bool failed) -> void
|
|
34
32
|
def increment_progress(failed = false)
|
|
35
33
|
if failed
|
|
36
34
|
mark_as_failed
|
|
@@ -39,17 +37,17 @@ module Packwerk
|
|
|
39
37
|
end
|
|
40
38
|
end
|
|
41
39
|
|
|
42
|
-
|
|
40
|
+
#: -> void
|
|
43
41
|
def mark_as_inspected
|
|
44
42
|
@out.print(".")
|
|
45
43
|
end
|
|
46
44
|
|
|
47
|
-
|
|
45
|
+
#: -> void
|
|
48
46
|
def mark_as_failed
|
|
49
47
|
@out.print("#{@style.error}E#{@style.reset}")
|
|
50
48
|
end
|
|
51
49
|
|
|
52
|
-
|
|
50
|
+
#: -> void
|
|
53
51
|
def interrupted
|
|
54
52
|
@out.puts
|
|
55
53
|
@out.puts("Manually interrupted. Violations caught so far are listed below:")
|
|
@@ -58,19 +56,19 @@ module Packwerk
|
|
|
58
56
|
|
|
59
57
|
private
|
|
60
58
|
|
|
61
|
-
|
|
59
|
+
#: (Float execution_time) -> void
|
|
62
60
|
def finished(execution_time)
|
|
63
61
|
@out.puts
|
|
64
62
|
@out.puts("📦 Finished in #{execution_time.round(2)} seconds")
|
|
65
63
|
@out.puts
|
|
66
64
|
end
|
|
67
65
|
|
|
68
|
-
|
|
66
|
+
#: -> void
|
|
69
67
|
def start_validation
|
|
70
68
|
@out.puts("📦 Packwerk is running validation...")
|
|
71
69
|
end
|
|
72
70
|
|
|
73
|
-
|
|
71
|
+
#: (FilesForProcessing::relative_file_set target_files) -> void
|
|
74
72
|
def start_inspection(target_files)
|
|
75
73
|
files_size = target_files.size
|
|
76
74
|
files_string = "file".pluralize(files_size)
|
|
@@ -6,26 +6,22 @@ require "erb"
|
|
|
6
6
|
module Packwerk
|
|
7
7
|
module Generators
|
|
8
8
|
class ConfigurationFile
|
|
9
|
-
extend T::Sig
|
|
10
|
-
|
|
11
9
|
CONFIGURATION_TEMPLATE_FILE_PATH = "templates/packwerk.yml.erb"
|
|
12
10
|
|
|
13
11
|
class << self
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
sig { params(root: String, out: T.any(IO, StringIO)).returns(T::Boolean) }
|
|
12
|
+
#: (root: String, out: (IO | StringIO)) -> bool
|
|
17
13
|
def generate(root:, out:)
|
|
18
14
|
new(root: root, out: out).generate
|
|
19
15
|
end
|
|
20
16
|
end
|
|
21
17
|
|
|
22
|
-
|
|
18
|
+
#: (root: String, ?out: (StringIO | IO)) -> void
|
|
23
19
|
def initialize(root:, out: $stdout)
|
|
24
20
|
@root = root
|
|
25
21
|
@out = out
|
|
26
22
|
end
|
|
27
23
|
|
|
28
|
-
|
|
24
|
+
#: -> bool
|
|
29
25
|
def generate
|
|
30
26
|
@out.puts("📦 Generating Packwerk configuration file...")
|
|
31
27
|
default_config_path = File.join(@root, Configuration::DEFAULT_CONFIG_PATH)
|
|
@@ -43,12 +39,12 @@ module Packwerk
|
|
|
43
39
|
|
|
44
40
|
private
|
|
45
41
|
|
|
46
|
-
|
|
42
|
+
#: -> String
|
|
47
43
|
def render
|
|
48
44
|
ERB.new(template, trim_mode: "-").result(binding)
|
|
49
45
|
end
|
|
50
46
|
|
|
51
|
-
|
|
47
|
+
#: -> String
|
|
52
48
|
def template
|
|
53
49
|
template_file_path = File.join(__dir__, CONFIGURATION_TEMPLATE_FILE_PATH)
|
|
54
50
|
File.read(template_file_path)
|
|
@@ -4,24 +4,20 @@
|
|
|
4
4
|
module Packwerk
|
|
5
5
|
module Generators
|
|
6
6
|
class RootPackage
|
|
7
|
-
extend T::Sig
|
|
8
|
-
|
|
9
7
|
class << self
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
sig { params(root: String, out: T.any(IO, StringIO)).returns(T::Boolean) }
|
|
8
|
+
#: (root: String, out: (IO | StringIO)) -> bool
|
|
13
9
|
def generate(root:, out:)
|
|
14
10
|
new(root: root, out: out).generate
|
|
15
11
|
end
|
|
16
12
|
end
|
|
17
13
|
|
|
18
|
-
|
|
14
|
+
#: (root: String, ?out: (IO | StringIO)) -> void
|
|
19
15
|
def initialize(root:, out: $stdout)
|
|
20
16
|
@root = root
|
|
21
17
|
@out = out
|
|
22
18
|
end
|
|
23
19
|
|
|
24
|
-
|
|
20
|
+
#: -> bool
|
|
25
21
|
def generate
|
|
26
22
|
if Dir.glob("#{@root}/package.yml").any?
|
|
27
23
|
@out.puts("⚠️ Root package already exists.")
|
data/lib/packwerk/graph.rb
CHANGED
|
@@ -8,13 +8,7 @@ module Packwerk
|
|
|
8
8
|
class Graph
|
|
9
9
|
include TSort
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
sig do
|
|
13
|
-
params(
|
|
14
|
-
# The edges of the graph; represented as an Hash of Arrays.
|
|
15
|
-
edges: T::Hash[T.any(String, Integer, NilClass), T::Array[T.any(String, Integer, NilClass)]]
|
|
16
|
-
).void
|
|
17
|
-
end
|
|
11
|
+
#: (Hash[(String | Integer | NilClass), Array[(String | Integer | NilClass)]] edges) -> void
|
|
18
12
|
def initialize(edges)
|
|
19
13
|
@edges = edges
|
|
20
14
|
end
|
|
@@ -10,9 +10,7 @@ module Packwerk
|
|
|
10
10
|
class TypeError < ArgumentError; end
|
|
11
11
|
|
|
12
12
|
class << self
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
sig { params(class_or_module_node: AST::Node).returns(String) }
|
|
13
|
+
#: (AST::Node class_or_module_node) -> String
|
|
16
14
|
def class_or_module_name(class_or_module_node)
|
|
17
15
|
case type_of(class_or_module_node)
|
|
18
16
|
when CLASS, MODULE
|
|
@@ -27,7 +25,7 @@ module Packwerk
|
|
|
27
25
|
end
|
|
28
26
|
end
|
|
29
27
|
|
|
30
|
-
|
|
28
|
+
#: (AST::Node constant_node) -> String
|
|
31
29
|
def constant_name(constant_node)
|
|
32
30
|
case type_of(constant_node)
|
|
33
31
|
when CONSTANT_ROOT_NAMESPACE
|
|
@@ -59,12 +57,7 @@ module Packwerk
|
|
|
59
57
|
end
|
|
60
58
|
end
|
|
61
59
|
|
|
62
|
-
|
|
63
|
-
params(
|
|
64
|
-
node: AST::Node,
|
|
65
|
-
block: T.nilable(T.proc.params(arg0: Parser::AST::Node).void),
|
|
66
|
-
).returns(T::Enumerable[AST::Node])
|
|
67
|
-
end
|
|
60
|
+
#: (AST::Node node) ?{ (Parser::AST::Node arg0) -> void } -> Enumerable[AST::Node]
|
|
68
61
|
def each_child(node, &block)
|
|
69
62
|
if block
|
|
70
63
|
node.children.each do |child|
|
|
@@ -75,7 +68,7 @@ module Packwerk
|
|
|
75
68
|
end
|
|
76
69
|
end
|
|
77
70
|
|
|
78
|
-
|
|
71
|
+
#: (AST::Node starting_node, ancestors: Array[AST::Node]) -> Array[String]
|
|
79
72
|
def enclosing_namespace_path(starting_node, ancestors:)
|
|
80
73
|
ancestors.select { |n| [CLASS, MODULE].include?(type_of(n)) }
|
|
81
74
|
.each_with_object([]) do |node, namespace|
|
|
@@ -88,7 +81,7 @@ module Packwerk
|
|
|
88
81
|
end
|
|
89
82
|
end
|
|
90
83
|
|
|
91
|
-
|
|
84
|
+
#: (AST::Node string_or_symbol_node) -> (String | Symbol)
|
|
92
85
|
def literal_value(string_or_symbol_node)
|
|
93
86
|
case type_of(string_or_symbol_node)
|
|
94
87
|
when STRING, SYMBOL
|
|
@@ -102,48 +95,48 @@ module Packwerk
|
|
|
102
95
|
end
|
|
103
96
|
end
|
|
104
97
|
|
|
105
|
-
|
|
98
|
+
#: (Parser::AST::Node node) -> Node::Location
|
|
106
99
|
def location(node)
|
|
107
100
|
location = node.location
|
|
108
101
|
Node::Location.new(location.line, location.column)
|
|
109
102
|
end
|
|
110
103
|
|
|
111
|
-
|
|
104
|
+
#: (AST::Node node) -> bool
|
|
112
105
|
def constant?(node)
|
|
113
106
|
type_of(node) == CONSTANT
|
|
114
107
|
end
|
|
115
108
|
|
|
116
|
-
|
|
109
|
+
#: (AST::Node node) -> bool
|
|
117
110
|
def constant_assignment?(node)
|
|
118
111
|
type_of(node) == CONSTANT_ASSIGNMENT
|
|
119
112
|
end
|
|
120
113
|
|
|
121
|
-
|
|
114
|
+
#: (AST::Node node) -> bool
|
|
122
115
|
def class?(node)
|
|
123
116
|
type_of(node) == CLASS
|
|
124
117
|
end
|
|
125
118
|
|
|
126
|
-
|
|
119
|
+
#: (AST::Node node) -> bool
|
|
127
120
|
def method_call?(node)
|
|
128
121
|
type_of(node) == METHOD_CALL
|
|
129
122
|
end
|
|
130
123
|
|
|
131
|
-
|
|
124
|
+
#: (AST::Node node) -> bool
|
|
132
125
|
def hash?(node)
|
|
133
126
|
type_of(node) == HASH
|
|
134
127
|
end
|
|
135
128
|
|
|
136
|
-
|
|
129
|
+
#: (AST::Node node) -> bool
|
|
137
130
|
def string?(node)
|
|
138
131
|
type_of(node) == STRING
|
|
139
132
|
end
|
|
140
133
|
|
|
141
|
-
|
|
134
|
+
#: (AST::Node node) -> bool
|
|
142
135
|
def symbol?(node)
|
|
143
136
|
type_of(node) == SYMBOL
|
|
144
137
|
end
|
|
145
138
|
|
|
146
|
-
|
|
139
|
+
#: (AST::Node method_call_node) -> Array[AST::Node]
|
|
147
140
|
def method_arguments(method_call_node)
|
|
148
141
|
raise TypeError unless method_call?(method_call_node)
|
|
149
142
|
|
|
@@ -152,7 +145,7 @@ module Packwerk
|
|
|
152
145
|
method_call_node.children.slice(2..-1)
|
|
153
146
|
end
|
|
154
147
|
|
|
155
|
-
|
|
148
|
+
#: (AST::Node method_call_node) -> Symbol
|
|
156
149
|
def method_name(method_call_node)
|
|
157
150
|
raise TypeError unless method_call?(method_call_node)
|
|
158
151
|
|
|
@@ -161,7 +154,7 @@ module Packwerk
|
|
|
161
154
|
method_call_node.children[1]
|
|
162
155
|
end
|
|
163
156
|
|
|
164
|
-
|
|
157
|
+
#: (AST::Node node) -> String?
|
|
165
158
|
def module_name_from_definition(node)
|
|
166
159
|
case type_of(node)
|
|
167
160
|
when CLASS, MODULE
|
|
@@ -186,9 +179,10 @@ module Packwerk
|
|
|
186
179
|
end
|
|
187
180
|
end
|
|
188
181
|
|
|
189
|
-
|
|
182
|
+
#: (AST::Node node) -> Node::Location?
|
|
190
183
|
def name_location(node)
|
|
191
|
-
location =
|
|
184
|
+
location = node #: as Parser::AST::Node
|
|
185
|
+
.location
|
|
192
186
|
|
|
193
187
|
if location.respond_to?(:name)
|
|
194
188
|
name = location.name
|
|
@@ -196,7 +190,7 @@ module Packwerk
|
|
|
196
190
|
end
|
|
197
191
|
end
|
|
198
192
|
|
|
199
|
-
|
|
193
|
+
#: (AST::Node class_node) -> AST::Node?
|
|
200
194
|
def parent_class(class_node)
|
|
201
195
|
raise TypeError unless type_of(class_node) == CLASS
|
|
202
196
|
|
|
@@ -205,7 +199,7 @@ module Packwerk
|
|
|
205
199
|
class_node.children[1]
|
|
206
200
|
end
|
|
207
201
|
|
|
208
|
-
|
|
202
|
+
#: (ancestors: Array[AST::Node]) -> String
|
|
209
203
|
def parent_module_name(ancestors:)
|
|
210
204
|
definitions = ancestors
|
|
211
205
|
.select { |n| [CLASS, MODULE, CONSTANT_ASSIGNMENT, BLOCK].include?(type_of(n)) }
|
|
@@ -217,7 +211,7 @@ module Packwerk
|
|
|
217
211
|
names.empty? ? "Object" : names.reverse.join("::")
|
|
218
212
|
end
|
|
219
213
|
|
|
220
|
-
|
|
214
|
+
#: (AST::Node hash_node, Symbol key) -> untyped
|
|
221
215
|
def value_from_hash(hash_node, key)
|
|
222
216
|
raise TypeError unless hash?(hash_node)
|
|
223
217
|
|
|
@@ -245,12 +239,12 @@ module Packwerk
|
|
|
245
239
|
:MODULE, :SELF, :STRING, :SYMBOL,
|
|
246
240
|
)
|
|
247
241
|
|
|
248
|
-
|
|
242
|
+
#: (AST::Node node) -> Symbol
|
|
249
243
|
def type_of(node)
|
|
250
244
|
node.type
|
|
251
245
|
end
|
|
252
246
|
|
|
253
|
-
|
|
247
|
+
#: (AST::Node hash_pair_node) -> untyped
|
|
254
248
|
def hash_pair_key(hash_pair_node)
|
|
255
249
|
raise TypeError unless type_of(hash_pair_node) == HASH_PAIR
|
|
256
250
|
|
|
@@ -261,7 +255,7 @@ module Packwerk
|
|
|
261
255
|
hash_pair_node.children[0]
|
|
262
256
|
end
|
|
263
257
|
|
|
264
|
-
|
|
258
|
+
#: (AST::Node hash_pair_node) -> untyped
|
|
265
259
|
def hash_pair_value(hash_pair_node)
|
|
266
260
|
raise TypeError unless type_of(hash_pair_node) == HASH_PAIR
|
|
267
261
|
|
|
@@ -272,7 +266,7 @@ module Packwerk
|
|
|
272
266
|
hash_pair_node.children[1]
|
|
273
267
|
end
|
|
274
268
|
|
|
275
|
-
|
|
269
|
+
#: (AST::Node hash_node) -> Array[AST::Node]
|
|
276
270
|
def hash_pairs(hash_node)
|
|
277
271
|
raise TypeError unless hash?(hash_node)
|
|
278
272
|
|
|
@@ -281,7 +275,7 @@ module Packwerk
|
|
|
281
275
|
hash_node.children.select { |n| type_of(n) == HASH_PAIR }
|
|
282
276
|
end
|
|
283
277
|
|
|
284
|
-
|
|
278
|
+
#: (AST::Node block_node) -> AST::Node
|
|
285
279
|
def method_call_node(block_node)
|
|
286
280
|
raise TypeError unless type_of(block_node) == BLOCK
|
|
287
281
|
|
|
@@ -290,7 +284,7 @@ module Packwerk
|
|
|
290
284
|
block_node.children[0]
|
|
291
285
|
end
|
|
292
286
|
|
|
293
|
-
|
|
287
|
+
#: (AST::Node node) -> bool
|
|
294
288
|
def module_creation?(node)
|
|
295
289
|
# "Class.new"
|
|
296
290
|
# "Module.new"
|
|
@@ -299,14 +293,14 @@ module Packwerk
|
|
|
299
293
|
method_name(node) == :new
|
|
300
294
|
end
|
|
301
295
|
|
|
302
|
-
|
|
296
|
+
#: (AST::Node? node) -> bool
|
|
303
297
|
def dynamic_class_creation?(node)
|
|
304
298
|
!!node &&
|
|
305
299
|
constant?(node) &&
|
|
306
300
|
["Class", "Module"].include?(constant_name(node))
|
|
307
301
|
end
|
|
308
302
|
|
|
309
|
-
|
|
303
|
+
#: (AST::Node node) -> String?
|
|
310
304
|
def name_from_block_definition(node)
|
|
311
305
|
if method_name(method_call_node(node)) == :class_eval
|
|
312
306
|
receiver = receiver(node)
|
|
@@ -314,7 +308,7 @@ module Packwerk
|
|
|
314
308
|
end
|
|
315
309
|
end
|
|
316
310
|
|
|
317
|
-
|
|
311
|
+
#: (AST::Node node) -> String?
|
|
318
312
|
def name_part_from_definition(node)
|
|
319
313
|
case type_of(node)
|
|
320
314
|
when CLASS, MODULE, CONSTANT_ASSIGNMENT
|
|
@@ -324,7 +318,7 @@ module Packwerk
|
|
|
324
318
|
end
|
|
325
319
|
end
|
|
326
320
|
|
|
327
|
-
|
|
321
|
+
#: (AST::Node method_call_or_block_node) -> AST::Node?
|
|
328
322
|
def receiver(method_call_or_block_node)
|
|
329
323
|
case type_of(method_call_or_block_node)
|
|
330
324
|
when METHOD_CALL
|
|
@@ -4,25 +4,13 @@
|
|
|
4
4
|
module Packwerk
|
|
5
5
|
# Processes a single node in an abstract syntax tree (AST) using the provided checkers.
|
|
6
6
|
class NodeProcessor
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
sig do
|
|
10
|
-
params(
|
|
11
|
-
reference_extractor: ReferenceExtractor,
|
|
12
|
-
relative_file: String,
|
|
13
|
-
).void
|
|
14
|
-
end
|
|
7
|
+
#: (reference_extractor: ReferenceExtractor, relative_file: String) -> void
|
|
15
8
|
def initialize(reference_extractor:, relative_file:)
|
|
16
9
|
@reference_extractor = reference_extractor
|
|
17
10
|
@relative_file = relative_file
|
|
18
11
|
end
|
|
19
12
|
|
|
20
|
-
|
|
21
|
-
params(
|
|
22
|
-
node: Parser::AST::Node,
|
|
23
|
-
ancestors: T::Array[Parser::AST::Node]
|
|
24
|
-
).returns(T.nilable(UnresolvedReference))
|
|
25
|
-
end
|
|
13
|
+
#: (Parser::AST::Node node, Array[Parser::AST::Node] ancestors) -> UnresolvedReference?
|
|
26
14
|
def call(node, ancestors)
|
|
27
15
|
return unless NodeHelpers.method_call?(node) || NodeHelpers.constant?(node)
|
|
28
16
|
|
|
@@ -2,14 +2,20 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
module Packwerk
|
|
5
|
-
class NodeProcessorFactory
|
|
6
|
-
|
|
5
|
+
class NodeProcessorFactory
|
|
6
|
+
#: String
|
|
7
|
+
attr_reader :root_path
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const :constant_name_inspectors, T::Array[ConstantNameInspector]
|
|
9
|
+
#: Array[ConstantNameInspector]
|
|
10
|
+
attr_reader :constant_name_inspectors
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
#: (root_path: String, constant_name_inspectors: Array[ConstantNameInspector]) -> void
|
|
13
|
+
def initialize(root_path:, constant_name_inspectors:)
|
|
14
|
+
@root_path = root_path
|
|
15
|
+
@constant_name_inspectors = constant_name_inspectors
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
#: (relative_file: String, node: AST::Node) -> NodeProcessor
|
|
13
19
|
def for(relative_file:, node:)
|
|
14
20
|
NodeProcessor.new(
|
|
15
21
|
reference_extractor: reference_extractor(node: node),
|
|
@@ -19,7 +25,7 @@ module Packwerk
|
|
|
19
25
|
|
|
20
26
|
private
|
|
21
27
|
|
|
22
|
-
|
|
28
|
+
#: (node: AST::Node) -> ReferenceExtractor
|
|
23
29
|
def reference_extractor(node:)
|
|
24
30
|
ReferenceExtractor.new(
|
|
25
31
|
constant_name_inspectors: constant_name_inspectors,
|