Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to ignore :nodoc: methods in Typing rules #557

Merged
merged 3 commits into from
Jan 31, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions spec/ameba/ast/util_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,39 @@ module Ameba::AST
end
end

describe "#nodoc?" do
it "returns true if a node has a single `:nodoc:` annotation" do
node = as_node <<-CRYSTAL, wants_doc: true
# :nodoc:
def foo; end
CRYSTAL

subject.nodoc?(node).should be_true
end

it "returns true if a node has a `:nodoc:` annotation in the first line" do
node = as_node <<-CRYSTAL, wants_doc: true
# :nodoc:
#
# foo
def foo; end
CRYSTAL

subject.nodoc?(node).should be_true
end

it "returns false if a node has a `:nodoc:` annotation in the middle" do
node = as_node <<-CRYSTAL, wants_doc: true
# foo
# :nodoc:
# bar
def foo; end
CRYSTAL

subject.nodoc?(node).should be_false
end
end

describe "#control_exp_code" do
it "returns the exp code of a control expression" do
s = "return 1"
Expand Down
21 changes: 21 additions & 0 deletions spec/ameba/rule/typing/method_parameter_type_restriction_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ module Ameba::Rule::Typing
CRYSTAL
end

it "passes if a method has a `:nodoc:` annotation" do
expect_no_issues subject, <<-CRYSTAL
# :nodoc:
def foo(bar); end
CRYSTAL
end

it "fails if a public method parameter doesn't have a type restriction" do
expect_issue subject, <<-CRYSTAL
def hello(a)
Expand Down Expand Up @@ -195,6 +202,20 @@ module Ameba::Rule::Typing
CRYSTAL
end
end

context "#nodoc_methods" do
rule = MethodParameterTypeRestriction.new
rule.nodoc_methods = true

it "fails if a public method parameter doesn't have a type restriction" do
expect_issue rule, <<-CRYSTAL
# :nodoc:
def foo(bar)
# ^ error: Method parameter should have a type restriction
end
CRYSTAL
end
end
end
end
end
21 changes: 21 additions & 0 deletions spec/ameba/rule/typing/method_return_type_restriction_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ module Ameba::Rule::Typing
CRYSTAL
end

it "passes if a method has a `:nodoc:` annotation" do
expect_no_issues subject, <<-CRYSTAL
# :nodoc:
def foo; end
CRYSTAL
end

it "fails if a public method doesn't have a return type restriction" do
expect_issue subject, <<-CRYSTAL
def hello
Expand Down Expand Up @@ -119,6 +126,20 @@ module Ameba::Rule::Typing
CRYSTAL
end
end

context "#nodoc_methods" do
rule = MethodReturnTypeRestriction.new
rule.nodoc_methods = true

it "fails if a public method doesn't have a return type restriction" do
expect_issue rule, <<-CRYSTAL
# :nodoc:
def foo
# ^^^^^ error: Method should have a return type restriction
end
CRYSTAL
end
end
end
end
end
10 changes: 6 additions & 4 deletions spec/spec_helper.cr
Original file line number Diff line number Diff line change
Expand Up @@ -320,12 +320,14 @@ def with_presenter(klass, *args, deansify = true, **kwargs, &)
yield presenter, output
end

def as_node(source)
Crystal::Parser.new(source).parse
def as_node(source, *, wants_doc = false)
Crystal::Parser.new(source)
.tap(&.wants_doc = wants_doc)
.parse
end

def as_nodes(source)
Ameba::TestNodeVisitor.new(as_node source)
def as_nodes(source, *, wants_doc = false)
Ameba::TestNodeVisitor.new(as_node(source, wants_doc: wants_doc))
end

def trailing_whitespace
Expand Down
8 changes: 8 additions & 0 deletions src/ameba/ast/util.cr
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,14 @@ module Ameba::AST::Util
end
end

# Returns `true` if node has a `:nodoc:` annotation as the first line.
def nodoc?(node)
return false unless node.responds_to?(:doc)
return false unless doc = node.doc.presence

doc.lines.first?.try(&.strip) == ":nodoc:"
end

# Returns the exp code of a control expression.
# Wraps implicit tuple literal with curly brackets (e.g. multi-return).
def control_exp_code(node : Crystal::ControlExpression, code_lines)
Expand Down
10 changes: 9 additions & 1 deletion src/ameba/rule/typing/method_parameter_type_restriction.cr
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ module Ameba::Rule::Typing
# When the config options `PrivateMethods` and `ProtectedMethods`
# are true, this rule is also applied to private and protected methods, respectively.
#
# The `NodocMethods` configuration option controls whether this rule applies to
# methods with a `:nodoc:` directive.
#
# The `BlockParameters` configuration option will extend this to block parameters, where these are invalid:
#
# ```
Expand Down Expand Up @@ -49,8 +52,11 @@ module Ameba::Rule::Typing
# BlockParameters: false
# PrivateMethods: false
# ProtectedMethods: false
# NodocMethods: false
# ```
class MethodParameterTypeRestriction < Base
include AST::Util

properties do
since_version "1.7.0"
description "Recommends that method parameters have type restrictions"
Expand All @@ -59,6 +65,7 @@ module Ameba::Rule::Typing
block_parameters false
private_methods false
protected_methods false
nodoc_methods false
end

MSG = "Method parameter should have a type restriction"
Expand All @@ -80,7 +87,8 @@ module Ameba::Rule::Typing

private def valid_visibility?(node : Crystal::ASTNode) : Bool
(!private_methods? && node.visibility.private?) ||
(!protected_methods? && node.visibility.protected?)
(!protected_methods? && node.visibility.protected?) ||
(!nodoc_methods? && nodoc?(node))
end
end
end
10 changes: 9 additions & 1 deletion src/ameba/rule/typing/method_return_type_restriction.cr
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,28 @@ module Ameba::Rule::Typing
# When the config options `PrivateMethods` and `ProtectedMethods`
# are true, this rule is also applied to private and protected methods, respectively.
#
# The `NodocMethods` configuration option controls whether this rule applies to
# methods with a `:nodoc:` directive.
#
# YAML configuration example:
#
# ```
# Typing/MethodReturnTypeRestriction:
# Enabled: true
# PrivateMethods: false
# ProtectedMethods: false
# NodocMethods: false
# ```
class MethodReturnTypeRestriction < Base
include AST::Util

properties do
since_version "1.7.0"
description "Recommends that methods have a return type restriction"
enabled false
private_methods false
protected_methods false
nodoc_methods false
end

MSG = "Method should have a return type restriction"
Expand All @@ -46,7 +53,8 @@ module Ameba::Rule::Typing
private def valid_return_type?(node : Crystal::ASTNode) : Bool
!!node.return_type ||
(node.visibility.private? && !private_methods?) ||
(node.visibility.protected? && !protected_methods?)
(node.visibility.protected? && !protected_methods?) ||
(!nodoc_methods? && nodoc?(node))
end
end
end
Loading