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.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/exe/packwerk +0 -4
  3. data/lib/packwerk/application_validator.rb +11 -10
  4. data/lib/packwerk/association_inspector.rb +21 -32
  5. data/lib/packwerk/cache.rb +43 -36
  6. data/lib/packwerk/checker.rb +24 -26
  7. data/lib/packwerk/cli.rb +13 -20
  8. data/lib/packwerk/commands/base_command.rb +20 -26
  9. data/lib/packwerk/commands/check_command.rb +8 -8
  10. data/lib/packwerk/commands/help_command.rb +3 -4
  11. data/lib/packwerk/commands/init_command.rb +2 -3
  12. data/lib/packwerk/commands/lazy_loaded_entry.rb +5 -7
  13. data/lib/packwerk/commands/update_todo_command.rb +3 -3
  14. data/lib/packwerk/commands/uses_parse_run.rb +20 -26
  15. data/lib/packwerk/commands/validate_command.rb +6 -7
  16. data/lib/packwerk/commands/version_command.rb +2 -3
  17. data/lib/packwerk/commands.rb +5 -8
  18. data/lib/packwerk/configuration.rb +29 -43
  19. data/lib/packwerk/const_node_inspector.rb +5 -9
  20. data/lib/packwerk/constant_context.rb +0 -2
  21. data/lib/packwerk/constant_discovery.rb +3 -16
  22. data/lib/packwerk/constant_name_inspector.rb +4 -11
  23. data/lib/packwerk/extension_loader.rb +1 -2
  24. data/lib/packwerk/file_processor.rb +20 -25
  25. data/lib/packwerk/files_for_processing.rb +13 -29
  26. data/lib/packwerk/formatters/default_offenses_formatter.rb +14 -12
  27. data/lib/packwerk/formatters/progress_formatter.rb +10 -12
  28. data/lib/packwerk/generators/configuration_file.rb +5 -9
  29. data/lib/packwerk/generators/root_package.rb +3 -7
  30. data/lib/packwerk/graph.rb +1 -7
  31. data/lib/packwerk/node_helpers.rb +32 -38
  32. data/lib/packwerk/node_processor.rb +2 -14
  33. data/lib/packwerk/node_processor_factory.rb +13 -7
  34. data/lib/packwerk/node_visitor.rb +2 -10
  35. data/lib/packwerk/offense.rb +6 -12
  36. data/lib/packwerk/offense_collection.rb +22 -35
  37. data/lib/packwerk/offenses_formatter.rb +27 -34
  38. data/lib/packwerk/output_style.rb +10 -11
  39. data/lib/packwerk/output_styles/coloured.rb +6 -4
  40. data/lib/packwerk/output_styles/plain.rb +6 -4
  41. data/lib/packwerk/package.rb +15 -16
  42. data/lib/packwerk/package_set.rb +15 -25
  43. data/lib/packwerk/package_todo.rb +21 -30
  44. data/lib/packwerk/parse_run.rb +10 -37
  45. data/lib/packwerk/parsed_constant_definitions.rb +10 -24
  46. data/lib/packwerk/parsers/erb.rb +11 -22
  47. data/lib/packwerk/parsers/factory.rb +9 -9
  48. data/lib/packwerk/parsers/parser_interface.rb +5 -10
  49. data/lib/packwerk/parsers/ruby.rb +9 -14
  50. data/lib/packwerk/parsers.rb +2 -4
  51. data/lib/packwerk/rails_load_paths.rb +6 -11
  52. data/lib/packwerk/reference_checking/checkers/dependency_checker.rb +10 -15
  53. data/lib/packwerk/reference_checking/reference_checker.rb +2 -8
  54. data/lib/packwerk/reference_extractor.rb +22 -55
  55. data/lib/packwerk/reference_offense.rb +5 -15
  56. data/lib/packwerk/run_context.rb +28 -39
  57. data/lib/packwerk/spring_command.rb +4 -7
  58. data/lib/packwerk/validator/result.rb +12 -5
  59. data/lib/packwerk/validator.rb +23 -33
  60. data/lib/packwerk/validators/dependency_validator.rb +9 -10
  61. data/lib/packwerk/version.rb +1 -1
  62. data/lib/packwerk.rb +0 -1
  63. data/sorbet/config +2 -0
  64. data/sorbet/rbi/gems/prism@1.9.0.rbi +43359 -0
  65. data/sorbet/rbi/shims/packwerk/reference.rbi +5 -12
  66. data/sorbet/rbi/shims/packwerk/unresolved_reference.rbi +5 -12
  67. data/sorbet/rbi/shims/parser.rbi +1 -1
  68. metadata +18 -19
  69. data/lib/packwerk/disable_sorbet.rb +0 -41
  70. data/sorbet/rbi/gems/prism@0.27.0.rbi +0 -36983
@@ -5,28 +5,21 @@ require "yaml"
5
5
 
6
6
  module Packwerk
7
7
  class PackageTodo
8
- extend T::Sig
9
-
10
- PackageName = T.type_alias { String }
11
- ConstantName = T.type_alias { String }
12
- FilePath = T.type_alias { String }
13
- Entry = T.type_alias { T::Hash[ConstantName, T::Hash[ConstantName, T::Array[FilePath]]] }
14
- Entries = T.type_alias do
15
- T::Hash[PackageName, Entry]
16
- end
8
+ #: type package_name = String
9
+ #: type constant_name = String
10
+ #: type file_path = String
11
+ #: type entry = Hash[constant_name, Hash[constant_name, Array[file_path]]]
12
+ #: type entries = Hash[package_name, entry]
17
13
 
18
- sig { params(package: Packwerk::Package, path: String).void }
14
+ #: (Packwerk::Package package, String path) -> void
19
15
  def initialize(package, path)
20
16
  @package = package
21
17
  @path = path
22
- @new_entries = T.let({}, Entries)
23
- @old_entries = T.let(nil, T.nilable(Entries))
18
+ @new_entries = {} #: entries
19
+ @old_entries = nil #: entries?
24
20
  end
25
21
 
26
- sig do
27
- params(reference: Packwerk::Reference, violation_type: String)
28
- .returns(T::Boolean)
29
- end
22
+ #: (Packwerk::Reference reference, violation_type: String) -> bool
30
23
  def listed?(reference, violation_type:)
31
24
  violated_constants_found = old_entries.dig(reference.constant.package.name, reference.constant.name)
32
25
  return false unless violated_constants_found
@@ -37,9 +30,7 @@ module Packwerk
37
30
  violated_constants_found.fetch("violations", []).include?(violation_type)
38
31
  end
39
32
 
40
- sig do
41
- params(reference: Packwerk::Reference, violation_type: String).returns(T::Boolean)
42
- end
33
+ #: (Packwerk::Reference reference, String violation_type) -> bool
43
34
  def add_entries(reference, violation_type)
44
35
  package_violations = new_entries.fetch(reference.constant.package.name, {})
45
36
  entries_for_constant = package_violations[reference.constant.name] ||= {}
@@ -54,7 +45,7 @@ module Packwerk
54
45
  listed?(reference, violation_type: violation_type)
55
46
  end
56
47
 
57
- sig { params(for_files: T::Set[String]).returns(T::Boolean) }
48
+ #: (Set[String] for_files) -> bool
58
49
  def stale_violations?(for_files)
59
50
  prepare_entries_for_dump
60
51
 
@@ -71,7 +62,7 @@ module Packwerk
71
62
  end
72
63
  end
73
64
 
74
- sig { void }
65
+ #: -> void
75
66
  def dump
76
67
  if new_entries.empty?
77
68
  delete_if_exists
@@ -93,24 +84,24 @@ module Packwerk
93
84
  end
94
85
  end
95
86
 
96
- sig { void }
87
+ #: -> void
97
88
  def delete_if_exists
98
89
  File.delete(@path) if File.exist?(@path)
99
90
  end
100
91
 
101
92
  private
102
93
 
103
- sig { returns(Entries) }
94
+ #: entries
104
95
  attr_reader(:new_entries)
