guideline 0.0.5 → 0.0.6

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/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: