GithubHelp home page GithubHelp logo

troessner / reek Goto Github PK

View Code? Open in Web Editor NEW
4.0K 48.0 280.0 5.82 MB

Code smell detector for Ruby

Home Page: https://github.com/troessner/reek

License: MIT License

Ruby 84.44% HTML 0.39% Gherkin 15.07% Dockerfile 0.11%
smell ruby smell-warnings smell-detector static-analysis linters quality parsing

reek's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

reek's Issues

Audit masked smells

How about two options to reek:

% reek --include-masked-smells
% reek --only-masked-smells

That let you identify smells that config files have disabled compared to the defaults. (eg FeatureEnvy if it was disabled, LongMethod if it was set to 20 and it found a method of length 7-19)

This would provide a way to put really awkward bits on the back burner, but give a way to go back to them later.

Long Method should count nested assignments

The following code includes 3 nested assignments, yet none of these contribute to the method's "length":

def parse(arg, argv, &error)
  if !(val = arg) and (argv.empty? or /\A-/ =~ (val = argv[0]))
    return nil, block, nil
  end
  opt = (val = parse_arg(val, &error))[1]
  val = conv_arg(*val)
  if opt and !arg
    argv.shift
  else
    val[0] = nil
  end
  val
end

The metho'ds length is reported as 6, but should be 9.

Fail on unnecessary exclusions

[Raised by Ashley Moran]

Say you have the following config file:


---
FeatureEnvy:
  exclude:
  - view

but the view method that gets analysed does not have Feature Envy. Should this be considered an error? It seems that exclusions could persist after the code smells have been removed, silently ignoring the smell being introduced.

I've done a few refactorings now that removed code smells, and had to remember to manually take them out of the configs.
Similar idea to code coverage failing if your coverage percentage increases on the basis that you want to maintain any improvements you make.

Possibly the sanest behaviour would be to fail if the config is in the same directory as the file affected, so that global excludes don't raise loads of errors.

FeatureEnvy can miss envious instance variables

The following method is envious

def func
  @other.a
  @other.b
  @nother.c
end

because it could be moved to @other, creating a method like tthis:

def other.func(me)
  a
  b
  me.nother_c
end

But FeatureEnvy doesn't pick this up.

Adapters are different from domain code

In a Hexagonal Architectural view of an app, the code style in the Adapters is special. So any name matching /Adapter/ should be exempted from certain smells (particularly those related to conditional code).

Class methods defined in "class << self; end" not recognised as such

