rubocop-cask 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a7bfd4f036ef39c44b9eb7b4674f42f9b01914c8
4
- data.tar.gz: 22211aefd4d93daeb700fcdbb2b1749b539cbc5f
3
+ metadata.gz: 9cdfd026586c969df6476b261c953b19a97c0d96
4
+ data.tar.gz: f5eec7b28ca3f9011a73505bb1caef81ccc09ed4
5
5
  SHA512:
6
- metadata.gz: 7ff1dfab7f15095c227549f4dc54d44c1cab1c398b64767c070c01e38d60b46f65f4c5233ae1a101111428a1e1bcfc436f8c18f1a2f43c9aa60c976a73134689
7
- data.tar.gz: 5807adcf506a9da06929422184d3d831665abf94d5f532d0c11d801f86718812b78f54cb7023af5d7f8ccdae348ff452ddd65892def4bfa64ee3f703a824266a
6
+ metadata.gz: 087b2408052d624ca8c94b59de9314474261bdd63f728e0673763fc76a3a7e750ce4288d19580ff83d6342b722989e0bebb0dcd430692ca97efe90e117583ead
7
+ data.tar.gz: 05aed98a4ea27b6ac1060476de4aa6b0a70a52ba9e41c7c2ff12824b9fbea4ff994e93bbb9bd40a6e8d6e6a582d6b28b7b4902bda59bb43a7660e1f6c6169fb8
data/lib/rubocop-cask.rb CHANGED
@@ -1,5 +1,9 @@
1
1
  require 'rubocop'
2
2
 
3
+ require 'rubocop/cask/node_help'
4
+ require 'rubocop/cask/cask_help'
5
+ require 'rubocop/cask/cask_header'
6
+ require 'rubocop/cask/cask_block'
3
7
  require 'rubocop/cask/version'
4
8
  require 'rubocop/cask/inject'
5
9
 
