rubocop-sorbet 0.3.2 → 0.3.3

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
  SHA256:
3
- metadata.gz: 7baa291ded0aa343c64c841b2d03cf91d52ad07071883a680f8b725297d0d8e9
4
- data.tar.gz: 95e36584da91cccee6423d2d65fcc061ea74e1abfc51c4c5fb1a18f8b1878e62
3
+ metadata.gz: c8e5d981eb3753f8e4a5599105ffca85878383e8c9babe36126529d13408c578
4
+ data.tar.gz: 19162fbc227c9d40774bec276129f739ee885201bb688b74cd3a7901253770ac
5
5
  SHA512:
6
- metadata.gz: 2d3772bb095eed330fbab2f2ff723f932bc4b40a175738532e043c6fbb66c9c2116a9435b4b210cf2b0f59dc3b8be889da976293db38f6e42f583be9dd8ddb26
7
- data.tar.gz: 04a54d3d285223f71d48f4a164ec69124ce9b45d74eba3c7232abd6388e9638acb3e8fada94f2f88533432e51077d03952037d1828850261e623797dacd7b9a5
6
+ metadata.gz: fd590134345de1400d2c653b263d2b0936aa1f02f6e199fc5d2f65eca50b37aef77df4d4463afe403ca7ba3f795dd389a72164d62c796dc943fb108e4eef76df
7
+ data.tar.gz: 4b5caba384adc3a2b45e8532cd1dba357bf7404d577da3a24defb9279a903a7b1c02bb1efdd28571517cab33ba3fa01dde88b1319da8cd8d051ecb308cd9d8b5
@@ -6,7 +6,6 @@ inherit_from:
6
6
  AllCops:
7
7
  TargetRubyVersion: 2.5
8
8
  Exclude:
9
- - lib/waffle_cone/rbi_compilers/yard_type_parser.rb
10
9
  - vendor/**/*
11
10
 
12
11
  Naming/AccessorMethodName:
@@ -19,9 +18,6 @@ Naming/FileName:
19
18
  Exclude:
20
19
  - lib/rubocop-sorbet.rb
21
20
 
22
- Style/StringLiterals:
23
- EnforcedStyle: single_quotes
24
-
25
21
  Lint/HandleExceptions:
26
22
  Exclude:
27
23
  - Rakefile
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rubocop-sorbet (0.3.2)
4
+ rubocop-sorbet (0.3.3)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -1,3 +1,3 @@
1
- Sorbet/ValidSorbetSigil:
1
+ Sorbet/ValidSigil:
2
2
  Enabled: true
