Skip to content

Commit

Permalink
Add Typing/MacroCallArgumentTypeRestriction (#521)
Browse files Browse the repository at this point in the history
  • Loading branch information
nobodywasishere authored Jan 9, 2025
1 parent bde34f4 commit 65f7db0
Show file tree
Hide file tree
Showing 2 changed files with 164 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
require "../../../spec_helper"

module Ameba::Rule::Typing
describe MacroCallArgumentTypeRestriction do
subject = MacroCallArgumentTypeRestriction.new

it "passes if macro call args have type restrictions" do
expect_no_issues subject, <<-CRYSTAL
class Greeter
getter name : String?
class_getter age : Int32 = 0
setter tasks : Array(String) = [] of String
class_setter queue : Array(Int32)?
property task_mutex : Mutex = Mutex.new
class_property asdf : String
end
record Task,
cmd : String,
args : Array(String) = %w[]
CRYSTAL
end

it "fails if a macro call arg doesn't have a type restriction" do
expect_issue subject, <<-CRYSTAL
class Greeter
getter name
# ^^^^ error: Argument should have a type restriction
getter :age
# ^^^^ error: Argument should have a type restriction
getter "height"
# ^^^^^^^^ error: Argument should have a type restriction
end
CRYSTAL
end

it "passes if a record call arg with a default value doesn't have a type restriction" do
expect_no_issues subject, <<-CRYSTAL
record Task,
cmd : String,
args = %[]
CRYSTAL
end

context "properties" do
context "#default_value" do
rule = MacroCallArgumentTypeRestriction.new
rule.default_value = true

it "fails if a macro call arg with a default value doesn't have a type restriction" do
expect_issue rule, <<-CRYSTAL
class Greeter
getter name = "Kenobi"
# ^^^^ error: Argument should have a type restriction
end
CRYSTAL
end

it "fails if a record call arg with default value doesn't have a type restriction" do
expect_issue rule, <<-CRYSTAL
record Task,
cmd : String,
args = %[]
# ^^^^ error: Argument should have a type restriction
CRYSTAL
end
end
end
end
end
94 changes: 94 additions & 0 deletions src/ameba/rule/typing/macro_call_argument_type_restriction.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
module Ameba::Rule::Typing
# A rule that enforces call arguments to specific macros have a type restriction.
# By default these macros are: `(class_)getter/setter/property(?/!)` and `record`.
#
# For example, these are considered invalid:
#
# ```
# class Greeter
# getter name
# getter age = 0.days
# getter :height
# end
#
# record Task,
# cmd = "",
# args = %w[]
# ```
#
# And these are considered valid:
#
# ```
# class Greeter
# getter name : String?
# getter age : Time::Span = 0.days
# getter height : Float64?
# end
#
# record Task,
# cmd : String = "",
# args : Array(String) = %w[]
# ```
#
# The `DefaultValue` configuration option controls whether this rule applies to
# call arguments that have a default value.
#
# YAML configuration example:
#
# ```
# Typing/MacroCallArgumentTypeRestriction:
# Enabled: false
# DefaultValue: false
# MacroNames:
# - getter
# - getter?
# - getter!
# - class_getter
# - class_getter?
# - class_getter!
# - setter
# - setter?
# - setter!
# - class_setter
# - class_setter?
# - class_setter!
# - property
# - property?
# - property!
# - class_property
# - class_property?
# - class_property!
# - record
# ```
class MacroCallArgumentTypeRestriction < Base
properties do
since_version "1.7.0"
description "Recommends that call arguments to certain macros have type restrictions"
enabled false
default_value false
macro_names %w[
getter getter? getter! class_getter class_getter? class_getter!
setter setter? setter! class_setter class_setter? class_setter!
property property? property! class_property class_property? class_property!
record
]
end

MSG = "Argument should have a type restriction"

def test(source, node : Crystal::Call)
return unless node.name.in?(macro_names)

node.args.each do |arg|
case arg
when Crystal::Assign
next unless default_value?

issue_for arg.target, MSG, prefer_name_location: true
when Crystal::Var, Crystal::Call, Crystal::StringLiteral, Crystal::SymbolLiteral
issue_for arg, MSG, prefer_name_location: true
end
end
end
end
end

0 comments on commit 65f7db0

Please sign in to comment.