class RuboCop::Cop::Sorbet::EnforceSignatures
-
‘ReturnTypePlaceholder`: placeholders used for return types (default: ’T.untyped’)
* ‘ParameterTypePlaceholder`: placeholders used for parameter types (default: ’T.untyped’)
You can configure the placeholders used by changing the following options:
“‘
def foo(a, b, c); end
sig { params(a: T.untyped, b: T.untyped, c: T.untyped).returns(T.untyped)
“`
Will be corrected as:
“`
def foo(a, b, c); end
“`
It also suggest an autocorrect with placeholders so the following code:
Checks that every method definition and attribute accessor has a Sorbet signature.
def autocorrect(corrector, node)
def autocorrect(corrector, node) suggest = SigSuggestion.new(node.loc.column, param_type_placeholder, return_type_placeholder) if node.is_a?(RuboCop::AST::DefNode) # def something node.arguments.each do |arg| suggest.params << arg.children.first end elsif accessor?(node) # attr reader, writer, accessor method = node.children[1] symbol = node.children[2] suggest.params << symbol.value if symbol && (method == :attr_writer || method == :attr_accessor) suggest.returns = "void" if method == :attr_writer end corrector.insert_before(node, suggest.to_autocorrect) end
def check_node(node)
def check_node(node) scope = self.scope(node) unless @last_sig_for_scope[scope] || has_rbs_comment?(node) add_offense( node, message: "Each method is required to have a signature.", ) do |corrector| autocorrect(corrector, node) end end @last_sig_for_scope[scope] = nil end
def has_rbs_comment?(node)
def has_rbs_comment?(node) return false unless cop_config["AllowRBS"] == true node = node.parent while RuboCop::AST::SendNode === node.parent return false if (comments = preceeding_comments(node)).empty? last_comment = comments.last return false if last_comment.loc.line + 1 < node.loc.line comments.any? { |comment| RBS_COMMENT_REGEX.match?(comment.text) } end
def initialize(config = nil, options = nil)
def initialize(config = nil, options = nil) super(config, options) @last_sig_for_scope = {} end
def on_def(node)
def on_def(node) check_node(node) end
def on_defs(node)
def on_defs(node) check_node(node) end
def on_send(node)
def on_send(node) check_node(node) if accessor?(node) end
def on_signature(node)
def on_signature(node) @last_sig_for_scope[scope(node)] = node end
def param_type_placeholder
def param_type_placeholder cop_config["ParameterTypePlaceholder"] || "T.untyped" end
def preceeding_comments(node)
def preceeding_comments(node) processed_source.ast_with_comments[node].select { |comment| comment.loc.line < node.loc.line } end
def return_type_placeholder
def return_type_placeholder cop_config["ReturnTypePlaceholder"] || "T.untyped" end
def scope(node)
def scope(node) return unless node.parent return node.parent if [:begin, :block, :class, :module].include?(node.parent.type) scope(node.parent) end