3
3
  EnforcedStyle: typed_files
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubocop'
4
+ require_relative 'has_sigil'
5
+
6
+ module RuboCop
7
+ module Cop
8
+ module Sorbet
9
+ # This cop makes the Sorbet `false` sigil mandatory in all files.
10
+ class FalseSigil < HasSigil
11
+ def minimum_strictness
12
+ 'false'
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubocop'
4
+ require_relative 'valid_sigil'
5
+
6
+ module RuboCop
7
+ module Cop
8
+ module Sorbet
9
+ # This cop makes the Sorbet typed sigil mandatory in all files.
10
+ #
11
+ # Options:
12
+ #
13
+ # * `SuggestedStrictness`: Sorbet strictness level suggested in offense messages (default: 'false')
14
+ # * `MinimumStrictness`: If set, make offense if the strictness level in the file is below this one
15
+ #
16
+ # If a `MinimumStrictness` level is specified, it will be used in offense messages and autocorrect.
17
+ class HasSigil < ValidSigil
18
+ @registry = Cop.registry # So we can properly subclass this cop
19
+
20
+ def require_sigil_on_all_files?
21
+ true
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubocop'
4
+ require_relative 'has_sigil'
5
+
6
+ module RuboCop
7
+ module Cop
8
+ module Sorbet
9
+ # This cop makes the Sorbet `ignore` sigil mandatory in all files.
10
+ class IgnoreSigil < HasSigil
11
+ def minimum_strictness
12
+ 'ignore'
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubocop'
4
+ require_relative 'has_sigil'
5
+
6
+ module RuboCop
7
+ module Cop
8
+ module Sorbet
9
+ # This cop makes the Sorbet `strict` sigil mandatory in all files.
10
+ class StrictSigil < HasSigil
11
+ def minimum_strictness
12
+ 'strict'
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubocop'
4
+ require_relative 'has_sigil'
5
+
6
+ module RuboCop
7
+ module Cop
8
+ module Sorbet
9
+ # This cop makes the Sorbet `strong` sigil mandatory in all files.
10
+ class StrongSigil < HasSigil
11
+ def minimum_strictness
12
+ 'strong'
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubocop'
4
+ require_relative 'has_sigil'
5
+
6
+ module RuboCop
7
+ module Cop
8
+ module Sorbet
9
+ # This cop makes the Sorbet `true` sigil mandatory in all files.
10
+ class TrueSigil < HasSigil
11
+ def minimum_strictness
12
+ 'true'
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubocop'
4
+
5
+ module RuboCop
6
+ module Cop
7
+ module Sorbet
8
+ # This cop checks that every Ruby file contains a valid Sorbet sigil.
9
+ # Adapted from: https://gist.github.com/clarkdave/85aca4e16f33fd52aceb6a0a29936e52
10
+ #
11
+ # Options:
12
+ #
13
+ # * `RequireSigilOnAllFiles`: make offense if the Sorbet typed is not found in the file (default: false)
14
+ # * `SuggestedStrictness`: Sorbet strictness level suggested in offense messages (default: 'false')
15
+ # * `MinimumStrictness`: If set, make offense if the strictness level in the file is below this one
16
+ #
17
+ # If a `MinimumStrictness` level is specified, it will be used in offense messages and autocorrect.
18
+ class ValidSigil < RuboCop::Cop::Cop
19
+ @registry = Cop.registry # So we can properly subclass this cop
20
+
21
+ def investigate(processed_source)
22
+ return if processed_source.tokens.empty?
23
+
24
+ sigil = extract_sigil(processed_source)
25
+ return unless check_sigil_present(sigil)
26
+
27
+ strictness = extract_strictness(sigil)
28
+ return unless check_strictness_not_empty(sigil, strictness)
29
+ return unless check_strictness_valid(sigil, strictness)
30
+ return unless check_strictness_level(sigil, strictness)
31
+ end
32
+
33
+ def autocorrect(_node)
34
+ lambda do |corrector|
35
+ return unless require_sigil_on_all_files?
36
+ return unless extract_sigil(processed_source).nil?
37
+
38
+ token = processed_source.tokens.first
39
+ corrector.insert_before(token.pos, "# typed: #{minimum_strictness || suggested_strictness}\n")
40
+ end
41
+ end
42
+
43
+ protected
44
+
45
+ STRICTNESS_LEVELS = %w(ignore false true strict strong)
46
+ SIGIL_REGEX = /#\s+typed:(?:\s+([\w]+))?/
47
+
48
+ # extraction
49
+
50
+ def extract_sigil(processed_source)
51
+ processed_source.tokens
52
+ .take_while { |token| token.type == :tCOMMENT }
53
+ .find { |token| SIGIL_REGEX.match?(token.text) }
54
+ end
55
+
56
+ def extract_strictness(sigil)
57
+ sigil.text.match(SIGIL_REGEX)&.captures&.first
58
+ end
59
+
60
+ # checks
61
+
62
+ def check_sigil_present(sigil)
63
+ return true unless sigil.nil?
64
+
65
+ token = processed_source.tokens.first
66
+ if require_sigil_on_all_files?
67
+ strictness = minimum_strictness || suggested_strictness
68
+ add_offense(
69
+ token,
70
+ location: token.pos,
71
+ message: 'No Sorbet sigil found in file. ' \
72
+ "Try a `typed: #{strictness}` to start (you can also use `rubocop -a` to automatically add this)."
73
+ )
74
+ end
75
+ false
76
+ end
77
+
78
+ def check_strictness_not_empty(sigil, strictness)
79
+ return true if strictness
80
+
81
+ add_offense(
82
+ sigil,
83
+ location: sigil.pos,
84
+ message: 'Sorbet sigil should not be empty.'
85
+ )
86
+ false
87
+ end
88
+
89
+ def check_strictness_valid(sigil, strictness)
90
+ return true if STRICTNESS_LEVELS.include?(strictness)
91
+
92
+ add_offense(
93
+ sigil,
94
+ location: sigil.pos,
95
+ message: "Invalid Sorbet sigil `#{strictness}`."
96
+ )
97
+ false
98
+ end
99
+
100
+ def check_strictness_level(sigil, strictness)
101
+ return true unless minimum_strictness
102
+
103
+ minimum_level = STRICTNESS_LEVELS.index(minimum_strictness)
104
+ current_level = STRICTNESS_LEVELS.index(strictness)
105
+ if current_level < minimum_level
106
+ add_offense(
107
+ sigil,
108
+ location: sigil.pos,
109
+ message: "Sorbet sigil should be at least `#{minimum_strictness}` got `#{strictness}`."
110
+ )
111
+ return false
112
+ end
113
+ true
114
+ end
115
+
116
+ # options
117
+
118
+ # Default is `false`
119
+ def require_sigil_on_all_files?
120
+ !!cop_config['RequireSigilOnAllFiles']
121
+ end
122
+
123
+ # Default is `'false'`
124
+ def suggested_strictness
125
+ cop_config['SuggestedStrictness'] || 'false'
126
+ end
127
+
128
+ # Default is `nil`
129
+ def minimum_strictness
130
+ cop_config['MinimumStrictness']
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
@@ -9,4 +9,11 @@ require_relative 'rubocop/cop/sorbet/forbid_superclass_const_literal'
9
9
  require_relative 'rubocop/cop/sorbet/forbid_include_const_literal'
