← All posts

Ameba 1.0.0 has been released

This release includes a long-waiting autocorrection feature, new rules and several improvements. Check out the release notes to see a full scope of changes.

Crystal compatibility

This release introduces Crystal 1.4 compatibility and breaks compatibility with previous Crystal versions. Use the latest Ameba bugfix release 0.14.4 if you need compatibility with Crystal 1.3.x or below.

Autocorrection

Thanks to the community, there is a huge step forward implementing autocorrection for Ameba. The feature was originally developed in #248 and afterwards improved in several cycles.

Now if Ameba reports an issue which can be corrected, it adds a [Correctable] notice:

$ ameba --only Style/RedundantBegin src/file_utils.cr

src/file_utils.cr:428:5 [Correctable]
[C] Style/RedundantBegin: Redundant `begin` block detected
> begin
  ^---^

meaning, if you append a new --fix command-line flag to the command it will automatically correct the issue adding another notice [Corrected]:

ameba --only Style/RedundantBegin src/file_utils.cr --fix

src/file_utils.cr:428:5 [Corrected]
[C] Style/RedundantBegin: Redundant `begin` block detected
> begin
  ^---^

using a git diff we can quickly check that Ameba removed a reported redundant begin block and used the exception handler as part of a method:

diff --git a/src/file_utils.cr b/src/file_utils.cr
index e82e3c1e1..d416ed05b 100644
--- a/src/file_utils.cr
+++ b/src/file_utils.cr
@@ -425,10 +425,8 @@ module FileUtils
   # FileUtils.rm_rf("non_existent_file")
   # ```
   def rm_rf(path : Path | String) : Nil
-    begin
-      rm_r(path)
-    rescue File::Error
-    end
+    rm_r(path)
+  rescue File::Error
   end

Note: not all rules support autocorrection yet, but if you see a [Correctable] flag on a reported issue, do not hesitate to autocorrect it in order to save some time during refactoring.

New rules

Lint/AmbiguousAssignment

A tiny rule that checks for mistyped shorthand assignments.

Bad

x =- y
x =+ y
x =! y

Good

x -= y # or x = -y
x += y # or x = +y
x != y # or x = !y

Lint/DebugCalls

A rule that disallows calls to debug-related methods. This is because we don’t want debug calls accidentally being committed into our codebase.

a = 2
pp! a # error: Possibly forgotten debug-related `pp!` call detected
a = a + 1

Check out the API doc to see a full list of supported debug-related calls.

Style/GuardClause

A rule that enforces a guard clause instead of wrapping the code inside a conditional expression.

Bad

def test
  if something
    work
  end
end

Good

def test
  return unless something

  work
end

New spec matchers

Ameba has a high code coverage which was obviously achieved by a big amount of tests. However, most of the rule specs were too imperative and it led to code duplication and some readability issues.

In this release, new spec matchers for rule tests were introduced. This new declarative approach allows to easily track all the reported issues in specs.

it "reports multiple shared variables in spawn" do
  expect_issue subject, <<-CRYSTAL
    foo, bar, baz = 0, 0, 0

    while foo < 10
      baz += 1

      spawn do
        puts foo
           # ^^^ error: Shared variable `foo` is used in fiber
        puts foo + bar + baz
           # ^^^ error: Shared variable `foo` is used in fiber
                       # ^^^ error: Shared variable `baz` is used in fiber
      end

      foo += 1
    end
    CRYSTAL
end

Some explanation:

  • ^^^ - tracks location of the reported node
  • error - error message annotation marker
  • Shared variable 'foo' is used in fiber - the reported error message

These new matchers are used internally and of course can be used by Ameba extensions. Check out the doc for more details.