rubocop-cask 0.2.2 → 0.3.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: 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