rubocop 0.0.0 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rubocop might be problematic. Click here for more details.
- data/Gemfile +1 -0
- data/Gemfile.lock +2 -0
- data/VERSION +1 -1
- data/bin/rubocop +10 -2
- data/lib/rubocop.rb +16 -1
- data/lib/rubocop/cli.rb +48 -13
- data/lib/rubocop/cop/cop.rb +60 -3
- data/lib/rubocop/cop/empty_lines.rb +25 -0
- data/lib/rubocop/cop/encoding.rb +17 -0
- data/lib/rubocop/cop/grammar.rb +74 -0
- data/lib/rubocop/cop/indentation.rb +55 -0
- data/lib/rubocop/cop/line_length.rb +19 -0
- data/lib/rubocop/cop/offence.rb +12 -4
- data/lib/rubocop/cop/space_after_comma_etc.rb +24 -0
- data/lib/rubocop/cop/surrounding_space.rb +44 -0
- data/lib/rubocop/cop/tab.rb +17 -0
- data/lib/rubocop/cop/trailing_whitespace.rb +17 -0
- data/lib/rubocop/report/emacs_style.rb +15 -0
- data/lib/rubocop/report/plain_text.rb +18 -0
- data/lib/rubocop/report/report.rb +41 -0
- data/lib/rubocop/version.rb +2 -0
- data/rubocop.gemspec +103 -0
- data/spec/rubocop/cli_spec.rb +61 -0
- data/spec/rubocop/cops/cop_spec.rb +29 -0
- data/spec/rubocop/cops/empty_lines_spec.rb +82 -0
- data/spec/rubocop/cops/grammar_spec.rb +24 -0
- data/spec/rubocop/cops/indentation_spec.rb +60 -0
- data/spec/rubocop/cops/line_length_spec.rb +20 -0
- data/spec/rubocop/cops/offence_spec.rb +22 -0
- data/spec/rubocop/cops/space_after_comma_etc_spec.rb +37 -0
- data/spec/rubocop/cops/surrounding_space_spec.rb +128 -0
- data/spec/rubocop/cops/tab_spec.rb +19 -0
- data/spec/rubocop/cops/trailing_whitespace_spec.rb +25 -0
- data/spec/rubocop/reports/emacs_style_spec.rb +23 -0
- data/spec/rubocop/reports/report_spec.rb +27 -0
- data/spec/spec_helper.rb +25 -1
- metadata +88 -18
- data/lib/rubocop/cop/line_length_cop.rb +0 -11
- data/spec/rubocop_spec.rb +0 -7
@@ -0,0 +1,24 @@
|
|
1
|
+
module Rubocop
|
2
|
+
module Cop
|
3
|
+
class SpaceAfterCommaEtc < Cop
|
4
|
+
ERROR_MESSAGE = 'Space missing after %s.'
|
5
|
+
|
6
|
+
def inspect(file, source, tokens, sexp)
|
7
|
+
tokens.each_index { |ix|
|
8
|
+
pos, name, text = tokens[ix]
|
9
|
+
kind = case name
|
10
|
+
when :on_comma then 'comma'
|
11
|
+
when :on_label then 'colon'
|
12
|
+
when :on_op then 'colon' if text == ':'
|
13
|
+
when :on_semicolon then 'semicolon'
|
14
|
+
end
|
15
|
+
if kind and not [:on_sp, :on_ignored_nl].include?(tokens[ix + 1][1])
|
16
|
+
index = pos[0] - 1
|
17
|
+
add_offence(:convention, index, source[index],
|
18
|
+
ERROR_MESSAGE % kind)
|
19
|
+
end
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require_relative 'grammar'
|
2
|
+
|
3
|
+
module Rubocop
|
4
|
+
module Cop
|
5
|
+
class SurroundingSpace < Cop
|
6
|
+
ERROR_MESSAGE = 'Surrounding space missing for operator'
|
7
|
+
|
8
|
+
def inspect(file, source, tokens, sexp)
|
9
|
+
Grammar.new(tokens).correlate(sexp).sort.each { |ix, grammar_path|
|
10
|
+
pos, name, text = tokens[ix]
|
11
|
+
if name == :on_op
|
12
|
+
unless surrounded_by_whitespace?(tokens[ix - 1, 3])
|
13
|
+
unless ok_without_spaces?(grammar_path)
|
14
|
+
index = pos[0] - 1
|
15
|
+
add_offence(:convention, index, source[index],
|
16
|
+
ERROR_MESSAGE + " '#{text}'.")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
def ok_without_spaces?(grammar_path)
|
24
|
+
grandparent, parent, child = grammar_path.values_at(-3, -2, -1)
|
25
|
+
return true if [:unary, :symbol, :defs, :def, :call].include?(parent)
|
26
|
+
return true if [:rest_param, :blockarg, :block_var, :args_add_star,
|
27
|
+
:args_add_block, :const_path_ref, :dot2,
|
28
|
+
:dot3].include?(child)
|
29
|
+
return true if grandparent == :unary && parent == :vcall
|
30
|
+
return true if parent == :command_call && child == :'::'
|
31
|
+
false
|
32
|
+
end
|
33
|
+
|
34
|
+
def surrounded_by_whitespace?(nearby_tokens)
|
35
|
+
left, _, right = nearby_tokens
|
36
|
+
whitespace?(left) && whitespace?(right)
|
37
|
+
end
|
38
|
+
|
39
|
+
def whitespace?(token)
|
40
|
+
[:on_sp, :on_ignored_nl, :on_nl].include?(token[1])
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Rubocop
|
4
|
+
module Cop
|
5
|
+
class Tab < Cop
|
6
|
+
ERROR_MESSAGE = 'Tab detected.'
|
7
|
+
|
8
|
+
def inspect(file, source)
|
9
|
+
source.each_with_index do |line, index|
|
10
|
+
if line =~ /^ *\t/
|
11
|
+
add_offence(:convention, index, line, ERROR_MESSAGE)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Rubocop
|
4
|
+
module Cop
|
5
|
+
class TrailingWhitespace < Cop
|
6
|
+
ERROR_MESSAGE = 'Trailing whitespace detected.'
|
7
|
+
|
8
|
+
def inspect(file, source)
|
9
|
+
source.each_with_index do |line, index|
|
10
|
+
if line =~ /.*[ \t]+$/
|
11
|
+
add_offence(:convention, index, line, ERROR_MESSAGE)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Rubocop
|
4
|
+
module Report
|
5
|
+
# Plain text report, suitable for display in Emacs *compilation* buffers.
|
6
|
+
class EmacsStyle < PlainText
|
7
|
+
# Generates a string representation of the report
|
8
|
+
def generate
|
9
|
+
entries.map { |e|
|
10
|
+
"#@filename:#{e.line_number + 1}: #{e.encode_severity}: #{e.message}"
|
11
|
+
}.join("\n")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Rubocop
|
4
|
+
module Report
|
5
|
+
# Plain text report, suitable for display in terminals.
|
6
|
+
class PlainText < Report
|
7
|
+
# Generates a string representation of the report
|
8
|
+
def generate
|
9
|
+
report = "== #{filename} ==\n"
|
10
|
+
report << entries.join("\n")
|
11
|
+
end
|
12
|
+
|
13
|
+
def display(stream = $stdout)
|
14
|
+
stream.puts generate
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Rubocop
|
4
|
+
module Report
|
5
|
+
# Creates a Report object, based on the current settings
|
6
|
+
#
|
7
|
+
# @param [String] the filename for the report
|
8
|
+
# @return [Report] a report object
|
9
|
+
def create(file, output_mode = :default)
|
10
|
+
case output_mode
|
11
|
+
when :default then PlainText.new(file)
|
12
|
+
when :emacs_style then EmacsStyle.new(file)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module_function :create
|
17
|
+
|
18
|
+
class Report
|
19
|
+
attr_accessor :entries
|
20
|
+
attr_accessor :filename
|
21
|
+
|
22
|
+
# @param [String] the filename for this report
|
23
|
+
def initialize(filename)
|
24
|
+
@filename = filename
|
25
|
+
@entries = []
|
26
|
+
end
|
27
|
+
|
28
|
+
# Appends offences registered by cops to the report.
|
29
|
+
# @param [Cop] a cop with something to report
|
30
|
+
def <<(cop)
|
31
|
+
cop.offences.each do |entry|
|
32
|
+
@entries << entry
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def empty?
|
37
|
+
entries.empty?
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/rubocop/version.rb
CHANGED
data/rubocop.gemspec
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "rubocop"
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Bozhidar Batsov"]
|
12
|
+
s.date = "2012-12-20"
|
13
|
+
s.description = "Automatic Ruby code style checking tool. Aims to enforce the community-driven Ruby Style Guide."
|
14
|
+
s.email = "bozhidar@batsov.com"
|
15
|
+
s.executables = ["rubocop"]
|
16
|
+
s.extra_rdoc_files = [
|
17
|
+
"LICENSE.txt",
|
18
|
+
"README.md"
|
19
|
+
]
|
20
|
+
s.files = [
|
21
|
+
".document",
|
22
|
+
".rspec",
|
23
|
+
".rvmrc",
|
24
|
+
"Gemfile",
|
25
|
+
"Gemfile.lock",
|
26
|
+
"LICENSE.txt",
|
27
|
+
"README.md",
|
28
|
+
"Rakefile",
|
29
|
+
"VERSION",
|
30
|
+
"bin/rubocop",
|
31
|
+
"features/rubocop.feature",
|
32
|
+
"features/step_definitions/rubocop_steps.rb",
|
33
|
+
"features/support/env.rb",
|
34
|
+
"lib/rubocop.rb",
|
35
|
+
"lib/rubocop/cli.rb",
|
36
|
+
"lib/rubocop/cop/cop.rb",
|
37
|
+
"lib/rubocop/cop/empty_lines.rb",
|
38
|
+
"lib/rubocop/cop/encoding.rb",
|
39
|
+
"lib/rubocop/cop/grammar.rb",
|
40
|
+
"lib/rubocop/cop/indentation.rb",
|
41
|
+
"lib/rubocop/cop/line_length.rb",
|
42
|
+
"lib/rubocop/cop/offence.rb",
|
43
|
+
"lib/rubocop/cop/space_after_comma_etc.rb",
|
44
|
+
"lib/rubocop/cop/surrounding_space.rb",
|
45
|
+
"lib/rubocop/cop/tab.rb",
|
46
|
+
"lib/rubocop/cop/trailing_whitespace.rb",
|
47
|
+
"lib/rubocop/report/emacs_style.rb",
|
48
|
+
"lib/rubocop/report/plain_text.rb",
|
49
|
+
"lib/rubocop/report/report.rb",
|
50
|
+
"lib/rubocop/version.rb",
|
51
|
+
"rubocop.gemspec",
|
52
|
+
"spec/rubocop/cli_spec.rb",
|
53
|
+
"spec/rubocop/cops/cop_spec.rb",
|
54
|
+
"spec/rubocop/cops/empty_lines_spec.rb",
|
55
|
+
"spec/rubocop/cops/grammar_spec.rb",
|
56
|
+
"spec/rubocop/cops/indentation_spec.rb",
|
57
|
+
"spec/rubocop/cops/line_length_spec.rb",
|
58
|
+
"spec/rubocop/cops/offence_spec.rb",
|
59
|
+
"spec/rubocop/cops/space_after_comma_etc_spec.rb",
|
60
|
+
"spec/rubocop/cops/surrounding_space_spec.rb",
|
61
|
+
"spec/rubocop/cops/tab_spec.rb",
|
62
|
+
"spec/rubocop/cops/trailing_whitespace_spec.rb",
|
63
|
+
"spec/rubocop/reports/emacs_style_spec.rb",
|
64
|
+
"spec/rubocop/reports/report_spec.rb",
|
65
|
+
"spec/spec_helper.rb"
|
66
|
+
]
|
67
|
+
s.homepage = "http://github.com/bbatsov/rubocop"
|
68
|
+
s.licenses = ["MIT"]
|
69
|
+
s.require_paths = ["lib"]
|
70
|
+
s.rubygems_version = "1.8.23"
|
71
|
+
s.summary = "Automatic Ruby code style checking tool."
|
72
|
+
|
73
|
+
if s.respond_to? :specification_version then
|
74
|
+
s.specification_version = 3
|
75
|
+
|
76
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
77
|
+
s.add_development_dependency(%q<rspec>, ["~> 2.8.0"])
|
78
|
+
s.add_development_dependency(%q<yard>, ["~> 0.7"])
|
79
|
+
s.add_development_dependency(%q<redcarpet>, [">= 0"])
|
80
|
+
s.add_development_dependency(%q<cucumber>, [">= 0"])
|
81
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.1.0"])
|
82
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.8.3"])
|
83
|
+
s.add_development_dependency(%q<simplecov>, [">= 0"])
|
84
|
+
else
|
85
|
+
s.add_dependency(%q<rspec>, ["~> 2.8.0"])
|
86
|
+
s.add_dependency(%q<yard>, ["~> 0.7"])
|
87
|
+
s.add_dependency(%q<redcarpet>, [">= 0"])
|
88
|
+
s.add_dependency(%q<cucumber>, [">= 0"])
|
89
|
+
s.add_dependency(%q<bundler>, ["~> 1.1.0"])
|
90
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
|
91
|
+
s.add_dependency(%q<simplecov>, [">= 0"])
|
92
|
+
end
|
93
|
+
else
|
94
|
+
s.add_dependency(%q<rspec>, ["~> 2.8.0"])
|
95
|
+
s.add_dependency(%q<yard>, ["~> 0.7"])
|
96
|
+
s.add_dependency(%q<redcarpet>, [">= 0"])
|
97
|
+
s.add_dependency(%q<cucumber>, [">= 0"])
|
98
|
+
s.add_dependency(%q<bundler>, ["~> 1.1.0"])
|
99
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
|
100
|
+
s.add_dependency(%q<simplecov>, [">= 0"])
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Rubocop
|
4
|
+
module Report
|
5
|
+
describe CLI do
|
6
|
+
let(:cli) { CLI.new }
|
7
|
+
before(:each) { $stdout = StringIO.new }
|
8
|
+
after(:each) { $stdout = STDOUT }
|
9
|
+
|
10
|
+
it 'exits cleanly when -h is used' do
|
11
|
+
lambda { cli.run ['-h'] }.should exit_with_code(0)
|
12
|
+
lambda { cli.run ['--help'] }.should exit_with_code(0)
|
13
|
+
message = ['Usage: rubocop [options] [file1, file2, ...]',
|
14
|
+
' -v, --[no-]verbose Run verbosely',
|
15
|
+
' -e, --emacs Emacs style output']
|
16
|
+
$stdout.string.should == (message * 2).join("\n") + "\n"
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'checks a given correct file and returns 0' do
|
20
|
+
File.open('example.rb', 'w') { |f| f.puts 'x = 0' }
|
21
|
+
begin
|
22
|
+
cli.run(['example.rb']).should == 0
|
23
|
+
$stdout.string.should == "\n1 files inspected, 0 offences detected\n"
|
24
|
+
ensure
|
25
|
+
File.delete 'example.rb'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'checks a given file with faults and returns 1' do
|
30
|
+
File.open('example.rb', 'w') { |f| f.puts 'x = 0 ' }
|
31
|
+
begin
|
32
|
+
cli.run(['example.rb']).should == 1
|
33
|
+
$stdout.string.should == ['== example.rb ==',
|
34
|
+
'C: 0: Trailing whitespace detected.',
|
35
|
+
'',
|
36
|
+
'1 files inspected, 1 offences detected',
|
37
|
+
''].join("\n")
|
38
|
+
ensure
|
39
|
+
File.delete 'example.rb'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'can report in emacs style' do
|
44
|
+
File.open('example1.rb', 'w') { |f| f.puts 'x = 0 ' }
|
45
|
+
File.open('example2.rb', 'w') { |f| f.puts "\tx = 0" }
|
46
|
+
begin
|
47
|
+
cli.run(['--emacs', 'example1.rb', 'example2.rb']).should == 1
|
48
|
+
$stdout.string.should ==
|
49
|
+
['example1.rb:1: C: Trailing whitespace detected.',
|
50
|
+
'example2.rb:1: C: Tab detected.',
|
51
|
+
'',
|
52
|
+
'2 files inspected, 2 offences detected',
|
53
|
+
''].join("\n")
|
54
|
+
ensure
|
55
|
+
File.delete 'example1.rb'
|
56
|
+
File.delete 'example2.rb'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Rubocop
|
4
|
+
module Cop
|
5
|
+
describe Cop do
|
6
|
+
let (:cop) { Cop.new }
|
7
|
+
|
8
|
+
it 'initially has 0 offences' do
|
9
|
+
cop.offences.size.should == 0
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'initially has nothing to report' do
|
13
|
+
cop.has_report?.should be_false
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'keeps track of offences' do
|
17
|
+
cop.add_offence('file', 0, 'line', 'message')
|
18
|
+
|
19
|
+
cop.offences.size.should == 1
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'will report registered offences' do
|
23
|
+
cop.add_offence('file', 0, 'line', 'message')
|
24
|
+
|
25
|
+
cop.has_report?.should be_true
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Rubocop
|
4
|
+
module Cop
|
5
|
+
describe EmptyLines do
|
6
|
+
let (:empty_lines) { EmptyLines.new }
|
7
|
+
|
8
|
+
it 'finds offences in inner classes' do
|
9
|
+
empty_lines.inspect_source('', ['class K',
|
10
|
+
' def m',
|
11
|
+
' end',
|
12
|
+
' class J',
|
13
|
+
' def n',
|
14
|
+
' end',
|
15
|
+
' def o',
|
16
|
+
' end',
|
17
|
+
' end',
|
18
|
+
' # checks something',
|
19
|
+
' def p',
|
20
|
+
' end',
|
21
|
+
'end'])
|
22
|
+
empty_lines.offences.size.should == 2
|
23
|
+
empty_lines.offences.map(&:line).sort.should == [' def o',
|
24
|
+
' def p']
|
25
|
+
end
|
26
|
+
|
27
|
+
# Only one def, so rule about empty line *between* defs does not
|
28
|
+
# apply.
|
29
|
+
it 'accepts a def that follows a line with code' do
|
30
|
+
empty_lines.inspect_source('', ['x = 0',
|
31
|
+
'def m',
|
32
|
+
'end'])
|
33
|
+
empty_lines.offences.size.should == 0
|
34
|
+
end
|
35
|
+
|
36
|
+
# Only one def, so rule about empty line *between* defs does not
|
37
|
+
# apply.
|
38
|
+
it 'accepts a def that follows code and a comment' do
|
39
|
+
empty_lines.inspect_source('', [' x = 0',
|
40
|
+
' # 123',
|
41
|
+
' def m',
|
42
|
+
' end'])
|
43
|
+
empty_lines.offences.size.should == 0
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'accepts the first def without leading empty line in a class' do
|
47
|
+
empty_lines.inspect_source('', ['class K',
|
48
|
+
' def m',
|
49
|
+
' end',
|
50
|
+
'end'])
|
51
|
+
empty_lines.offences.size.should == 0
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'accepts a def that follows an empty line and then a comment' do
|
55
|
+
empty_lines.inspect_source('', ['class A',
|
56
|
+
' # calculates value',
|
57
|
+
' def m',
|
58
|
+
' end',
|
59
|
+
'',
|
60
|
+
' private',
|
61
|
+
' # calculates size',
|
62
|
+
' def n',
|
63
|
+
' end',
|
64
|
+
'end',
|
65
|
+
])
|
66
|
+
empty_lines.offences.size.should == 0
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'accepts a def that is the first of a module' do
|
70
|
+
source = ['module Util',
|
71
|
+
' public',
|
72
|
+
' #',
|
73
|
+
' def html_escape(s)',
|
74
|
+
' end',
|
75
|
+
'end',
|
76
|
+
]
|
77
|
+
empty_lines.inspect_source('', source)
|
78
|
+
empty_lines.offences.map(&:message).should == []
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|