105
96
 
106
- sig { params(package: String).returns(T::Array[String]) }
97
+ #: (String package) -> Array[String]
107
98
  def deleted_files_for(package)
108
99
  old_files = old_entries.fetch(package, {}).values.flat_map { |violation| violation.fetch("files") }
109
100
  new_files = new_entries.fetch(package, {}).values.flat_map { |violation| violation.fetch("files") }
110
101
  old_files - new_files
111
102
  end
112
103
 
113
- sig { params(package: String, violations: Entry).returns(T::Boolean) }
104
+ #: (String package, violations: entry) -> bool
114
105
  def stale_violation_for_package?(package, violations:)
115
106
  violations.any? do |constant_name, entries_for_constant|
116
107
  new_entries_violation_types = new_entries.dig(package, constant_name, "violations")
@@ -129,10 +120,10 @@ module Packwerk
129
120
  end
130
121
  end
131
122
 
132
- sig { params(package_violations: Entry, files: T::Set[String]).returns(Entry) }
123
+ #: (entry package_violations, files: Set[String]) -> entry
133
124
  def package_violations_for(package_violations, files:)
134
125
  {}.tap do |package_violations_for_files|
135
- package_violations_for_files = T.cast(package_violations_for_files, Entry)
126
+ package_violations_for_files = package_violations_for_files #: as entry
136
127
 
137
128
  package_violations.each do |constant_name, entries_for_constant|
138
129
  entries_for_files = files & entries_for_constant.fetch("files")
@@ -146,7 +137,7 @@ module Packwerk
146
137
  end
147
138
  end
148
139
 
149
- sig { returns(Entries) }
140
+ #: -> entries
150
141
  def prepare_entries_for_dump
151
142
  new_entries.each do |package_name, package_violations|
152
143
  package_violations.each do |_, entries_for_constant|
@@ -159,12 +150,12 @@ module Packwerk
159
150
  @new_entries = new_entries.sort.to_h
160
151
  end
161
152
 
162
- sig { returns(Entries) }
153
+ #: -> entries
163
154
  def old_entries
164
155
  @old_entries ||= load_yaml_file(@path)
165
156
  end
166
157
 
167
- sig { params(path: String).returns(Entries) }
158
+ #: (String path) -> entries
168
159
  def load_yaml_file(path)
169
160
  File.exist?(path) && YAML.load_file(path) || {}
170
161
  rescue Psych::Exception
@@ -5,32 +5,15 @@ require "parallel"
5
5
 
6
6
  module Packwerk
7
7
  class ParseRun
8
- extend T::Sig
8
+ #: type process_file_proc = ^(String path) -> Array[Offense]
9
9
 
10
- ProcessFileProc = T.type_alias do
11
- T.proc.params(path: String).returns(T::Array[Offense])
12
- end
13
-
14
- sig do
15
- params(
16
- relative_file_set: FilesForProcessing::RelativeFileSet,
17
- parallel: T::Boolean,
18
- ).void
19
- end
10
+ #: (relative_file_set: FilesForProcessing::relative_file_set, parallel: bool) -> void
20
11
  def initialize(relative_file_set:, parallel:)
21
12
  @relative_file_set = relative_file_set
22
13
  @parallel = parallel
23
14
  end
24
15
 
25
- sig do
26
- params(
27
- run_context: RunContext,
28
- on_interrupt: T.nilable(T.proc.void),
29
- block: T.nilable(T.proc.params(
30
- offenses: T::Array[Packwerk::Offense],
31
- ).void)
32
- ).returns(T::Array[Offense])
33
- end
16
+ #: (RunContext run_context, ?on_interrupt: (^-> void)?) ?{ (Array[Packwerk::Offense] offenses) -> void } -> Array[Offense]
34
17
  def find_offenses(run_context, on_interrupt: nil, &block)
35
18
  process_file_proc = process_file_proc(run_context, &block)
36
19
 
@@ -45,32 +28,22 @@ module Packwerk
45
28
 
46
29
  private
47
30
 
