rubocop-sorbet 0.3.2 → 0.3.3
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 +4 -4
- data/.rubocop.yml +0 -4
- data/Gemfile.lock +1 -1
- data/config/default.yml +1 -1
- data/lib/rubocop/cop/sorbet/sigils/false_sigil.rb +17 -0
- data/lib/rubocop/cop/sorbet/sigils/has_sigil.rb +26 -0
- data/lib/rubocop/cop/sorbet/sigils/ignore_sigil.rb +17 -0
- data/lib/rubocop/cop/sorbet/sigils/strict_sigil.rb +17 -0
- data/lib/rubocop/cop/sorbet/sigils/strong_sigil.rb +17 -0
- data/lib/rubocop/cop/sorbet/sigils/true_sigil.rb +17 -0
- data/lib/rubocop/cop/sorbet/sigils/valid_sigil.rb +135 -0
- data/lib/rubocop_sorbet.rb +8 -1
- data/rubocop-sorbet.gemspec +1 -1
- data/service.yml +6 -0
- metadata +10 -3
- data/lib/rubocop/cop/sorbet/valid_sorbet_sigil.rb +0 -102
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c8e5d981eb3753f8e4a5599105ffca85878383e8c9babe36126529d13408c578
|
4
|
+
data.tar.gz: 19162fbc227c9d40774bec276129f739ee885201bb688b74cd3a7901253770ac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fd590134345de1400d2c653b263d2b0936aa1f02f6e199fc5d2f65eca50b37aef77df4d4463afe403ca7ba3f795dd389a72164d62c796dc943fb108e4eef76df
|
7
|
+
data.tar.gz: 4b5caba384adc3a2b45e8532cd1dba357bf7404d577da3a24defb9279a903a7b1c02bb1efdd28571517cab33ba3fa01dde88b1319da8cd8d051ecb308cd9d8b5
|
data/.rubocop.yml
CHANGED
@@ -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
|
data/Gemfile.lock
CHANGED
data/config/default.yml
CHANGED
@@ -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
|
data/lib/rubocop_sorbet.rb
CHANGED
@@ -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
|
-
|
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'
|
data/rubocop-sorbet.gemspec
CHANGED
@@ -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.
|
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
|
|
data/service.yml
ADDED
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.
|
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-
|
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
|