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

Crystal 1.4 compatibility #259

Merged
merged 8 commits into from
Apr 5, 2022
Merged
Show file tree
Hide file tree
Changes from 7 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
2 changes: 1 addition & 1 deletion shard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ scripts:
executables:
- ameba

crystal: ">= 0.35.0"
crystal: ">= 1.4.0"

license: MIT
8 changes: 1 addition & 7 deletions spec/ameba/ast/util_spec.cr
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
require "../../spec_helper"
require "semantic_version"

module Ameba::AST
struct Test
Expand Down Expand Up @@ -77,12 +76,7 @@ module Ameba::AST
CRYSTAL
node = as_nodes(s).nil_literal_nodes.first
source = subject.node_source node, s.split("\n")

if SemanticVersion.parse(Crystal::VERSION) <= SemanticVersion.parse("0.35.1")
source.should be_nil
else
source.should eq "nil"
end
source.should eq "nil"
end
end

Expand Down
35 changes: 9 additions & 26 deletions spec/ameba/rule/lint/empty_ensure_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Ameba::Rule::Lint
subject = EmptyEnsure.new

it "passes if there is no empty ensure blocks" do
s = Source.new %(
expect_no_issues subject, <<-CRYSTAL
def some_method
do_some_stuff
ensure
Expand All @@ -23,47 +23,30 @@ module Ameba::Rule::Lint
ensure
nil
end
)
subject.catch(s).should be_valid
CRYSTAL
end

it "fails if there is an empty ensure in method" do
s = Source.new %(
expect_issue subject, <<-CRYSTAL
def method
do_some_stuff
ensure
# ^^^^^^ error: Empty `ensure` block detected
end
)
subject.catch(s).should_not be_valid
CRYSTAL
end

it "fails if there is an empty ensure in a block" do
s = Source.new %(
begin
do_some_stuff
ensure
# nothing here
end
)
subject.catch(s).should_not be_valid
end

it "reports rule, pos and message" do
s = Source.new %(
expect_issue subject, <<-CRYSTAL
begin
do_some_stuff
rescue
do_some_other_stuff
ensure
# ^^^^^^ error: Empty `ensure` block detected
# nothing here
end
), "source.cr"
subject.catch(s).should_not be_valid
issue = s.issues.first

issue.rule.should_not be_nil
issue.location.to_s.should eq "source.cr:2:3"
issue.end_location.to_s.should eq "source.cr:6:3"
issue.message.should eq "Empty `ensure` block detected"
CRYSTAL
end
end
end
98 changes: 52 additions & 46 deletions spec/ameba/rule/lint/shadowed_exception_spec.cr
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
require "../../../spec_helper"

private def check_shadowed(source, exceptions)
s = Ameba::Source.new source
Ameba::Rule::Lint::ShadowedException.new.catch(s).should_not be_valid
s.issues.first.message.should contain exceptions.join(", ")
end

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

it "passes if there isn't shadowed exception" do
s = Source.new %(
expect_no_issues subject, <<-CRYSTAL
def method
do_something
rescue ArgumentError
Expand All @@ -31,146 +25,158 @@ module Ameba::Rule::Lint
rescue e : Exception
handle_exception
end
)
subject.catch(s).should be_valid
CRYSTAL
end

it "fails if there is a shadowed exception" do
check_shadowed %(
expect_issue subject, <<-CRYSTAL
begin
do_something
rescue Exception
handle_exception
rescue ArgumentError
# ^^^^^^^^^^^^^ error: Shadowed exception found: ArgumentError
handle_argument_error_exception
end
), %w(ArgumentError)
CRYSTAL
end

it "fails if there is a custom shadowed exceptions" do
check_shadowed %(
expect_issue subject, <<-CRYSTAL
begin
1
rescue Exception
2
rescue MySuperException
# ^^^^^^^^^^^^^^^^ error: Shadowed exception found: MySuperException
3
end
), %w(MySuperException)
CRYSTAL
end

it "fails if there is a shadowed exception in a type list" do
check_shadowed %(
expect_issue subject, <<-CRYSTAL
begin
rescue Exception | IndexError
# ^^^^^^^^^^ error: Shadowed exception found: IndexError
end
), %w(IndexError)
CRYSTAL
end

