Skip to content

Commit 3ac18d7

Browse files
Add Lint/TopLevelOperatorDefinition (#579)
1 parent 2b9c370 commit 3ac18d7

File tree

2 files changed

+105
-0
lines changed

2 files changed

+105
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
require "../../../spec_helper"
2+
3+
module Ameba::Rule::Lint
4+
describe TopLevelOperatorDefinition do
5+
subject = TopLevelOperatorDefinition.new
6+
7+
it "passes if an operator method is defined within a class" do
8+
expect_no_issues subject, <<-CRYSTAL
9+
class Foo
10+
def +(other)
11+
end
12+
end
13+
CRYSTAL
14+
end
15+
16+
it "passes if an operator method is defined within an enum" do
17+
expect_no_issues subject, <<-CRYSTAL
18+
enum Foo
19+
def +(other)
20+
end
21+
end
22+
CRYSTAL
23+
end
24+
25+
it "passes if an operator method is defined within a module" do
26+
expect_no_issues subject, <<-CRYSTAL
27+
module Foo
28+
def +(other)
29+
end
30+
end
31+
CRYSTAL
32+
end
33+
34+
it "passes if a top-level operator method has a receiver" do
35+
expect_no_issues subject, <<-CRYSTAL
36+
def Foo.+(other)
37+
end
38+
CRYSTAL
39+
end
40+
41+
it "fails if a + operator method is defined top-level" do
42+
expect_issue subject, <<-CRYSTAL
43+
def +(other)
44+
# ^^^^^^^^^^ error: Top level operator method definitions cannot be called
45+
end
46+
CRYSTAL
47+
end
48+
49+
it "fails if an index operator method is defined top-level" do
50+
expect_issue subject, <<-CRYSTAL
51+
def [](other)
52+
# ^^^^^^^^^^^ error: Top level operator method definitions cannot be called
53+
end
54+
CRYSTAL
55+
end
56+
end
57+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
module Ameba::Rule::Lint
2+
# A rule that disallows top level operator method definitions, since these cannot be called.
3+
#
4+
# For example, this is considered invalid:
5+
#
6+
# ```
7+
# def +(other)
8+
# end
9+
# ```
10+
#
11+
# And has to be written within a class, struct, or module:
12+
#
13+
# ```
14+
# class Foo
15+
# def +(other)
16+
# end
17+
# end
18+
# ```
19+
#
20+
# YAML configuration example:
21+
#
22+
# ```
23+
# Lint/TopLevelOperatorDefinition:
24+
# Enabled: true
25+
# ```
26+
class TopLevelOperatorDefinition < Base
27+
properties do
28+
since_version "1.7.0"
29+
description "Disallows top level operator method definitions"
30+
end
31+
32+
MSG = "Top level operator method definitions cannot be called"
33+
34+
def test(source)
35+
AST::NodeVisitor.new self, source, skip: [
36+
Crystal::ClassDef,
37+
Crystal::EnumDef,
38+
Crystal::ModuleDef,
39+
]
40+
end
41+
42+
def test(source, node : Crystal::Def)
43+
return if node.receiver || node.name.chars.any?(&.alphanumeric?)
44+
45+
issue_for node, MSG
46+
end
47+
end
48+
end

0 commit comments

Comments
 (0)