rubocop-cask 0.2.2 → 0.3.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: d6a5b8a17cf24bee4d483755261047e0b8e36545
4
- data.tar.gz: 411f20070b3fe9c196afa06df99e3bd495080346
3
+ metadata.gz: bb51eac3550f067eca7d72c40f8e328b22b5025c
4
+ data.tar.gz: 47d413dba32958d1ac635d8b2c6fbdd56408cef7
5
5
  SHA512:
6
- metadata.gz: 4af05ad480b53239355e3622893caf33db75f510c161e18b6b9d44c1c4ef3207752b4c4d6b8a2b76c3eeaa50bdeab4b9e884d8984903b3f1cfa85949c4c8f45d
7
- data.tar.gz: 30c12c402d6194e77bdf40077b0b8647da6103b64f7aabd6abde1c4fdfa20f09cc65d58d880bdf7457af6aaf5a0de76ec742792ac03818967073519644be348e
6
+ metadata.gz: 2c35ec1f44568927cdd99ebbab3fb0905dffa3452a6e8d3d29fee49cdea1f6480fa8dd86c4ba60686e6e46f294e816a1ea1bf2e5c45cab341faece793defedbc
7
+ data.tar.gz: 4abb51a80d7d1a24a1ae4fd300779da7bed220b539381e8a2b84c51ddfa63361d89798be085d300a39965a451ed9e22650819e3e94db975d18e71b6806559c82
data/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  [![Code Climate](https://codeclimate.com/github/caskroom/rubocop-cask/badges/gpa.svg)](https://codeclimate.com/github/caskroom/rubocop-cask)
8
8
  [![Inline docs](http://inch-ci.org/github/caskroom/rubocop-cask.svg)](http://inch-ci.org/github/caskroom/rubocop-cask)
9
9
 
10
- Cask-specific analysis for your Homebrew-Cask taps, as an extension to
10
+ Cask-specific analysis for your [Homebrew-Cask](https://github.com/caskroom/homebrew-cask) taps, as an extension to
11
11
  [RuboCop](https://github.com/bbatsov/rubocop). Heavily inspired by [`rubocop-rspec`](https://github.com/nevir/rubocop-rspec).
12
12
 
13
13
 
@@ -1,11 +1,15 @@
1
- Cask/NoDslVersion:
2
- Description: 'Do not use the deprecated DSL version syntax in your cask header.'
1
+ Cask/LicenseUnknownComment:
2
+ Description: 'Always follow `license :unknown` with the machine-generated TODO comment.'
3
3
  Enabled: true
4
4
 
5
- Cask/StanzaOrder:
6
- Description: 'Ensure that cask stanzas are sorted correctly. More info at https://github.com/caskroom/homebrew-cask/blob/master/CONTRIBUTING.md#stanza-order'
5
+ Cask/NoDslVersion:
6
+ Description: 'Do not use the deprecated DSL version syntax in your cask header.'
7
7
  Enabled: true
8
8
 
9
9
  Cask/StanzaGrouping:
10
10
  Description: 'Ensure that cask stanzas are grouped correctly. More info at https://github.com/caskroom/homebrew-cask/blob/master/CONTRIBUTING.md#stanza-order'
11
11
  Enabled: true
12
+
13
+ Cask/StanzaOrder:
14
+ Description: 'Ensure that cask stanzas are sorted correctly. More info at https://github.com/caskroom/homebrew-cask/blob/master/CONTRIBUTING.md#stanza-order'
15
+ Enabled: true
@@ -12,6 +12,7 @@ require 'rubocop/cask/inject'
12
12
  RuboCop::Cask::Inject.defaults!
13
13
 
14
14
  require 'rubocop/cop/cask/mixin/cask_help'
15
+ require 'rubocop/cop/cask/license_unknown_comment'
15
16
  require 'rubocop/cop/cask/no_dsl_version'
16
17
  require 'rubocop/cop/cask/stanza_order'
17
18
  require 'rubocop/cop/cask/stanza_grouping'
@@ -18,16 +18,15 @@ module RuboCop
18
18
 
19
19
  alias_method :cask_node, :block_node
20
20
 
21
- def cask_body
22
- cask_node.block_body
23
- end
21
+ def_delegator :cask_node, :block_body, :cask_body
24
22
 
25
23
  def header
26
24
  @header ||= CaskHeader.new(cask_node.method_node)
27
25
  end
28
26
 
29
27
  def stanzas
30
- @stanzas ||= cask_body.descendants
28
+ return [] unless cask_body
29
+ @stanzas ||= cask_body.each_node
31
30
  .select(&:stanza?)
32
31
  .map { |node| Stanza.new(node, stanza_comments(node)) }
33
32
  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.2.2'
7
+ STRING = '0.3.0'
8
8
 
9
9
  def self.gem_version
10
10
  Gem::Version.new(STRING)
@@ -0,0 +1,74 @@
1
+ require 'pry'
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Cask
6
+ # This cop checks that if a cask uses `license :unknown`, it is followed
7
+ # on the same line by the machine-generated TODO comment.
8
+ class LicenseUnknownComment < Cop
9
+ include CaskHelp
10
+
11
+ COMMENT_TEXT = '# TODO: change license and remove this comment; ' \
12
+ "':unknown' is a machine-generated placeholder"
13
+ MISSING_MSG = "Missing required comment: `#{COMMENT_TEXT}'"
14
+ INLINE_MSG = "Comment belongs on the same line as `license :unknown'"
15
+
16
+ def on_cask(cask_block)
17
+ license_stanza = cask_block.stanzas.find(&:license?)
18
+ return unless license_stanza && license_unknown?(license_stanza)
19
+ add_offenses(license_stanza)
20
+ end
21
+
22
+ def autocorrect(stanza)
23
+ lambda do |corrector|
24
+ comment = license_unknown_comment
25
+ remove_comment(corrector, comment) if comment
26
+ add_comment(corrector, stanza)
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ attr_reader :cask_block
33
+
34
+ def license_unknown?(stanza)
35
+ stanza.source.include?(':unknown')
36
+ end
37
+
38
+ def add_offenses(stanza)
39
+ comment = license_unknown_comment
40
+ add_missing_offense(stanza) unless comment
41
+ add_not_inline_offense(stanza, comment) if comment &&
42
+ !on_same_line?(stanza, comment)
43
+ end
44
+
45
+ def license_unknown_comment
46
+ processed_source.comments.find { |c| c.text == COMMENT_TEXT }
47
+ end
48
+
49
+ def add_missing_offense(stanza)
50
+ add_offense(stanza, stanza.source_range, MISSING_MSG)
51
+ end
52
+
53
+ def add_not_inline_offense(stanza, comment)
54
+ add_offense(stanza, comment.loc.expression, INLINE_MSG)
55
+ end
56
+
57
+ def on_same_line?(stanza, comment)
58
+ stanza.source_range.line == comment.loc.line
59
+ end
60
+
61
+ def remove_comment(corrector, comment)
62
+ line = comment.loc.line
63
+ length = processed_source[line - 1].length
64
+ range = source_range(processed_source.buffer, line, 0, length + 1)
65
+ corrector.remove(range)
66
+ end
67
+
68
+ def add_comment(corrector, stanza)
69
+ corrector.insert_after(stanza.source_range, " #{COMMENT_TEXT}")
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -40,11 +40,11 @@ module RuboCop
40
40
  end
41
41
 
42
42
  def offending_stanzas
43
- offending = []
44
- toplevel_stanzas.each_with_index do |stanza, i|
45
- offending << stanza unless stanza == sorted_toplevel_stanzas[i]
43
+ stanza_pairs = toplevel_stanzas.zip(sorted_toplevel_stanzas)
44
+ stanza_pairs.each_with_object([]) do |stanza_pair, offending_stanzas|
45
+ stanza, sorted_stanza = *stanza_pair
46
+ offending_stanzas << stanza unless stanza == sorted_stanza
46
47
  end
47
- offending
48
48
  end
49
49
  end
50
50
  end
@@ -0,0 +1,87 @@
1
+ describe RuboCop::Cop::Cask::LicenseUnknownComment do
2
+ include CopSharedExamples
3
+
4
+ subject(:cop) { described_class.new }
5
+ let(:license_unknown_comment) { described_class.const_get(:COMMENT_TEXT) }
6
+
7
+ context 'when cask has no license stanza' do
8
+ let(:source) { "cask 'foo' do; end" }
9
+
10
+ include_examples 'does not report any offenses'
11
+ end
12
+
13
+ context 'when license is not :unknown' do
14
+ let(:source) do
15
+ <<-CASK.undent
16
+ cask 'foo' do
17
+ license :mit
18
+ end
19
+ CASK
20
+ end
21
+
22
+ include_examples 'does not report any offenses'
23
+ end
24
+
25
+ context 'when license is :unknown' do
26
+ let(:correct_source) do
27
+ <<-CASK.undent
28
+ cask 'foo' do
29
+ license :unknown #{license_unknown_comment}
30
+ end
31
+ CASK
32
+ end
33
+
34
+ context 'with required comment on same line' do
35
+ let(:source) { correct_source }
36
+
37
+ include_examples 'does not report any offenses'
38
+ end
39
+
40
+ context 'with required comment on preceding line' do
41
+ let(:source) do
42
+ <<-CASK.undent
43
+ cask 'foo' do
44
+ #{license_unknown_comment}
45
+ license :unknown
46
+ end
47
+ CASK
48
+ end
49
+ let(:expected_offenses) do
50
+ [{
51
+ message: "Comment belongs on the same line as `license :unknown'",
52
+ severity: :convention,
53
+ line: 2,
54
+ column: 2,
55
+ source: "#{license_unknown_comment}"
56
+ }]
57
+ end
58
+
59
+ include_examples 'reports offenses'
60
+
61
+ include_examples 'autocorrects source'
62
+ end
63
+
64
+ context 'with required comment missing' do
65
+ let(:source) do
66
+ <<-CASK.undent
67
+ cask 'foo' do
68
+ license :unknown
69
+ end
70
+ CASK
71
+ end
72
+ let(:expected_offenses) do
73
+ [{
74
+ message: "Missing required comment: `#{license_unknown_comment}'",
75
+ severity: :convention,
76
+ line: 2,
77
+ column: 2,
78
+ source: 'license :unknown'
79
+ }]
80
+ end
81
+
82
+ include_examples 'reports offenses'
83
+
84
+ include_examples 'autocorrects source'
85
+ end
86
+ end
87
+ end
@@ -16,15 +16,13 @@ describe RuboCop::Cop::Cask::NoDslVersion do
16
16
  let(:source) { "cask :v1 => 'foo' do; end" }
17
17
  let(:correct_source) { "cask 'foo' do; end" }
18
18
  let(:expected_offenses) do
19
- [
20
- {
21
- message: "Use `cask 'foo'` instead of `cask :v1 => 'foo'`",
22
- severity: :convention,
23
- line: 1,
24
- column: 0,
25
- source: "cask :v1 => 'foo'"
26
- }
27
- ]
19
+ [{
20
+ message: "Use `cask 'foo'` instead of `cask :v1 => 'foo'`",
21
+ severity: :convention,
22
+ line: 1,
23
+ column: 0,
24
+ source: "cask :v1 => 'foo'"
25
+ }]
28
26
  end
29
27
 
30
28
  include_examples 'reports offenses'
@@ -36,15 +34,13 @@ describe RuboCop::Cop::Cask::NoDslVersion do
36
34
  let(:source) { "cask :v1test => 'foo' do; end" }
37
35
  let(:correct_source) { "test_cask 'foo' do; end" }
38
36
  let(:expected_offenses) do
39
- [
40
- {
41
- message: "Use `test_cask 'foo'` instead of `cask :v1test => 'foo'`",
42
- severity: :convention,
43
- line: 1,
44
- column: 0,
45
- source: "cask :v1test => 'foo'"
46
- }
47
- ]
37
+ [{
38
+ message: "Use `test_cask 'foo'` instead of `cask :v1test => 'foo'`",
39
+ severity: :convention,
40
+ line: 1,
41
+ column: 0,
42
+ source: "cask :v1test => 'foo'"
43
+ }]
48
44
  end
49
45
 
50
46
  include_examples 'reports offenses'
@@ -64,16 +60,14 @@ describe RuboCop::Cop::Cask::NoDslVersion do
64
60
  let(:source) { "test_cask :v1 => 'foo' do; end" }
65
61
  let(:correct_source) { "test_cask 'foo' do; end" }
66
62
  let(:expected_offenses) do
67
- [
68
- {
69
- message: "Use `test_cask 'foo'` instead of "\
70
- "`test_cask :v1 => 'foo'`",
71
- severity: :convention,
72
- line: 1,
73
- column: 0,
74
- source: "test_cask :v1 => 'foo'"
75
- }
76
- ]
63
+ [{
64
+ message: "Use `test_cask 'foo'` instead of "\
65
+ "`test_cask :v1 => 'foo'`",
66
+ severity: :convention,
67
+ line: 1,
68
+ column: 0,
69
+ source: "test_cask :v1 => 'foo'"
70
+ }]
77
71
  end
78
72
 
79
73
  include_examples 'reports offenses'
@@ -41,15 +41,13 @@ describe RuboCop::Cop::Cask::StanzaGrouping do
41
41
  CASK
42
42
  end
43
43
  let(:expected_offenses) do
44
- [
45
- {
46
- message: extra_line_msg,
47
- severity: :convention,
48
- line: 3,
49
- column: 0,
50
- source: "\n"
51
- }
52
- ]
44
+ [{
45
+ message: extra_line_msg,
46
+ severity: :convention,
47
+ line: 3,
48
+ column: 0,
49
+ source: "\n"
50
+ }]
53
51
  end
54
52
 
55
53
  include_examples 'reports offenses'
@@ -95,36 +93,31 @@ describe RuboCop::Cop::Cask::StanzaGrouping do
95
93
  CASK
96
94
  end
97
95
  let(:expected_offenses) do
98
- [
99
- {
100
- message: missing_line_msg,
101
- severity: :convention,
102
- line: 4,
103
- column: 0,
104
- source: " url 'https://foo.example.com/foo.zip'"
105
- },
106
- {
107
- message: extra_line_msg,
108
- severity: :convention,
109
- line: 5,
110
- column: 0,
111
- source: "\n"
112
- },
113
- {
114
- message: extra_line_msg,
115
- severity: :convention,
116
- line: 7,
117
- column: 0,
118
- source: "\n"
119
- },
120
- {
121
- message: missing_line_msg,
122
- severity: :convention,
123
- line: 12,
124
- column: 0,
125
- source: " uninstall :quit => 'com.example.foo',"
126
- }
127
- ]
96
+ [{
97
+ message: missing_line_msg,
98
+ severity: :convention,
99
+ line: 4,
100
+ column: 0,
101
+ source: " url 'https://foo.example.com/foo.zip'"
102
+ }, {
103
+ message: extra_line_msg,
104
+ severity: :convention,
105
+ line: 5,
106
+ column: 0,
107
+ source: "\n"
108
+ }, {
109
+ message: extra_line_msg,
110
+ severity: :convention,
111
+ line: 7,
112
+ column: 0,
113
+ source: "\n"
114
+ }, {
115
+ message: missing_line_msg,
116
+ severity: :convention,
117
+ line: 12,
118
+ column: 0,
119
+ source: " uninstall :quit => 'com.example.foo',"
120
+ }]
128
121
  end
129
122
 
130
123
  include_examples 'reports offenses'
@@ -34,22 +34,19 @@ describe RuboCop::Cop::Cask::StanzaOrder do
34
34
  CASK
35
35
  end
36
36
  let(:expected_offenses) do
37
- [
38
- {
39
- message: '`sha256` stanza out of order',
40
- severity: :convention,
41
- line: 2,
42
- column: 2,
43
- source: 'sha256 :no_check'
44
- },
45
- {
46
- message: '`version` stanza out of order',
47
- severity: :convention,
48
- line: 3,
49
- column: 2,
50
- source: 'version :latest'
51
- }
52
- ]
37
+ [{
38
+ message: '`sha256` stanza out of order',
39
+ severity: :convention,
40
+ line: 2,
41
+ column: 2,
42
+ source: 'sha256 :no_check'
43
+ }, {
44
+ message: '`version` stanza out of order',
45
+ severity: :convention,
46
+ line: 3,
47
+ column: 2,
48
+ source: 'version :latest'
49
+ }]
53
50
  end
54
51
 
55
52
  include_examples 'reports offenses'
@@ -83,37 +80,32 @@ describe RuboCop::Cop::Cask::StanzaOrder do
83
80
  CASK
84
81
  end
85
82
  let(:expected_offenses) do
86
- [
87
- {
88
- message: '`url` stanza out of order',
89
- severity: :convention,
90
- line: 2,
91
- column: 2,
92
- source: "url 'https://foo.example.com/foo.zip'"
93
- },
94
- {
95
- message: '`uninstall` stanza out of order',
96
- severity: :convention,
97
- line: 3,
98
- column: 2,
99
- source: "uninstall :quit => 'com.example.foo',\n" \
83
+ [{
84
+ message: '`url` stanza out of order',
85
+ severity: :convention,
86
+ line: 2,
87
+ column: 2,
88
+ source: "url 'https://foo.example.com/foo.zip'"
89
+ }, {
90
+ message: '`uninstall` stanza out of order',
91
+ severity: :convention,
92
+ line: 3,
93
+ column: 2,
94
+ source: "uninstall :quit => 'com.example.foo',\n" \
100
95
  " :kext => 'com.example.foo.kext'"
101
- },
102
- {
103
- message: '`version` stanza out of order',
104
- severity: :convention,
105
- line: 5,
106
- column: 2,
107
- source: 'version :latest'
108
- },
109
- {
110
- message: '`sha256` stanza out of order',
111
- severity: :convention,
112
- line: 7,
113
- column: 2,
114
- source: 'sha256 :no_check'
115
- }
116
- ]
96
+ }, {
97
+ message: '`version` stanza out of order',
98
+ severity: :convention,
99
+ line: 5,
100
+ column: 2,
101
+ source: 'version :latest'
102
+ }, {
103
+ message: '`sha256` stanza out of order',
104
+ severity: :convention,
105
+ line: 7,
106
+ column: 2,
107
+ source: 'sha256 :no_check'
108
+ }]
117
109
  end
118
110
 
119
111
  include_examples 'reports offenses'
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.2.2
4
+ version: 0.3.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: 2016-01-04 00:00:00.000000000 Z
11
+ date: 2016-01-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -47,11 +47,13 @@ files:
47
47
  - lib/rubocop/cask/extend/string.rb
48
48
  - lib/rubocop/cask/inject.rb
49
49
  - lib/rubocop/cask/version.rb
50
+ - lib/rubocop/cop/cask/license_unknown_comment.rb
50
51
  - lib/rubocop/cop/cask/mixin/cask_help.rb
51
52
  - lib/rubocop/cop/cask/no_dsl_version.rb
52
53
  - lib/rubocop/cop/cask/stanza_grouping.rb
53
54
  - lib/rubocop/cop/cask/stanza_order.rb
54
55
  - spec/project_spec.rb
56
+ - spec/rubocop/cop/cask/license_unknown_comment_spec.rb
55
57
  - spec/rubocop/cop/cask/no_dsl_version_spec.rb
56
58
  - spec/rubocop/cop/cask/stanza_grouping_spec.rb
57
59
  - spec/rubocop/cop/cask/stanza_order_spec.rb
@@ -83,6 +85,7 @@ specification_version: 4
83
85
  summary: Code style checking for Homebrew-Cask files
84
86
  test_files:
85
87
  - spec/project_spec.rb
88
+ - spec/rubocop/cop/cask/license_unknown_comment_spec.rb
86
89
  - spec/rubocop/cop/cask/no_dsl_version_spec.rb
87
90
  - spec/rubocop/cop/cask/stanza_grouping_spec.rb
88
91
  - spec/rubocop/cop/cask/stanza_order_spec.rb