@@ -0,0 +1,20 @@
1
+ module RuboCop
2
+ module Cask
3
+ # This class wraps the AST block node that represents the entire cask
4
+ # definition. It includes various helper methods to aid cops in their
5
+ # analysis.
6
+ class CaskBlock
7
+ include CaskHelp
8
+
9
+ attr_reader :block_node
10
+
11
+ def initialize(block_node)
12
+ @block_node = block_node
13
+ end
14
+
15
+ def header
16
+ @header ||= CaskHeader.new(method_node(block_node))
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,59 @@
1
+ module RuboCop
2
+ module Cask
3
+ # This class wraps the AST method node that represents the cask header. It
4
+ # includes various helper methods to aid cops in their analysis.
5
+ class CaskHeader
6
+ include CaskHelp
7
+
8
+ attr_reader :method_node
9
+
10
+ def initialize(method_node)
11
+ @method_node = method_node
12
+ end
13
+
14
+ def dsl_version?
15
+ hash_node
16
+ end
17
+
18
+ def test_cask?
19
+ header_method_name == :test_cask || dsl_version.to_s.include?('test')
20
+ end
21
+
22
+ def header_str
23
+ @header_str ||= source_range.source
24
+ end
25
+
26
+ def source_range
27
+ @source_range ||= method_node.loc.expression
28
+ end
29
+
30
+ def preferred_header_str
31
+ "#{preferred_header_method_name} '#{cask_token}'"
32
+ end
33
+
34
+ def preferred_header_method_name
35
+ test_cask? ? :test_cask : :cask
36
+ end
37
+
38
+ def header_method_name
39
+ @header_method_name ||= method_name(method_node)
40
+ end
41
+
42
+ def dsl_version
43
+ @dsl_version ||= key_node(pair_node).children.first
44
+ end
45
+
46
+ def cask_token
47
+ @cask_token ||= value_node(pair_node).children.first
48
+ end
49
+
50
+ def hash_node
51
+ @hash_node ||= hash_children(method_node).first
52
+ end
53
+
54
+ def pair_node
55
+ @pair_node ||= pair_children(hash_node).first
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,32 @@
1
+ module RuboCop
2
+ module Cask
3
+ # Common functionality for cops checking casks
4
+ module CaskHelp
5
+ include NodeHelp
6
+
7
+ CASK_METHOD_NAMES = %i(cask test_cask)
8
+
9
+ def cask?(block_node)
10
+ block?(block_node) && cask_method?(method_node(block_node))
11
+ end
12
+
13
+ def cask_method?(method_node)
14
+ CASK_METHOD_NAMES.include?(method_name(method_node))
15
+ end
16
+
17
+ def cask_children(node)
18
+ node_children(node).select { |e| cask?(e) }
19
+ end
20
+
21
+ def on_block(block_node)
22
+ super if defined? super
23
+ return unless respond_to?(:on_cask)
24
+ return unless cask?(block_node)
25
+
26
+ method_node, _args, block_body = *block_node
27
+
28
+ on_cask(block_node, method_node, block_body)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,81 @@
1
+ module RuboCop
2
+ module Cask
3
+ # Helpers for traversing AST nodes
4
+ module NodeHelp
5
+ def root_node
6
+ processed_source.ast
7
+ end
8
+
9
+ def node?(node, type: nil)
10
+ return unless node.is_a?(Parser::AST::Node)
11
+ type ? node.type == type : true
12
+ end
13
+
14
+ def method?(node)
15
+ node?(node, type: :send)
16
+ end
17
+
18
+ def block?(node)
19
+ node?(node, type: :block)
20
+ end
21
+
22
+ def hash?(node)
23
+ node?(node, type: :hash)
24
+ end
25
+
26
+ def pair?(node)
27
+ node?(node, type: :pair)
28
+ end
29
+
30
+ def node_children(node, type: nil)
31
+ node.children.select { |e| node?(e, type: type) }
32
+ end
33
+
34
+ def method_children(node)
35
+ node_children(node, type: :send)
36
+ end
37
+
38
+ def block_children(node)
39
+ node_children(node, type: :block)
40
+ end
41
+
42
+ def hash_children(node)
43
+ node_children(node, type: :hash)
44
+ end
45
+
46
+ def pair_children(node)
47
+ node_children(node, type: :pair)
48
+ end
49
+
50
+ def method_node(block_node)
51
+ fail 'Not a block node' unless block?(block_node)
52
+ method_node, _args, _body = *block_node
53
+ method_node
54
+ end
55
+
56
+ def method_name(method_node)
57
+ fail 'Not a send node' unless method?(method_node)
58
+ _receiver, method_name, *_method_args = *method_node
59
+ method_name
60
+ end
61
+
62
+ def method_args(method_node)
63
+ fail 'Not a send node' unless method?(method_node)
64
+ _receiver, _method_name, *method_args = *method_node
65
+ method_args
66
+ end
67
+
68
+ def key_node(pair_node)
69
+ fail 'Not a pair node' unless pair?(pair_node)
70
+ key_node, _value_node = *pair_node
71
+ key_node
72
+ end
73
+
74
+ def value_node(pair_node)
75
+ fail 'Not a pair node' unless pair?(pair_node)
76
+ _key_node, value_node = *pair_node
77
+ value_node
78
+ end
79
+ end
80
+ end
81
+ end
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module Cask
5
5
  # Version information for the Cask RuboCop plugin.
6
6
  module Version
7
- STRING = '0.0.1'
7
+ STRING = '0.1.0'
8
8
 
9
9
  def self.gem_version
10
10
  Gem::Version.new(STRING)
@@ -1,3 +1,5 @@
1
+ require 'forwardable'
2
+
1
3
  module RuboCop
2
4
  module Cop
3
5
  module Cask
@@ -14,34 +16,43 @@ module RuboCop
14
16
  # ...
15
17
  # end
16
18
  class NoDslVersion < Cop
19
+ extend Forwardable
20
+ include RuboCop::Cask::CaskHelp
21
+
17
22
  MESSAGE = 'Use `%s` instead of `%s`'
18
23
 
19
- CASK_METHOD_NAMES = [:cask, :test_cask]
24
+ def on_cask(_block_node, method_node, _block_body)
25
+ @cask_header = cask_header(method_node)
26
+ return unless offense?
27
+ offense
28
+ end
20
29
 
21
- def on_block(node)
22
- method, _args, _body = node.children
23
- _receiver, method_name, object = method.children
24
- return unless CASK_METHOD_NAMES.include?(method_name)
25
- check(method_name, object)
30
+ def autocorrect(method_node)
31
+ @cask_header = cask_header(method_node)
32
+ lambda do |corrector|
33
+ corrector.replace(header_range, preferred_header_str)
34
+ end
26
35
  end