it "fails if there is a first shadowed exception in a type list" do
check_shadowed %(
expect_issue subject, <<-CRYSTAL
begin
rescue IndexError | Exception
# ^^^^^^^^^^ error: Shadowed exception found: IndexError
rescue Exception
# ^^^^^^^^^ error: Shadowed exception found: Exception
rescue
end
), %w(IndexError)
CRYSTAL
end

it "fails if there is a shadowed duplicated exception" do
check_shadowed %(
expect_issue subject, <<-CRYSTAL
begin
rescue IndexError
rescue ArgumentError
rescue IndexError
# ^^^^^^^^^^ error: Shadowed exception found: IndexError
end
), %w(IndexError)
CRYSTAL
end

it "fails if there is a shadowed duplicated exception in a type list" do
check_shadowed %(
expect_issue subject, <<-CRYSTAL
begin
rescue IndexError
rescue ArgumentError | IndexError
# ^^^^^^^^^^ error: Shadowed exception found: IndexError
end
), %w(IndexError)
CRYSTAL
end

it "fails if there is only shadowed duplicated exceptions" do
check_shadowed %(
expect_issue subject, <<-CRYSTAL
begin
rescue IndexError
rescue IndexError
# ^^^^^^^^^^ error: Shadowed exception found: IndexError
rescue Exception
end
), %w(IndexError)
CRYSTAL
end

it "fails if there is only shadowed duplicated exceptions in a type list" do
check_shadowed %(
expect_issue subject, <<-CRYSTAL
begin
rescue IndexError | IndexError
# ^^^^^^^^^^ error: Shadowed exception found: IndexError
end
), %w(IndexError)
CRYSTAL
end

it "fails if all rescues are shadowed and there is a catch-all rescue" do
check_shadowed %(
expect_issue subject, <<-CRYSTAL
begin
rescue Exception
rescue ArgumentError
# ^^^^^^^^^^^^^ error: Shadowed exception found: ArgumentError
rescue IndexError
# ^^^^^^^^^^ error: Shadowed exception found: IndexError
rescue KeyError | IO::Error
# ^^^^^^^^^ error: Shadowed exception found: IO::Error
# ^^^^^^^^ error: Shadowed exception found: KeyError
rescue
end
), %w(IndexError KeyError IO::Error)
CRYSTAL
end

it "fails if there are shadowed exception with args" do
check_shadowed %(
expect_issue subject, <<-CRYSTAL
begin
rescue Exception
rescue ex : IndexError
# ^^^^^^^^^^ error: Shadowed exception found: IndexError
rescue
end
), %w(IndexError)
CRYSTAL
end

it "fails if there are multiple shadowed exceptions" do
check_shadowed %(
expect_issue subject, <<-CRYSTAL
begin
rescue Exception
rescue ArgumentError
# ^^^^^^^^^^^^^ error: Shadowed exception found: ArgumentError
rescue IndexError
# ^^^^^^^^^^ error: Shadowed exception found: IndexError
end
), %w(ArgumentError IndexError)
CRYSTAL
end

it "fails if there are multiple shadowed exceptions in a type list" do
check_shadowed %(
expect_issue subject, <<-CRYSTAL
begin
rescue Exception
rescue ArgumentError | IndexError
# ^^^^^^^^^^ error: Shadowed exception found: IndexError
# ^^^^^^^^^^^^^ error: Shadowed exception found: ArgumentError
rescue IO::Error
# ^^^^^^^^^ error: Shadowed exception found: IO::Error
end
), %w(ArgumentError IndexError IO::Error)
CRYSTAL
end

it "reports rule, location and a message" do
s = Source.new %q(
it "fails if there are multiple shadowed exceptions in a single rescue" do
expect_issue subject, <<-CRYSTAL
begin
do_something
rescue Exception | IndexError
rescue Exception | IndexError | ArgumentError
# ^^^^^^^^^^^^^ error: Shadowed exception found: ArgumentError
# ^^^^^^^^^^ error: Shadowed exception found: IndexError
end
), "source.cr"
subject.catch(s).should_not be_valid
issue = s.issues.first

