-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add
Lint/Unused{Local,Instance,Class}VariableAccess
(#552)
* ImplicitReturnVisitor keeps track of whether the current node is in a macro or not Fixes for ImplicitReturnVisitor macro implicit returns * Add `Lint/UnusedLocalVariableAccess` * Add `Lint/UnusedInstanceVariableAccess` * Add `Lint/UnusedClassVariableAccess` * Update src/ameba/rule/lint/unused_local_variable_access.cr Co-authored-by: Sijawusz Pur Rahnama <[email protected]> * Update src/ameba/rule/lint/unused_instance_variable_access.cr Co-authored-by: Sijawusz Pur Rahnama <[email protected]> * Fix heredoc interpolations * Update specs from review * Apply suggestions from code review Co-authored-by: Sijawusz Pur Rahnama <[email protected]> * Update specs, disable unused cvars in macros * Update spec/ameba/rule/lint/unused_instance_variable_access_spec.cr Co-authored-by: Sijawusz Pur Rahnama <[email protected]> * Reorder spec --------- Co-authored-by: Sijawusz Pur Rahnama <[email protected]>
- Loading branch information
1 parent
3332098
commit 70dc11d
Showing
10 changed files
with
423 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
require "../../../spec_helper" | ||
|
||
module Ameba::Rule::Lint | ||
describe UnusedClassVariableAccess do | ||
subject = UnusedClassVariableAccess.new | ||
|
||
it "passes if class variables are used for assignment" do | ||
expect_no_issues subject, <<-CRYSTAL | ||
class MyClass | ||
foo = @@ivar | ||
end | ||
CRYSTAL | ||
end | ||
|
||
it "passes if an class variable is used as a target in multi-assignment" do | ||
expect_no_issues subject, <<-CRYSTAL | ||
class MyClass | ||
@@foo, @@bar = 1, 2 | ||
end | ||
CRYSTAL | ||
end | ||
|
||
it "fails if class variables are unused in void context of class" do | ||
expect_issue subject, <<-CRYSTAL | ||
class Actor | ||
@@name : String = "George" | ||
@@name | ||
# ^^^^^^ error: Value from class variable access is unused | ||
end | ||
CRYSTAL | ||
end | ||
|
||
it "fails if class variables are unused in void context of method" do | ||
expect_issue subject, <<-'CRYSTAL' | ||
def hello : String | ||
@@name | ||
# ^^^^^^ error: Value from class variable access is unused | ||
|
||
"Hello, #{@@name}!" | ||
end | ||
CRYSTAL | ||
end | ||
end | ||
end |
64 changes: 64 additions & 0 deletions
64
spec/ameba/rule/lint/unused_instance_variable_access_spec.cr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
require "../../../spec_helper" | ||
|
||
module Ameba::Rule::Lint | ||
describe UnusedInstanceVariableAccess do | ||
subject = UnusedInstanceVariableAccess.new | ||
|
||
it "passes if instance variables are used for assignment" do | ||
expect_no_issues subject, <<-CRYSTAL | ||
class MyClass | ||
foo = @ivar | ||
end | ||
CRYSTAL | ||
end | ||
|
||
it "passes if an instance variable is used as a target in multi-assignment" do | ||
expect_no_issues subject, <<-CRYSTAL | ||
class MyClass | ||
@foo, @bar = 1, 2 | ||
end | ||
CRYSTAL | ||
end | ||
|
||
it "fails if instance variables are unused in void context of class" do | ||
expect_issue subject, <<-CRYSTAL | ||
class Actor | ||
@name : String = "George" | ||
@name | ||
# ^^^^^ error: Value from instance variable access is unused | ||
end | ||
CRYSTAL | ||
end | ||
|
||
it "fails if instance variables are unused in void context of method" do | ||
expect_issue subject, <<-'CRYSTAL' | ||
def hello : String | ||
@name | ||
# ^^^^^ error: Value from instance variable access is unused | ||
|
||
"Hello, #{@name}!" | ||
end | ||
CRYSTAL | ||
end | ||
|
||
it "passes if @type is unused within a macro expression" do | ||
expect_no_issues subject, <<-CRYSTAL | ||
def foo | ||
{% @type %} | ||
:bar | ||
end | ||
CRYSTAL | ||
end | ||
|
||
it "fails if instance variable is unused within a macro expression" do | ||
expect_issue subject, <<-CRYSTAL | ||
def foo | ||
{% @bar %} | ||
# ^^^^ error: Value from instance variable access is unused | ||
:baz | ||
end | ||
CRYSTAL | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
require "../../../spec_helper" | ||
|
||
module Ameba::Rule::Lint | ||
describe UnusedLocalVariableAccess do | ||
subject = UnusedLocalVariableAccess.new | ||
|
||
it "passes if local variables are used in assign" do | ||
expect_no_issues subject, <<-CRYSTAL | ||
foo = 1 | ||
foo += 1 | ||
foo, bar = 2, 3 | ||
CRYSTAL | ||
end | ||
|
||
it "passes if a local variable is a call argument" do | ||
expect_no_issues subject, <<-CRYSTAL | ||
foo = 1 | ||
puts foo | ||
CRYSTAL | ||
end | ||
|
||
it "passes if local variable on left side of a comparison" do | ||
expect_no_issues subject, <<-CRYSTAL | ||
def hello | ||
foo = 1 | ||
foo || (puts "foo is falsey") | ||
foo | ||
end | ||
CRYSTAL | ||
end | ||
|
||
it "passes if skip_file is used in a macro" do | ||
expect_no_issues subject, <<-CRYSTAL | ||
{% skip_file %} | ||
CRYSTAL | ||
end | ||
|
||
it "passes if debug is used in a macro" do | ||
expect_no_issues subject, <<-CRYSTAL | ||
{% debug %} | ||
CRYSTAL | ||
end | ||
|
||
it "fails if a local variable is in a void context" do | ||
expect_issue subject, <<-CRYSTAL | ||
foo = 1 | ||
begin | ||
foo | ||
# ^^^ error: Value from local variable access is unused | ||
puts foo | ||
end | ||
CRYSTAL | ||
end | ||
|
||
it "fails if a parameter is in a void context" do | ||
expect_issue subject, <<-CRYSTAL | ||
def foo(bar) | ||
if bar > 0 | ||
bar | ||
# ^^^ error: Value from local variable access is unused | ||
end | ||
nil | ||
end | ||
CRYSTAL | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
module Ameba::Rule::Lint | ||
# A rule that disallows unused class variable access. | ||
# | ||
# For example, this is considered invalid: | ||
# | ||
# ``` | ||
# class MyClass | ||
# @@my_var : String = "hello" | ||
# | ||
# @@my_var | ||
# | ||
# def hello : String | ||
# @@my_var | ||
# | ||
# "hello, world!" | ||
# end | ||
# end | ||
# ``` | ||
# | ||
# And these are considered valid: | ||
# | ||
# ``` | ||
# class MyClass | ||
# @@my_var : String = "hello" | ||
# | ||
# @@my_other_var = @@my_var | ||
# | ||
# def hello : String | ||
# return @@my_var if @@my_var == "hello" | ||
# | ||
# "hello, world!" | ||
# end | ||
# end | ||
# ``` | ||
# | ||
# YAML configuration example: | ||
# | ||
# ``` | ||
# Lint/UnusedClassVariableAccess: | ||
# Enabled: true | ||
# ``` | ||
class UnusedClassVariableAccess < Base | ||
properties do | ||
since_version "1.7.0" | ||
description "Disallows unused access to class variables" | ||
end | ||
|
||
MSG = "Value from class variable access is unused" | ||
|
||
def test(source : Source) | ||
AST::ImplicitReturnVisitor.new(self, source) | ||
end | ||
|
||
def test(source, node : Crystal::ClassVar, in_macro : Bool) | ||
# Class variables aren't supported in macros | ||
return if in_macro | ||
|
||
issue_for node, MSG | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.