class RuboCop::Cop::Sorbet::ValidSigil
This cop checks that every Ruby file contains a valid Sorbet
sigil. Adapted from: gist.github.com/clarkdave/85aca4e16f33fd52aceb6a0a29936e52
Options:
-
`RequireSigilOnAllFiles`: make offense if the
Sorbet
typed is not found in the file (default: false) -
`SuggestedStrictness`:
Sorbet
strictness level suggested in offense messages (default: 'false') -
`MinimumStrictness`: If set, make offense if the strictness level in the file is below this one
If a `MinimumStrictness` level is specified, it will be used in offense messages and autocorrect.
Constants
- SIGIL_REGEX
- STRICTNESS_LEVELS
Public Instance Methods
autocorrect(_node)
click to toggle source
# File lib/rubocop/cop/sorbet/sigils/valid_sigil.rb, line 33 def autocorrect(_node) lambda do |corrector| return unless require_sigil_on_all_files? return unless extract_sigil(processed_source).nil? token = processed_source.tokens.first replace_with = suggested_strictness_level(minimum_strictness, suggested_strictness) sigil = "# typed: #{replace_with}" if token.text.start_with?("#!") # shebang line corrector.insert_after(token.pos, "\n#{sigil}") else corrector.insert_before(token.pos, "#{sigil}\n") end end end
investigate(processed_source)
click to toggle source
# File lib/rubocop/cop/sorbet/sigils/valid_sigil.rb, line 21 def investigate(processed_source) return if processed_source.tokens.empty? sigil = extract_sigil(processed_source) return unless check_sigil_present(sigil) strictness = extract_strictness(sigil) return unless check_strictness_not_empty(sigil, strictness) return unless check_strictness_valid(sigil, strictness) return unless check_strictness_level(sigil, strictness) end
Protected Instance Methods
check_sigil_present(sigil)
click to toggle source
checks
# File lib/rubocop/cop/sorbet/sigils/valid_sigil.rb, line 68 def check_sigil_present(sigil) return true unless sigil.nil? token = processed_source.tokens.first if require_sigil_on_all_files? strictness = suggested_strictness_level(minimum_strictness, suggested_strictness) add_offense( token, location: token.pos, message: 'No Sorbet sigil found in file. ' \ "Try a `typed: #{strictness}` to start (you can also use `rubocop -a` to automatically add this)." ) end false end
check_strictness_level(sigil, strictness)
click to toggle source
# File lib/rubocop/cop/sorbet/sigils/valid_sigil.rb, line 125 def check_strictness_level(sigil, strictness) return true unless minimum_strictness minimum_level = STRICTNESS_LEVELS.index(minimum_strictness) current_level = STRICTNESS_LEVELS.index(strictness) if current_level < minimum_level add_offense( sigil, location: sigil.pos, message: "Sorbet sigil should be at least `#{minimum_strictness}` got `#{strictness}`." ) return false end true end
check_strictness_not_empty(sigil, strictness)
click to toggle source
# File lib/rubocop/cop/sorbet/sigils/valid_sigil.rb, line 103 def check_strictness_not_empty(sigil, strictness) return true if strictness add_offense( sigil, location: sigil.pos, message: 'Sorbet sigil should not be empty.' ) false end
check_strictness_valid(sigil, strictness)
click to toggle source
# File lib/rubocop/cop/sorbet/sigils/valid_sigil.rb, line 114 def check_strictness_valid(sigil, strictness) return true if STRICTNESS_LEVELS.include?(strictness) add_offense( sigil, location: sigil.pos, message: "Invalid Sorbet sigil `#{strictness}`." ) false end
extract_sigil(processed_source)
click to toggle source
extraction
# File lib/rubocop/cop/sorbet/sigils/valid_sigil.rb, line 56 def extract_sigil(processed_source) processed_source.tokens .take_while { |token| token.type == :tCOMMENT } .find { |token| SIGIL_REGEX.match?(token.text) } end
extract_strictness(sigil)
click to toggle source
# File lib/rubocop/cop/sorbet/sigils/valid_sigil.rb, line 62 def extract_strictness(sigil) sigil.text.match(SIGIL_REGEX)&.captures&.first end
minimum_strictness()
click to toggle source
Default is `nil`
# File lib/rubocop/cop/sorbet/sigils/valid_sigil.rb, line 155 def minimum_strictness config = cop_config['MinimumStrictness'].to_s config if STRICTNESS_LEVELS.include?(config) end
require_sigil_on_all_files?()
click to toggle source
Default is `false`
# File lib/rubocop/cop/sorbet/sigils/valid_sigil.rb, line 144 def require_sigil_on_all_files? !!cop_config['RequireSigilOnAllFiles'] end
suggested_strictness()
click to toggle source
Default is `'false'`
# File lib/rubocop/cop/sorbet/sigils/valid_sigil.rb, line 149 def suggested_strictness config = cop_config['SuggestedStrictness'].to_s STRICTNESS_LEVELS.include?(config) ? config : 'false' end
suggested_strictness_level(minimum_strictness, suggested_strictness)
click to toggle source
# File lib/rubocop/cop/sorbet/sigils/valid_sigil.rb, line 84 def suggested_strictness_level(minimum_strictness, suggested_strictness) # if no minimum strictness is set (eg. using Sorbet/HasSigil without config) then # we always use the suggested strictness which defaults to `false` return suggested_strictness unless minimum_strictness # special case: if you're using Sorbet/IgnoreSigil without config, we should recommend `ignore` return "ignore" if minimum_strictness == "ignore" && cop_config['SuggestedStrictness'].nil? # if a minimum strictness is set (eg. you're using Sorbet/FalseSigil) # we want to compare the minimum strictness and suggested strictness. this is because # the suggested strictness might be higher than the minimum (eg. if you want all new files # at a higher strictness level, without having to migrate existing files at lower levels). suggested_level = STRICTNESS_LEVELS.index(suggested_strictness) minimum_level = STRICTNESS_LEVELS.index(minimum_strictness) suggested_level > minimum_level ? suggested_strictness : minimum_strictness end