48
- sig do
49
- params(
50
- run_context: RunContext,
51
- block: T.nilable(T.proc.params(offenses: T::Array[Offense]).void)
52
- ).returns(ProcessFileProc)
53
- end
31
+ #: (RunContext run_context) ?{ (Array[Offense] offenses) -> void } -> process_file_proc
54
32
  def process_file_proc(run_context, &block)
55
33
  if block
56
- T.let(proc do |relative_file|
34
+ proc do |relative_file|
57
35
  run_context.process_file(relative_file: relative_file).tap(&block)
58
- end, ProcessFileProc)
36
+ end #: process_file_proc
59
37
  else
60
- T.let(proc do |relative_file|
38
+ proc do |relative_file|
61
39
  run_context.process_file(relative_file: relative_file)
62
- end, ProcessFileProc)
40
+ end #: process_file_proc
63
41
  end
64
42
  end
65
43
 
66
- sig do
67
- params(
68
- on_interrupt: T.nilable(T.proc.void),
69
- block: ProcessFileProc
70
- ).returns(T::Array[Offense])
71
- end
44
+ #: (?on_interrupt: (^-> void)?) { (?) -> untyped } -> Array[Offense]
72
45
  def serial_find_offenses(on_interrupt: nil, &block)
73
- all_offenses = T.let([], T::Array[Offense])
46
+ all_offenses = [] #: Array[Offense]
74
47
  begin
75
48
  @relative_file_set.each do |relative_file|
76
49
  offenses = yield(relative_file)
@@ -6,13 +6,9 @@ require "ast/node"
6
6
  module Packwerk
7
7
  # A collection of constant definitions parsed from an Abstract Syntax Tree (AST).
8
8
  class ParsedConstantDefinitions
9
- extend T::Sig
10
-
11
9
  class << self
12
- extend T::Sig
13
-
14
10
  # What fully qualified constants can this constant refer to in this context?
15
- sig { params(constant_name: String, namespace_path: T::Array[T.nilable(String)]).returns(T::Array[String]) }
11
+ #: (String constant_name, namespace_path: Array[String?]) -> Array[String]
16
12
  def reference_qualifications(constant_name, namespace_path:)
17
13
  return [constant_name] if constant_name.start_with?("::")
18
14
 
@@ -26,20 +22,14 @@ module Packwerk
26
22
  end
27
23
  end
28
24
 
29
- sig { params(root_node: T.nilable(AST::Node)).void }
25
+ #: (root_node: AST::Node?) -> void
30
26
  def initialize(root_node:)
31
- @local_definitions = T.let({}, T::Hash[String, T.nilable(Node::Location)])
27
+ @local_definitions = {} #: Hash[String, Node::Location?]
32
28
 
33
29
  collect_local_definitions_from_root(root_node) if root_node
34
30
  end
35
31
 
36
- sig do
37
- params(
38
- constant_name: String,
39
- location: T.nilable(Node::Location),
40
- namespace_path: T::Array[String],
41
- ).returns(T::Boolean)
42
- end
32
+ #: (String constant_name, ?location: Node::Location?, ?namespace_path: Array[String]) -> bool
43
33
  def local_reference?(constant_name, location: nil, namespace_path: [])
44
34
  qualifications = self.class.reference_qualifications(constant_name, namespace_path: namespace_path)
45
35
 
@@ -51,14 +41,16 @@ module Packwerk
51
41
 
52
42
  private
53
43
 
54
- sig { params(node: AST::Node, current_namespace_path: T::Array[T.nilable(String)]).void }
44
+ #: (AST::Node node, ?Array[String?] current_namespace_path) -> void
55
45
  def collect_local_definitions_from_root(node, current_namespace_path = [])
56
46
  if NodeHelpers.constant_assignment?(node)
57
47
  add_definition(NodeHelpers.constant_name(node), current_namespace_path, NodeHelpers.name_location(node))
58
48
  elsif NodeHelpers.module_name_from_definition(node)
59
49
  # handle compact constant nesting (e.g. "module Sales::Order")
60
- tempnode = T.let(node, T.nilable(AST::Node))
61
- while (tempnode = NodeHelpers.each_child(T.must(tempnode)).find { |node| NodeHelpers.constant?(node) })
50
+ tempnode = node #: AST::Node?
51
+ while (tempnode = NodeHelpers.each_child(
52
+ tempnode #: as !nil
53
+ ).find { |node| NodeHelpers.constant?(node) })
62
54
  add_definition(NodeHelpers.constant_name(tempnode), current_namespace_path,
63
55
  NodeHelpers.name_location(tempnode))
64
56
  end
@@ -69,13 +61,7 @@ module Packwerk
69
61
  NodeHelpers.each_child(node) { |child| collect_local_definitions_from_root(child, current_namespace_path) }
70
62
  end
71
63
 
72
- sig do
73
- params(
74
- constant_name: String,
75
- current_namespace_path: T::Array[T.nilable(String)],
76
- location: T.nilable(Node::Location),
77
- ).void
78
- end
64
+ #: (String constant_name, Array[String?] current_namespace_path, Node::Location? location) -> void
79
65
  def add_definition(constant_name, current_namespace_path, location)
80
66
  resolved_constant = [""].concat(current_namespace_path).push(constant_name).join("::")
81
67
 
@@ -9,24 +9,23 @@ require "parser/source/buffer"
9
9
  module Packwerk
10
10
  module Parsers
11
11
  class Erb
12
- extend T::Sig
13
-
14
12
  include ParserInterface
15
13
 
16
- sig { params(parser_class: T.untyped, ruby_parser: Ruby).void }
14
+ #: (?parser_class: untyped, ?ruby_parser: Ruby) -> void
17
15
  def initialize(parser_class: BetterHtml::Parser, ruby_parser: Ruby.new)
18
- @parser_class = T.let(parser_class, T.class_of(BetterHtml::Parser))
16
+ @parser_class = parser_class #: singleton(BetterHtml::Parser)
19
17
  @ruby_parser = ruby_parser
20
18
  end
21
19
 
22
- sig { override.params(io: T.any(IO, StringIO), file_path: String).returns(T.untyped) }
20
+ # @override
21
+ #: (io: (IO | StringIO), ?file_path: String) -> untyped
23
22
  def call(io:, file_path: "<unknown>")
24
23
  buffer = Parser::Source::Buffer.new(file_path)
25
24
  buffer.source = io.read
26
25
  parse_buffer(buffer, file_path: file_path)
27
26
  end
28
27
 
29
- sig { params(buffer: Parser::Source::Buffer, file_path: String).returns(T.nilable(AST::Node)) }
28
+ #: (Parser::Source::Buffer buffer, file_path: String) -> AST::Node?
30
29
  def parse_buffer(buffer, file_path:)
31
30
  parser = @parser_class.new(buffer, template_language: :html)
32
31
  to_ruby_ast(parser.ast, file_path)
@@ -40,18 +39,15 @@ module Packwerk
40
39
 
41
40
  private
42
41
 
43
- sig do
44
- params(
45
- erb_ast: T.all(::AST::Node, Object),
46
- file_path: String
47
- ).returns(T.nilable(::AST::Node))
48
- end
42
+ #: ((::AST::Node & Object) erb_ast, String file_path) -> ::AST::Node?
49
43
  def to_ruby_ast(erb_ast, file_path)
50
44
  # Note that we're not using the source location (line/column) at the moment, but if we did
51
45
  # care about that, we'd need to tweak this to insert empty lines and spaces so that things
52
46
  # line up with the ERB file
53
- code_pieces = T.must(code_nodes(erb_ast)).map do |node|
54
- T.cast(node, ::AST::Node).children.first
47
+ nodes = code_nodes(erb_ast) #: as !nil
48
+ code_pieces = nodes.map do |node|
49
+ node #: as ::AST::Node
50
+ .children.first
55
51
  end
56
52
 
57
53
  @ruby_parser.call(
@@ -60,14 +56,7 @@ module Packwerk
60
56
  )
61
57
  end
62
58
 
