sabat-guard-rubocop 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: