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 Lint/UnusedSelf and Lint/UnusedPseudoMethod #556

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
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
60 changes: 60 additions & 0 deletions spec/ameba/rule/lint/unused_pseudo_method_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
require "../../../spec_helper"

module Ameba::Rule::Lint
describe UnusedPseudoMethod do
subject = UnusedPseudoMethod.new

it "passes if return value of typeof or as isn't used" do
expect_no_issues subject, <<-CRYSTAL
typeof(1)
as(Int32)
CRYSTAL
end

it "fails if pseudo methods are unused top-level" do
expect_issue subject, <<-CRYSTAL
pointerof(Int32)
# ^^^^^^^^^^^^^^ error: Pseudo-method is not used
sizeof(Int32)
# ^^^^^^^^^^^ error: Pseudo-method is not used
instance_sizeof(Int32)
# ^^^^^^^^^^^^^^^^^^^^ error: Pseudo-method is not used
alignof(Int32)
# ^^^^^^^^^^^^ error: Pseudo-method is not used
instance_alignof(Int32)
# ^^^^^^^^^^^^^^^^^^^^^ error: Pseudo-method is not used
offsetof(Int32, 1)
# ^^^^^^^^^^^^^^^^ error: Pseudo-method is not used
is_a?(Int32)
# ^^^^^^^^^^ error: Pseudo-method is not used
as?(Int32)
# ^^^^^^^^ error: Pseudo-method is not used
responds_to?(:hello)
# ^^^^^^^^^^^^^^^^^^ error: Pseudo-method is not used
nil?
# ^^ error: Pseudo-method is not used
true.!
# ^^^^ error: Pseudo-method is not used
!true
# ^^^ error: Pseudo-method is not used
CRYSTAL
end

it "passes if pseudo methods are used as assign values" do
expect_no_issues subject, <<-CRYSTAL
var = pointerof(Int32)
var = sizeof(Int32)
var = instance_sizeof(Int32)
var = alignof(Int32)
var = instance_alignof(Int32)
var = offsetof(Int32, 1)
var = is_a?(Int32)
var = as?(Int32)
var = responds_to?(:hello)
var = nil?
var = true.!
var = !true
CRYSTAL
end
end
end
47 changes: 47 additions & 0 deletions spec/ameba/rule/lint/unused_self_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
require "../../../spec_helper"

module Ameba::Rule::Lint
describe UnusedSelf do
subject = UnusedSelf.new

it "passes if self is used" do
expect_no_issues subject, <<-CRYSTAL
class MyClass
class_property name : String = "George"

def self.hello
puts "hello, #{self.name}!"
end

def name : String
name.self

self.class.name
end
end
CRYSTAL
end

it "fails if self is unused" do
expect_issue subject, <<-CRYSTAL
class MyClass
self
# ^^^^ error: `self` is not used

class_property name : String = begin
self
# ^^^^ error: `self` is not used

"George"
end

def self.hello
self
# ^^^^ error: `self` is not used
puts "hello, #{self.name}!"
end
end
CRYSTAL
end
end
end
64 changes: 64 additions & 0 deletions src/ameba/rule/lint/unused_pseudo_method.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
module Ameba::Rule::Lint
# A rule that disallows unused pseudo methods (is_a?, sizeof, etc).
#
# For example, these are considered invalid:
#
# ```
# pointerof(1234_f32)
#
# method_call.as(Int32)
#
# def method
# if guard?
# !!valid?
# end
#
# true
# end
# ```
#
# And these are considered valid:
#
# ```
# a : pointerof(1234_f32)
#
# var = method_call.as(Int32)
#
# def method
# if guard?
# return !!valid?
# end
#
# true
# end
# ```
#
# YAML configuration example:
#
# ```
# Lint/UnusedPseudoMethod:
# Enabled: true
# ```
class UnusedPseudoMethod < Base
properties do
since_version "1.7.0"
description "Disallows unused pseudo-methods"
end

MSG = "Pseudo-method is not used"

def test(source : Source)
AST::ImplicitReturnVisitor.new(self, source)
end

def test(
source,
node : Crystal::PointerOf | Crystal::SizeOf | Crystal::InstanceSizeOf |
Crystal::AlignOf | Crystal::InstanceAlignOf | Crystal::OffsetOf |
Crystal::IsA | Crystal::NilableCast | Crystal::RespondsTo | Crystal::Not,
node_is_used : Bool,
)
issue_for node, MSG unless node_is_used
end
end
end
52 changes: 52 additions & 0 deletions src/ameba/rule/lint/unused_self.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
module Ameba::Rule::Lint
# A rule that disallows unused `self`.
#
# For example, this is considered invalid:
#
# ```
# class MyClass
# self
# end
# ```
#
# And these are considered valid:
#
# ```
# class MyClass
# def self.hello
# puts "Hello, world!"
# end
#
# self.hello
# end
# ```
#
# YAML configuration example:
#
# ```
# Lint/UnusedSelf:
# Enabled: true
# ```
class UnusedSelf < Base
properties do
since_version "1.7.0"
description "Disallows unused self"
end

MSG = "`self` is not used"

def test(source : Source)
AST::ImplicitReturnVisitor.new(self, source)
end

def test(source, node : Crystal::Self, node_is_used : Bool)
issue_for node, MSG unless node_is_used
end

def test(source, node : Crystal::Var, node_is_used : Bool)
return if node_is_used || node.name != "self"

issue_for node, MSG
end
end
end
Loading