63
- sig do
64
- params(
65
- node: T.any(::AST::Node, String, NilClass),
66
- block: T.nilable(T.proc.params(arg0: ::AST::Node).void),
67
- ).returns(
68
- T.any(T::Enumerator[::AST::Node], T::Array[String], NilClass)
69
- )
70
- end
59
+ #: ((::AST::Node | String)? node) ?{ (::AST::Node arg0) -> void } -> (Enumerator[::AST::Node] | Array[String])?
71
60
  def code_nodes(node, &block)
72
61
  return enum_for(:code_nodes, node) unless block
73
62
  return unless node.is_a?(::AST::Node)
@@ -6,7 +6,6 @@ require "singleton"
6
6
  module Packwerk
7
7
  module Parsers
8
8
  class Factory
9
- extend T::Sig
10
9
  include Singleton
11
10
 
12
11
  RUBY_REGEX = %r{
@@ -20,29 +19,30 @@ module Packwerk
20
19
  ERB_REGEX = /\.erb\Z/
21
20
  private_constant :ERB_REGEX
22
21
 
23
- sig { void }
22
+ #: -> void
24
23
  def initialize
25
- @ruby_parser = T.let(nil, T.nilable(ParserInterface))
26
- @erb_parser = T.let(nil, T.nilable(ParserInterface))
27
- @erb_parser_class = T.let(nil, T.nilable(T::Class[T.anything]))
24
+ @ruby_parser = nil #: ParserInterface?
25
+ @erb_parser = nil #: ParserInterface?
26
+ @erb_parser_class = nil #: Class[top]?
28
27
  end
29
28
 
30
- sig { params(path: String).returns(T.nilable(ParserInterface)) }
29
+ #: (String path) -> ParserInterface?
31
30
  def for_path(path)
32
31
  case path
33
32
  when RUBY_REGEX
34
33
  @ruby_parser ||= Ruby.new
35
34
  when ERB_REGEX
36
- @erb_parser ||= T.unsafe(erb_parser_class).new
35
+ erb_parser_class_ = erb_parser_class #: as untyped
36
+ @erb_parser ||= erb_parser_class_.new
37
37
  end
38
38
  end
39
39
 
40
- sig { returns(T::Class[T.anything]) }
40
+ #: -> Class[top]
41
41
  def erb_parser_class
42
42
  @erb_parser_class ||= Erb
43
43
  end
44
44
 
45
- sig { params(klass: T.nilable(T::Class[T.anything])).void }
45
+ #: (Class[top]? klass) -> void
46
46
  def erb_parser_class=(klass)
47
47
  @erb_parser_class = klass
48
48
  @erb_parser = nil
@@ -3,17 +3,12 @@
3
3
 
4
4
  module Packwerk
5
5
  module Parsers
6
+ # @requires_ancestor: Kernel
7
+ # @interface
6
8
  module ParserInterface
7
- extend T::Helpers
8
- extend T::Sig
9
-
10
- requires_ancestor { Kernel }
11
-
12
- interface!
13
-
14
- sig { abstract.params(io: T.any(IO, StringIO), file_path: String).returns(T.untyped) }
15
- def call(io:, file_path:)
16
- end
9
+ # @abstract
10
+ #: (io: (IO | StringIO), file_path: String) -> untyped
11
+ def call(io:, file_path:) = raise NotImplementedError, "Abstract method called"
17
12
  end
18
13
  end
19
14
  end
@@ -7,14 +7,10 @@ require "prism"
7
7
  module Packwerk
8
8
  module Parsers
9
9
  class Ruby
10
- extend T::Sig
11
-
12
10
  include ParserInterface
13
11
 
14
12
  class RaiseExceptionsParser < Prism::Translation::Parser
15
- extend T::Sig
16
-
17
- sig { params(builder: T.untyped).void }
13
+ #: (untyped builder) -> void
18
14
  def initialize(builder)
19
15
  super(builder)
20
16
  super.diagnostics.all_errors_are_fatal = true
@@ -22,28 +18,27 @@ module Packwerk
22
18
 
23
19
  private
24
20
 
25
- sig { params(error: Prism::ParseError).returns(T::Boolean) }
21
+ #: (Prism::ParseError error) -> bool
26
22
  def valid_error?(error)
27
23
  error.type != :invalid_yield
28
24
  end
29
25
  end
30
26
 
31
- class TolerateInvalidUtf8Builder < Parser::Builders::Default
32
- extend T::Sig
33
-
34
- sig { params(token: T.untyped).returns(T.untyped) }
27
+ class TolerateInvalidUtf8Builder < Prism::Translation::Parser::Builder
28
+ #: (untyped token) -> untyped
35
29
  def string_value(token)
36
30
  value(token)
37
31
  end
38
32
  end
39
33
 
40
- sig { params(parser_class: T.untyped).void }
34
+ #: (?parser_class: untyped) -> void
41
35
  def initialize(parser_class: RaiseExceptionsParser)
42
- @builder = T.let(TolerateInvalidUtf8Builder.new, Object)
43
- @parser_class = T.let(parser_class, T.class_of(RaiseExceptionsParser))
36
+ @builder = TolerateInvalidUtf8Builder.new #: Object
37
+ @parser_class = parser_class #: singleton(RaiseExceptionsParser)
44
38
  end
45
39
 
46
- sig { override.params(io: T.any(IO, StringIO), file_path: String).returns(T.nilable(Parser::AST::Node)) }
40
+ # @override
41
+ #: (io: (IO | StringIO), ?file_path: String) -> Parser::AST::Node?
47
42
  def call(io:, file_path: "<unknown>")
48
43
  buffer = Parser::Source::Buffer.new(file_path)
49
44
  buffer.source = io.read
@@ -11,12 +11,10 @@ module Packwerk
11
11
  class ParseResult < Offense; end
12
12
 
13
13
  class ParseError < StandardError
14
- extend T::Sig
15
-
16
- sig { returns(ParseResult) }
14
+ #: ParseResult
17
15
  attr_reader(:result)
18
16
 
19
- sig { params(result: ParseResult).void }
17
+ #: (ParseResult result) -> void
20
18
  def initialize(result)
21
19
  super(result.message)
22
20
  @result = result
@@ -9,9 +9,7 @@ module Packwerk
9
9
  # Extracts the load paths from the analyzed application so that we can map constant names to paths.
10
10
  module RailsLoadPaths
11
11
  class << self
12
- extend T::Sig
13
-
14
- sig { params(root: String, environment: String).returns(T::Hash[String, Module]) }
12
+ #: (String root, environment: String) -> Hash[String, Module[top]]
15
13
  def for(root, environment:)
16
14
  require_application(root, environment)
17
15
  all_paths = extract_application_autoload_paths
@@ -22,17 +20,14 @@ module Packwerk
22
20
 
23
21
  private
24
22
 
25
- sig { returns(T::Hash[String, Module]) }
23
+ #: -> Hash[String, Module[top]]
26
24
  def extract_application_autoload_paths
27
25
  Rails.autoloaders.inject({}) do |h, loader|
28
26
  h.merge(loader.dirs(namespaces: true))
29
27
  end
30
28
  end
31
29
 
32
- sig do
33
- params(all_paths: T::Hash[String, Module], bundle_path: Pathname, rails_root: Pathname)
34
- .returns(T::Hash[Pathname, Module])
35
- end
30
+ #: (Hash[String, Module[top]] all_paths, ?bundle_path: Pathname, ?rails_root: Pathname) -> Hash[Pathname, Module[top]]
36
31
  def filter_relevant_paths(all_paths, bundle_path: Bundler.bundle_path, rails_root: Rails.root)
37
32
  bundle_path_match = bundle_path.join("**")
38
33
  rails_root_match = rails_root.join("**")
@@ -43,12 +38,12 @@ module Packwerk
43
38
  .reject { |path| path.fnmatch(bundle_path_match.to_s) } # reject paths from vendored gems
44
39
  end
45
40
 
46
- sig { params(load_paths: T::Hash[Pathname, Module], rails_root: Pathname).returns(T::Hash[String, Module]) }
41
+ #: (Hash[Pathname, Module[top]] load_paths, ?rails_root: Pathname) -> Hash[String, Module[top]]
47
42
  def relative_path_strings(load_paths, rails_root: Rails.root)
48
43
  load_paths.transform_keys { |path| Pathname.new(path).relative_path_from(rails_root).to_s }
49
44
  end
50
45
 
51
- sig { params(root: String, environment: String).void }
46
+ #: (String root, String environment) -> void
52
47
  def require_application(root, environment)
53
48
  environment_file = "#{root}/config/environment"
54
49
 
@@ -61,7 +56,7 @@ module Packwerk
61
56
  end
62
57
  end
63
58
 
64
- sig { params(paths: T::Hash[T.untyped, Module]).void }
59
+ #: (Hash[untyped, Module[top]] paths) -> void
65
60
  def assert_load_paths_present(paths)
66
61
  if paths.empty?
67
62
  raise <<~EOS
@@ -6,21 +6,18 @@ module Packwerk
6
6
  module Checkers
7
7
  # Checks whether a given reference conforms to the configured graph of dependencies.
8
8
  class DependencyChecker
9
- extend T::Sig
10
9
  include Checker
11
10
 
12
- VIOLATION_TYPE = T.let("dependency", String)
11
+ VIOLATION_TYPE = "dependency" #: String
13
12
 
14
- sig { override.returns(String) }
13
+ # @override
14
+ #: -> String
15
15
  def violation_type
16
16
  VIOLATION_TYPE
17
17
  end
18
18
 
19
- sig do
20
- override
21
- .params(reference: Packwerk::Reference)
22
- .returns(T::Boolean)
23
- end
19
+ # @override
20
+ #: (Packwerk::Reference reference) -> bool
24
21
  def invalid_reference?(reference)
25
22
  return false unless reference.package.enforce_dependencies?
26
23
  return false if reference.package.dependency?(reference.constant.package)
@@ -28,11 +25,8 @@ module Packwerk
28
25
  true
29
26
  end
30
27
 
31
- sig do
32
- override
33
- .params(reference: Packwerk::Reference)
34
- .returns(String)
35
- end
28
+ # @override
29
+ #: (Packwerk::Reference reference) -> String
36
30
  def message(reference)
37
31
  const_name = reference.constant.name
38
32
  const_package = reference.constant.package
@@ -46,7 +40,8 @@ module Packwerk
46
40
  EOS
47
41
  end
48
42
 
49
- sig { override.params(offense: ReferenceOffense).returns(T::Boolean) }
43
+ # @override
44
+ #: (ReferenceOffense offense) -> bool
50
45
  def strict_mode_violation?(offense)
51
46
  referencing_package = offense.reference.package
52
47
  referencing_package.config["enforce_dependencies"] == "strict"
@@ -54,7 +49,7 @@ module Packwerk
54
49
 
55
50
  private
56
51
 
57
- sig { params(reference: Reference).returns(String) }
52
+ #: (Reference reference) -> String
58
53
  def standard_help_message(reference)
59
54
  standard_message = <<~EOS
60
55
  Inference details: this is a reference to #{reference.constant.name} which seems to be defined in #{reference.constant.location}.
@@ -4,18 +4,12 @@
4
4
  module Packwerk
5
5
  module ReferenceChecking
6
6
  class ReferenceChecker
7
- extend T::Sig
8
-
9
- sig { params(checkers: T::Array[Checker]).void }
7
+ #: (Array[Checker] checkers) -> void
10
8
  def initialize(checkers)
11
9
  @checkers = checkers
12
10
  end
13
11
 
14
- sig do
15
- params(
16
- reference: Reference
17
- ).returns(T::Array[Packwerk::Offense])
18
- end
12
+ #: (Reference reference) -> Array[Packwerk::Offense]
19
13
  def call(reference)
20
14
  @checkers.each_with_object([]) do |checker, violations|
21
15
  next unless checker.invalid_reference?(reference)