For example, the following method reports Feature Envy (I think - I'd have to check). But Utility Function is the most common one that gets reported.

class ProposedQuestion
  class << self
    def new_for_facts_with_format(times_table_facts, question_format)
      times_table_facts.map { |fact| ProposedQuestion.new(:times_table_fact => fact, :question_format => question_format) }
    end
  end
end

Temporary Field

A class has a field that is not set in the constructor, but is used in some method that doesn't also set it.

Or a class provides an attr_writer.

Plug-in for NetBeans

The plug-in should mark up source files in the editor view, showing where the smells are.

Configure reek per-file, not per-smell

This came up today. We have a file of ugly monkey-patching hacks to workaround framework bugs, and we wanted to turn reek off for this. But we couldn't control the smells on a per-file basis, so we had to put them in one by one.

Being able to configure smells per-file or per-class/module would have made this easier.

WDYT?

DataMapper models trigger false positive Large Class

I get the following code smell with a DataMapper model:

"app/models/response.rb" -- 1 warnings:
Response has at least 27 methods (Large Class)

I'm sure you'll agree the class doesn't have that many methods...

class Response
  include DataMapper::Resource

  property :id,           Serial
  property :response,     Integer,  :nullable => false
  property :made_at,      Time,     :nullable => false, :default => lambda { Clock.current_time }

  belongs_to  :proposed_question

  def correct?
    question.accepts_as_correct?(response)
  end

  def <=>(other)
    other.made_at <=> made_at
  end

  def ==(other)
    made_at == other.made_at &&
      response == other.response
  end
end

Similarly wacky numbers come out of all my other DM models, 37 being the highest...

Open Secret: multiple return values

There's an Open Secret when a method returns multiple values. For example:

url, url_title = check_refs( url )

Or is it a kind of Data Clump?

Large Module

The name Large Class is a hangover from Martin Fowler's original Java smells; in Ruby it should probably be renamed to Large Module.

Provide YAML output for ease of parsing

Tools such as metric_fu currently parse Reek's text output. It would be easier for them to load a YAML file produced by Reek. So I propose a new option --format taking one of (initially) three values: none, yaml, or text; the last would produce the current output, and would be the default.

Plug-in for Aptana

The plug-in should mark up source files in the editor view, showing where the smells are.

Some smells shouldn't apply in memory

When Reek is asked to examine an in-memory object, via

MyClass.should_not reek

for example, certain smells should be disabled. Most obvious of these is LargeClass.

DescriptionlessModule

Every class and module should have a brief description of its responsibilities in the comments just ahead of its definition

Large Class should count extensions

The methods in a class may be defined in multiple batches, possibly in multiple source files. So Reek needs to remember what it sees over the whole file set, and add methods and ivars to an existing class where necessary.

Large Class should not count added methods from validations / associations in Rails

[Raised originally by dbalatero]

Given an ActiveRecord model with a number of validations and associations added, and no extra methods, the method count can balloon to larger than the max count really fast.

I believe this is because validates*of-type methods in Rails add methods to the class itself, so they don't get seen as separate modules / inherited methods.

Would there be a way to whitelist some of these generated methods?

Simulated Polymorphism

Check for repeated identical conditional expressions within the same class or module.

Add a config option to set the number of occurrences of the expressions that will trigger a warning. Set it to 3 by default.

Data Clump

Examine the parameters to the parsed methods and look for clumps of common names.

Configure by minimum clump size and min repetition threshold.

Quiet RSpec matcher

Sorry for any duplication - can't find a ticket for the --quiet option anywhere. I think the RSpec matcher should be quiet by default, and certainly configurable: showing a huge list of "0 warnings" makes it much harder to work through and fix code issues.

Remove dependency on ParseTree

Ryan Davis, author of both ParseTree and ruby_parser, says ParseTree will be end-of-lifed at the same time as Ruby 1.8 And even now it is no longer actively supported.

smell severity

Tools such as perlcritic categorise the smells they report with a "severity". Good idea.

reek --profile relaxed | strict

Store a variety of profiles as profile.reek files in config/, and allow the user to pick which one is used as the base for the run's config. Start with relaxed | strict.

Output parseable reports

Add an optino to write a YAML report into an output folder.
(Could look at metric_fu for the report's format?)

%f and %l in smell warnings

Currently smell warnings describe the code element in which the smell sits, but this can be ambiguous or vague (for example, nested iterators in a large method can be hard to identify). Reek should offer %f (filename) and %l (line number) in smell reports.

Can't load reek 1.1.3.13 with 1.1.3.10 installed

Got this in spec_helper.rb:

gem 'kevinrutherford-reek'
require 'reek'
require 'reek/spec'

You get this error:

/opt/local/lib/ruby/vendor_ruby/1.8/rubygems.rb:149:in `activate': can't activate kevinrutherford-reek (= 1.1.3.10, runtime), already activated kevinrutherford-reek-1.1.3.13 (Gem::Exception)
    from /opt/local/lib/ruby/vendor_ruby/1.8/rubygems/custom_require.rb:35:in `require'

Removing old gems solves it, but it should be able to load?

Law of Demeter

Add a detector for the Law of Demeter. This should at least report methods called on a value returned from a method.

Core extension

Attempt to detect when a method has been added to a core class.

Feature Envy for blocks and code fragments

Feature Envy currently applies only to whole methods. It would be great to find a way to have it report a block, or the else-clause of a conditional, or any branch of a switch.

Inline exception configuration

Would be nice to be able to disable smells for specific bits of code instead of using the config file. for example...

def my_method #:nosmell[utility_function]
  ...
end

[Raised by S. Brent Faulkner]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.