sabat-guard-rubocop 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md ADDED
@@ -0,0 +1,26 @@
1
+ # CHANGELOG
2
+
3
+ ## v0.1.0
4
+
5
+ * Update RuboCop dependency to 0.9 or later and earlier than 1.0
6
+ * Rework with JSON formatter
7
+ * Change the displayed text to "Inspecting ..."
8
+ * Print relative file paths when they are under current working directory
9
+
10
+ ## v0.0.4
11
+
12
+ * Specify dependency on rubocop gem as under 0.9.0
13
+ * Force RuboCop to colorize output even though output is not TTY
14
+ * Revert "Use rubocop 0.6.1 --no-color option instead of uncoloring colored output"
15
+
16
+ ## v0.0.3
17
+
18
+ * Use rubocop 0.6.1 --no-color option instead of uncoloring colored output
19
+
20
+ ## v0.0.2
21
+
22
+ * Fix capitalization of the name RuboCop in notification title
23
+
24
+ ## v0.0.1
25
+
26
+ * Initial release
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem 'coveralls', '~> 0.6'
7
+ gem 'simplecov-rcov', '~> 0.2'
8
+ gem 'ci_reporter', '~> 1.8'
9
+ end
data/Guardfile ADDED
@@ -0,0 +1,14 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :rspec, all_after_pass: true, all_on_start: true, keep_failed: true do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+ watch(%r{^spec/support/.+\.rb$}) { "spec" }
9
+ end
10
+
11
+ guard :rubocop do
12
+ watch(%r{.+\.rb$})
13
+ watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
14
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Yuji Nakayama
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,71 @@
1
+ [![Gem Version](https://badge.fury.io/rb/guard-rubocop.png)](http://badge.fury.io/rb/guard-rubocop) [![Dependency Status](https://gemnasium.com/yujinakayama/guard-rubocop.png)](https://gemnasium.com/yujinakayama/guard-rubocop) [![Build Status](https://travis-ci.org/yujinakayama/guard-rubocop.png?branch=master)](https://travis-ci.org/yujinakayama/guard-rubocop) [![Coverage Status](https://coveralls.io/repos/yujinakayama/guard-rubocop/badge.png?branch=master)](https://coveralls.io/r/yujinakayama/guard-rubocop) [![Code Climate](https://codeclimate.com/github/yujinakayama/guard-rubocop.png)](https://codeclimate.com/github/yujinakayama/guard-rubocop)
2
+
3
+ # Guard::Rubocop
4
+
5
+ Guard::Rubocop allows you to automatically check Ruby code style with [RuboCop](https://github.com/bbatsov/rubocop) when files are modified.
6
+
7
+ Tested on MRI 1.9 and MRI 2.0, according to RuboCop.
8
+
9
+ ## Installation
10
+
11
+ Please make sure to have [Guard](https://github.com/guard/guard) installed before continue.
12
+
13
+ Add `guard-rubocop` to your `Gemfile`:
14
+
15
+ ```ruby
16
+ group :development do
17
+ gem 'guard-rubocop'
18
+ end
19
+ ```
20
+
21
+ and then execute:
22
+
23
+ ```sh
24
+ $ bundle install
25
+ ```
26
+
27
+ or install it yourself as:
28
+
29
+ ```sh
30
+ $ gem install guard-rubocop
31
+ ```
32
+
33
+ Add the default Guard::Rubocop definition to your `Guardfile` by running:
34
+
35
+ ```sh
36
+ $ guard init rubocop
37
+ ```
38
+
39
+ ## Usage
40
+
41
+ Please read the [Guard usage documentation](https://github.com/guard/guard#readme).
42
+
43
+ ## Options
44
+
45
+ You can pass some options in `Guardfile`:
46
+
47
+ ```ruby
48
+ guard :rubocop, all_on_start: false, notification: true do
49
+ # ...
50
+ end
51
+ ```
52
+
53
+ ### Available Options
54
+
55
+ ```ruby
56
+ all_on_start: true # Check all files at Guard startup, default: true
57
+ keep_failed: true # Keep failed files until they pass, default: true
58
+ notification: :failed # Display Growl notification after each run
59
+ # true - Always notify
60
+ # false - Never notify
61
+ # :failed - Notify only when failed
62
+ # default: :failed
63
+ ```
64
+
65
+ ## Contributing
66
+
67
+ 1. Fork it
68
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
69
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
70
+ 4. Push to the branch (`git push origin my-new-feature`)
71
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ namespace :ci do
7
+ task :spec do
8
+ ENV['CI'] = 'true'
9
+
10
+ ENV['CI_REPORTS'] = 'spec/reports'
11
+ require 'ci/reporter/rake/rspec'
12
+ Rake::Task['ci:setup:rspec'].invoke
13
+
14
+ Rake::Task['spec'].invoke
15
+ end
16
+ end
17
+
18
+ task default: :spec
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ require 'guard/rubocop/version'
7
+
8
+ Gem::Specification.new do |spec|
9
+ spec.name = 'sabat-guard-rubocop'
10
+ spec.version = Guard::RubocopVersion::VERSION
11
+ spec.authors = ['Yuji Nakayama']
12
+ spec.email = ['nkymyj@gmail.com']
13
+ spec.summary = 'Guard plugin for RuboCop'
14
+ spec.description = 'Guard::Rubocop automatically checks Ruby code style with RuboCop when files are modified.'
15
+ spec.homepage = 'https://github.com/sabat/guard-rubocop'
16
+ spec.license = 'MIT'
17
+
18
+ spec.files = `git ls-files`.split($/).reject { |f| File.basename(f).start_with?('.') }
19
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
21
+ spec.require_paths = ['lib']
22
+
23
+ spec.add_runtime_dependency 'guard', '~> 1.8'
24
+ spec.add_runtime_dependency 'sabat-rubocop', '~> 0.9'
25
+
26
+ spec.add_development_dependency 'bundler', '~> 1.3'
27
+ spec.add_development_dependency 'rake', '~> 10.0'
28
+ spec.add_development_dependency 'rspec', '~> 2.13'
29
+ spec.add_development_dependency 'simplecov', '~> 0.7'
30
+ spec.add_development_dependency 'guard-rspec', '~> 3.0'
31
+ spec.add_development_dependency 'ruby_gntp', '~> 0.3'
32
+ end
@@ -0,0 +1,85 @@
1
+ # coding: utf-8
2
+
3
+ require 'guard'
4
+ require 'guard/guard'
5
+
6
+ module Guard
7
+ class Rubocop < Guard
8
+ autoload :Runner, 'guard/rubocop/runner'
9
+
10
+ attr_reader :options, :failed_paths
11
+
12
+ def initialize(watchers = [], options = {})
13
+ super
14
+
15
+ @options = {
16
+ all_on_start: true,
17
+ keep_failed: true,
18
+ notification: :failed
19
+ }.merge(options)
20
+
21
+ @failed_paths = []
22
+ end
23
+
24
+ def start
25
+ run_all if @options[:all_on_start]
26
+ end
27
+
28
+ def run_all
29
+ UI.info 'Inspecting Ruby code style of all files'
30
+ run
31
+ end
32
+
33
+ def run_on_changes(paths)
34
+ paths += @failed_paths if @options[:keep_failed]
35
+ paths = clean_paths(paths)
36
+
37
+ displayed_paths = paths.map { |path| smart_path(path) }
38
+ UI.info "Inspecting Ruby code style: #{displayed_paths.join(' ')}"
39
+
40
+ run(paths)
41
+ end
42
+
43
+ def reload
44
+ @failed_paths = []
45
+ end
46
+
47
+ def clean_paths(paths)
48
+ paths = paths.dup
49
+ paths.map! { |path| File.expand_path(path) }
50
+ paths.uniq!
51
+ paths.reject! do |path|
52
+ included_in_other_path?(path, paths)
53
+ end
54
+ paths
55
+ end
56
+
57
+ private
58
+
59
+ def run(paths = [])
60
+ runner = Runner.new(@options)
61
+ passed = runner.run(paths)
62
+ @failed_paths = runner.failed_paths
63
+ throw :task_has_failed unless passed
64
+ rescue => error
65
+ UI.error 'The following exception occurred while running guard-rubocop: ' +
66
+ "#{error.backtrace.first} #{error.message} (#{error.class.name})"
67
+ end
68
+
69
+ def included_in_other_path?(target_path, other_paths)
70
+ dir_paths = other_paths.select { |path| File.directory?(path) }
71
+ dir_paths.delete(target_path)
72
+ dir_paths.any? do |dir_path|
73
+ target_path.start_with?(dir_path)
74
+ end
75
+ end
76
+
77
+ def smart_path(path)
78
+ if path.start_with?(Dir.pwd)
79
+ Pathname.new(path).relative_path_from(Pathname.getwd).to_s
80
+ else
81
+ path
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,93 @@
1
+ # coding: utf-8
2
+
3
+ require 'json'
4
+
5
+ module Guard
6
+ class Rubocop
7
+ class Runner
8
+ def initialize(options)
9
+ @options = options
10
+ end
11
+
12
+ def run(paths = [])
13
+ command = build_command(paths)
14
+ passed = system(*command)
15
+
16
+ case @options[:notification]
17
+ when :failed
18
+ notify(passed) unless passed
19
+ when true
20
+ notify(passed)
21
+ end
22
+
23
+ passed
24
+ end
25
+
26
+ def build_command(paths)
27
+ command = ['rubocop']
28
+ command.concat(%w(--format progress)) # Keep default formatter for console.
29
+ command.concat(['--format', 'json', '--out', json_file_path])
30
+ command.concat(['--list-cops']) if @options[:cops]
31
+ command.concat(paths)
32
+ end
33
+
34
+ def json_file_path
35
+ @tempfile_path ||= begin
36
+ # Just generate random tempfile path.
37
+ basename = self.class.name.downcase.gsub('::', '_')
38
+ tempfile = Tempfile.new(basename)
39
+ tempfile.close
40
+ tempfile.path
41
+ end
42
+ end
43
+
44
+ def result
45
+ @result ||= begin
46
+ File.open(json_file_path) do |file|
47
+ # Rubinius 2.0.0.rc1 does not support `JSON.load` with 3 args.
48
+ JSON.parse(file.read, symbolize_names: true)
49
+ end
50
+ end
51
+ end
52
+
53
+ def notify(passed)
54
+ image = passed ? :success : :failed
55
+ Notifier.notify(summary_text, title: 'RuboCop results', image: image)
56
+ end
57
+
58
+ def summary_text
59
+ summary = result[:summary]
60
+
61
+ text = pluralize(summary[:inspected_file_count], 'file')
62
+ text << ' inspected, '
63
+
64
+ text << pluralize(summary[:offence_count], 'offence', no_for_zero: true)
65
+ text << ' detected'
66
+ end
67
+
68
+ def failed_paths
69
+ failed_files = result[:files].reject do |file|
70
+ file[:offences].empty?
71
+ end
72
+ failed_files.map do |file|
73
+ file[:path]
74
+ end
75
+ end
76
+
77
+ def pluralize(number, thing, options = {})
78
+ text = ''
79
+
80
+ if number == 0 && options[:no_for_zero]
81
+ text = 'no'
82
+ else
83
+ text << number.to_s
84
+ end
85
+
86
+ text << " #{thing}"
87
+ text << 's' unless number == 1
88
+
89
+ text
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,4 @@
1
+ guard :rubocop do
2
+ watch(%r{.+\.rb$})
3
+ watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
4
+ end
@@ -0,0 +1,13 @@
1
+ # coding: utf-8
2
+
3
+ module Guard
4
+ # A workaround for declaring `class Rubocop`
5
+ # before `class Rubocop < Guard` in rubocop.rb
6
+ module RubocopVersion
7
+ # http://semver.org/
8
+ MAJOR = 0
9
+ MINOR = 1
10
+ PATCH = 1
11
+ VERSION = [MAJOR, MINOR, PATCH].join('.')
12
+ end
13
+ end
@@ -0,0 +1,302 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper.rb'
4
+
5
+ describe Guard::Rubocop::Runner do
6
+ subject(:runner) { Guard::Rubocop::Runner.new(options) }
7
+ let(:options) { {} }
8
+
9
+ describe '#run' do
10
+ subject { super().run(paths) }
11
+ let(:paths) { ['spec/spec_helper.rb'] }
12
+
13
+ before do
14
+ runner.stub(:system)
15
+ end
16
+
17
+ it 'executes rubocop' do
18
+ runner.should_receive(:system) do |*args|
19
+ args.first.should == 'rubocop'
20
+ end
21
+ runner.run
22
+ end
23
+
24
+ context 'when RuboCop exited with 0 status' do
25
+ before do
26
+ runner.stub(:system).and_return(true)
27
+ end
28
+ it { should be_true }
29
+ end
30
+
31
+ context 'when RuboCop exited with non 0 status' do
32
+ before do
33
+ runner.stub(:system).and_return(false)
34
+ end
35
+ it { should be_false }
36
+ end
37
+
38
+ shared_examples 'notifies', :notifies do
39
+ it 'notifies' do
40
+ runner.should_receive(:notify)
41
+ runner.run
42
+ end
43
+ end
44
+
45
+ shared_examples 'does not notify', :does_not_notify do
46
+ it 'does not notify' do
47
+ runner.should_not_receive(:notify)
48
+ runner.run
49
+ end
50
+ end
51
+
52
+ shared_examples 'notification' do |expectations|
53
+ context 'when passed' do
54
+ before do
55
+ runner.stub(:system).and_return(true)
56
+ end
57
+
58
+ if expectations[:passed]
59
+ include_examples 'notifies'
60
+ else
61
+ include_examples 'does not notify'
62
+ end
63
+ end
64
+
65
+ context 'when failed' do
66
+ before do
67
+ runner.stub(:system).and_return(false)
68
+ end
69
+
70
+ if expectations[:failed]
71
+ include_examples 'notifies'
72
+ else
73
+ include_examples 'does not notify'
74
+ end
75
+ end
76
+ end
77
+
78
+ context 'when :notification option is true' do
79
+ let(:options) { { notification: true } }
80
+ include_examples 'notification', { passed: true, failed: true }
81
+ end
82
+
83
+ context 'when :notification option is :failed' do
84
+ let(:options) { { notification: :failed } }
85
+ include_examples 'notification', { passed: false, failed: true }
86
+ end
87
+
88
+ context 'when :notification option is false' do
89
+ let(:options) { { notification: false } }
90
+ include_examples 'notification', { passed: false, failed: false }
91
+ end
92
+
93
+ context 'when :cops option is true' do
94
+ let(:options) { { cops: true } }
95
+
96
+ end
97
+ end
98
+
99
+ describe '#build_command' do
100
+ let(:paths) { %w(file1.rb file2.rb) }
101
+
102
+ it 'adds args for the default formatter for console' do
103
+ runner.build_command(paths)[0..2].should == %w(rubocop --format progress)
104
+ end
105
+
106
+ it 'adds args for JSON formatter ' do
107
+ runner.build_command(paths)[3..4].should == %w(--format json)
108
+ end
109
+
110
+ it 'adds args for output file path of JSON formatter ' do
111
+ command = runner.build_command(paths)
112
+ command[5].should == '--out'
113
+ command[6].should_not be_empty
114
+ end
115
+
116
+ context 'cops option is set' do
117
+ let(:options) { { cops: true } }
118
+
119
+ it 'adds the --list-cops flag' do
120
+ command = runner.build_command(paths)
121
+ command[7].should == '--list-cops'
122
+ end
123
+ end
124
+
125
+ it 'adds the passed paths' do
126
+ runner.build_command(paths)[7..-1].should == %w(file1.rb file2.rb)
127
+ end
128
+ end
129
+
130
+ describe '#json_file_path' do
131
+ it 'is not world readable' do
132
+ File.world_readable?(runner.json_file_path).should be_false
133
+ end
134
+ end
135
+
136
+ shared_context 'JSON file', :json_file do
137
+ before do
138
+ json = <<-END
139
+ {
140
+ "metadata": {
141
+ "rubocop_version": "0.9.0",
142
+ "ruby_engine": "ruby",
143
+ "ruby_version": "2.0.0",
144
+ "ruby_patchlevel": "195",
145
+ "ruby_platform": "x86_64-darwin12.3.0"
146
+ },
147
+ "files": [{
148
+ "path": "lib/foo.rb",
149
+ "offences": []
150
+ }, {
151
+ "path": "lib/bar.rb",
152
+ "offences": [{
153
+ "severity": "convention",
154
+ "message": "Line is too long. [81/79]",
155
+ "cop_name": "LineLength",
156
+ "location": {
157
+ "line": 546,
158
+ "column": 80
159
+ }
160
+ }, {
161
+ "severity": "warning",
162
+ "message": "Unreachable code detected.",
163
+ "cop_name": "UnreachableCode",
164
+ "location": {
165
+ "line": 15,
166
+ "column": 9
167
+ }
168
+ }
169
+ ]
170
+ }
171
+ ],
172
+ "summary": {
173
+ "offence_count": 2,
174
+ "target_file_count": 2,
175
+ "inspected_file_count": 2
176
+ }
177
+ }
178
+ END
179
+ File.write(runner.json_file_path, json)
180
+ end
181
+ end
182
+
183
+ describe '#result', :json_file do
184
+ it 'parses JSON file' do
185
+ runner.result[:summary][:offence_count].should == 2
186
+ end
187
+ end
188
+
189
+ describe '#notify' do
190
+ before do
191
+ runner.stub(:result).and_return(
192
+ {
193
+ summary: {
194
+ offence_count: 4,
195
+ target_file_count: 3,
196
+ inspected_file_count: 2
197
+ }
198
+ }
199
+ )
200
+ end
201
+
202
+ it 'notifies summary' do
203
+ Guard::Notifier.should_receive(:notify) do |message, options|
204
+ message.should == '2 files inspected, 4 offences detected'
205
+ end
206
+ runner.notify(true)
207
+ end
208
+
209
+ it 'notifies with title "RuboCop results"' do
210
+ Guard::Notifier.should_receive(:notify) do |message, options|
211
+ options[:title].should == 'RuboCop results'
212
+ end
213
+ runner.notify(true)
214
+ end
215
+
216
+ context 'when passed' do
217
+ it 'shows success image' do
218
+ Guard::Notifier.should_receive(:notify) do |message, options|
219
+ options[:image].should == :success
220
+ end
221
+ runner.notify(true)
222
+ end
223
+ end
224
+
225
+ context 'when failed' do
226
+ it 'shows failed image' do
227
+ Guard::Notifier.should_receive(:notify) do |message, options|
228
+ options[:image].should == :failed
229
+ end
230
+ runner.notify(false)
231
+ end
232
+ end
233
+ end
234
+
235
+ describe '#summary_text' do
236
+ before do
237
+ runner.stub(:result).and_return(
238
+ {
239
+ summary: {
240
+ offence_count: offence_count,
241
+ target_file_count: target_file_count,
242
+ inspected_file_count: inspected_file_count
243
+ }
244
+ }
245
+ )
246
+ end
247
+
248
+ subject(:summary_text) { runner.summary_text }
249
+
250
+ let(:offence_count) { 0 }
251
+ let(:target_file_count) { 0 }
252
+ let(:inspected_file_count) { 0 }
253
+
254
+ context 'when no files are inspected' do
255
+ let(:inspected_file_count) { 0 }
256
+ it 'includes "0 files"' do
257
+ summary_text.should include '0 files'
258
+ end
259
+ end
260
+
261
+ context 'when a file is inspected' do
262
+ let(:inspected_file_count) { 1 }
263
+ it 'includes "1 file"' do
264
+ summary_text.should include '1 file'
265
+ end
266
+ end
267
+
268
+ context 'when 2 files are inspected' do
269
+ let(:inspected_file_count) { 2 }
270
+ it 'includes "2 files"' do
271
+ summary_text.should include '2 files'
272
+ end
273
+ end
274
+
275
+ context 'when no offences are detected' do
276
+ let(:offence_count) { 0 }
277
+ it 'includes "no offences"' do
278
+ summary_text.should include 'no offences'
279
+ end
280
+ end
281
+
282
+ context 'when an offence is detected' do
283
+ let(:offence_count) { 1 }
284
+ it 'includes "1 offence"' do
285
+ summary_text.should include '1 offence'
286
+ end
287
+ end
288
+
289
+ context 'when 2 offences are detected' do
290
+ let(:offence_count) { 2 }
291
+ it 'includes "2 offences"' do
292
+ summary_text.should include '2 offences'
293
+ end
294
+ end
295
+ end
296
+
297
+ describe '#failed_paths', :json_file do
298
+ it 'returns file paths which have offences' do
299
+ runner.failed_paths.should == ['lib/bar.rb']
300
+ end
301
+ end
302
+ end
@@ -0,0 +1,202 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper.rb'
4
+
5
+ describe Guard::Rubocop, :silence_output do
6
+ subject(:guard) { Guard::Rubocop.new(watchers, options) }
7
+ let(:watchers) { [] }
8
+ let(:options) { {} }
9
+
10
+ let(:runner) { Guard::Rubocop::Runner.any_instance }
11
+
12
+ describe '#options' do
13
+ subject { super().options }
14
+
15
+ context 'by default' do
16
+ let(:options) { {} }
17
+ its([:all_on_start]) { should be_true }
18
+ its([:keep_failed]) { should be_true }
19
+ its([:notification]) { should == :failed }
20
+ its([:cops]) { should be_false }
21
+ end
22
+ end
23
+
24
+ describe '#start' do
25
+ context 'when :all_on_start option is enabled' do
26
+ let(:options) { { all_on_start: true } }
27
+
28
+ it 'runs all' do
29
+ guard.should_receive(:run_all)
30
+ guard.start
31
+ end
32
+ end
33
+
34
+ context 'when :all_on_start option is disabled' do
35
+ let(:options) { { all_on_start: false } }
36
+
37
+ it 'does nothing' do
38
+ guard.should_not_receive(:run_all)
39
+ guard.start
40
+ end
41
+ end
42
+ end
43
+
44
+ shared_examples 'processes after running', :processes_after_running do
45
+ context 'when passed' do
46
+ it 'throws nothing' do
47
+ runner.stub(:run).and_return(true)
48
+ expect { subject }.not_to throw_symbol
49
+ end
50
+
51
+ it 'clears failed paths' do
52
+ runner.stub(:run).and_return(true)
53
+ runner.stub(:failed_paths).and_return([])
54
+ subject
55
+ guard.failed_paths.should be_empty
56
+ end
57
+ end
58
+
59
+ context 'when failed' do
60
+ it 'throws symbol :task_has_failed' do
61
+ runner.stub(:run).and_return(false)
62
+ expect { subject }.to throw_symbol(:task_has_failed)
63
+ end
64
+
65
+ it 'keeps failed paths' do
66
+ guard.stub(:throw)
67
+ failed_paths = [
68
+ 'some_failed_file.rb',
69
+ 'dir/another_failed_file.rb'
70
+ ]
71
+ runner.stub(:run).and_return(false)
72
+ runner.stub(:failed_paths).and_return(failed_paths)
73
+ subject
74
+ guard.failed_paths.should == failed_paths
75
+ end
76
+ end
77
+
78
+ context 'when an exception is raised' do
79
+ it 'prevents itself from firing' do
80
+ runner.stub(:run).and_raise(RuntimeError)
81
+ expect { subject }.not_to raise_error
82
+ end
83
+ end
84
+ end
85
+
86
+ describe '#run_all', :processes_after_running do
87
+ subject { super().run_all }
88
+
89
+ before do
90
+ runner.stub(:run).and_return(true)
91
+ runner.stub(:failed_paths).and_return([])
92
+ end
93
+
94
+ it 'inspects all files with rubocop' do
95
+ runner.should_receive(:run).with([])
96
+ guard.run_all
97
+ end
98
+ end
99
+
100
+ describe '#run_on_changes', :processes_after_running do
101
+ subject { super().run_on_changes(changed_paths) }
102
+ let(:changed_paths) { ['some.rb', 'dir/another.rb', 'dir/../some.rb'] }
103
+
104
+ before do
105
+ runner.stub(:run).and_return(true)
106
+ runner.stub(:failed_paths).and_return([])
107
+ end
108
+
109
+ it 'inspects changed files with rubocop' do
110
+ runner.should_receive(:run)
111
+ guard.run_on_changes(changed_paths)
112
+ end
113
+
114
+ it 'passes cleaned paths to rubocop' do
115
+ runner.should_receive(:run) do |paths|
116
+ paths.should == [
117
+ File.expand_path('some.rb'),
118
+ File.expand_path('dir/another.rb')
119
+ ]
120
+ end
121
+ guard.run_on_changes(changed_paths)
122
+ end
123
+
124
+ let(:failed_path) { File.expand_path('failed_file_last_time.rb') }
125
+
126
+ context 'when :keep_failed option is enabled' do
127
+ let(:options) { { keep_failed: true } }
128
+
129
+ it 'also inspects paths which are failed last time' do
130
+ guard.failed_paths << failed_path
131
+ runner.should_receive(:run) do |paths|
132
+ paths.should include failed_path
133
+ end
134
+ guard.run_on_changes(changed_paths)
135
+ end
136
+ end
137
+
138
+ context 'when :keep_failed option is disabled' do
139
+ let(:options) { { keep_failed: false } }
140
+ let(:changed_paths) do
141
+ [
142
+ File.expand_path('some.rb'),
143
+ File.expand_path('dir/another.rb')
144
+ ]
145
+ end
146
+
147
+ it 'inspects just changed paths' do
148
+ guard.failed_paths << failed_path
149
+ runner.should_receive(:run) do |paths|
150
+ paths.should == changed_paths
151
+ end
152
+ guard.run_on_changes(changed_paths)
153
+ end
154
+ end
155
+ end
156
+
157
+ describe '#reload' do
158
+ it 'clears failed paths' do
159
+ guard.failed_paths << 'failed.rb'
160
+ guard.reload
161
+ guard.failed_paths.should be_empty
162
+ end
163
+ end
164
+
165
+ describe '#clean_paths' do
166
+ it 'converts to absolute paths' do
167
+ paths = [
168
+ 'lib/guard/rubocop.rb',
169
+ 'spec/spec_helper.rb'
170
+ ]
171
+ guard.clean_paths(paths).should == [
172
+ File.expand_path('lib/guard/rubocop.rb'),
173
+ File.expand_path('spec/spec_helper.rb')
174
+ ]
175
+ end
176
+
177
+ it 'removes duplicated paths' do
178
+ paths = [
179
+ 'lib/guard/rubocop.rb',
180
+ 'spec/spec_helper.rb',
181
+ 'lib/guard/../guard/rubocop.rb'
182
+ ]
183
+ guard.clean_paths(paths).should == [
184
+ File.expand_path('lib/guard/rubocop.rb'),
185
+ File.expand_path('spec/spec_helper.rb')
186
+ ]
187
+ end
188
+
189
+ it 'removes paths which are included in another path' do
190
+ paths = [
191
+ 'lib/guard/rubocop.rb',
192
+ 'spec/spec_helper.rb',
193
+ 'spec'
194
+ ]
195
+ guard.clean_paths(paths).should == [
196
+ File.expand_path('lib/guard/rubocop.rb'),
197
+ File.expand_path('spec')
198
+ ]
199
+ end
200
+ end
201
+
202
+ end
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+
3
+ RSpec.configure do |config|
4
+ config.treat_symbols_as_metadata_keys_with_true_values = true
5
+ end
6
+
7
+ Dir[File.join(File.dirname(__FILE__), 'support', '*')].each do |path|
8
+ require path
9
+ end
10
+
11
+ require 'simplecov'
12
+ SimpleCov.coverage_dir(File.join('spec', 'coverage'))
13
+
14
+ if ENV['TRAVIS']
15
+ require 'coveralls'
16
+ SimpleCov.formatter = Coveralls::SimpleCov::Formatter
17
+ elsif ENV['CI'] # rubocop:disable IfUnlessModifier
18
+ require 'simplecov-rcov'
19
+ SimpleCov.formatter = SimpleCov::Formatter::RcovFormatter
20
+ end
21
+
22
+ SimpleCov.start do
23
+ add_filter '/spec/'
24
+ add_filter '/vendor/bundle/'
25
+ end
26
+
27
+ require 'guard/rubocop'
@@ -0,0 +1,18 @@
1
+ # coding: utf-8
2
+
3
+ shared_context 'silence output', silence_output: true do
4
+ before do
5
+ null_output = double('output').as_null_object
6
+
7
+ @original_stdout = $stdout
8
+ @original_stderr = $stderr
9
+
10
+ $stdout = null_output
11
+ $stderr = null_output
12
+ end
13
+
14
+ after do
15
+ $stdout = @original_stdout
16
+ $stderr = @original_stderr
17
+ end
18
+ end
metadata ADDED
@@ -0,0 +1,195 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sabat-guard-rubocop
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Yuji Nakayama
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-07-04 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: guard
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.8'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.8'
30
+ - !ruby/object:Gem::Dependency
31
+ name: sabat-rubocop
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '0.9'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '0.9'
46
+ - !ruby/object:Gem::Dependency
47
+ name: bundler
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '1.3'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.3'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rake
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '10.0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '10.0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: rspec
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: '2.13'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: '2.13'
94
+ - !ruby/object:Gem::Dependency
95
+ name: simplecov
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: '0.7'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: '0.7'
110
+ - !ruby/object:Gem::Dependency
111
+ name: guard-rspec
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: '3.0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ~>
124
+ - !ruby/object:Gem::Version
125
+ version: '3.0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: ruby_gntp
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ~>
132
+ - !ruby/object:Gem::Version
133
+ version: '0.3'
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ~>
140
+ - !ruby/object:Gem::Version
141
+ version: '0.3'
142
+ description: Guard::Rubocop automatically checks Ruby code style with RuboCop when
143
+ files are modified.
144
+ email:
145
+ - nkymyj@gmail.com
146
+ executables: []
147
+ extensions: []
148
+ extra_rdoc_files: []
149
+ files:
150
+ - CHANGELOG.md
151
+ - Gemfile
152
+ - Guardfile
153
+ - LICENSE.txt
154
+ - README.md
155
+ - Rakefile
156
+ - guard-rubocop.gemspec
157
+ - lib/guard/rubocop.rb
158
+ - lib/guard/rubocop/runner.rb
159
+ - lib/guard/rubocop/templates/Guardfile
160
+ - lib/guard/rubocop/version.rb
161
+ - spec/guard/rubocop/runner_spec.rb
162
+ - spec/guard/rubocop_spec.rb
163
+ - spec/spec_helper.rb
164
+ - spec/support/silence_output.rb
165
+ homepage: https://github.com/sabat/guard-rubocop
166
+ licenses:
167
+ - MIT
168
+ post_install_message:
169
+ rdoc_options: []
170
+ require_paths:
171
+ - lib
172
+ required_ruby_version: !ruby/object:Gem::Requirement
173
+ none: false
174
+ requirements:
175
+ - - ! '>='
176
+ - !ruby/object:Gem::Version
177
+ version: '0'
178
+ required_rubygems_version: !ruby/object:Gem::Requirement
179
+ none: false
180
+ requirements:
181
+ - - ! '>='
182
+ - !ruby/object:Gem::Version
183
+ version: '0'
184
+ requirements: []
185
+ rubyforge_project:
186
+ rubygems_version: 1.8.25
187
+ signing_key:
188
+ specification_version: 3
189
+ summary: Guard plugin for RuboCop
190
+ test_files:
191
+ - spec/guard/rubocop/runner_spec.rb
192
+ - spec/guard/rubocop_spec.rb
193
+ - spec/spec_helper.rb
194
+ - spec/support/silence_output.rb
195
+ has_rdoc: