guideline 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/bin/guideline CHANGED
@@ -8,6 +8,7 @@ options = Runner.parse(ARGV)
8
8
 
9
9
  checkers = CheckerFactory.new(
10
10
  options[:config],
11
+ UnusedMethodChecker,
11
12
  HashCommaChecker,
12
13
  LongLineChecker,
13
14
  LongMethodChecker,
@@ -15,5 +16,6 @@ checkers = CheckerFactory.new(
15
16
  ).create
16
17
 
17
18
  visitor = Visitor.new(:only => ARGV[0], :checker => checkers)
19
+ visitor.prepare
18
20
  visitor.visit
19
21
  visitor.render
data/guideline.gemspec CHANGED
@@ -18,6 +18,7 @@ Gem::Specification.new do |gem|
18
18
  gem.require_paths = ["lib"]
19
19
 
20
20
  gem.add_dependency "slop"
21
+ gem.add_dependency "code_analyzer"
21
22
  gem.add_dependency "active_support"
22
23
  gem.add_dependency "i18n"
23
24
  gem.add_development_dependency "rspec", ">=2.12.0"
@@ -0,0 +1,114 @@
1
+ require "code_analyzer"
2
+
3
+ module Guideline
4
+ class UnusedMethodChecker < Checker
5
+ def check(path)
6
+ definition_visitor.check(path.to_s, path.read)
7
+ report_unused_methods(path)
8
+ clear_definitions
9
+ end
10
+
11
+ def prepare(path)
12
+ call_visitor.check(path.to_s, path.read)
13
+ end
14
+
15
+ private
16
+
17
+ def calls
18
+ @calls ||= []
19
+ end
20
+
21
+ def call_visitor
22
+ create_visitor(call_checker)
23
+ end
24
+
25
+ def call_checker
26
+ MethodCallChecker.new do |method_name|
27
+ calls << method_name
28
+ end
29
+ end
30
+
31
+ def definitions
32
+ @definitions ||= []
33
+ end
34
+
35
+ def definition_visitor
36
+ create_visitor(definition_checker)
37
+ end
38
+
39
+ def definition_checker
40
+ MethodDefinitionChecker.new do |definition|
41
+ definitions << definition
42
+ end
43
+ end
44
+
45
+ def create_visitor(checker)
46
+ CodeAnalyzer::CheckingVisitor::Default.new(checkers: [checker])
47
+ end
48
+
49
+ def report_unused_methods(path)
50
+ unused_methods.each do |method|
51
+ report(
52
+ :message => "Remove unused method <#{method.name}>",
53
+ :path => path,
54
+ :line => method.line
55
+ )
56
+ end
57
+ end
58
+
59
+ def unused_methods
60
+ definitions.reject do |method|
61
+ calls.include?(method.name)
62
+ end
63
+ end
64
+
65
+ def clear_definitions
66
+ definitions.clear
67
+ end
68
+
69
+ class MethodChecker < CodeAnalyzer::Checker
70
+ def initialize(*, &callback)
71
+ @callback = callback
72
+ super
73
+ end
74
+
75
+ def call(method)
76
+ @callback.call(method)
77
+ end
78
+ end
79
+
80
+ class MethodDefinitionChecker < MethodChecker
81
+ interesting_files /.*\.rb/
82
+ interesting_nodes :def
83
+
84
+ add_callback :start_def do |node|
85
+ definition = Definition.new(:line => node.line, :name => node.method_name.to_s)
86
+ call(definition)
87
+ end
88
+ end
89
+
90
+ class MethodCallChecker < MethodChecker
91
+ interesting_files /.*\.rb/
92
+ interesting_nodes :call, :fcall, :vcall, :var_ref
93
+
94
+ add_callback :start_call do |node|
95
+ call(node.message.to_s)
96
+ end
97
+
98
+ add_callback :start_fcall do |node|
99
+ call(node.message.to_s)
100
+ end
101
+
102
+ add_callback :start_vcall do |node|
103
+ call(node.to_s)
104
+ end
105
+
106
+ add_callback :start_var_ref do |node|
107
+ call(node.to_s)
108
+ end
109
+ end
110
+
111
+ class Definition < OpenStruct
112
+ end
113
+ end
114
+ end
@@ -8,6 +8,7 @@ module Guideline
8
8
  def parse(argv)
9
9
  hash = Parser.parse(argv)
10
10
  hash[:config] = load_config(hash[:config])
11
+ hash.delete(:help)
11
12
  hash
12
13
  end
13
14
 
@@ -1,3 +1,3 @@
1
1
  module Guideline
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  end
@@ -16,7 +16,14 @@ module Guideline
16
16
  checker.check(path)
17
17
  end
18
18
  end
19
- self
19
+ end
20
+
21
+ def prepare
22
+ paths.each do |path|
23
+ checkers.each do |checker|
24
+ checker.prepare(path) if checker.respond_to?(:prepare)
25
+ end
26
+ end
20
27
  end
21
28
 
22
29
  def render
data/lib/guideline.rb CHANGED
@@ -8,3 +8,4 @@ require "guideline/checkers/long_line_checker"
8
8
  require "guideline/checkers/long_method_checker"
9
9
  require "guideline/checkers/hard_tab_indent_checker"
10
10
  require "guideline/checkers/hash_comma_checker"
11
+ require "guideline/checkers/unused_method_checker"
@@ -8,11 +8,11 @@ module Guideline
8
8
  end
9
9
 
10
10
  let(:path) do
11
- mock(:each_line => content.each_line)
11
+ mock(:each_line => script.each_line)
12
12
  end
13
13
 
14
14
  context "when there is hard tab indent" do
15
- let(:content) do
15
+ let(:script) do
16
16
  <<-EOF
17
17
  def foo
18
18
  \t1
@@ -20,14 +20,14 @@ module Guideline
20
20
  EOF
21
21
  end
22
22
 
23
- specify "checker detects error" do
23
+ it "detects error" do
24
24
  checker.check(path)
25
25
  checker.should have_error
26
26
  end
27
27
  end
28
28
 
29
29
  context "when there is no hard tab indent" do
30
- let(:content) do
30
+ let(:script) do
31
31
  <<-EOF
32
32
  def foo
33
33
  1
@@ -35,7 +35,7 @@ module Guideline
35
35
  EOF
36
36
  end
37
37
 
38
- specify "checker does not detect error" do
38
+ it "does not detect error" do
39
39
  checker.check(path)
40
40
  checker.should_not have_error
41
41
  end
@@ -23,7 +23,7 @@ module Guideline
23
23
  EOF
24
24
  end
25
25
 
26
- specify "checker does not detect error" do
26
+ it "does not detect error" do
27
27
  should_not have_error
28
28
  end
29
29
  end
@@ -35,7 +35,7 @@ module Guideline
35
35
  EOF
36
36
  end
37
37
 
38
- specify "checker does not detect error" do
38
+ it "does not detect error" do
39
39
  should_not have_error
40
40
  end
41
41
  end
@@ -49,7 +49,21 @@ module Guideline
49
49
  EOF
50
50
  end
51
51
 
52
- specify "checker detects error" do
52
+ it "detects error" do
53
+ should have_error
54
+ end
55
+ end
56
+
57
+ context "when there is no last comma in multiline hash of new syntax" do
58
+ let(:script) do
59
+ <<-EOF
60
+ {
61
+ a: 1
62
+ }
63
+ EOF
64
+ end
65
+
66
+ it "detects error" do
53
67
  should have_error
54
68
  end
55
69
  end
@@ -63,7 +77,7 @@ module Guideline
63
77
  EOF
64
78
  end
65
79
 
66
- specify "checker detects error" do
80
+ it "detects error" do
67
81
  should have_error
68
82
  end
69
83
  end
@@ -77,7 +91,7 @@ module Guideline
77
91
  EOF
78
92
  end
79
93
 
80
- specify "checker does not detect error" do
94
+ it "does not detect error" do
81
95
  should_not have_error
82
96
  end
83
97
  end
@@ -93,7 +107,7 @@ module Guideline
93
107
  EOF
94
108
  end
95
109
 
96
- specify "checker detects error" do
110
+ it "detects error" do
97
111
  should have_error
98
112
  end
99
113
  end
@@ -8,11 +8,11 @@ module Guideline
8
8
  end
9
9
 
10
10
  let(:path) do
11
- mock(:each_line => content.each_line)
11
+ mock(:each_line => script.each_line)
12
12
  end
13
13
 
14
14
  context "when there is too line" do
15
- let(:content) do
15
+ let(:script) do
16
16
  <<-EOF
17
17
  def foo
18
18
  too looooooooooooooooooooooooong line
@@ -20,14 +20,14 @@ module Guideline
20
20
  EOF
21
21
  end
22
22
 
23
- specify "checker detects error" do
23
+ it "detects error" do
24
24
  checker.check(path)
25
25
  checker.should have_error
26
26
  end
27
27
  end
28
28
 
29
29
  context "when there is no too long line" do
30
- let(:content) do
30
+ let(:script) do
31
31
  <<-EOF
32
32
  def foo
33
33
  not loooooooooooooooooooooooong line
@@ -35,7 +35,7 @@ module Guideline
35
35
  EOF
36
36
  end
37
37
 
38
- specify "checker does not detect error" do
38
+ it "does not detect error" do
39
39
  checker.check(path)
40
40
  checker.should_not have_error
41
41
  end
@@ -8,11 +8,11 @@ module Guideline
8
8
  end
9
9
 
10
10
  let(:path) do
11
- mock(:read => content)
11
+ mock(:read => script)
12
12
  end
13
13
 
14
14
  context "when there is too long method" do
15
- let(:content) do
15
+ let(:script) do
16
16
  <<-EOF
17
17
  def foo
18
18
  1
@@ -21,14 +21,14 @@ module Guideline
21
21
  EOF
22
22
  end
23
23
 
24
- specify "checker detects error" do
24
+ it "detects error" do
25
25
  checker.check(path)
26
26
  checker.should have_error
27
27
  end
28
28
  end
29
29
 
30
30
  context "when there is no too long method" do
31
- let(:content) do
31
+ let(:script) do
32
32
  <<-EOF
33
33
  def foo
34
34
  1
@@ -36,7 +36,7 @@ module Guideline
36
36
  EOF
37
37
  end
38
38
 
39
- specify "checker does not detect error" do
39
+ it "does not detect error" do
40
40
  checker.check(path)
41
41
  checker.should_not have_error
42
42
  end
@@ -0,0 +1,73 @@
1
+ require "spec_helper"
2
+
3
+ module Guideline
4
+ describe UnusedMethodChecker do
5
+ let(:checker) do
6
+ described_class.new
7
+ end
8
+
9
+ let(:path) do
10
+ mock(:read => script, :to_s => "mock.rb")
11
+ end
12
+
13
+ describe "#prepare" do
14
+ let(:script) do
15
+ <<-EOF
16
+ a
17
+ b()
18
+ d.c
19
+ f.e()
20
+ EOF
21
+ end
22
+
23
+ it "remembers method calls" do
24
+ checker.prepare(path)
25
+ checker.send(:calls).should == %w[a b c d e f]
26
+ end
27
+ end
28
+
29
+ describe "#check" do
30
+ before do
31
+ checker.instance_variable_set(:@calls, %w[a b])
32
+ end
33
+
34
+ let(:script) do
35
+ <<-EOF
36
+ def a
37
+ 1
38
+ end
39
+
40
+ def b
41
+ 2
42
+ end
43
+
44
+ def c
45
+ 3
46
+ end
47
+ EOF
48
+ end
49
+
50
+ it "remembers method definitions" do
51
+ checker.stub(:clear_definitions)
52
+ checker.check(path)
53
+ checker.send(:definitions).map(&:name).should == %w[a b c]
54
+ end
55
+
56
+ it "detects unused method definitions" do
57
+ checker.stub(:clear_definitions)
58
+ checker.check(path)
59
+ checker.send(:unused_methods).map(&:name).should == %w[c]
60
+ end
61
+
62
+ it "reports unused method definitions" do
63
+ checker.should_receive(:report)
64
+ checker.check(path)
65
+ end
66
+
67
+ it "clears up its definitions after check" do
68
+ checker.check(path)
69
+ checker.send(:definitions).should be_empty
70
+ end
71
+ end
72
+ end
73
+ end
@@ -7,17 +7,34 @@ module Guideline
7
7
  described_class.parse(argv)
8
8
  end
9
9
 
10
+ before do
11
+ YAML.stub(:load_file).and_return(config)
12
+ end
13
+
14
+ let(:config) do
15
+ { "a" => 1 }
16
+ end
17
+
10
18
  let(:path) do
11
19
  File.expand_path("../../../guideline.yml", __FILE__)
12
20
  end
13
21
 
14
- context "when config option is passed" do
15
- let(:argv) do
16
- ["--config", path]
17
- end
22
+ let(:argv) do
23
+ ["--config", path]
24
+ end
18
25
 
19
- it "parses ARGV and returns options with config hash" do
20
- should have_key(:config)
26
+ it "loads config option as YAML path" do
27
+ YAML.should_receive(:load_file).with(path)
28
+ subject
29
+ end
30
+
31
+ it "returns config option as HashWithIndifferentAccess" do
32
+ subject[:config].should be_a HashWithIndifferentAccess
33
+ end
34
+
35
+ context "when config option is passed" do
36
+ it "returns parsed options" do
37
+ should == { :config => config }
21
38
  end
22
39
  end
23
40
 
@@ -26,8 +43,8 @@ module Guideline
26
43
  ["-c", path]
27
44
  end
28
45
 
29
- it "parses ARGV and returns options with config hash" do
30
- should have_key(:config)
46
+ it "returns parsed options" do
47
+ should == { :config => config }
31
48
  end
32
49
  end
33
50
 
@@ -36,20 +53,11 @@ module Guideline
36
53
  []
37
54
  end
38
55
 
39
- it "parses ARGV and returns options with config hash" do
56
+ it "returns parsed options with default config path" do
57
+ described_class.should_receive(:default_config_path)
40
58
  should have_key(:config)
41
59
  end
42
60
  end
43
-
44
- context "when config option is wrong" do
45
- let(:argv) do
46
- ["--config", "wrong config path"]
47
- end
48
-
49
- it do
50
- expect { subject }.to raise_error(StandardError)
51
- end
52
- end
53
61
  end
54
62
  end
55
63
  end
@@ -23,10 +23,34 @@ module Guideline
23
23
  end
24
24
 
25
25
  describe "#visit" do
26
- it "calls checker#check with matched path" do
26
+ it "calls checker#check with path" do
27
27
  checker.should_receive(:check).with(path)
28
28
  visitor.visit
29
29
  end
30
30
  end
31
+
32
+ describe "#prepare" do
33
+ context "if checker can respond to #prepare" do
34
+ before do
35
+ checker.stub(:respond_to?).with(:prepare).and_return(true)
36
+ end
37
+
38
+ it "calls checker#prepare with path" do
39
+ checker.should_receive(:prepare).with(path)
40
+ visitor.prepare
41
+ end
42
+ end
43
+
44
+ context "if checker cannot respond to #prepare" do
45
+ before do
46
+ checker.stub(:respond_to?).with(:prepare).and_return(false)
47
+ end
48
+
49
+ it "does not call checker#prepare with path" do
50
+ checker.should_not_receive(:prepare)
51
+ visitor.prepare
52
+ end
53
+ end
54
+ end
31
55
  end
32
56
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: guideline
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-23 00:00:00.000000000 Z
12
+ date: 2012-11-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: slop
16
- requirement: &70304744680520 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,31 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70304744680520
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: code_analyzer
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
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'
25
46
  - !ruby/object:Gem::Dependency
26
47
  name: active_support
27
- requirement: &70304744680100 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
28
49
  none: false
29
50
  requirements:
30
51
  - - ! '>='
@@ -32,10 +53,15 @@ dependencies:
32
53
  version: '0'
33
54
  type: :runtime
34
55
  prerelease: false
35
- version_requirements: *70304744680100
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
36
62
  - !ruby/object:Gem::Dependency
37
63
  name: i18n
38
- requirement: &70304744679680 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
39
65
  none: false
40
66
  requirements:
41
67
  - - ! '>='
@@ -43,10 +69,15 @@ dependencies:
43
69
  version: '0'
44
70
  type: :runtime
45
71
  prerelease: false
46
- version_requirements: *70304744679680
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
47
78
  - !ruby/object:Gem::Dependency
48
79
  name: rspec
49
- requirement: &70304744679180 !ruby/object:Gem::Requirement
80
+ requirement: !ruby/object:Gem::Requirement
50
81
  none: false
51
82
  requirements:
52
83
  - - ! '>='
@@ -54,10 +85,15 @@ dependencies:
54
85
  version: 2.12.0
55
86
  type: :development
56
87
  prerelease: false
57
- version_requirements: *70304744679180
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: 2.12.0
58
94
  - !ruby/object:Gem::Dependency
59
95
  name: pry
60
- requirement: &70304744678760 !ruby/object:Gem::Requirement
96
+ requirement: !ruby/object:Gem::Requirement
61
97
  none: false
62
98
  requirements:
63
99
  - - ! '>='
@@ -65,7 +101,12 @@ dependencies:
65
101
  version: '0'
66
102
  type: :development
67
103
  prerelease: false
68
- version_requirements: *70304744678760
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
69
110
  description: Guideline.gem checks if your code observes your coding guidelines
70
111
  email:
71
112
  - r7kamura@gmail.com
@@ -89,6 +130,7 @@ files:
89
130
  - lib/guideline/checkers/hash_comma_checker.rb
90
131
  - lib/guideline/checkers/long_line_checker.rb
91
132
  - lib/guideline/checkers/long_method_checker.rb
133
+ - lib/guideline/checkers/unused_method_checker.rb
92
134
  - lib/guideline/error.rb
93
135
  - lib/guideline/runner.rb
94
136
  - lib/guideline/version.rb
@@ -99,6 +141,7 @@ files:
99
141
  - spec/guideline/checkers/hash_comma_checker_spec.rb
100
142
  - spec/guideline/checkers/long_line_checker_spec.rb
101
143
  - spec/guideline/checkers/long_method_checker_spec.rb
144
+ - spec/guideline/checkers/unused_method_checker_spec.rb
102
145
  - spec/guideline/runner_spec.rb
103
146
  - spec/guideline/visitor_spec.rb
104
147
  - spec/guideline_spec.rb
@@ -123,7 +166,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
123
166
  version: '0'
124
167
  requirements: []
125
168
  rubyforge_project:
126
- rubygems_version: 1.8.15
169
+ rubygems_version: 1.8.24
127
170
  signing_key:
128
171
  specification_version: 3
129
172
  summary: The guideline of your code
@@ -134,8 +177,8 @@ test_files:
134
177
  - spec/guideline/checkers/hash_comma_checker_spec.rb
135
178
  - spec/guideline/checkers/long_line_checker_spec.rb
136
179
  - spec/guideline/checkers/long_method_checker_spec.rb
180
+ - spec/guideline/checkers/unused_method_checker_spec.rb
137
181
  - spec/guideline/runner_spec.rb
138
182
  - spec/guideline/visitor_spec.rb
139
183
  - spec/guideline_spec.rb
140
184
  - spec/spec_helper.rb
141
- has_rdoc: