From a4433ffd9aa444b055fb816bcade76e79e337451 Mon Sep 17 00:00:00 2001
From: sangamcse <ksangam68@gmail.com>
Date: Sun, 8 Jul 2018 21:09:52 +0530
Subject: [PATCH] RubyFastererBear.py: Add `fasterer`

This adds a `Local Bear` for `Ruby`, wrapping
`fasterer`.

Closes https://github.com/coala/coala-bears/issues/444
---
 Gemfile                                       |  1 +
 bear-requirements.yaml                        |  2 +
 bears/ruby/RubyFastererBear.py                | 27 ++++++++++
 tests/ruby/RubyFastererBearTest.py            | 53 +++++++++++++++++++
 tests/ruby/fasterer_test_files/module_eval.rb | 15 ++++++
 .../fasterer_test_files/sort_vs_sort_by.rb    |  9 ++++
 6 files changed, 107 insertions(+)
 create mode 100644 bears/ruby/RubyFastererBear.py
 create mode 100644 tests/ruby/RubyFastererBearTest.py
 create mode 100644 tests/ruby/fasterer_test_files/module_eval.rb
 create mode 100644 tests/ruby/fasterer_test_files/sort_vs_sort_by.rb

diff --git a/Gemfile b/Gemfile
index 3b9a795d71..c02002b433 100644
--- a/Gemfile
+++ b/Gemfile
@@ -2,6 +2,7 @@ source 'https://rubygems.org'
 
 gem "brakeman", "~>4.1.1", require: false
 gem "csvlint", "~>0.4.0", require: false
+gem "fasterer", "~>0.4.1", require: false
 gem "haml_lint", "~>0.27.0", require: false
 gem "puppet-lint", "~>2.1.1", require: false
 gem "reek", "~>4.6", require: false
diff --git a/bear-requirements.yaml b/bear-requirements.yaml
index 5352668592..19082406bf 100644
--- a/bear-requirements.yaml
+++ b/bear-requirements.yaml
@@ -6,6 +6,8 @@ gem_requirements:
     version: ~>4.1.1
   csvlint:
     version: ~>0.4.0
+  fasterer:
+    version: ~>0.4.1
   haml_lint:
     version: ~>0.27.0
   puppet-lint:
diff --git a/bears/ruby/RubyFastererBear.py b/bears/ruby/RubyFastererBear.py
new file mode 100644
index 0000000000..073ca52223
--- /dev/null
+++ b/bears/ruby/RubyFastererBear.py
@@ -0,0 +1,27 @@
+from coalib.bearlib.abstractions.Linter import linter
+from dependency_management.requirements.GemRequirement import GemRequirement
+
+
+@linter(executable='fasterer',
+        output_format='regex',
+        output_regex=r'(?P<message>.*\.).*:\s(?P<line>\d+)')
+class RubyFastererBear:
+    """
+    The ``RubyFastererBear`` will suggest some speed improvements which you
+    can check in details at the <https://github.com/JuanitoFatas/fast-ruby>.
+
+    It uses ``fasterer``. See <https://www.rubydoc.info/gems/fasterer/0.4.1>
+    for more info.
+    """
+
+    LANGUAGES = {'Ruby'}
+    REQUIREMENTS = {GemRequirement('fasterer', '0.4.1')}
+    AUTHORS = {'The coala developers'}
+    AUTHORS_EMAILS = {'coala-devel@googlegroups.com'}
+    LICENSE = 'AGPL-3.0'
+    CAN_DETECT = {'Complexity'}
+    SEE_MORE = 'https://github.com/DamirSvrtan/fasterer'
+
+    @staticmethod
+    def create_arguments(filename, file, config_file):
+        return filename,
diff --git a/tests/ruby/RubyFastererBearTest.py b/tests/ruby/RubyFastererBearTest.py
new file mode 100644
index 0000000000..4fda8adb3d
--- /dev/null
+++ b/tests/ruby/RubyFastererBearTest.py
@@ -0,0 +1,53 @@
+import os
+from queue import Queue
+
+from coalib.results.Result import Result
+from coalib.settings.Section import Section
+from coalib.testing.BearTestHelper import generate_skip_decorator
+from coalib.testing.LocalBearTestHelper import LocalBearTestHelper
+
+from bears.ruby.RubyFastererBear import RubyFastererBear
+
+
+def get_testfile_path(name):
+    return os.path.join(os.path.dirname(__file__),
+                        'fasterer_test_files',
+                        name)
+
+
+def load_testfile(name):
+    with open(get_testfile_path(name)) as f:
+        return f.readlines()
+
+
+@generate_skip_decorator(RubyFastererBear)
+class RubyFastererBearTest(LocalBearTestHelper):
+
+    def setUp(self):
+        self.uut = RubyFastererBear(Section('name'), Queue())
+
+    def test_module_eval_vs_define_method(self):
+        filename = 'module_eval.rb'
+        file_contents = load_testfile(filename)
+        self.check_results(
+            self.uut,
+            file_contents,
+            [Result.from_values('RubyFastererBear',
+                                message='Using module_eval is slower than '
+                                        'define_method.',
+                                file=get_testfile_path(filename),
+                                line=3)],
+            filename=get_testfile_path(filename))
+
+    def test_sort_vs_sort_by(self):
+        filename = 'sort_vs_sort_by.rb'
+        file_contents = load_testfile(filename)
+        self.check_results(
+            self.uut,
+            file_contents,
+            [Result.from_values('RubyFastererBear',
+                                message='Enumerable#sort is slower than '
+                                        'Enumerable#sort_by.',
+                                file=get_testfile_path(filename),
+                                line=6)],
+            filename=get_testfile_path(filename))
diff --git a/tests/ruby/fasterer_test_files/module_eval.rb b/tests/ruby/fasterer_test_files/module_eval.rb
new file mode 100644
index 0000000000..380f08697c
--- /dev/null
+++ b/tests/ruby/fasterer_test_files/module_eval.rb
@@ -0,0 +1,15 @@
+module Hihi
+  class << self
+    module_eval %{
+      def hello
+        puts "win"
+      end
+    }
+  end
+end
+
+Hihi.hello
+
+Hihi.module_eval %{
+  puts @foo
+}
diff --git a/tests/ruby/fasterer_test_files/sort_vs_sort_by.rb b/tests/ruby/fasterer_test_files/sort_vs_sort_by.rb
new file mode 100644
index 0000000000..1b34b45e1d
--- /dev/null
+++ b/tests/ruby/fasterer_test_files/sort_vs_sort_by.rb
@@ -0,0 +1,9 @@
+User  = Struct.new(:name)
+ARRAY = Array.new(3) do
+  User.new(sprintf("%010d"), rand(1_000_000_000))
+end
+
+ARRAY.sort { |a, b| a.name <=> b.name }
+ARRAY.sort_by(&:name)
+
+ARRAY.sort