Skip to content

Commit 05ce998

Browse files
committed
Improve violation output to look more like ripgrep to compress the output
1 parent efcb4db commit 05ce998

File tree

7 files changed

+60
-62
lines changed

7 files changed

+60
-62
lines changed

lib/chatwerk/api.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def packages(package_path: nil)
1414
has_packwerk_yml = File.exist?('packwerk.yml')
1515
Views::NoPackagesView.render(has_packwerk_yml:)
1616
else
17-
Views::PackagesView.render(packages:, has_packwerk_yml:)
17+
Views::PackagesView.render(packages:)
1818
end
1919
rescue StandardError => e
2020
raise Chatwerk::Error.new(e, package_path:)

lib/chatwerk/views/packages_view.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
module Chatwerk
44
module Views
55
class PackagesView < BaseView
6-
def render
6+
def template(packages:, package_path: nil)
77
if packages.empty?
8-
"No packages found matching #{package_path.inspect}"
8+
"No packages found matching #{package_path.inspect}\n"
99
else
10-
packages.map(&:name).sort.join("\n")
10+
packages.map { |p| "#{p.name}\n" }.sort.join
1111
end
1212
end
1313
end

lib/chatwerk/views/violations_details_view.rb

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,44 @@ module Chatwerk
44
module Views
55
class ViolationsDetailsView < BaseView
66
def template(package:, violations:, constant_name:)
7-
say "The following code violates package boundaries:\n"
8-
97
relevant_violations = violations
108
.anonymous_sources_with_locations
119
.select { |c, _| c.start_with?(constant_name) }
1210

1311
if relevant_violations.empty?
14-
say Views::NoViolationsView.render(package:, constant_name:)
12+
Views::NoViolationsView.render(package:, constant_name:)
1513
else
16-
relevant_violations.each do |name, source|
17-
say "# Constant `#{name}`"
18-
if source && !source.empty?
19-
source.each do |code, files|
20-
say " #{code}"
21-
files.each do |file|
22-
say " - #{file}"
23-
end
24-
end
25-
else
26-
say ' No usages found.'
14+
grep_formatted_violations(relevant_violations)
15+
end
16+
end
17+
18+
private
19+
20+
def grep_formatted_violations(relevant_violations)
21+
# Group violations by file
22+
files_to_violations = {}
23+
24+
relevant_violations.each do |constant, source_info|
25+
say "No sources found for #{constant}" if source_info.empty?
26+
source_info.each do |code, files|
27+
say "No files found for #{constant} with code: #{code}" if files.empty?
28+
29+
files.each do |file_with_line|
30+
file, line = file_with_line.split(':')
31+
files_to_violations[file] ||= []
32+
files_to_violations[file] << { constant:, code:, line: line }
2733
end
2834
end
2935
end
36+
37+
# Output violations grouped by file
38+
files_to_violations.sort.map do |file, violations|
39+
lines = violations.sort_by { |v| v[:line].to_i }.map do |violation|
40+
"#{violation[:line]}: #{violation[:code]}"
41+
end.join("\n")
42+
43+
"#{file}\n#{lines}\n"
44+
end.join("\n")
3045
end
3146
end
3247
end

spec/chatwerk/api_spec.rb

Lines changed: 12 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
let(:constant_name) { '::TestPackage::TestClass' }
1010
let(:package) { instance_double('Packwerk::Package', name: 'packs/test_package') }
1111
let(:violations) { instance_double('QueryPackwerk::Violations') }
12-
let(:anonymous_sources_with_locations) { { '::TestPackage::TestClass' => { 'example usage' => ['app/models/test.rb'] } } }
12+
let(:anonymous_sources_with_locations) { { '::TestPackage::TestClass' => { 'example usage' => ['app/models/test.rb:1'] } } }
1313

1414
before do
1515
allow(Chatwerk::Helpers).to receive(:chdir)
@@ -23,7 +23,7 @@
2323
end
2424

2525
it 'returns the packages view' do
26-
expect(described_class.packages).to eq('packs/test_package')
26+
expect(described_class.packages).to eq("packs/test_package\n")
2727
end
2828

2929
it 'accepts an optional package path filter' do
@@ -40,7 +40,7 @@
4040
end
4141

4242
it 'returns the no packages view' do
43-
expect(described_class.packages.chomp).to eq(<<~STRING.chomp)
43+
expect(described_class.packages).to eq(<<~STRING)
4444
0 packages found.
4545
`packwerk.yml` file exists in project root: /test/workspace
4646
@@ -98,23 +98,17 @@
9898

9999
it 'returns the violations list view' do
100100
expect(described_class.package_todos(package_path: package_path)).to eq(<<~STRING)
101-
The following code violates package boundaries:
102-
103-
# Constant `::TestPackage::TestClass`
104-
example usage
105-
- app/models/test.rb
101+
app/models/test.rb
102+
1: example usage
106103
STRING
107104
end
108105
end
109106

110107
context 'with constant name' do
111108
it 'returns the violations details view' do
112109
expect(described_class.package_todos(package_path: package_path, constant_name: constant_name)).to eq(<<~STRING)
113-
The following code violates package boundaries:
114-
115-
# Constant `::TestPackage::TestClass`
116-
example usage
117-
- app/models/test.rb
110+
app/models/test.rb
111+
1: example usage
118112
STRING
119113
end
120114

