packwerk 1.1.3 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +6 -5
- data/USAGE.md +17 -16
- data/lib/packwerk.rb +72 -36
- data/lib/packwerk/application_validator.rb +0 -5
- data/lib/packwerk/association_inspector.rb +0 -3
- data/lib/packwerk/checker.rb +2 -8
- data/lib/packwerk/cli.rb +22 -77
- data/lib/packwerk/configuration.rb +5 -0
- data/lib/packwerk/const_node_inspector.rb +0 -2
- data/lib/packwerk/constant_discovery.rb +2 -0
- data/lib/packwerk/constant_name_inspector.rb +0 -1
- data/lib/packwerk/dependency_checker.rb +2 -15
- data/lib/packwerk/deprecated_references.rb +3 -9
- data/lib/packwerk/file_processor.rb +0 -4
- data/lib/packwerk/formatters/offenses_formatter.rb +3 -8
- data/lib/packwerk/formatters/progress_formatter.rb +5 -4
- data/lib/packwerk/generators/configuration_file.rb +0 -1
- data/lib/packwerk/inflector.rb +0 -2
- data/lib/packwerk/node.rb +1 -0
- data/lib/packwerk/node_processor.rb +14 -32
- data/lib/packwerk/node_processor_factory.rb +0 -5
- data/lib/packwerk/node_visitor.rb +1 -4
- data/lib/packwerk/offense.rb +0 -4
- data/lib/packwerk/offense_collection.rb +84 -0
- data/lib/packwerk/offenses_formatter.rb +15 -0
- data/lib/packwerk/package.rb +8 -0
- data/lib/packwerk/package_set.rb +0 -2
- data/lib/packwerk/parse_run.rb +104 -0
- data/lib/packwerk/parsed_constant_definitions.rb +0 -2
- data/lib/packwerk/parsers.rb +0 -2
- data/lib/packwerk/parsers/erb.rb +0 -2
- data/lib/packwerk/parsers/factory.rb +0 -2
- data/lib/packwerk/privacy_checker.rb +2 -15
- data/lib/packwerk/reference_extractor.rb +0 -8
- data/lib/packwerk/reference_offense.rb +49 -0
- data/lib/packwerk/result.rb +9 -0
- data/lib/packwerk/run_context.rb +4 -21
- data/lib/packwerk/sanity_checker.rb +0 -2
- data/lib/packwerk/version.rb +1 -1
- data/lib/packwerk/violation_type.rb +0 -2
- data/packwerk.gemspec +1 -0
- data/service.yml +1 -4
- data/sorbet/rbi/gems/parallel@1.20.1.rbi +111 -2
- data/sorbet/tapioca/require.rb +1 -0
- metadata +22 -12
- data/lib/packwerk/cache_deprecated_references.rb +0 -55
- data/lib/packwerk/checking_deprecated_references.rb +0 -43
- data/lib/packwerk/commands/detect_stale_violations_command.rb +0 -60
- data/lib/packwerk/commands/offense_progress_marker.rb +0 -24
- data/lib/packwerk/commands/result.rb +0 -13
- data/lib/packwerk/commands/update_deprecations_command.rb +0 -81
- data/lib/packwerk/detect_stale_deprecated_references.rb +0 -14
- data/lib/packwerk/reference_lister.rb +0 -23
- data/lib/packwerk/updating_deprecated_references.rb +0 -14
@@ -0,0 +1,104 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "benchmark"
|
5
|
+
require "parallel"
|
6
|
+
|
7
|
+
module Packwerk
|
8
|
+
class ParseRun
|
9
|
+
extend T::Sig
|
10
|
+
|
11
|
+
def initialize(
|
12
|
+
files:,
|
13
|
+
configuration:,
|
14
|
+
progress_formatter: Formatters::ProgressFormatter.new(StringIO.new),
|
15
|
+
offenses_formatter: Formatters::OffensesFormatter.new
|
16
|
+
)
|
17
|
+
@configuration = configuration
|
18
|
+
@progress_formatter = progress_formatter
|
19
|
+
@offenses_formatter = offenses_formatter
|
20
|
+
@files = files
|
21
|
+
end
|
22
|
+
|
23
|
+
def detect_stale_violations
|
24
|
+
offense_collection = find_offenses
|
25
|
+
|
26
|
+
result_status = !offense_collection.stale_violations?
|
27
|
+
message = if result_status
|
28
|
+
"No stale violations detected"
|
29
|
+
else
|
30
|
+
"There were stale violations found, please run `packwerk update-deprecations`"
|
31
|
+
end
|
32
|
+
|
33
|
+
Result.new(message: message, status: result_status)
|
34
|
+
end
|
35
|
+
|
36
|
+
def update_deprecations
|
37
|
+
offense_collection = find_offenses
|
38
|
+
offense_collection.dump_deprecated_references_files
|
39
|
+
|
40
|
+
message = <<~EOS
|
41
|
+
#{@offenses_formatter.show_offenses(offense_collection.errors)}
|
42
|
+
✅ `deprecated_references.yml` has been updated.
|
43
|
+
EOS
|
44
|
+
|
45
|
+
Result.new(message: message, status: offense_collection.errors.empty?)
|
46
|
+
end
|
47
|
+
|
48
|
+
def check
|
49
|
+
offense_collection = find_offenses(show_errors: true)
|
50
|
+
message = @offenses_formatter.show_offenses(offense_collection.outstanding_offenses)
|
51
|
+
Result.new(message: message, status: offense_collection.outstanding_offenses.empty?)
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def find_offenses(show_errors: false)
|
57
|
+
offense_collection = OffenseCollection.new(@configuration.root_path)
|
58
|
+
@progress_formatter.started(@files)
|
59
|
+
|
60
|
+
run_context = Packwerk::RunContext.from_configuration(@configuration)
|
61
|
+
all_offenses = T.let([], T.untyped)
|
62
|
+
|
63
|
+
process_file = -> (path) do
|
64
|
+
run_context.process_file(file: path).tap do |offenses|
|
65
|
+
failed = show_errors && offenses.any? { |offense| !offense_collection.listed?(offense) }
|
66
|
+
update_progress(failed: failed)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
execution_time = Benchmark.realtime do
|
71
|
+
all_offenses = if @configuration.parallel?
|
72
|
+
Parallel.flat_map(@files, &process_file)
|
73
|
+
else
|
74
|
+
serial_find_offenses(&process_file)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
@progress_formatter.finished(execution_time)
|
79
|
+
|
80
|
+
all_offenses.each { |offense| offense_collection.add_offense(offense) }
|
81
|
+
offense_collection
|
82
|
+
end
|
83
|
+
|
84
|
+
def serial_find_offenses
|
85
|
+
all_offenses = T.let([], T.untyped)
|
86
|
+
@files.each do |path|
|
87
|
+
offenses = yield path
|
88
|
+
all_offenses.concat(offenses)
|
89
|
+
end
|
90
|
+
all_offenses
|
91
|
+
rescue Interrupt
|
92
|
+
@progress_formatter.interrupted
|
93
|
+
all_offenses
|
94
|
+
end
|
95
|
+
|
96
|
+
def update_progress(failed: false)
|
97
|
+
if failed
|
98
|
+
@progress_formatter.mark_as_failed
|
99
|
+
else
|
100
|
+
@progress_formatter.mark_as_inspected
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
data/lib/packwerk/parsers.rb
CHANGED
data/lib/packwerk/parsers/erb.rb
CHANGED
@@ -1,9 +1,6 @@
|
|
1
1
|
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require "packwerk/violation_type"
|
5
|
-
require "packwerk/checker"
|
6
|
-
|
7
4
|
module Packwerk
|
8
5
|
class PrivacyChecker
|
9
6
|
extend T::Sig
|
@@ -16,10 +13,10 @@ module Packwerk
|
|
16
13
|
|
17
14
|
sig do
|
18
15
|
override
|
19
|
-
.params(reference: Packwerk::Reference
|
16
|
+
.params(reference: Packwerk::Reference)
|
20
17
|
.returns(T::Boolean)
|
21
18
|
end
|
22
|
-
def invalid_reference?(reference
|
19
|
+
def invalid_reference?(reference)
|
23
20
|
return false if reference.constant.public?
|
24
21
|
|
25
22
|
privacy_option = reference.constant.package.enforce_privacy
|
@@ -28,19 +25,9 @@ module Packwerk
|
|
28
25
|
return false unless privacy_option == true ||
|
29
26
|
explicitly_private_constant?(reference.constant, explicitly_private_constants: privacy_option)
|
30
27
|
|
31
|
-
return false if reference_lister.listed?(reference, violation_type: violation_type)
|
32
|
-
|
33
28
|
true
|
34
29
|
end
|
35
30
|
|
36
|
-
sig { override.params(reference: Packwerk::Reference).returns(String) }
|
37
|
-
def message_for(reference)
|
38
|
-
source_desc = reference.source_package ? "'#{reference.source_package}'" : "here"
|
39
|
-
"Privacy violation: '#{reference.constant.name}' is private to '#{reference.constant.package}' but " \
|
40
|
-
"referenced from #{source_desc}.\n" \
|
41
|
-
"Is there a public entrypoint in '#{reference.constant.package.public_path}' that you can use instead?"
|
42
|
-
end
|
43
|
-
|
44
31
|
private
|
45
32
|
|
46
33
|
sig do
|
@@ -1,14 +1,6 @@
|
|
1
1
|
# typed: true
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require "sorbet-runtime"
|
5
|
-
|
6
|
-
require "packwerk/constant_discovery"
|
7
|
-
require "packwerk/constant_name_inspector"
|
8
|
-
require "packwerk/node"
|
9
|
-
require "packwerk/parsed_constant_definitions"
|
10
|
-
require "packwerk/reference"
|
11
|
-
|
12
4
|
module Packwerk
|
13
5
|
# extracts a possible constant reference from a given AST node
|
14
6
|
class ReferenceExtractor
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Packwerk
|
5
|
+
class ReferenceOffense < Offense
|
6
|
+
extend T::Sig
|
7
|
+
extend T::Helpers
|
8
|
+
|
9
|
+
attr_reader :reference, :violation_type
|
10
|
+
|
11
|
+
sig do
|
12
|
+
params(
|
13
|
+
reference: Packwerk::Reference,
|
14
|
+
violation_type: Packwerk::ViolationType,
|
15
|
+
location: T.nilable(Node::Location)
|
16
|
+
)
|
17
|
+
.void
|
18
|
+
end
|
19
|
+
def initialize(reference:, violation_type:, location: nil)
|
20
|
+
super(file: reference.relative_path, message: build_message(reference, violation_type), location: location)
|
21
|
+
@reference = reference
|
22
|
+
@violation_type = violation_type
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def build_message(reference, violation_type)
|
28
|
+
violation_message = case violation_type
|
29
|
+
when ViolationType::Privacy
|
30
|
+
source_desc = reference.source_package ? "'#{reference.source_package}'" : "here"
|
31
|
+
"Privacy violation: '#{reference.constant.name}' is private to '#{reference.constant.package}' but " \
|
32
|
+
"referenced from #{source_desc}.\n" \
|
33
|
+
"Is there a public entrypoint in '#{reference.constant.package.public_path}' that you can use instead?"
|
34
|
+
when ViolationType::Dependency
|
35
|
+
"Dependency violation: #{reference.constant.name} belongs to '#{reference.constant.package}', but " \
|
36
|
+
"'#{reference.source_package}' does not specify a dependency on " \
|
37
|
+
"'#{reference.constant.package}'.\n" \
|
38
|
+
"Are we missing an abstraction?\n" \
|
39
|
+
"Is the code making the reference, and the referenced constant, in the right packages?\n"
|
40
|
+
end
|
41
|
+
|
42
|
+
<<~EOS
|
43
|
+
#{violation_message}
|
44
|
+
Inference details: this is a reference to #{reference.constant.name} which seems to be defined in #{reference.constant.location}.
|
45
|
+
To receive help interpreting or resolving this error message, see: https://github.com/Shopify/packwerk/blob/main/TROUBLESHOOT.md#Troubleshooting-violations
|
46
|
+
EOS
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/packwerk/run_context.rb
CHANGED
@@ -3,17 +3,6 @@
|
|
3
3
|
|
4
4
|
require "constant_resolver"
|
5
5
|
|
6
|
-
require "packwerk/association_inspector"
|
7
|
-
require "packwerk/constant_discovery"
|
8
|
-
require "packwerk/const_node_inspector"
|
9
|
-
require "packwerk/dependency_checker"
|
10
|
-
require "packwerk/file_processor"
|
11
|
-
require "packwerk/inflector"
|
12
|
-
require "packwerk/package_set"
|
13
|
-
require "packwerk/privacy_checker"
|
14
|
-
require "packwerk/reference_extractor"
|
15
|
-
require "packwerk/node_processor_factory"
|
16
|
-
|
17
6
|
module Packwerk
|
18
7
|
class RunContext
|
19
8
|
extend T::Sig
|
@@ -27,23 +16,20 @@ module Packwerk
|
|
27
16
|
:checker_classes,
|
28
17
|
)
|
29
18
|
|
30
|
-
attr_accessor :reference_lister
|
31
|
-
|
32
19
|
DEFAULT_CHECKERS = [
|
33
20
|
::Packwerk::DependencyChecker,
|
34
21
|
::Packwerk::PrivacyChecker,
|
35
22
|
]
|
36
23
|
|
37
24
|
class << self
|
38
|
-
def from_configuration(configuration
|
25
|
+
def from_configuration(configuration)
|
39
26
|
inflector = ::Packwerk::Inflector.from_file(configuration.inflections_file)
|
40
27
|
new(
|
41
28
|
root_path: configuration.root_path,
|
42
29
|
load_paths: configuration.load_paths,
|
43
30
|
package_paths: configuration.package_paths,
|
44
31
|
inflector: inflector,
|
45
|
-
custom_associations: configuration.custom_associations
|
46
|
-
reference_lister: reference_lister,
|
32
|
+
custom_associations: configuration.custom_associations
|
47
33
|
)
|
48
34
|
end
|
49
35
|
end
|
@@ -54,8 +40,7 @@ module Packwerk
|
|
54
40
|
package_paths: nil,
|
55
41
|
inflector: nil,
|
56
42
|
custom_associations: [],
|
57
|
-
checker_classes: DEFAULT_CHECKERS
|
58
|
-
reference_lister:
|
43
|
+
checker_classes: DEFAULT_CHECKERS
|
59
44
|
)
|
60
45
|
@root_path = root_path
|
61
46
|
@load_paths = load_paths
|
@@ -63,7 +48,6 @@ module Packwerk
|
|
63
48
|
@inflector = inflector
|
64
49
|
@custom_associations = custom_associations
|
65
50
|
@checker_classes = checker_classes
|
66
|
-
@reference_lister = reference_lister
|
67
51
|
end
|
68
52
|
|
69
53
|
sig { params(file: String).returns(T::Array[T.nilable(::Packwerk::Offense)]) }
|
@@ -84,8 +68,7 @@ module Packwerk
|
|
84
68
|
context_provider: context_provider,
|
85
69
|
checkers: checkers,
|
86
70
|
root_path: root_path,
|
87
|
-
constant_name_inspectors: constant_name_inspectors
|
88
|
-
reference_lister: reference_lister
|
71
|
+
constant_name_inspectors: constant_name_inspectors
|
89
72
|
)
|
90
73
|
end
|
91
74
|
|
@@ -1,8 +1,6 @@
|
|
1
1
|
# typed: false
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require "packwerk/application_validator"
|
5
|
-
|
6
4
|
module Packwerk
|
7
5
|
# To do: This alias and file should be removed as it is deprecated
|
8
6
|
warn("DEPRECATION WARNING: Packwerk::SanityChecker is deprecated, use Packwerk::ApplicationValidator instead.")
|
data/lib/packwerk/version.rb
CHANGED
data/packwerk.gemspec
CHANGED
data/service.yml
CHANGED
@@ -4,5 +4,114 @@
|
|
4
4
|
|
5
5
|
# typed: true
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
module Parallel
|
8
|
+
extend(::Parallel::ProcessorCount)
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def all?(*args, &block); end
|
12
|
+
def any?(*args, &block); end
|
13
|
+
def each(array, options = T.unsafe(nil), &block); end
|
14
|
+
def each_with_index(array, options = T.unsafe(nil), &block); end
|
15
|
+
def flat_map(*args, &block); end
|
16
|
+
def in_processes(options = T.unsafe(nil), &block); end
|
17
|
+
def in_threads(options = T.unsafe(nil)); end
|
18
|
+
def map(source, options = T.unsafe(nil), &block); end
|
19
|
+
def map_with_index(array, options = T.unsafe(nil), &block); end
|
20
|
+
def worker_number; end
|
21
|
+
def worker_number=(worker_num); end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def add_progress_bar!(job_factory, options); end
|
26
|
+
def call_with_index(item, index, options, &block); end
|
27
|
+
def create_workers(job_factory, options, &block); end
|
28
|
+
def extract_count_from_options(options); end
|
29
|
+
def process_incoming_jobs(read, write, job_factory, options, &block); end
|
30
|
+
def replace_worker(job_factory, workers, i, options, blk); end
|
31
|
+
def with_instrumentation(item, index, options); end
|
32
|
+
def work_direct(job_factory, options, &block); end
|
33
|
+
def work_in_processes(job_factory, options, &blk); end
|
34
|
+
def work_in_threads(job_factory, options, &block); end
|
35
|
+
def worker(job_factory, options, &block); end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class Parallel::Break < ::StandardError
|
40
|
+
def initialize(value = T.unsafe(nil)); end
|
41
|
+
|
42
|
+
def value; end
|
43
|
+
end
|
44
|
+
|
45
|
+
class Parallel::DeadWorker < ::StandardError
|
46
|
+
end
|
47
|
+
|
48
|
+
class Parallel::ExceptionWrapper
|
49
|
+
def initialize(exception); end
|
50
|
+
|
51
|
+
def exception; end
|
52
|
+
end
|
53
|
+
|
54
|
+
class Parallel::JobFactory
|
55
|
+
def initialize(source, mutex); end
|
56
|
+
|
57
|
+
def next; end
|
58
|
+
def pack(item, index); end
|
59
|
+
def size; end
|
60
|
+
def unpack(data); end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def producer?; end
|
65
|
+
def queue_wrapper(array); end
|
66
|
+
end
|
67
|
+
|
68
|
+
class Parallel::Kill < ::Parallel::Break
|
69
|
+
end
|
70
|
+
|
71
|
+
module Parallel::ProcessorCount
|
72
|
+
def physical_processor_count; end
|
73
|
+
def processor_count; end
|
74
|
+
end
|
75
|
+
|
76
|
+
Parallel::Stop = T.let(T.unsafe(nil), Object)
|
77
|
+
|
78
|
+
class Parallel::UndumpableException < ::StandardError
|
79
|
+
def initialize(original); end
|
80
|
+
|
81
|
+
def backtrace; end
|
82
|
+
end
|
83
|
+
|
84
|
+
class Parallel::UserInterruptHandler
|
85
|
+
class << self
|
86
|
+
def kill(thing); end
|
87
|
+
def kill_on_ctrl_c(pids, options); end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def restore_interrupt(old, signal); end
|
92
|
+
def trap_interrupt(signal); end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
Parallel::UserInterruptHandler::INTERRUPT_SIGNAL = T.let(T.unsafe(nil), Symbol)
|
97
|
+
|
98
|
+
Parallel::VERSION = T.let(T.unsafe(nil), String)
|
99
|
+
|
100
|
+
Parallel::Version = T.let(T.unsafe(nil), String)
|
101
|
+
|
102
|
+
class Parallel::Worker
|
103
|
+
def initialize(read, write, pid); end
|
104
|
+
|
105
|
+
def close_pipes; end
|
106
|
+
def pid; end
|
107
|
+
def read; end
|
108
|
+
def stop; end
|
109
|
+
def thread; end
|
110
|
+
def thread=(_arg0); end
|
111
|
+
def work(data); end
|
112
|
+
def write; end
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
def wait; end
|
117
|
+
end
|