issue.rule.should_not be_nil
issue.location.to_s.should eq "source.cr:2:3"
issue.end_location.to_s.should eq "source.cr:4:3"
issue.message.should eq(
"Exception handler has shadowed exceptions: IndexError"
)
CRYSTAL
end
end
end
22 changes: 11 additions & 11 deletions spec/ameba/tokenizer_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,38 @@ require "../spec_helper"
module Ameba
private def it_tokenizes(str, expected)
it "tokenizes #{str}" do
([] of Symbol).tap do |token_types|
([] of String).tap do |token_types|
Tokenizer.new(Source.new str, normalize: false)
.run { |token| token_types << token.type }
.run { |token| token_types << token.type.to_s }
.should be_true
end.should eq expected
end
end

describe Tokenizer do
describe "#run" do
it_tokenizes %("string"), %i(DELIMITER_START STRING DELIMITER_END EOF)
it_tokenizes %(100), %i(NUMBER EOF)
it_tokenizes %('a'), %i(CHAR EOF)
it_tokenizes %([]), %i([] EOF)
it_tokenizes %([] of String), %i([] SPACE IDENT SPACE CONST EOF)
it_tokenizes %q("str #{3}"), %i(
it_tokenizes %("string"), %w(DELIMITER_START STRING DELIMITER_END EOF)
it_tokenizes %(100), %w(NUMBER EOF)
it_tokenizes %('a'), %w(CHAR EOF)
it_tokenizes %([]), %w([] EOF)
it_tokenizes %([] of String), %w([] SPACE IDENT SPACE CONST EOF)
it_tokenizes %q("str #{3}"), %w(
DELIMITER_START STRING INTERPOLATION_START NUMBER } DELIMITER_END EOF
)

it_tokenizes %(%w(1 2)),
%i(STRING_ARRAY_START STRING STRING STRING_ARRAY_END EOF)
%w(STRING_ARRAY_START STRING STRING STRING_ARRAY_END EOF)

it_tokenizes %(%i(one two)),
%i(SYMBOL_ARRAY_START STRING STRING STRING_ARRAY_END EOF)
%w(SYMBOL_ARRAY_START STRING STRING STRING_ARRAY_END EOF)

it_tokenizes %(
class A
def method
puts "hello"
end
end
), %i(
), %w(
NEWLINE SPACE IDENT SPACE CONST NEWLINE SPACE IDENT SPACE IDENT
NEWLINE SPACE IDENT SPACE DELIMITER_START STRING DELIMITER_END
NEWLINE SPACE IDENT NEWLINE SPACE IDENT NEWLINE SPACE EOF
Expand Down
6 changes: 3 additions & 3 deletions src/ameba/ast/util.cr
Original file line number Diff line number Diff line change
Expand Up @@ -194,9 +194,9 @@ module Ameba::AST::Util
return 0 unless node.responds_to?(:name) && (name = node.name)

case name
when Crystal::ASTNode then name.name_size
when Symbol then name.to_s.size # Crystal::MagicConstant
else name.size
when Crystal::ASTNode then name.name_size
when Crystal::Token::Kind then name.to_s.size # Crystal::MagicConstant
else name.size
end
end

Expand Down
2 changes: 1 addition & 1 deletion src/ameba/inline_comments.cr
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ module Ameba
commented = false

lexer = Crystal::Lexer.new(line).tap(&.comments_enabled = true)
Tokenizer.new(lexer).run { |t| commented = true if t.type == :COMMENT }
Tokenizer.new(lexer).run { |t| commented = true if t.type.comment? }
commented
end
end
Expand Down
2 changes: 1 addition & 1 deletion src/ameba/rule/lint/bad_directive.cr
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ module Ameba::Rule::Lint

def test(source)
Tokenizer.new(source).run do |token|
next unless token.type == :COMMENT
next unless token.type.comment?
next unless directive = source.parse_inline_directive(token.value.to_s)

check_action source, token, directive[:action]
Expand Down
2 changes: 1 addition & 1 deletion src/ameba/rule/lint/empty_ensure.cr
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ module Ameba::Rule::Lint
node_ensure = node.ensure
return if node_ensure.nil? || !node_ensure.nop?

issue_for node, MSG
issue_for node.ensure_location, node.end_location, MSG
end
end
end
Loading