Skip to content
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`, `.mm` and
`.C`, are checked.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does .C have to be capitalized?

Copy link
Contributor Author

@robertodr robertodr Aug 10, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to Wikipedia Objective-C files usually have those extensions. I only kept Objective-C source file extensions as defaults for the file_extensions input parameter.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good find, I've never seen that extension in the wild, though. Also, it's effectively equal to .c extension on case-insensitive filesystems (i.e. on most Macs).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, of course! I'll remove it and leave .m, .mm and .h as defaults.


![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
64 changes: 42 additions & 22 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", ".mm" and
# ".C", are checked.
#
# @example Ensure that changes do not violate code style in Objective-C files
#
# It uses 'clang-format' and only checks ".h", ".m" and ".mm" files
# code_style_validation.check
#
# @example Ensure that added lines does not violate code style
# @example Ensure that changes do not violate code style in files with given extensions
#
# code_style_validation.check
# code_style_validation.check file_extensions: ['.hpp', '.cpp']
#
# @example Ensure that changes don't violate code style, ignoring Pods directory
# @example Ensure that changes do not violate code style, ignoring Pods directory
#
# code_style_validation.check ignore_file_patterns: [/^Pods\//]
#
Expand All @@ -24,6 +27,9 @@ class DangerCodeStyleValidation < Plugin
#
# @return [void]
def check(config = {})
defaults = {file_extensions: ['.h', '.m', '.mm', '.C'], 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"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trailing space.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooops... Sorry. I haven't yet reconfigured my Neovim properly after reinstalling the OS.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries!

offending_files.each do |file_name|
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You seem to be using tabs here. Please use spaces.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could be helpful to configure Rubocop support in your editor. This repo doesn't have Rubocop's config yet, so it'll report some false positives, but it will also detect things like inconsistent indentation and trailing spaces.

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(' ')
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
2 changes: 1 addition & 1 deletion spec/code_style_validation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module Danger
diff = File.read('spec/fixtures/violated_diff.diff')

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

expect(@dangerfile.status_report[:errors]).to eq([DangerCodeStyleValidation::VIOLATION_ERROR_MESSAGE])
end
Expand Down