@@ -123,8 +117,6 @@
123117

124118
it 'returns the no violations view' do
125119
expect(described_class.package_todos(package_path: package_path, constant_name: constant_name).strip).to eq(<<~STRING.strip)
126-
The following code violates package boundaries:
127-
128120
No violations found in "packs/test_package" for "::TestPackage::TestClass".
129121
Ensure that constant_name is given in the format of "::ConstantName" or "::ConstantName::NestedConstant".
130122
STRING
@@ -157,33 +149,25 @@
157149

158150
it 'returns the violations list view' do
159151
expect(described_class.package_violations(package_path: package_path)).to eq(<<~STRING)
160-
The following code violates package boundaries:
161-
162-
# Constant `::TestPackage::TestClass`
163-
example usage
164-
- app/models/test.rb
152+
app/models/test.rb
153+
1: example usage
165154
STRING
166155
end
167156
end
168157

169158
context 'with constant name' do
170159
it 'returns the violations details view' do
171160
expect(described_class.package_violations(package_path: package_path, constant_name: constant_name)).to eq(<<~STRING)
172-
The following code violates package boundaries:
173-
174-
# Constant `::TestPackage::TestClass`
175-
example usage
176-
- app/models/test.rb
161+
app/models/test.rb
162+
1: example usage
177163
STRING
178164
end
179165

180166
context 'when no violations found' do
181167
let(:anonymous_sources_with_locations) { {} }
182168

183169
it 'returns the no violations view' do
184-
expect(described_class.package_violations(package_path: package_path, constant_name: constant_name).strip).to eq(<<~STRING.strip)
185-
The following code violates package boundaries:
186-
170+
expect(described_class.package_violations(package_path: package_path, constant_name: constant_name)).to eq(<<~STRING)
187171
No violations found in "packs/test_package" for "::TestPackage::TestClass".
188172
Ensure that constant_name is given in the format of "::ConstantName" or "::ConstantName::NestedConstant".
189173
STRING

spec/chatwerk/views/package_view_spec.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
todos: [],
1717
violations: [])
1818

19-
expect(described_class.render(package:).chomp).to eq(<<~OUTPUT)
19+
expect(described_class.render(package:)).to eq(<<~OUTPUT)
2020
---
2121
name: orders
2222
enforce_dependencies: true
@@ -29,6 +29,7 @@
2929
- consumer1
3030
todos_count: 0
3131
violations_count: 0
32+
3233
OUTPUT
3334
end
3435
end

spec/chatwerk/views/packages_view_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
]
1111
package_path = 'app/packages'
1212

13-
expect(described_class.render(packages:, package_path:)).to eq(<<~OUTPUT.chomp)
13+
expect(described_class.render(packages:, package_path:)).to eq(<<~OUTPUT)
1414
orders
1515
payments
1616
users
@@ -23,7 +23,7 @@
2323
packages = []
2424
package_path = 'app/invalid_path'
2525

26-
expect(described_class.render(packages:, package_path:)).to eq(<<~OUTPUT.chomp)
26+
expect(described_class.render(packages:, package_path:)).to eq(<<~OUTPUT)
2727
No packages found matching "app/invalid_path"
2828
OUTPUT
2929
end

spec/chatwerk/views/violations_details_view_spec.rb

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,22 @@
77
constant_name = '::Core::User'
88
sources = {
99
'::Core::User' => {
10-
'User.find(order.user_id)' => ['app/packages/orders/app/models/order.rb:45', 'app/packages/orders/app/services/order_service.rb:12'],
11-
'User.create(user_params)' => ['app/packages/orders/app/controllers/orders_controller.rb:28']
10+
'User.find(_)' => ['app/packages/orders/app/models/order.rb:45', 'app/packages/orders/app/services/order_service.rb:12'],
11+
'User.create(_)' => ['app/packages/orders/app/controllers/orders_controller.rb:28', 'app/packages/orders/app/models/order.rb:48']
1212
}
1313
}
1414
violations = instance_double('QueryPackwerk::Violations', anonymous_sources_with_locations: sources)
1515

1616
expect(described_class.render(package:, violations:, constant_name:)).to eq(<<~OUTPUT)
17-
The following code violates package boundaries:
17+
app/packages/orders/app/controllers/orders_controller.rb
18+
28: User.create(_)
1819
19-
# Constant `::Core::User`
20-
User.find(order.user_id)
21-
- app/packages/orders/app/models/order.rb:45
22-
- app/packages/orders/app/services/order_service.rb:12
23-
User.create(user_params)
24-
- app/packages/orders/app/controllers/orders_controller.rb:28
20+
app/packages/orders/app/models/order.rb
21+
45: User.find(_)
22+
48: User.create(_)
23+
24+
app/packages/orders/app/services/order_service.rb
25+
12: User.find(_)
2526
OUTPUT
2627
end
2728
end
@@ -36,10 +37,7 @@
3637
violations = instance_double('QueryPackwerk::Violations', anonymous_sources_with_locations: sources)
3738

3839
expect(described_class.render(package:, violations:, constant_name:)).to eq(<<~OUTPUT)
39-
The following code violates package boundaries:
40-
41-
# Constant `::Core::Product`
42-
No usages found.
40+
No sources found for ::Core::Product
4341
OUTPUT
4442
end
4543
end

0 commit comments

Comments
 (0)