Skip to content

Add more file extensions #8

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Aug 18, 2017
Merged
1 change: 1 addition & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
BasedOnStyle: LLVM
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ branches:
addons:
apt:
packages: [
clang-format-3.6
clang-format-3.8
]

before_install:
Expand Down
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

[![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)

This plugin looks for code style violations for added lines and suggests patches.

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

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

Expand All @@ -24,6 +25,12 @@ Inside your `Dangerfile` :
code_style_validation.check
```

To check files with extensions other than the default ones:

```ruby
code_style_validation.check file_extensions: ['.hpp', '.cpp']
```

To ignore specific paths, use `ignore_file_patterns` :

```ruby
Expand Down
66 changes: 43 additions & 23 deletions lib/code_style_validation/plugin.rb
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
module Danger
# This plugin looks for code style violations for
# added lines on the current MR / PR,
# and offers inline patches.
# This plugin uses 'clang-format' to look for code style violations in added
# lines on the current MR / PR, and offers inline patches.
# By default only Objective-C files, with extensions ".h", ".m", and ".mm"
# are checked.
#
# It uses 'clang-format' and only checks ".h", ".m" and ".mm" files
#
# @example Ensure that added lines does not violate code style
# @example Ensure that changes do not violate code style in Objective-C files
#
# code_style_validation.check
#
# @example Ensure that changes don't violate code style, ignoring Pods directory
# @example Ensure that changes do not violate code style in files with given extensions
#
# code_style_validation.check file_extensions: ['.hpp', '.cpp']
#
# @example Ensure that changes do not violate code style, ignoring Pods directory
#
# code_style_validation.check ignore_file_patterns: [/^Pods\//]
#
Expand All @@ -18,12 +21,15 @@ module Danger
#
class DangerCodeStyleValidation < Plugin
VIOLATION_ERROR_MESSAGE = 'Code style violations detected.'.freeze

# Validates the code style of changed & added files using clang-format.
# Generates Markdown message with respective patches.
#
# @return [void]
def check(config = {})
defaults = {file_extensions: ['.h', '.m', '.mm'], ignore_file_patterns: []}
config = defaults.merge(config)
file_extensions = [*config[:file_extensions]]
ignore_file_patterns = [*config[:ignore_file_patterns]]

diff = ''
Expand All @@ -38,19 +44,31 @@ def check(config = {})
raise 'Unknown SCM Provider'
end

changes = get_changes(diff, ignore_file_patterns)
message = resolve_changes(changes)
changes = get_changes(diff, file_extensions, ignore_file_patterns)
offending_files, patches = resolve_changes(changes)

message = ''
unless offending_files.empty?
message = 'Code style violations detected in the following files:' + "\n"
offending_files.each do |file_name|
message += '* `' + file_name + "`\n\n"
end
message += 'Execute one of the following actions and commit again:' + "\n"
message += '1. Run `clang-format` on the offending files' + "\n"
message += '2. Apply the suggested patches with `git apply patch`.' + "\n\n"
message += patches.join("\n")
end

return if message.empty?
fail VIOLATION_ERROR_MESSAGE
markdown '### Code Style Check (`.h`, `.m` and `.mm`)'
markdown '### Code Style Check'
markdown '---'
markdown message
end

private

def get_changes(diff_str, ignore_file_patterns)
def get_changes(diff_str, file_extensions, ignore_file_patterns)
changes = {}
line_cursor = 0

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

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

unless file_name.end_with?('.m', '.h', '.mm')
unless file_name.end_with?(*file_extensions)
next
end

Expand Down Expand Up @@ -121,17 +139,17 @@ def parse_diff(diff)
patches
end

def generate_markdown(title, content)
markup_message = '#### ' + title + "\n"
markup_message += "```diff \n" + content + "\n``` \n"
markup_message
def generate_patch(title, content)
markup_patch = '#### ' + title + "\n"
markup_patch += "```diff \n" + content + "\n``` \n"
markup_patch
end

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

markup_message = ''

offending_files = []
patches = []
# patches.each do |patch|
changes.each do |file_name, changed_lines|
changed_lines_command_array = []
Expand All @@ -157,14 +175,16 @@ def resolve_changes(changes)
formatted_temp_file.close
formatted_temp_file.unlink

# generate Markup message of patch suggestions
# to prevent code-style violations
# generate arrays with:
# 1. Name of offending files
# 2. Suggested patches, in Markdown format
unless diff.empty?
markup_message += generate_markdown(file_name, diff)
offending_files.push(file_name)
patches.push(generate_patch(file_name, diff))
end
end

markup_message
return offending_files, patches
end
end
end
37 changes: 29 additions & 8 deletions spec/code_style_validation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,28 @@ module Danger

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

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

expect(@dangerfile.status_report[:errors]).to eq([DangerCodeStyleValidation::VIOLATION_ERROR_MESSAGE])
expect(@dangerfile.status_report[:markdowns].map(&:message).join("\n")).to eq(expected_message)
end

it 'Does not report error when extension is excluded' do
diff = File.read('spec/fixtures/violated_diff.diff')

allow(@my_plugin.github).to receive(:pr_diff).and_return diff
@my_plugin.check file_extensions: ['.h', '.c']

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

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

@my_plugin.github.stub(:pr_diff).and_return diff
allow(@my_plugin.github).to receive(:pr_diff).and_return diff
@my_plugin.check

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

@my_plugin.github.stub(:pr_diff).and_return diff
allow(@my_plugin.github).to receive(:pr_diff).and_return diff
@my_plugin.check

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

@my_plugin.github.stub(:pr_diff).and_return diff
allow(@my_plugin.github).to receive(:pr_diff).and_return diff
@my_plugin.check

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

@my_plugin.github.stub(:pr_diff).and_return diff
@my_plugin.check ignore_file_patterns: [%r{^spec/}]
allow(@my_plugin.github).to receive(:pr_diff).and_return diff
@my_plugin.check file_extensions: ['.h', '.m'],
ignore_file_patterns: [%r{^spec/}]

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

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

@my_plugin.github.stub(:pr_diff).and_return diff
allow(@my_plugin.github).to receive(:pr_diff).and_return diff
@my_plugin.check ignore_file_patterns: %r{^spec/}

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

it 'Allows single file extension instead of array' do
diff = File.read('spec/fixtures/violated_diff.diff')

allow(@my_plugin.github).to receive(:pr_diff).and_return diff
@my_plugin.check file_extensions: '.m'

expect(@dangerfile.status_report[:errors]).to eq([DangerCodeStyleValidation::VIOLATION_ERROR_MESSAGE])
end
end
end
end
30 changes: 30 additions & 0 deletions spec/fixtures/violated_diff_message.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
### Code Style Check
---
Code style violations detected in the following files:
* `spec/fixtures/BadViewController.m`

Execute one of the following actions and commit again:
1. Run `clang-format` on the offending files
2. Apply the suggested patches with `git apply patch`.

#### spec/fixtures/BadViewController.m
```diff
--- spec/fixtures/BadViewController.m
+++ spec/fixtures/BadViewController.m
@@ -1,9 +1,10 @@
-@interface ViewController ( ) @end
+@interface ViewController ()
+@end

@implementation ViewController
--(void ) viewDidLoad {
- [super viewDidLoad];
- NSLog( @"perfect change!") ;
+- (void)viewDidLoad {
+ [super viewDidLoad];
+ NSLog(@"perfect change!");
}

@end

```