27
36
 
28
37
  private
29
38
 
30
- def check(method_name, object)
31
- return unless object.type == :hash
32
- message = build_message(method_name, object)
33
- add_offense(object, :expression, message)
39
+ def_delegator :@cask_header, :source_range, :header_range
40
+ def_delegators :@cask_header, :header_str, :preferred_header_str
41
+
42
+ def cask_header(method_node)
43
+ RuboCop::Cask::CaskHeader.new(method_node)
44
+ end
45
+
46
+ def offense?
47
+ @cask_header.dsl_version?
48
+ end
49
+
50
+ def offense
51
+ add_offense(@cask_header.method_node, header_range, error_msg)
34
52
  end
35
53
 
36
- def build_message(method_name, object)
37
- left, right = *object.children.first
38
- cask_token = right.children.first
39
- dsl_version_str = left.children.first.to_s
40
- new_method_name =
41
- dsl_version_str.include?('test') ? :test_cask : method_name
42
- preferred_header = "#{new_method_name} '#{cask_token}'"
43
- actual_header = "#{method_name} #{object.loc.expression.source}"
44
- format(MESSAGE, preferred_header, actual_header)
54
+ def error_msg
55
+ format(MESSAGE, preferred_header_str, header_str)
45
56
  end
46
57
  end
47
58
  end
@@ -1,58 +1,105 @@
1
1
  describe RuboCop::Cop::Cask::NoDslVersion do
2
2
  subject(:cop) { described_class.new }
3
3
 
4
- it 'checks for dsl version in cask header' do
5
- inspect_source(cop, [
6
- "cask :v1 => 'foo' do",
7
- 'end'
8
- ])
9
- expect(cop.offenses.size).to eq(1)
10
- expect(cop.offenses.first.line).to eq(1)
11
- expect(cop.messages)
12
- .to eq(["Use `cask 'foo'` instead of `cask :v1 => 'foo'`"])
13
- expect(cop.highlights)
14
- .to eq([":v1 => 'foo'"])
15
- end
4
+ context 'with header method `cask`' do
5
+ context 'with no dsl version' do
6
+ it 'passes' do
7
+ inspect_source(cop, [
8
+ "cask 'foo' do",
9
+ 'end'
10
+ ])
11
+ expect(cop.offenses).to be_empty
12
+ end
13
+ end
16
14
 
17
- it 'checks for dsl version with test in cask header' do
18
- inspect_source(cop, [
19
- "cask :v1test => 'foo' do",
20
- 'end'
21
- ])
22
- expect(cop.offenses.size).to eq(1)
23
- expect(cop.offenses.first.line).to eq(1)
24
- expect(cop.messages)
25
- .to eq(["Use `test_cask 'foo'` instead of `cask :v1test => 'foo'`"])
26
- expect(cop.highlights)
27
- .to eq([":v1test => 'foo'"])
28
- end
15
+ context 'with dsl version' do
16
+ it 'fails' do
17
+ inspect_source(cop, [
18
+ "cask :v1 => 'foo' do",
19
+ 'end'
20
+ ])
21
+ expect(cop.offenses.size).to eq(1)
22
+ expect(cop.offenses.first.line).to eq(1)
23
+ expect(cop.messages)
24
+ .to eq(["Use `cask 'foo'` instead of `cask :v1 => 'foo'`"])
25
+ expect(cop.highlights)
26
+ .to eq(["cask :v1 => 'foo'"])
27
+ end
29
28
 
30
- it 'ignores cask header with no dsl version' do
31
- inspect_source(cop, [
32
- "cask 'foo' do",
33
- 'end'
34
- ])
35
- expect(cop.offenses).to be_empty
36
- end
29
+ it 'autocorrects' do
30
+ new_source = autocorrect_source(cop, [
31
+ "cask :v1 => 'foo' do",
32
+ 'end'
33
+ ])
34
+ expect(new_source).to eq([
35
+ "cask 'foo' do",
36
+ 'end'
37
+ ].join("\n"))
38
+ end
39
+ end
37
40
 
