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.

Files changed (39) hide show
  1. data/Gemfile +1 -0
  2. data/Gemfile.lock +2 -0
  3. data/VERSION +1 -1
  4. data/bin/rubocop +10 -2
  5. data/lib/rubocop.rb +16 -1
  6. data/lib/rubocop/cli.rb +48 -13
  7. data/lib/rubocop/cop/cop.rb +60 -3
  8. data/lib/rubocop/cop/empty_lines.rb +25 -0
  9. data/lib/rubocop/cop/encoding.rb +17 -0
  10. data/lib/rubocop/cop/grammar.rb +74 -0
  11. data/lib/rubocop/cop/indentation.rb +55 -0
  12. data/lib/rubocop/cop/line_length.rb +19 -0
  13. data/lib/rubocop/cop/offence.rb +12 -4
  14. data/lib/rubocop/cop/space_after_comma_etc.rb +24 -0
  15. data/lib/rubocop/cop/surrounding_space.rb +44 -0
  16. data/lib/rubocop/cop/tab.rb +17 -0
  17. data/lib/rubocop/cop/trailing_whitespace.rb +17 -0
  18. data/lib/rubocop/report/emacs_style.rb +15 -0
  19. data/lib/rubocop/report/plain_text.rb +18 -0
  20. data/lib/rubocop/report/report.rb +41 -0
  21. data/lib/rubocop/version.rb +2 -0
  22. data/rubocop.gemspec +103 -0
  23. data/spec/rubocop/cli_spec.rb +61 -0
  24. data/spec/rubocop/cops/cop_spec.rb +29 -0
  25. data/spec/rubocop/cops/empty_lines_spec.rb +82 -0
  26. data/spec/rubocop/cops/grammar_spec.rb +24 -0
  27. data/spec/rubocop/cops/indentation_spec.rb +60 -0
  28. data/spec/rubocop/cops/line_length_spec.rb +20 -0
  29. data/spec/rubocop/cops/offence_spec.rb +22 -0
  30. data/spec/rubocop/cops/space_after_comma_etc_spec.rb +37 -0
  31. data/spec/rubocop/cops/surrounding_space_spec.rb +128 -0
  32. data/spec/rubocop/cops/tab_spec.rb +19 -0
  33. data/spec/rubocop/cops/trailing_whitespace_spec.rb +25 -0
  34. data/spec/rubocop/reports/emacs_style_spec.rb +23 -0
  35. data/spec/rubocop/reports/report_spec.rb +27 -0
  36. data/spec/spec_helper.rb +25 -1
  37. metadata +88 -18
  38. data/lib/rubocop/cop/line_length_cop.rb +0 -11
  39. 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
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Rubocop
2
4
  VERSION = "0.0.1"
3
5
  end
@@ -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