Skip to content

Commit a15872d

Browse files
authored
Merge pull request #147 from Shopify/yuta/simplify-orchestration
Refactor - simplify orchestration layer - Extract checkers into its own namespace / module. - Decouple reference extraction from offence checks.
2 parents e4bf8fc + 93d1c28 commit a15872d

20 files changed

+300
-175
lines changed

lib/packwerk.rb

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,11 @@ module Packwerk
1212
autoload :ApplicationValidator
1313
autoload :AssociationInspector
1414
autoload :OffenseCollection
15-
autoload :Checker
1615
autoload :Cli
1716
autoload :Configuration
1817
autoload :ConstantDiscovery
1918
autoload :ConstantNameInspector
2019
autoload :ConstNodeInspector
21-
autoload :DependencyChecker
2220
autoload :DeprecatedReferences
2321
autoload :FileProcessor
2422
autoload :FilesForProcessing
@@ -36,7 +34,6 @@ module Packwerk
3634
autoload :ParsedConstantDefinitions
3735
autoload :Parsers
3836
autoload :ParseRun
39-
autoload :PrivacyChecker
4037
autoload :Reference
4138
autoload :ReferenceExtractor
4239
autoload :ReferenceOffense
@@ -77,4 +74,18 @@ module Generators
7774
autoload :InflectionsFile
7875
autoload :RootPackage
7976
end
77+
78+
module ReferenceChecking
79+
extend ActiveSupport::Autoload
80+
81+
autoload :ReferenceChecker
82+
83+
module Checkers
84+
extend ActiveSupport::Autoload
85+
86+
autoload :Checker
87+
autoload :DependencyChecker
88+
autoload :PrivacyChecker
89+
end
90+
end
8091
end

lib/packwerk/checker.rb

Lines changed: 0 additions & 17 deletions
This file was deleted.

lib/packwerk/dependency_checker.rb

Lines changed: 0 additions & 26 deletions
This file was deleted.

lib/packwerk/file_processor.rb

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
# typed: false
1+
# typed: true
22
# frozen_string_literal: true
33

44
require "ast/node"
55

66
module Packwerk
77
class FileProcessor
8+
extend T::Sig
9+
810
class UnknownFileTypeResult < Offense
911
def initialize(file:)
1012
super(file: file, message: "unknown file type")
@@ -16,24 +18,47 @@ def initialize(node_processor_factory:, parser_factory: nil)
1618
@parser_factory = parser_factory || Packwerk::Parsers::Factory.instance
1719
end
1820

21+
sig do
22+
params(file_path: String).returns(
23+
T::Array[
24+
T.any(
25+
Packwerk::Reference,
26+
Packwerk::Offense,
27+
)
28+
]
29+
)
30+
end
1931
def call(file_path)
20-
parser = @parser_factory.for_path(file_path)
21-
return [UnknownFileTypeResult.new(file: file_path)] if parser.nil?
32+
return [UnknownFileTypeResult.new(file: file_path)] if parser_for(file_path).nil?
2233

23-
node = File.open(file_path, "r", external_encoding: Encoding::UTF_8) do |file|
24-
parser.call(io: file, file_path: file_path)
25-
rescue Parsers::ParseError => e
26-
return [e.result]
27-
end
34+
node = parse_into_ast(file_path)
35+
return [] unless node
36+
37+
references_from_ast(node, file_path)
38+
rescue Parsers::ParseError => e
39+
[e.result]
40+
end
41+
42+
private
2843

29-
result = []
30-
if node
31-
node_processor = @node_processor_factory.for(filename: file_path, node: node)
32-
node_visitor = Packwerk::NodeVisitor.new(node_processor: node_processor)
44+
def references_from_ast(node, file_path)
45+
references = []
3346