10
10
  require_relative 'rubocop/cop/sorbet/parameters_ordering_in_signature'
11
11
  require_relative 'rubocop/cop/sorbet/keyword_argument_ordering'
12
- require_relative 'rubocop/cop/sorbet/valid_sorbet_sigil'
12
+
13
+ require_relative 'rubocop/cop/sorbet/sigils/valid_sigil'
14
+ require_relative 'rubocop/cop/sorbet/sigils/has_sigil'
15
+ require_relative 'rubocop/cop/sorbet/sigils/ignore_sigil'
16
+ require_relative 'rubocop/cop/sorbet/sigils/false_sigil'
17
+ require_relative 'rubocop/cop/sorbet/sigils/true_sigil'
18
+ require_relative 'rubocop/cop/sorbet/sigils/strict_sigil'
19
+ require_relative 'rubocop/cop/sorbet/sigils/strong_sigil'
@@ -5,7 +5,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = 'rubocop-sorbet'
8
- spec.version = '0.3.2'
8
+ spec.version = '0.3.3'
9
9
  spec.authors = ['Ufuk Kayserilioglu', 'Alan Wu', 'Alexandre Terrasa', 'Peter Zhu']
10
10
  spec.email = ['ruby@shopify.com']
11
11
 
@@ -0,0 +1,6 @@
1
+ # https://services.shopify.io/services/rubocop-sorbet/production
2
+ owners:
3
+ - Shopify/sorbet
4
+ classification: library
5
+ slack_channels:
6
+ - sorbet
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-sorbet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ufuk Kayserilioglu
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: exe
13
13
  cert_chain: []
14
- date: 2019-09-18 00:00:00.000000000 Z
14
+ date: 2019-10-08 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rspec
@@ -88,10 +88,17 @@ files:
88
88
  - lib/rubocop/cop/sorbet/forbid_superclass_const_literal.rb
89
89
  - lib/rubocop/cop/sorbet/keyword_argument_ordering.rb
90
90
  - lib/rubocop/cop/sorbet/parameters_ordering_in_signature.rb
