Skip to content

Commit 5c250d9

Browse files
robertodrnikolaykasyanov
authored andcommitted
Makes file extensions configurable (#8)
* Allow user to specify file extensions to check * Improve code style violation message and refactor its generation * Adds code style violation message verification * Adds .clang-format to make diffs produced in tests deterministic * Updates specs to fix #9 * Install clang-format-3.8 also on Linux
1 parent a9dc5f4 commit 5c250d9

File tree

6 files changed

+114
-35
lines changed

6 files changed

+114
-35
lines changed

.clang-format

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
BasedOnStyle: LLVM

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ branches:
1919
addons:
2020
apt:
2121
packages: [
22-
clang-format-3.6
22+
clang-format-3.8
2323
]
2424

2525
before_install:

README.md

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22

33
[![Build Status](https://travis-ci.org/flix-tech/danger-code_style_validation.svg?branch=master)](https://travis-ci.org/flix-tech/danger-code_style_validation)
44

5-
This plugin looks for code style violations for added lines and suggests patches.
6-
7-
It uses 'clang-format' and only checks `.h`, `.m` and `.mm` files
5+
This plugin uses 'clang-format' to look for code style violations in added
6+
lines on the current MR / PR, and offers inline patches.
7+
By default only Objective-C files, with extensions `.h`, `.m`, and `.mm` are
8+
checked.
89

910
![Example](/doc/images/example.png)
1011

@@ -24,6 +25,12 @@ Inside your `Dangerfile` :
2425
code_style_validation.check
2526
```
2627

28+
To check files with extensions other than the default ones:
29+
30+
```ruby
31+
code_style_validation.check file_extensions: ['.hpp', '.cpp']
32+
```
33+
2734
To ignore specific paths, use `ignore_file_patterns` :
2835

2936
```ruby

lib/code_style_validation/plugin.rb

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
module Danger
2-
# This plugin looks for code style violations for
3-
# added lines on the current MR / PR,
4-
# and offers inline patches.
2+
# This plugin uses 'clang-format' to look for code style violations in added
3+
# lines on the current MR / PR, and offers inline patches.
4+
# By default only Objective-C files, with extensions ".h", ".m", and ".mm"
5+
# are checked.
56
#
6-
# It uses 'clang-format' and only checks ".h", ".m" and ".mm" files
7-
#
8-
# @example Ensure that added lines does not violate code style
7+
# @example Ensure that changes do not violate code style in Objective-C files
98
#
109
# code_style_validation.check
1110
#
12-
# @example Ensure that changes don't violate code style, ignoring Pods directory
11+
# @example Ensure that changes do not violate code style in files with given extensions
12+
#
13+
# code_style_validation.check file_extensions: ['.hpp', '.cpp']
14+
#
15+
# @example Ensure that changes do not violate code style, ignoring Pods directory
1316
#
1417
# code_style_validation.check ignore_file_patterns: [/^Pods\//]
1518
#
@@ -18,12 +21,15 @@ module Danger
1821
#
1922
class DangerCodeStyleValidation < Plugin
2023
VIOLATION_ERROR_MESSAGE = 'Code style violations detected.'.freeze
21-
24+
2225
# Validates the code style of changed & added files using clang-format.
2326
# Generates Markdown message with respective patches.
2427
#
2528
# @return [void]
2629
def check(config = {})
30+
defaults = {file_extensions: ['.h', '.m', '.mm'], ignore_file_patterns: []}
31+
config = defaults.merge(config)
32+
file_extensions = [*config[:file_extensions]]
2733
ignore_file_patterns = [*config[:ignore_file_patterns]]
2834

2935
diff = ''
@@ -38,19 +44,31 @@ def check(config = {})
3844
raise 'Unknown SCM Provider'
3945
end
4046

41-
changes = get_changes(diff, ignore_file_patterns)
42-
message = resolve_changes(changes)
47+
changes = get_changes(diff, file_extensions, ignore_file_patterns)
48+
offending_files, patches = resolve_changes(changes)
49+
50+
message = ''
51+
unless offending_files.empty?
52+
message = 'Code style violations detected in the following files:' + "\n"
53+
offending_files.each do |file_name|
54+
message += '* `' + file_name + "`\n\n"
55+
end
56+
message += 'Execute one of the following actions and commit again:' + "\n"
57+
message += '1. Run `clang-format` on the offending files' + "\n"
58+
message += '2. Apply the suggested patches with `git apply patch`.' + "\n\n"
59+
message += patches.join("\n")
60+
end
4361

4462
return if message.empty?
4563
fail VIOLATION_ERROR_MESSAGE
46-
markdown '### Code Style Check (`.h`, `.m` and `.mm`)'
64+
markdown '### Code Style Check'
4765
markdown '---'
4866
markdown message
4967
end
5068

5169
private
5270

53-
def get_changes(diff_str, ignore_file_patterns)
71+
def get_changes(diff_str, file_extensions, ignore_file_patterns)
5472
changes = {}
5573
line_cursor = 0
5674

@@ -69,7 +87,7 @@ def get_changes(diff_str, ignore_file_patterns)
6987

7088
file_name = filename_line.split('+++ b/').last.chomp
7189

72-
unless file_name.end_with?('.m', '.h', '.mm')
90+
unless file_name.end_with?(*file_extensions)
7391
next
7492
end
7593

@@ -121,17 +139,17 @@ def parse_diff(diff)
121139
patches
122140
end
123141

124-
def generate_markdown(title, content)
125-
markup_message = '#### ' + title + "\n"
126-
markup_message += "```diff \n" + content + "\n``` \n"
127-
markup_message
142+
def generate_patch(title, content)
143+
markup_patch = '#### ' + title + "\n"
144+
markup_patch += "```diff \n" + content + "\n``` \n"
145+
markup_patch
128146
end
129147

130148
def resolve_changes(changes)
131149
# Parse all patches from diff string
132150

133-
markup_message = ''
134-
151+
offending_files = []
152+
patches = []
135153
# patches.each do |patch|
136154
changes.each do |file_name, changed_lines|
137155
changed_lines_command_array = []
@@ -157,14 +175,16 @@ def resolve_changes(changes)
157175
formatted_temp_file.close
158176
formatted_temp_file.unlink
159177

160-
# generate Markup message of patch suggestions
161-
# to prevent code-style violations
178+
# generate arrays with:
179+
# 1. Name of offending files
180+
# 2. Suggested patches, in Markdown format
162181
unless diff.empty?
163-
markup_message += generate_markdown(file_name, diff)
182+
offending_files.push(file_name)
183+
patches.push(generate_patch(file_name, diff))
164184
end
165185
end
166186

167-
markup_message
187+
return offending_files, patches
168188
end
169189
end
170190
end

spec/code_style_validation_spec.rb

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,28 @@ module Danger
1414

1515
it 'Reports code style violation as error' do
1616
diff = File.read('spec/fixtures/violated_diff.diff')
17+
expected_message = File.read('spec/fixtures/violated_diff_message.md')
1718

18-
@my_plugin.github.stub(:pr_diff).and_return diff
19-
@my_plugin.check
19+
allow(@my_plugin.github).to receive(:pr_diff).and_return diff
20+
@my_plugin.check file_extensions: ['.h', '.m', '.mm', '.cpp']
2021

2122
expect(@dangerfile.status_report[:errors]).to eq([DangerCodeStyleValidation::VIOLATION_ERROR_MESSAGE])
23+
expect(@dangerfile.status_report[:markdowns].map(&:message).join("\n")).to eq(expected_message)
24+
end
25+
26+
it 'Does not report error when extension is excluded' do
27+
diff = File.read('spec/fixtures/violated_diff.diff')
28+
29+
allow(@my_plugin.github).to receive(:pr_diff).and_return diff
30+
@my_plugin.check file_extensions: ['.h', '.c']
31+
32+
expect(@dangerfile.status_report[:errors]).to eq([])
2233
end
2334

2435
it 'Does not report error when code not violated' do
2536
diff = File.read('spec/fixtures/innocent_diff.diff')
2637

27-
@my_plugin.github.stub(:pr_diff).and_return diff
38+
allow(@my_plugin.github).to receive(:pr_diff).and_return diff
2839
@my_plugin.check
2940

3041
expect(@dangerfile.status_report[:errors]).to eq([])
@@ -33,7 +44,7 @@ module Danger
3344
it 'Does not report error for different extension types of files' do
3445
diff = File.read('spec/fixtures/ruby_diff.diff')
3546

36-
@my_plugin.github.stub(:pr_diff).and_return diff
47+
allow(@my_plugin.github).to receive(:pr_diff).and_return diff
3748
@my_plugin.check
3849

3950
expect(@dangerfile.status_report[:errors]).to eq([])
@@ -42,7 +53,7 @@ module Danger
4253
it 'Does not report unexpected errors when there are only removals in the diff' do
4354
diff = File.read('spec/fixtures/red_diff.diff')
4455

45-
@my_plugin.github.stub(:pr_diff).and_return diff
56+
allow(@my_plugin.github).to receive(:pr_diff).and_return diff
4657
@my_plugin.check
4758

4859
expect(@dangerfile.status_report[:errors]).to eq([])
@@ -51,20 +62,30 @@ module Danger
5162
it 'Ignores files matching ignored patterns' do
5263
diff = File.read('spec/fixtures/violated_diff.diff')
5364

54-
@my_plugin.github.stub(:pr_diff).and_return diff
55-
@my_plugin.check ignore_file_patterns: [%r{^spec/}]
65+
allow(@my_plugin.github).to receive(:pr_diff).and_return diff
66+
@my_plugin.check file_extensions: ['.h', '.m'],
67+
ignore_file_patterns: [%r{^spec/}]
5668

5769
expect(@dangerfile.status_report[:errors]).to eq([])
5870
end
5971

6072
it 'Allows single pattern instead of array' do
6173
diff = File.read('spec/fixtures/violated_diff.diff')
6274

63-
@my_plugin.github.stub(:pr_diff).and_return diff
75+
allow(@my_plugin.github).to receive(:pr_diff).and_return diff
6476
@my_plugin.check ignore_file_patterns: %r{^spec/}
6577

6678
expect(@dangerfile.status_report[:errors]).to eq([])
6779
end
80+
81+
it 'Allows single file extension instead of array' do
82+
diff = File.read('spec/fixtures/violated_diff.diff')
83+
84+
allow(@my_plugin.github).to receive(:pr_diff).and_return diff
85+
@my_plugin.check file_extensions: '.m'
86+
87+
expect(@dangerfile.status_report[:errors]).to eq([DangerCodeStyleValidation::VIOLATION_ERROR_MESSAGE])
88+
end
6889
end
6990
end
7091
end
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
### Code Style Check
2+
---
3+
Code style violations detected in the following files:
4+
* `spec/fixtures/BadViewController.m`
5+
6+
Execute one of the following actions and commit again:
7+
1. Run `clang-format` on the offending files
8+
2. Apply the suggested patches with `git apply patch`.
9+
10+
#### spec/fixtures/BadViewController.m
11+
```diff
12+
--- spec/fixtures/BadViewController.m
13+
+++ spec/fixtures/BadViewController.m
14+
@@ -1,9 +1,10 @@
15+
-@interface ViewController ( ) @end
16+
+@interface ViewController ()
17+
+@end
18+
19+
@implementation ViewController
20+
--(void ) viewDidLoad {
21+
- [super viewDidLoad];
22+
- NSLog( @"perfect change!") ;
23+
+- (void)viewDidLoad {
24+
+ [super viewDidLoad];
25+
+ NSLog(@"perfect change!");
26+
}
27+
28+
@end
29+
30+
```

0 commit comments

Comments
 (0)