34-
node_visitor.visit(node, ancestors: [], result: result)
47+
node_processor = @node_processor_factory.for(filename: file_path, node: node)
48+
node_visitor = Packwerk::NodeVisitor.new(node_processor: node_processor)
49+
node_visitor.visit(node, ancestors: [], result: references)
50+
51+
references
52+
end
53+
54+
def parse_into_ast(file_path)
55+
File.open(file_path, "r", nil, external_encoding: Encoding::UTF_8) do |file|
56+
parser_for(file_path).call(io: file, file_path: file_path)
3557
end
36-
result
58+
end
59+
60+
def parser_for(file_path)
61+
@parser_factory.for_path(file_path)
3762
end
3863
end
3964
end

lib/packwerk/node_processor.rb

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,35 +9,22 @@ class NodeProcessor
99
params(
1010
reference_extractor: ReferenceExtractor,
1111
filename: String,
12-
checkers: T::Array[Checker]
1312
).void
1413
end
15-
def initialize(reference_extractor:, filename:, checkers:)
14+
def initialize(reference_extractor:, filename:)
1615
@reference_extractor = reference_extractor
1716
@filename = filename
18-
@checkers = checkers
1917
end
2018

21-
sig { params(node: Parser::AST::Node, ancestors: T::Array[Parser::AST::Node]).returns(T::Array[Offense]) }
22-
def call(node, ancestors)
23-
return [] unless Node.method_call?(node) || Node.constant?(node)
24-
reference = @reference_extractor.reference_from_node(node, ancestors: ancestors, file_path: @filename)
25-
check_reference(reference, node)
19+
sig do
20+
params(
21+
node: Parser::AST::Node,
22+
ancestors: T::Array[Parser::AST::Node]
23+
).returns(T.nilable(Packwerk::Reference))
2624
end
27-
28-
private
29-
30-
def check_reference(reference, node)
31-
return [] unless reference
32-
@checkers.each_with_object([]) do |checker, violations|
33-
next unless checker.invalid_reference?(reference)
34-
offense = Packwerk::ReferenceOffense.new(
35-
location: Node.location(node),
36-
reference: reference,
37-
violation_type: checker.violation_type
38-
)
39-
violations << offense
40-
end
25+
def call(node, ancestors)
26+
return unless Node.method_call?(node) || Node.constant?(node)
27+
@reference_extractor.reference_from_node(node, ancestors: ancestors, file_path: @filename)
4128
end
4229
end
4330
end

lib/packwerk/node_processor_factory.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,12 @@ class NodeProcessorFactory < T::Struct
88
const :root_path, String
99
const :context_provider, Packwerk::ConstantDiscovery
1010
const :constant_name_inspectors, T::Array[ConstantNameInspector]
11-
const :checkers, T::Array[Checker]
1211

1312
sig { params(filename: String, node: AST::Node).returns(NodeProcessor) }
1413
def for(filename:, node:)
1514
::Packwerk::NodeProcessor.new(
1615
reference_extractor: reference_extractor(node: node),
1716
filename: filename,
18-
checkers: checkers,
1917
)
2018
end
2119

lib/packwerk/node_visitor.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ def initialize(node_processor:)
88
end
99

1010
def visit(node, ancestors:, result:)
11-
result.concat(@node_processor.call(node, ancestors))
11+
reference = @node_processor.call(node, ancestors)
12+
result << reference if reference
1213

1314
child_ancestors = [node] + ancestors
1415
Node.each_child(node) do |child|

lib/packwerk/privacy_checker.rb

Lines changed: 0 additions & 53 deletions
This file was deleted.

lib/packwerk/reference.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
# frozen_string_literal: true
33

44
module Packwerk
5-
Reference = Struct.new(:source_package, :relative_path, :constant)
5+
Reference = Struct.new(:source_package, :relative_path, :constant, :source_location)
66
end
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# typed: true
2+
# frozen_string_literal: true
3+
4+
module Packwerk
5+
module ReferenceChecking
6+
module Checkers
7+
module Checker
8+
extend T::Sig
9+
extend T::Helpers
10+
11+
interface!
12+
13+
sig { returns(ViolationType).abstract }
14+
def violation_type; end
15+
16+
sig { params(reference: Reference).returns(T::Boolean).abstract }
17+
def invalid_reference?(reference); end
18+
end
19+
end
20+
end
21+
end

0 commit comments

Comments
 (0)