91
+ - lib/rubocop/cop/sorbet/sigils/false_sigil.rb
92
+ - lib/rubocop/cop/sorbet/sigils/has_sigil.rb
93
+ - lib/rubocop/cop/sorbet/sigils/ignore_sigil.rb
94
+ - lib/rubocop/cop/sorbet/sigils/strict_sigil.rb
95
+ - lib/rubocop/cop/sorbet/sigils/strong_sigil.rb
96
+ - lib/rubocop/cop/sorbet/sigils/true_sigil.rb
97
+ - lib/rubocop/cop/sorbet/sigils/valid_sigil.rb
91
98
  - lib/rubocop/cop/sorbet/signature_build_order.rb
92
- - lib/rubocop/cop/sorbet/valid_sorbet_sigil.rb
93
99
  - lib/rubocop_sorbet.rb
94
100
  - rubocop-sorbet.gemspec
101
+ - service.yml
95
102
  - shipit.yml
96
103
  homepage: https://github.com/shopify/rubocop-sorbet
97
104
  licenses:
@@ -1,102 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rubocop'
4
-
5
- module RuboCop
6
- module Cop
7
- module Sorbet
8
- # This cop checks that every Ruby file contains a valid Sorbet sigil.
9
- # Adapted from: https://gist.github.com/clarkdave/85aca4e16f33fd52aceb6a0a29936e52
10
- #
11
- # @example RequireSigilOnAllFiles: false (default)
12
- #
13
- # # bad
14
- # # (start of file)
15
- # # typed: no
16
- #
17
- # # good
18
- # # (start of file)
19
- # class Foo; end
20
- #
21
- # # good
22
- # # (start of file)
23
- # # typed: true
24
- #
25
- # @example RequireSigilOnAllFiles: true
26
- #
27
- # # bad
28
- # # (start of file)
29
- # class Foo; end
30
- #
31
- # # bad
32
- # # (start of file)
33
- # # typed: no
34
- #
35
- # # good
36
- # # (start of file)
37
- # # typed: true
38
- class ValidSorbetSigil < RuboCop::Cop::Cop
39
- def investigate(processed_source)
40
- return if processed_source.tokens.empty?
41
-
42
- sorbet_sigil_line = sorbet_typed_sigil_comment(processed_source)
43
-
44
- if sorbet_sigil_line.nil?
45
- token = processed_source.tokens.first
46
-
47
- if require_sorbet_sigil_on_all_files?
48
- add_offense(
49
- token,
50
- location: token.pos,
51
- message: 'No Sorbet sigil found in file. ' \
52
- 'Try a `typed: false` to start (you can also use `rubocop -a` to automatically add this).'
53
- )
54
- end
55
- else
56
- strictness = sorbet_typed_strictness(sorbet_sigil_line)
57
- return if valid_sorbet_strictness?(strictness)
58
-
59
- add_offense(
60
- sorbet_sigil_line,
61
- location: sorbet_sigil_line.pos,
62
- message: "Invalid Sorbet sigil `#{strictness}`."
63
- )
64
- end
65
- end
66
-
67
- def autocorrect(_node)
68
- lambda do |corrector|
69
- return unless require_sorbet_sigil_on_all_files?
70
- return unless sorbet_typed_sigil_comment(processed_source).nil?
71
-
72
- token = processed_source.tokens.first
73
-
74
- corrector.insert_before(token.pos, "# typed: false\n")
75
- end
76
- end
77
-
78
- private
79
-
80
- def require_sorbet_sigil_on_all_files?
81
- !!cop_config['RequireSigilOnAllFiles']
82
- end
83
-
84
- SORBET_SIGIL_REGEX = /#\s+typed:\s+([\w]+)/
85
-
86
- def sorbet_typed_sigil_comment(processed_source)
87
- processed_source.tokens
88
- .take_while { |token| token.type == :tCOMMENT }
89
- .find { |token| SORBET_SIGIL_REGEX.match?(token.text) }
90
- end
91
-
92
- def valid_sorbet_strictness?(strictness)
93
- %w(ignore false true strict strong).include?(strictness)
94
- end
95
-
96
- def sorbet_typed_strictness(sigil_line)
97
- sigil_line.text.match(SORBET_SIGIL_REGEX)&.captures&.first
98
- end
99
- end
100
- end
101
- end
102
- end