rubocop-cask 0.0.1 → 0.1.0

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.
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