38
- it 'checks for dsl version in test_cask header' do
39
- inspect_source(cop, [
40
- "test_cask :v1 => 'foo' do",
41
- 'end'
42
- ])
43
- expect(cop.offenses.size).to eq(1)
44
- expect(cop.offenses.first.line).to eq(1)
45
- expect(cop.messages)
46
- .to eq(["Use `test_cask 'foo'` instead of `test_cask :v1 => 'foo'`"])
47
- expect(cop.highlights)
48
- .to eq([":v1 => 'foo'"])
41
+ context 'with dsl version containing "test"' do
42
+ it 'fails' do
43
+ inspect_source(cop, [
44
+ "cask :v1test => 'foo' do",
45
+ 'end'
46
+ ])
47
+ expect(cop.offenses.size).to eq(1)
48
+ expect(cop.offenses.first.line).to eq(1)
49
+ expect(cop.messages)
50
+ .to eq(["Use `test_cask 'foo'` instead of `cask :v1test => 'foo'`"])
51
+ expect(cop.highlights)
52
+ .to eq(["cask :v1test => 'foo'"])
53
+ end
54
+
55
+ it 'autocorrects' do
56
+ new_source = autocorrect_source(cop, [
57
+ "cask :v1test => 'foo' do",
58
+ 'end'
59
+ ])
60
+ expect(new_source).to eq([
61
+ "test_cask 'foo' do",
62
+ 'end'
63
+ ].join("\n"))
64
+ end
65
+ end
49
66
  end
50
67
 
51
- it 'ignores test_cask header with no dsl version' do
52
- inspect_source(cop, [
53
- "test_cask 'foo' do",
54
- 'end'
55
- ])
56
- expect(cop.offenses).to be_empty
68
+ context 'with header method `test_cask`' do
69
+ context 'with no dsl version' do
70
+ it 'passes' do
71
+ inspect_source(cop, [
72
+ "test_cask 'foo' do",
73
+ 'end'
74
+ ])
75
+ expect(cop.offenses).to be_empty
76
+ end
77
+ end
78
+
79
+ context 'with dsl version' do
80
+ it 'fails' do
81
+ inspect_source(cop, [
82
+ "test_cask :v1 => 'foo' do",
83
+ 'end'
84
+ ])
85
+ expect(cop.offenses.size).to eq(1)
86
+ expect(cop.offenses.first.line).to eq(1)
87
+ expect(cop.messages)
88
+ .to eq(["Use `test_cask 'foo'` instead of `test_cask :v1 => 'foo'`"])
89
+ expect(cop.highlights)
90
+ .to eq(["test_cask :v1 => 'foo'"])
91
+ end
92
+
93
+ it 'autocorrects' do
94
+ new_source = autocorrect_source(cop, [
95
+ "test_cask :v1 => 'foo' do",
96
+ 'end'
97
+ ])
98
+ expect(new_source).to eq([
99
+ "test_cask 'foo' do",
100
+ 'end'
101
+ ].join("\n"))
102
+ end
103
+ end
57
104
  end
58
105
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-cask
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joshua Hagins
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-18 00:00:00.000000000 Z
11
+ date: 2015-12-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -39,13 +39,17 @@ files:
39
39
  - README.md
40
40
  - config/default.yml
41
41
  - lib/rubocop-cask.rb
42
+ - lib/rubocop/cask/cask_block.rb
43
+ - lib/rubocop/cask/cask_header.rb
44
+ - lib/rubocop/cask/cask_help.rb
42
45
  - lib/rubocop/cask/inject.rb
46
+ - lib/rubocop/cask/node_help.rb
43
47
  - lib/rubocop/cask/version.rb
44
48
  - lib/rubocop/cop/cask/no_dsl_version.rb
45
49
  - spec/project_spec.rb
46
50
  - spec/rubocop/cop/cask/no_dsl_version_spec.rb
47
51
  - spec/spec_helper.rb
48
- homepage: https://github.com/jawshooah/rubocop-cask
52
+ homepage: https://github.com/caskroom/rubocop-cask
49
53
  licenses:
50
54
  - MIT
51
55
  metadata: {}
@@ -65,7 +69,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
65
69
  version: '0'
66
70
  requirements: []
67
71
  rubyforge_project:
68
- rubygems_version: 2.4.5.1
72
+ rubygems_version: 2.5.1
69
73
  signing_key:
70
74
  specification_version: 4
71
75
  summary: Code style checking for Homebrew-Cask files