[DRE-commits] [rubocop] 03/04: Imported Upstream version 0.20.1

Sebastien Badia sbadia-guest at moszumanska.debian.org
Mon Apr 21 14:08:43 UTC 2014


This is an automated email from the git hooks/post-receive script.

sbadia-guest pushed a commit to branch master
in repository rubocop.

commit d22303ac6b5c7e1e6c76bb2066f6d62154267f0e
Author: Sebastien Badia <seb at sebian.fr>
Date:   Mon Apr 21 16:06:48 2014 +0200

    Imported Upstream version 0.20.1
---
 .gitignore                                         |   51 +
 .rspec                                             |    1 +
 .rubocop.yml                                       |    3 +
 .travis.yml                                        |   16 +
 .yardopts                                          |    2 +
 CHANGELOG.md                                       |  851 +++++++++
 CONTRIBUTING.md                                    |   68 +
 Gemfile                                            |   13 +
 LICENSE.txt                                        |   20 +
 README.md                                          |  725 ++++++++
 Rakefile                                           |   43 +
 bin/rubocop                                        |   22 +
 config/default.yml                                 |  451 +++++
 config/disabled.yml                                |   13 +
 config/enabled.yml                                 |  729 ++++++++
 lib/rubocop.rb                                     |  262 +++
 lib/rubocop/cli.rb                                 |  109 ++
 lib/rubocop/comment_config.rb                      |   99 ++
 lib/rubocop/config.rb                              |  106 ++
 lib/rubocop/config_loader.rb                       |  161 ++
 lib/rubocop/config_store.rb                        |   45 +
 lib/rubocop/cop/commissioner.rb                    |  105 ++
 lib/rubocop/cop/cop.rb                             |  192 ++
 lib/rubocop/cop/corrector.rb                       |   84 +
 lib/rubocop/cop/ignored_node.rb                    |   31 +
 lib/rubocop/cop/lint/ambiguous_operator.rb         |   50 +
 lib/rubocop/cop/lint/ambiguous_regexp_literal.rb   |   36 +
 lib/rubocop/cop/lint/assignment_in_condition.rb    |   46 +
 lib/rubocop/cop/lint/block_alignment.rb            |  151 ++
 lib/rubocop/cop/lint/condition_position.rb         |   52 +
 lib/rubocop/cop/lint/debugger.rb                   |   35 +
 lib/rubocop/cop/lint/deprecated_class_methods.rb   |   62 +
 lib/rubocop/cop/lint/else_layout.rb                |   57 +
 lib/rubocop/cop/lint/empty_ensure.rb               |   18 +
 lib/rubocop/cop/lint/empty_interpolation.rb        |   22 +
 lib/rubocop/cop/lint/end_alignment.rb              |  129 ++
 lib/rubocop/cop/lint/end_in_method.rb              |   22 +
 lib/rubocop/cop/lint/ensure_return.rb              |   22 +
 lib/rubocop/cop/lint/eval.rb                       |   18 +
 lib/rubocop/cop/lint/handle_exceptions.rb          |   18 +
 lib/rubocop/cop/lint/invalid_character_literal.rb  |   37 +
 lib/rubocop/cop/lint/literal_in_condition.rb       |  138 ++
 lib/rubocop/cop/lint/literal_in_interpolation.rb   |   37 +
 lib/rubocop/cop/lint/loop.rb                       |   27 +
 .../cop/lint/parentheses_as_grouped_expression.rb  |   52 +
 lib/rubocop/cop/lint/require_parentheses.rb        |   68 +
 lib/rubocop/cop/lint/rescue_exception.rb           |   24 +
 .../cop/lint/shadowing_outer_local_variable.rb     |   31 +
 lib/rubocop/cop/lint/space_before_first_arg.rb     |   37 +
 .../cop/lint/string_conversion_in_interpolation.rb |   51 +
 lib/rubocop/cop/lint/syntax.rb                     |   28 +
 lib/rubocop/cop/lint/unreachable_code.rb           |   33 +
 lib/rubocop/cop/lint/useless_access_modifier.rb    |   58 +
 lib/rubocop/cop/lint/useless_assignment.rb         |   88 +
 lib/rubocop/cop/lint/useless_comparison.rb         |   30 +
 .../cop/lint/useless_else_without_rescue.rb        |   25 +
 lib/rubocop/cop/lint/useless_setter_call.rb        |  150 ++
 lib/rubocop/cop/lint/void.rb                       |   54 +
 lib/rubocop/cop/mixin/annotation_comment.rb        |   37 +
 lib/rubocop/cop/mixin/array_syntax.rb              |   24 +
 lib/rubocop/cop/mixin/autocorrect_alignment.rb     |   79 +
 .../cop/mixin/autocorrect_unless_changing_ast.rb   |   24 +
 lib/rubocop/cop/mixin/check_assignment.rb          |   26 +
 lib/rubocop/cop/mixin/check_methods.rb             |   18 +
 lib/rubocop/cop/mixin/code_length.rb               |   33 +
 .../cop/mixin/configurable_enforced_style.rb       |   53 +
 lib/rubocop/cop/mixin/configurable_max.rb          |   19 +
 lib/rubocop/cop/mixin/configurable_naming.rb       |   45 +
 lib/rubocop/cop/mixin/if_node.rb                   |   25 +
 lib/rubocop/cop/mixin/if_then_else.rb              |   23 +
 lib/rubocop/cop/mixin/negative_conditional.rb      |   24 +
 lib/rubocop/cop/mixin/parser_diagnostic.rb         |   34 +
 lib/rubocop/cop/mixin/safe_assignment.rb           |   19 +
 lib/rubocop/cop/mixin/space_after_punctuation.rb   |   33 +
 lib/rubocop/cop/mixin/space_inside.rb              |   35 +
 lib/rubocop/cop/mixin/statement_modifier.rb        |   60 +
 lib/rubocop/cop/mixin/string_help.rb               |   32 +
 lib/rubocop/cop/mixin/surrounding_space.rb         |   42 +
 lib/rubocop/cop/offense.rb                         |  119 ++
 lib/rubocop/cop/rails/action_filter.rb             |   73 +
 lib/rubocop/cop/rails/default_scope.rb             |   35 +
 lib/rubocop/cop/rails/has_and_belongs_to_many.rb   |   18 +
 lib/rubocop/cop/rails/output.rb                    |   26 +
 lib/rubocop/cop/rails/read_write_attribute.rb      |   43 +
 lib/rubocop/cop/rails/scope_args.rb                |   33 +
 lib/rubocop/cop/rails/validation.rb                |   31 +
 lib/rubocop/cop/severity.rb                        |   76 +
 .../cop/style/access_modifier_indentation.rb       |   94 +
 lib/rubocop/cop/style/accessor_method_name.rb      |   45 +
 lib/rubocop/cop/style/alias.rb                     |   48 +
 lib/rubocop/cop/style/align_array.rb               |   20 +
 lib/rubocop/cop/style/align_hash.rb                |  257 +++
 lib/rubocop/cop/style/align_parameters.rb          |   39 +
 lib/rubocop/cop/style/and_or.rb                    |   44 +
 lib/rubocop/cop/style/array_join.rb                |   25 +
 lib/rubocop/cop/style/ascii_comments.rb            |   19 +
 lib/rubocop/cop/style/ascii_identifiers.rb         |   20 +
 lib/rubocop/cop/style/attr.rb                      |   22 +
 lib/rubocop/cop/style/begin_block.rb               |   16 +
 lib/rubocop/cop/style/block_comments.rb            |   20 +
 lib/rubocop/cop/style/block_nesting.rb             |   55 +
 lib/rubocop/cop/style/blocks.rb                    |   80 +
 .../cop/style/braces_around_hash_parameters.rb     |   87 +
 lib/rubocop/cop/style/case_equality.rb             |   18 +
 lib/rubocop/cop/style/case_indentation.rb          |   62 +
 lib/rubocop/cop/style/character_literal.rb         |   42 +
 .../cop/style/class_and_module_camel_case.rb       |   29 +
 lib/rubocop/cop/style/class_and_module_children.rb |   69 +
 lib/rubocop/cop/style/class_length.rb              |   49 +
 lib/rubocop/cop/style/class_methods.rb             |   56 +
 lib/rubocop/cop/style/class_vars.rb                |   23 +
 lib/rubocop/cop/style/collection_methods.rb        |   73 +
 lib/rubocop/cop/style/colon_method_call.rb         |   33 +
 lib/rubocop/cop/style/comment_annotation.rb        |   37 +
 lib/rubocop/cop/style/constant_name.rb             |   29 +
 lib/rubocop/cop/style/cyclomatic_complexity.rb     |   41 +
 lib/rubocop/cop/style/def_with_parentheses.rb      |   33 +
 lib/rubocop/cop/style/deprecated_hash_methods.rb   |   39 +
 lib/rubocop/cop/style/documentation.rb             |   74 +
 lib/rubocop/cop/style/dot_position.rb              |   57 +
 lib/rubocop/cop/style/double_negation.rb           |   40 +
 lib/rubocop/cop/style/empty_line_between_defs.rb   |   46 +
 lib/rubocop/cop/style/empty_lines.rb               |   47 +
 .../style/empty_lines_around_access_modifier.rb    |   48 +
 lib/rubocop/cop/style/empty_lines_around_body.rb   |   74 +
 lib/rubocop/cop/style/empty_literal.rb             |   60 +
 lib/rubocop/cop/style/encoding.rb                  |   30 +
 lib/rubocop/cop/style/end_block.rb                 |   16 +
 lib/rubocop/cop/style/end_of_line.rb               |   30 +
 lib/rubocop/cop/style/even_odd.rb                  |   60 +
 lib/rubocop/cop/style/file_name.rb                 |   29 +
 lib/rubocop/cop/style/final_newline.rb             |   29 +
 lib/rubocop/cop/style/flip_flop.rb                 |   20 +
 lib/rubocop/cop/style/for.rb                       |   47 +
 lib/rubocop/cop/style/format_string.rb             |   66 +
 lib/rubocop/cop/style/global_vars.rb               |   74 +
 lib/rubocop/cop/style/guard_clause.rb              |   69 +
 lib/rubocop/cop/style/hash_syntax.rb               |   89 +
 lib/rubocop/cop/style/if_unless_modifier.rb        |   35 +
 lib/rubocop/cop/style/if_with_semicolon.rb         |   20 +
 lib/rubocop/cop/style/indent_array.rb              |   41 +
 lib/rubocop/cop/style/indent_hash.rb               |  144 ++
 lib/rubocop/cop/style/indentation_consistency.rb   |   43 +
 lib/rubocop/cop/style/indentation_width.rb         |  177 ++
 lib/rubocop/cop/style/lambda.rb                    |   45 +
 lib/rubocop/cop/style/lambda_call.rb               |   63 +
 lib/rubocop/cop/style/leading_comment_space.rb     |   34 +
 lib/rubocop/cop/style/line_end_concatenation.rb    |   66 +
 lib/rubocop/cop/style/line_length.rb               |   34 +
 lib/rubocop/cop/style/method_call_parentheses.rb   |   35 +
 .../cop/style/method_called_on_do_end_block.rb     |   41 +
 lib/rubocop/cop/style/method_def_parentheses.rb    |   72 +
 lib/rubocop/cop/style/method_length.rb             |   29 +
 lib/rubocop/cop/style/method_name.rb               |   42 +
 lib/rubocop/cop/style/module_function.rb           |   32 +
 lib/rubocop/cop/style/multiline_block_chain.rb     |   44 +
 lib/rubocop/cop/style/multiline_if_then.rb         |   50 +
 .../cop/style/multiline_ternary_operator.rb        |   22 +
 lib/rubocop/cop/style/negated_if.rb                |   46 +
 lib/rubocop/cop/style/negated_while.rb             |   45 +
 lib/rubocop/cop/style/nested_ternary_operator.rb   |   26 +
 lib/rubocop/cop/style/nil_comparison.rb            |   42 +
 lib/rubocop/cop/style/non_nil_check.rb             |  104 ++
 lib/rubocop/cop/style/not.rb                       |   34 +
 lib/rubocop/cop/style/numeric_literals.rb          |   73 +
 lib/rubocop/cop/style/one_line_conditional.rb      |   21 +
 lib/rubocop/cop/style/op_method.rb                 |   27 +
 lib/rubocop/cop/style/parameter_lists.rb           |   44 +
 .../cop/style/parentheses_around_condition.rb      |   62 +
 .../cop/style/percent_literal_delimiters.rb        |  153 ++
 lib/rubocop/cop/style/perl_backrefs.rb             |   26 +
 lib/rubocop/cop/style/predicate_name.rb            |   46 +
 lib/rubocop/cop/style/proc.rb                      |   32 +
 lib/rubocop/cop/style/raise_args.rb                |   68 +
 lib/rubocop/cop/style/redundant_begin.rb           |   35 +
 lib/rubocop/cop/style/redundant_exception.rb       |   32 +
 lib/rubocop/cop/style/redundant_return.rb          |   66 +
 lib/rubocop/cop/style/redundant_self.rb            |  145 ++
 lib/rubocop/cop/style/regexp_literal.rb            |   81 +
 lib/rubocop/cop/style/rescue_modifier.rb           |   39 +
 lib/rubocop/cop/style/self_assignment.rb           |   73 +
 lib/rubocop/cop/style/semicolon.rb                 |   68 +
 lib/rubocop/cop/style/signal_exception.rb          |   96 +
 lib/rubocop/cop/style/single_line_block_params.rb  |   62 +
 lib/rubocop/cop/style/single_line_methods.rb       |   70 +
 .../cop/style/single_space_before_first_arg.rb     |   41 +
 lib/rubocop/cop/style/space_after_colon.rb         |   36 +
 lib/rubocop/cop/style/space_after_comma.rb         |   16 +
 .../cop/style/space_after_control_keyword.rb       |   37 +
 lib/rubocop/cop/style/space_after_method_name.rb   |   40 +
 lib/rubocop/cop/style/space_after_not.rb           |   41 +
 lib/rubocop/cop/style/space_after_semicolon.rb     |   16 +
 .../space_around_equals_in_parameter_default.rb    |   68 +
 lib/rubocop/cop/style/space_around_operators.rb    |   82 +
 lib/rubocop/cop/style/space_before_block_braces.rb |   63 +
 .../cop/style/space_before_modifier_keyword.rb     |   40 +
 lib/rubocop/cop/style/space_inside_block_braces.rb |  151 ++
 lib/rubocop/cop/style/space_inside_brackets.rb     |   16 +
 .../cop/style/space_inside_hash_literal_braces.rb  |  111 ++
 lib/rubocop/cop/style/space_inside_parens.rb       |   16 +
 lib/rubocop/cop/style/special_global_vars.rb       |   84 +
 lib/rubocop/cop/style/string_literals.rb           |   46 +
 lib/rubocop/cop/style/symbol_array.rb              |   24 +
 lib/rubocop/cop/style/tab.rb                       |   26 +
 lib/rubocop/cop/style/trailing_blank_lines.rb      |   44 +
 lib/rubocop/cop/style/trailing_comma.rb            |  102 ++
 lib/rubocop/cop/style/trailing_whitespace.rb       |   28 +
 lib/rubocop/cop/style/trivial_accessors.rb         |   78 +
 lib/rubocop/cop/style/unless_else.rb               |   24 +
 lib/rubocop/cop/style/variable_interpolation.rb    |   33 +
 lib/rubocop/cop/style/variable_name.rb             |   44 +
 lib/rubocop/cop/style/when_then.rb                 |   24 +
 lib/rubocop/cop/style/while_until_do.rb            |   45 +
 lib/rubocop/cop/style/while_until_modifier.rb      |   33 +
 lib/rubocop/cop/style/word_array.rb                |   86 +
 lib/rubocop/cop/team.rb                            |  113 ++
 lib/rubocop/cop/util.rb                            |  166 ++
 lib/rubocop/cop/variable_inspector.rb              |  427 +++++
 lib/rubocop/cop/variable_inspector/assignment.rb   |  103 ++
 lib/rubocop/cop/variable_inspector/locatable.rb    |  162 ++
 lib/rubocop/cop/variable_inspector/reference.rb    |   31 +
 lib/rubocop/cop/variable_inspector/scope.rb        |   71 +
 lib/rubocop/cop/variable_inspector/variable.rb     |   87 +
 .../cop/variable_inspector/variable_table.rb       |  129 ++
 lib/rubocop/file_inspector.rb                      |  149 ++
 lib/rubocop/formatter/base_formatter.rb            |  119 ++
 lib/rubocop/formatter/clang_style_formatter.rb     |   35 +
 lib/rubocop/formatter/colorizable.rb               |   37 +
 lib/rubocop/formatter/disabled_config_formatter.rb |   65 +
 lib/rubocop/formatter/disabled_lines_formatter.rb  |   56 +
 lib/rubocop/formatter/emacs_style_formatter.rb     |   21 +
 lib/rubocop/formatter/file_list_formatter.rb       |   19 +
 lib/rubocop/formatter/formatter_set.rb             |   75 +
 lib/rubocop/formatter/fuubar_style_formatter.rb    |   74 +
 lib/rubocop/formatter/json_formatter.rb            |   74 +
 lib/rubocop/formatter/offense_count_formatter.rb   |   54 +
 lib/rubocop/formatter/progress_formatter.rb        |   55 +
 lib/rubocop/formatter/simple_text_formatter.rb     |  117 ++
 lib/rubocop/options.rb                             |  189 ++
 lib/rubocop/path_util.rb                           |   23 +
 lib/rubocop/processed_source.rb                    |   61 +
 lib/rubocop/rake_task.rb                           |   70 +
 lib/rubocop/source_parser.rb                       |   47 +
 lib/rubocop/target_finder.rb                       |   91 +
 lib/rubocop/token.rb                               |   22 +
 lib/rubocop/version.rb                             |   21 +
 relnotes/v0.19.0.md                                |   94 +
 relnotes/v0.19.1.md                                |   16 +
 relnotes/v0.20.0.md                                |   69 +
 relnotes/v0.20.1.md                                |   24 +
 rubocop-todo.yml                                   |   20 +
 rubocop.gemspec                                    |   39 +
 spec/.rubocop.yml                                  |    5 +
 spec/isolated_environment_spec.rb                  |   24 +
 spec/project_spec.rb                               |  118 ++
 spec/rubocop/cli_spec.rb                           | 1830 ++++++++++++++++++++
 spec/rubocop/comment_config_spec.rb                |  103 ++
 spec/rubocop/config_loader_spec.rb                 |  328 ++++
 spec/rubocop/config_spec.rb                        |  179 ++
 spec/rubocop/config_store_spec.rb                  |   53 +
 spec/rubocop/cop/commissioner_spec.rb              |   83 +
 spec/rubocop/cop/cop_spec.rb                       |  114 ++
 spec/rubocop/cop/corrector_spec.rb                 |   59 +
 spec/rubocop/cop/lint/ambiguous_operator_spec.rb   |  113 ++
 .../cop/lint/ambiguous_regexp_literal_spec.rb      |   35 +
 .../cop/lint/assignment_in_condition_spec.rb       |  107 ++
 spec/rubocop/cop/lint/block_alignment_spec.rb      |  411 +++++
 spec/rubocop/cop/lint/condition_position_spec.rb   |   49 +
 spec/rubocop/cop/lint/debugger_spec.rb             |   39 +
 .../cop/lint/deprecated_class_methods_spec.rb      |   38 +
 spec/rubocop/cop/lint/else_layout_spec.rb          |   65 +
 spec/rubocop/cop/lint/empty_ensure_spec.rb         |   27 +
 spec/rubocop/cop/lint/empty_interpolation_spec.rb  |   18 +
 spec/rubocop/cop/lint/end_alignment_spec.rb        |  135 ++
 spec/rubocop/cop/lint/end_in_method_spec.rb        |   29 +
 spec/rubocop/cop/lint/ensure_return_spec.rb        |   39 +
 spec/rubocop/cop/lint/eval_spec.rb                 |   33 +
 spec/rubocop/cop/lint/handle_exceptions_spec.rb    |   30 +
 .../cop/lint/invalid_character_literal_spec.rb     |   33 +
 spec/rubocop/cop/lint/literal_in_condition_spec.rb |  154 ++
 .../cop/lint/literal_in_interpolation_spec.rb      |   31 +
 spec/rubocop/cop/lint/loop_spec.rb                 |   27 +
 .../lint/parentheses_as_grouped_expression_spec.rb |   57 +
 spec/rubocop/cop/lint/require_parentheses_spec.rb  |   82 +
 spec/rubocop/cop/lint/rescue_exception_spec.rb     |  123 ++
 .../lint/shadowing_outer_local_variable_spec.rb    |  237 +++
 .../cop/lint/space_before_first_arg_spec.rb        |   58 +
 .../string_conversion_in_interpolation_spec.rb     |   51 +
 spec/rubocop/cop/lint/syntax_spec.rb               |   34 +
 spec/rubocop/cop/lint/unreachable_code_spec.rb     |   63 +
 .../cop/lint/useless_access_modifier_spec.rb       |  192 ++
 spec/rubocop/cop/lint/useless_assignment_spec.rb   | 1608 +++++++++++++++++
 spec/rubocop/cop/lint/useless_comparison_spec.rb   |   30 +
 .../cop/lint/useless_else_without_rescue_spec.rb   |   48 +
 spec/rubocop/cop/lint/useless_setter_call_spec.rb  |  149 ++
 spec/rubocop/cop/lint/void_spec.rb                 |   57 +
 spec/rubocop/cop/offense_spec.rb                   |  133 ++
 spec/rubocop/cop/rails/action_filter_spec.rb       |   69 +
 spec/rubocop/cop/rails/default_scope_spec.rb       |   37 +
 .../cop/rails/has_and_belongs_to_many_spec.rb      |   13 +
 spec/rubocop/cop/rails/output_spec.rb              |   31 +
 .../rubocop/cop/rails/read_write_attribute_spec.rb |   19 +
 spec/rubocop/cop/rails/scope_args_spec.rb          |   25 +
 spec/rubocop/cop/rails/validation_spec.rb          |   21 +
 spec/rubocop/cop/severity_spec.rb                  |  113 ++
 .../cop/style/access_modifier_indentation_spec.rb  |  361 ++++
 .../rubocop/cop/style/accessor_method_name_spec.rb |   81 +
 spec/rubocop/cop/style/alias_spec.rb               |   59 +
 spec/rubocop/cop/style/align_array_spec.rb         |   91 +
 spec/rubocop/cop/style/align_hash_spec.rb          |  391 +++++
 spec/rubocop/cop/style/align_parameters_spec.rb    |  295 ++++
 spec/rubocop/cop/style/and_or_spec.rb              |   57 +
 spec/rubocop/cop/style/array_join_spec.rb          |   29 +
 spec/rubocop/cop/style/ascii_comments_spec.rb      |   22 +
 spec/rubocop/cop/style/ascii_identifiers_spec.rb   |   36 +
 spec/rubocop/cop/style/attr_spec.rb                |   19 +
 spec/rubocop/cop/style/begin_block_spec.rb         |   13 +
 spec/rubocop/cop/style/block_comments_spec.rb      |   21 +
 spec/rubocop/cop/style/block_nesting_spec.rb       |  156 ++
 spec/rubocop/cop/style/blocks_spec.rb              |  105 ++
 .../style/braces_around_hash_parameters_spec.rb    |  284 +++
 spec/rubocop/cop/style/case_equality_spec.rb       |   13 +
 spec/rubocop/cop/style/case_indentation_spec.rb    |  292 ++++
 spec/rubocop/cop/style/character_literal_spec.rb   |   37 +
 .../cop/style/class_and_module_camel_case_spec.rb  |   40 +
 .../cop/style/class_and_module_children_spec.rb    |  129 ++
 spec/rubocop/cop/style/class_length_spec.rb        |  131 ++
 spec/rubocop/cop/style/class_methods_spec.rb       |   68 +
 spec/rubocop/cop/style/class_vars_spec.rb          |   19 +
 spec/rubocop/cop/style/collection_methods_spec.rb  |   48 +
 spec/rubocop/cop/style/colon_method_call_spec.rb   |   60 +
 spec/rubocop/cop/style/comment_annotation_spec.rb  |   86 +
 spec/rubocop/cop/style/constant_name_spec.rb       |   65 +
 .../cop/style/cyclomatic_complexity_spec.rb        |  204 +++
 .../rubocop/cop/style/def_with_parentheses_spec.rb |   39 +
 .../cop/style/deprecated_hash_methods_spec.rb      |   45 +
 spec/rubocop/cop/style/documentation_spec.rb       |  123 ++
 spec/rubocop/cop/style/dot_position_spec.rb        |   91 +
 spec/rubocop/cop/style/double_negation_spec.rb     |   22 +
 .../cop/style/empty_line_between_defs_spec.rb      |  135 ++
 .../empty_lines_around_access_modifier_spec.rb     |   56 +
 .../cop/style/empty_lines_around_body_spec.rb      |  131 ++
 spec/rubocop/cop/style/empty_lines_spec.rb         |   51 +
 spec/rubocop/cop/style/empty_literal_spec.rb       |  100 ++
 spec/rubocop/cop/style/encoding_spec.rb            |   56 +
 spec/rubocop/cop/style/end_block_spec.rb           |   13 +
 spec/rubocop/cop/style/end_of_line_spec.rb         |   47 +
 spec/rubocop/cop/style/even_odd_spec.rb            |   75 +
 spec/rubocop/cop/style/file_name_spec.rb           |   84 +
 spec/rubocop/cop/style/final_newline_spec.rb       |   30 +
 spec/rubocop/cop/style/flip_flop_spec.rb           |   23 +
 spec/rubocop/cop/style/for_spec.rb                 |  105 ++
 spec/rubocop/cop/style/format_string_spec.rb       |  136 ++
 spec/rubocop/cop/style/global_vars_spec.rb         |   34 +
 spec/rubocop/cop/style/guard_clause_spec.rb        |   77 +
 spec/rubocop/cop/style/hash_syntax_spec.rb         |  133 ++
 spec/rubocop/cop/style/if_unless_modifier_spec.rb  |  146 ++
 spec/rubocop/cop/style/if_with_semicolon_spec.rb   |   19 +
 spec/rubocop/cop/style/indent_array_spec.rb        |  136 ++
 spec/rubocop/cop/style/indent_hash_spec.rb         |  310 ++++
 .../cop/style/indentation_consistency_spec.rb      |  510 ++++++
 spec/rubocop/cop/style/indentation_width_spec.rb   |  606 +++++++
 spec/rubocop/cop/style/lambda_call_spec.rb         |   65 +
 spec/rubocop/cop/style/lambda_spec.rb              |   41 +
 .../cop/style/leading_comment_space_spec.rb        |   64 +
 .../cop/style/line_end_concatenation_spec.rb       |   62 +
 spec/rubocop/cop/style/line_length_spec.rb         |   20 +
 .../cop/style/method_call_parentheses_spec.rb      |   59 +
 .../style/method_called_on_do_end_block_spec.rb    |   60 +
 .../cop/style/method_def_parentheses_spec.rb       |  106 ++
 spec/rubocop/cop/style/method_length_spec.rb       |  147 ++
 spec/rubocop/cop/style/method_name_spec.rb         |  125 ++
 spec/rubocop/cop/style/module_function_spec.rb     |   24 +
 .../cop/style/multiline_block_chain_spec.rb        |   78 +
 spec/rubocop/cop/style/multiline_if_then_spec.rb   |  107 ++
 .../cop/style/multiline_ternary_operator_spec.rb   |   18 +
 spec/rubocop/cop/style/negated_if_spec.rb          |   98 ++
 spec/rubocop/cop/style/negated_while_spec.rb       |   62 +
 .../cop/style/nested_ternary_operator_spec.rb      |   21 +
 spec/rubocop/cop/style/nil_comparison_spec.rb      |   29 +
 spec/rubocop/cop/style/non_nil_check_spec.rb       |   70 +
 spec/rubocop/cop/style/not_spec.rb                 |   28 +
 spec/rubocop/cop/style/numeric_literals_spec.rb    |   70 +
 .../rubocop/cop/style/one_line_conditional_spec.rb |   13 +
 spec/rubocop/cop/style/op_method_spec.rb           |   82 +
 spec/rubocop/cop/style/parameter_lists_spec.rb     |   44 +
 .../cop/style/parentheses_around_condition_spec.rb |  123 ++
 .../cop/style/percent_literal_delimiters_spec.rb   |  262 +++
 spec/rubocop/cop/style/perl_backrefs_spec.rb       |   17 +
 spec/rubocop/cop/style/predicate_name_spec.rb      |   26 +
 spec/rubocop/cop/style/proc_spec.rb                |   27 +
 spec/rubocop/cop/style/raise_args_spec.rb          |   87 +
 spec/rubocop/cop/style/redundant_begin_spec.rb     |   57 +
 spec/rubocop/cop/style/redundant_exception_spec.rb |   27 +
 spec/rubocop/cop/style/redundant_return_spec.rb    |  171 ++
 spec/rubocop/cop/style/redundant_self_spec.rb      |  142 ++
 spec/rubocop/cop/style/regexp_literal_spec.rb      |  104 ++
 spec/rubocop/cop/style/rescue_modifier_spec.rb     |  116 ++
 spec/rubocop/cop/style/self_assignment_spec.rb     |   43 +
 spec/rubocop/cop/style/semicolon_spec.rb           |  114 ++
 spec/rubocop/cop/style/signal_exception_spec.rb    |  290 ++++
 .../cop/style/single_line_block_params_spec.rb     |   70 +
 spec/rubocop/cop/style/single_line_methods_spec.rb |   90 +
 .../style/single_space_before_first_arg_spec.rb    |   63 +
 spec/rubocop/cop/style/space_after_colon_spec.rb   |   38 +
 spec/rubocop/cop/style/space_after_comma_spec.rb   |   30 +
 .../cop/style/space_after_control_keyword_spec.rb  |   84 +
 .../cop/style/space_after_method_name_spec.rb      |   70 +
 spec/rubocop/cop/style/space_after_not_spec.rb     |   22 +
 .../cop/style/space_after_semicolon_spec.rb        |   23 +
 ...pace_around_equals_in_parameter_default_spec.rb |   75 +
 .../cop/style/space_around_operators_spec.rb       |  325 ++++
 .../cop/style/space_before_block_braces_spec.rb    |   72 +
 .../style/space_before_modifier_keyword_spec.rb    |   70 +
 .../cop/style/space_inside_block_braces_spec.rb    |  287 +++
 .../cop/style/space_inside_brackets_spec.rb        |   59 +
 .../style/space_inside_hash_literal_braces_spec.rb |  147 ++
 spec/rubocop/cop/style/space_inside_parens_spec.rb |   46 +
 spec/rubocop/cop/style/special_global_vars_spec.rb |   57 +
 spec/rubocop/cop/style/string_literals_spec.rb     |  212 +++
 spec/rubocop/cop/style/symbol_array_spec.rb        |   37 +
 spec/rubocop/cop/style/tab_spec.rb                 |   17 +
 .../rubocop/cop/style/trailing_blank_lines_spec.rb |   43 +
 spec/rubocop/cop/style/trailing_comma_spec.rb      |  230 +++
 spec/rubocop/cop/style/trailing_whitespace_spec.rb |   30 +
 spec/rubocop/cop/style/trivial_accessors_spec.rb   |  418 +++++
 spec/rubocop/cop/style/unless_else_spec.rb         |   23 +
 .../cop/style/variable_interpolation_spec.rb       |   56 +
 spec/rubocop/cop/style/variable_name_spec.rb       |  107 ++
 spec/rubocop/cop/style/when_then_spec.rb           |   40 +
 spec/rubocop/cop/style/while_until_do_spec.rb      |   53 +
 .../rubocop/cop/style/while_until_modifier_spec.rb |   93 +
 spec/rubocop/cop/style/word_array_spec.rb          |   97 ++
 spec/rubocop/cop/team_spec.rb                      |  142 ++
 spec/rubocop/cop/util_spec.rb                      |   49 +
 .../cop/variable_inspector/assignment_spec.rb      |  213 +++
 .../cop/variable_inspector/locatable_spec.rb       |  734 ++++++++
 spec/rubocop/cop/variable_inspector/scope_spec.rb  |  184 ++
 .../cop/variable_inspector/variable_spec.rb        |   73 +
 .../cop/variable_inspector/variable_table_spec.rb  |  269 +++
 spec/rubocop/cop/variable_inspector_spec.rb        |   29 +
 spec/rubocop/file_inspector_spec.rb                |   84 +
 spec/rubocop/formatter/base_formatter_spec.rb      |  191 ++
 .../formatter/clang_style_formatter_spec.rb        |  114 ++
 spec/rubocop/formatter/colorizable_spec.rb         |  107 ++
 .../formatter/disabled_config_formatter_spec.rb    |   50 +
 .../formatter/disabled_lines_formatter_spec.rb     |   69 +
 .../formatter/emacs_style_formatter_spec.rb        |   62 +
 spec/rubocop/formatter/file_list_formatter_spec.rb |   33 +
 spec/rubocop/formatter/formatter_set_spec.rb       |  132 ++
 .../formatter/fuubar_style_formatter_spec.rb       |  129 ++
 spec/rubocop/formatter/json_formatter_spec.rb      |  152 ++
 .../formatter/offense_count_formatter_spec.rb      |   77 +
 spec/rubocop/formatter/progress_formatter_spec.rb  |  182 ++
 .../formatter/simple_text_formatter_spec.rb        |  123 ++
 spec/rubocop/options_spec.rb                       |  176 ++
 spec/rubocop/path_util_spec.rb                     |   42 +
 spec/rubocop/processed_source_spec.rb              |  114 ++
 spec/rubocop/source_parser_spec.rb                 |   85 +
 spec/rubocop/target_finder_spec.rb                 |  211 +++
 spec/rubocop/token_spec.rb                         |   25 +
 spec/spec_helper.rb                                |  149 ++
 spec/support/ast_helper.rb                         |   15 +
 spec/support/file_helper.rb                        |   21 +
 spec/support/isolated_environment.rb               |   34 +
 spec/support/mri_syntax_checker.rb                 |   73 +
 spec/support/shared_context.rb                     |   22 +
 spec/support/shared_examples.rb                    |   33 +
 spec/support/statement_modifier_helper.rb          |   41 +
 469 files changed, 41307 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a0ac677
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,51 @@
+# rcov generated
+coverage
+coverage.data
+
+# rdoc generated
+rdoc
+
+# yard generated
+doc
+.yardoc
+
+# bundler
+.bundle
+Gemfile.lock
+Gemfile.local
+
+# jeweler generated
+pkg
+
+# Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore: 
+#
+# * Create a file at ~/.gitignore
+# * Include files you want ignored
+# * Run: git config --global core.excludesfile ~/.gitignore
+#
+# After doing this, these files will be ignored in all your git projects,
+# saving you from having to 'pollute' every project you touch with them
+#
+# Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
+#
+# For MacOS:
+#
+#.DS_Store
+
+# For TextMate
+#*.tmproj
+#tmtags
+
+# For emacs:
+#*~
+#\#*
+#.\#*
+
+# For vim:
+#*.swp
+
+# For redcar:
+#.redcar
+
+# For rubinius:
+#*.rbc
diff --git a/.rspec b/.rspec
new file mode 100644
index 0000000..4e1e0d2
--- /dev/null
+++ b/.rspec
@@ -0,0 +1 @@
+--color
diff --git a/.rubocop.yml b/.rubocop.yml
new file mode 100644
index 0000000..f9dc215
--- /dev/null
+++ b/.rubocop.yml
@@ -0,0 +1,3 @@
+# This is the configuration used to check the rubocop source code.
+
+inherit_from: rubocop-todo.yml
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..9166ed7
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,16 @@
+language: ruby
+rvm:
+  - 1.9.2
+  - 1.9.3
+  - 2.0.0
+  - 2.1.0
+  - ruby-head
+  - jruby-19mode
+  - rbx-2
+matrix:
+  allow_failures:
+    - rvm: ruby-head
+before_install: gem update --remote bundler
+script:
+  - bundle exec rspec
+  - bundle exec rubocop
diff --git a/.yardopts b/.yardopts
new file mode 100644
index 0000000..d0ca888
--- /dev/null
+++ b/.yardopts
@@ -0,0 +1,2 @@
+--markup markdown
+--hide-void-return
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..1e99947
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,851 @@
+# Change log
+
+## master (unreleased)
+
+## 0.20.1 (05/04/2014)
+
+### Bugs fixed
+
+* [#940](https://github.com/bbatsov/rubocop/issues/940): Fixed `UselessAccessModifier` not handling `attr_*` correctly. ([@fshowalter][])
+* `NegatedIf` properly handles negated `unless` condition. ([@bbatsov][])
+* `NegatedWhile` properly handles negated `until` condition. ([@bbatsov][])
+* [#925](https://github.com/bbatsov/rubocop/issues/925): Do not disable the `Syntax` cop in output from `--auto-gen-config`. ([@jonas054][])
+* [#943](https://github.com/bbatsov/rubocop/issues/943): Fix auto-correction interference problem between `SpaceAfterComma` and other cops. ([@jonas054][])
+* [#954](https://github.com/bbatsov/rubocop/pull/954): Fix auto-correction bug in `NilComparison`. ([@bbatsov][])
+* [#953](https://github.com/bbatsov/rubocop/pull/953): Fix auto-correction bug in `NonNilCheck`. ([@bbatsov][])
+* [#952](https://github.com/bbatsov/rubocop/pull/952): Handle implicit receiver in `StringConversionInInterpolation`. ([@bbatsov][])
+* [#956](https://github.com/bbatsov/rubocop/pull/956): Apply `ClassMethods` check only on `class`/`module` bodies. ([@bbatsov][])
+* [#945](https://github.com/bbatsov/rubocop/issues/945): Fix SpaceBeforeFirstArg cop for multiline argument and exclude assignments. ([@cschramm][])
+* [#948](https://github.com/bbatsov/rubocop/issues/948): `Blocks` cop avoids auto-correction if it would introduce a semantic change. ([@jonas054][])
+* [#946](https://github.com/bbatsov/rubocop/issues/946): Allow non-nil checks that are the final expressions of predicate method definitions in `NonNilCheck`. ([@bbatsov][])
+* [#957](https://github.com/bbatsov/rubocop/issues/957): Allow space + comment inside parentheses, braces, and square brackets. ([@jonas054][])
+
+## 0.20.0 (02/04/2014)
+
+### New features
+
+* New cop `GuardClause` checks for conditionals that can be replaced by guard clauses. ([@bbatsov][])
+* New cop `EmptyInterpolation` checks for empty interpolation in double-quoted strings. ([@bbatsov][])
+* [#899](https://github.com/bbatsov/rubocop/issues/899): Make `LineEndConcatenation` cop `<<` aware. ([@mockdeep][])
+* [#896](https://github.com/bbatsov/rubocop/issues/896): New option `--fail-level` changes minimum severity for exit with error code. ([@hiroponz][])
+* [#893](https://github.com/bbatsov/rubocop/issues/893): New option `--force-exclusion` forces excluding files specified in the configuration `Exclude` even if they are explicitly passed as arguments. ([@yujinakayama][])
+* `VariableInterpolation` cop does auto-correction. ([@bbatsov][])
+* `Not` cop does auto-correction. ([@bbatsov][])
+* `ClassMethods` cop does auto-correction. ([@bbatsov][])
+* `StringConversionInInterpolation` cop does auto-correction. ([@bbatsov][])
+* `NilComparison` cop does auto-correction. ([@bbatsov][])
+* `NonNilComparison` cop does auto-correction. ([@bbatsov][])
+* `NegatedIf` cop does auto-correction. ([@bbatsov][])
+* `NegatedWhile` cop does auto-correction. ([@bbatsov][])
+* New lint cop `SpaceBeforeFirstArg` checks for space between the method name and the first argument in method calls without parentheses. ([@jonas054][])
+* New style cop `SingleSpaceBeforeFirstArg` checks that no more than one space is used between the method name and the first argument in method calls without parentheses. ([@jonas054][])
+* New formatter `disabled_lines` displays cops and line ranges disabled by inline comments. ([@fshowalter][])
+* New cop `UselessAccessModifiers` checks for access modifiers that have no effect. ([@fshowalter][])
+
+### Changes
+
+* [#913](https://github.com/bbatsov/rubocop/issues/913): `FileName` accepts multiple extensions. ([@tamird][])
+* `AllCops/Excludes` and `AllCops/Includes` were renamed to `AllCops/Exclude` and `AllCops/Include` for consistency with standard cop params. ([@bbatsov][])
+* Extract `NonNilCheck` cop from `NilComparison`. ([@bbatsov][])
+* Renamed `FavorJoin` to `ArrayJoin`. ([@bbatsov][])
+* Renamed `FavorUnlessOverNegatedIf` to `NegatedIf`. ([@bbatsov][])
+* Renamed `FavorUntilOverNegatedWhile`to `NegatedWhile`. ([@bbatsov][])
+* Renamed `HashMethods` to `DeprecatedHashMethods`. ([@bbatsov][])
+* Renamed `ReadAttribute` to `ReadWriteAttribute` and extended it to check for uses of `write_attribute`. ([@bbatsov][])
+* Add experimental support for Ruby 2.2 (development version) by falling back to Ruby 2.1 parser. ([@yujinakayama][])
+
+### Bugs fixed
+
+* [#926](https://github.com/bbatsov/rubocop/issues/926): Fixed `BlockNesting` not auto-generating correctly. ([@tmorris-fiksu][])
+* [#904](https://github.com/bbatsov/rubocop/issues/904): Fixed a NPE in `LiteralInInterpolation`. ([@bbatsov][])
+* [#904](https://github.com/bbatsov/rubocop/issues/904): Fixed a NPE in `StringConversionInInterpolation`. ([@bbatsov][])
+* [#892](https://github.com/bbatsov/rubocop/issues/892): Make sure `Include` and `Exclude` paths in a `.rubocop.yml` are interpreted as relative to the directory of that file. ([@jonas054][])
+* [#906](https://github.com/bbatsov/rubocop/issues/906): Fixed a false positive in `LiteralInInterpolation`. ([@bbatsov][])
+* [#909](https://github.com/bbatsov/rubocop/issues/909): Handle properly multiple `rescue` clauses in `SignalException`. ([@bbatsov][])
+* [#876](https://github.com/bbatsov/rubocop/issues/876): Do a deep merge of hashes when overriding default configuration in a `.rubocop.yml` file. ([@jonas054][])
+* [#912](https://github.com/bbatsov/rubocop/issues/912): Fix a false positive in `LineEndConcatenation` for `%` string literals. ([@bbatsov][])
+* [#912](https://github.com/bbatsov/rubocop/issues/912): Handle top-level constant resolution in `DeprecatedClassMethods` (e.g. `::File.exists?`). ([@bbatsov][])
+* [#914](https://github.com/bbatsov/rubocop/issues/914): Fixed rdoc error during gem installation. ([@bbatsov][])
+* The `--only` option now enables the given cop in case it is disabled in configuration. ([@jonas054][])
+* Fix path resolution so that the default exclusion of `vendor` directories works. ([@jonas054][])
+* [#908](https://github.com/bbatsov/rubocop/issues/908): Fixed hanging while auto correct for `SpaceAfterComma` and `SpaceInsideBrackets`. ([@hiroponz][])
+* [#919](https://github.com/bbatsov/rubocop/issues/919): Don't avoid auto-correction in `HashSyntax` when there is missing space around operator. ([@jonas054][])
+* Fixed handling of floats in `NumericLiterals`. ([@bbatsov][])
+* [#927](https://github.com/bbatsov/rubocop/issues/927): Let `--auto-gen-config` overwrite an existing `rubocop-todo.yml` file instead of asking the user to remove it. ([@jonas054][])
+* [#936](https://github.com/bbatsov/rubocop/issues/936): Allow `_other` as well as `other` in `OpMethod`. ([@bbatsov][])
+
+## 0.19.1 (17/03/2014)
+
+### Bugs fixed
+
+* [#884](https://github.com/bbatsov/rubocop/issues/884): Fix --auto-gen-config for `NumericLiterals` so MinDigits is correct. ([@tmorris-fiksu][])
+* [#879](https://github.com/bbatsov/rubocop/issues/879): Fix --auto-gen-config for `RegexpLiteral` so we don't generate illegal values for `MaxSlashes`. ([@jonas054][])
+* Fix the name of the `Include` param in the default config of the Rails cops. ([@bbatsov][])
+* [#878](https://github.com/bbatsov/rubocop/pull/878): Blacklist `Rakefile`, `Gemfile` and `Capfile` by default in the `FileName` cop. ([@bbatsov][])
+* [#875](https://github.com/bbatsov/rubocop/issues/875): Handle `separator` style hashes in `IndentHash`. ([@jonas054][])
+* Fix a bug where multiple cli options that result in exit can be specified at once (e.g. `-vV`, `-v --show-cops`). ([@jkogara][])
+* [#889](https://github.com/bbatsov/rubocop/issues/889): Fix a false positive for `LiteralInCondition` when the condition is non-primitive array. ([@bbatsov][])
+
+## 0.19.0 (13/03/2014)
+
+### New features
+
+* New cop `FileName` makes sure that source files have snake_case names. ([@bbatsov][])
+* New cop `DeprecatedClassMethods` checks for deprecated class methods. ([@bbatsov][])
+* New cop `StringConversionInInterpolation` checks for redundant `Object#to_s` in string interpolation. ([@bbatsov][])
+* New cop `LiteralInInterpolation` checks for interpolated string literals. ([@bbatsov][])
+* New cop `SelfAssignment` checks for places where the self-assignment shorthand should have been used. ([@bbatsov][])
+* New cop `DoubleNegation` checks for uses of `!!`. ([@bbatsov][])
+* New cop `PercentLiteralDelimiters` enforces consistent usage of `%`-literal delimiters. ([@hannestyden][])
+* New Rails cop `ActionFilter` enforces the use of `_filter` or `_action` action filter methods. ([@bbatsov][])
+* New Rails cop `ScopeArgs` makes sure you invoke the `scope` method properly. ([@bbatsov][])
+* Add `with_fixed_indentation` style to `AlignParameters` cop. ([@hannestyden][])
+* Add `IgnoreLastArgumentHash` option to `AlignHash` cop. ([@hannestyden][])
+* [#743](https://github.com/bbatsov/rubocop/issues/743): `SingleLineMethods` cop does auto-correction. ([@jonas054][])
+* [#743](https://github.com/bbatsov/rubocop/issues/743): `Semicolon` cop does auto-correction. ([@jonas054][])
+* [#743](https://github.com/bbatsov/rubocop/issues/743): `EmptyLineBetweenDefs` cop does auto-correction. ([@jonas054][])
+* [#743](https://github.com/bbatsov/rubocop/issues/743): `IndentationWidth` cop does auto-correction. ([@jonas054][])
+* [#743](https://github.com/bbatsov/rubocop/issues/743): `IndentationConsistency` cop does auto-correction. ([@jonas054][])
+* [#809](https://github.com/bbatsov/rubocop/issues/809): New formatter `fuubar` displays a progress bar and shows details of offenses as soon as they are detected. ([@yujinakayama][])
+* [#797](https://github.com/bbatsov/rubocop/issues/797): New cop `IndentHash` checks the indentation of the first key in multi-line hash literals. ([@jonas054][])
+* [#797](https://github.com/bbatsov/rubocop/issues/797): New cop `IndentArray` checks the indentation of the first element in multi-line array literals. ([@jonas054][])
+* [#806](https://github.com/bbatsov/rubocop/issues/806): Now excludes files in `vendor/**` by default. ([@jeremyolliver][])
+* [#795](https://github.com/bbatsov/rubocop/issues/795): `IfUnlessModifier` and `WhileUntilModifier` supports `MaxLineLength`, which is independent of `LineLength` parameter `Max`. ([@agrimm][])
+* [#868](https://github.com/bbatsov/rubocop/issues/868): New cop `ClassAndModuleChildren` checks the style of children definitions at classes and modules: nested / compact. ([@geniou][])
+
+### Changes
+
+* [#793](https://github.com/bbatsov/rubocop/issues/793): Add printing total count when `rubocop --format offences`. ([@ma2gedev][])
+* Remove `Ignore` param from the Rails `Output` cop. The standard `Exclude/Include` should be used instead. ([@bbatsov][])
+* Renamed `FavorSprintf` to `FormatString` and made it configurable. ([@bbatsov][])
+* Renamed `Offence` to `Offense`. ([@bbatsov][])
+* Use `offense` in all messages instead of `offence`. ([@bbatsov][])
+* For indentation of `if`/`unless`/`while`/`until` bodies when the result is assigned to a variable, instead of supporting two styles simultaneously, `IndentationWidth` now supports one style of indentation at a time, specified by `EndAlignment`/`AlignWith`. ([@jonas054][])
+* Renamed `Style` param of `DotPosition` cop to `EnforcedStyle`. ([@bbatsov][])
+* Add `length` value to locations of offense in JSON formatter. ([@yujinakayama][])
+* `SpaceAroundBlockBraces` cop replaced by `SpaceBeforeBlockBraces` and `SpaceInsideBlockBraces`. ([@jonas054][])
+* `SpaceAroundEqualsInParameterDefault` cop is now configurable with the `EnforcedStyle` option. ([@jonas054][])
+
+### Bugs fixed
+
+* [#790](https://github.com/bbatsov/rubocop/issues/790): Fix auto-correction interference problem between `MethodDefParentheses` and other cops. ([@jonas054][])
+* [#794](https://github.com/bbatsov/rubocop/issues/794): Fix handling of modifier keywords with required parentheses in `ParenthesesAroundCondition`. ([@bbatsov][])
+* [#804](https://github.com/bbatsov/rubocop/issues/804): Fix a false positive with operator assignments in a loop (including `begin..rescue..end` with `retry`) in `UselessAssignment`. ([@yujinakayama][])
+* [#815](https://github.com/bbatsov/rubocop/issues/815): Fix a false positive for heredocs with blank lines in them in `EmptyLines`. ([@bbatsov][])
+* Auto-correction is now more robust and less likely to die because of `RangeError` or "clobbering". ([@jonas054][])
+* Offenses always reported in order of position in file, also during `--auto-correct` runs. ([@jonas054][])
+* Fix problem with `[Corrected]` tag sometimes missing in output from `--auto-correct` runs. ([@jonas054][])
+* Fix message from `EndAlignment` cop when `AlignWith` is `keyword`. ([@jonas054][])
+* Handle `case` conditions in `LiteralInCondition`. ([@bbatsov][])
+* [#822](https://github.com/bbatsov/rubocop/issues/822): Fix a false positive in `DotPosition` when enforced style is set to `trailing`. ([@bbatsov][])
+* Handle properly dynamic strings in `LineEndConcatenation`. ([@bbatsov][])
+* [#832](https://github.com/bbatsov/rubocop/issues/832): Fix auto-correction interference problem between `BracesAroundHashParameters` and `SpaceInsideHashLiteralBraces`. ([@jonas054][])
+* Fix bug in auto-correction of alignment so that only space can be removed. ([@jonas054][])
+* Fix bug in `IndentationWidth` auto-correction so it doesn't correct things that `IndentationConsistency` should correct. ([@jonas054][])
+* [#847](https://github.com/bbatsov/rubocop/issues/847): Fix bug in `RegexpLiteral` concerning `--auto-gen-config`. ([@jonas054][])
+* [#848](https://github.com/bbatsov/rubocop/issues/848): Fix bug in `--show-cops` that made it print the default configuration rather than the current configuration. ([@jonas054][])
+* [#862](https://github.com/bbatsov/rubocop/issues/862): Fix a bug where single line `rubocop:disable` comments with indentations were treated as multiline cop disabling comments. ([@yujinakayama][])
+* Fix a bug where `rubocop:disable` comments with a cop name including `all` (e.g. `MethodCallParentheses`) were disabling all cops. ([@yujinakayama][])
+* Fix a bug where string and regexp literals including `# rubocop:disable` were confused with real comments. ([@yujinakayama][])
+* [#877](https://github.com/bbatsov/rubocop/issues/877): Fix bug in `PercentLiteralDelimiters` concerning auto-correct of regular expressions with interpolation. ([@hannestyden][])
+
+## 0.18.1 (02/02/2014)
+
+### Bugs fixed
+
+* Remove double reporting in `EmptyLinesAroundBody` of empty line inside otherwise empty class/module/method that caused crash in autocorrect. ([@jonas054][])
+* [#779](https://github.com/bbatsov/rubocop/issues/779): Fix a false positive in `LineEndConcatenation`. ([@bbatsov][])
+* [#751](https://github.com/bbatsov/rubocop/issues/751): Fix `Documentation` cop so that a comment followed by an empty line and then a class definition is not considered to be class documentation. ([@jonas054][])
+* [#783](https://github.com/bbatsov/rubocop/issues/783): Fix a false positive in `ParenthesesAroundCondition` when the parentheses are actually required. ([@bbatsov][])
+* [#781](https://github.com/bbatsov/rubocop/issues/781): Fix problem with back-and-forth auto-correction in `AccessModifierIndentation`. ([@jonas054][])
+* [#785](https://github.com/bbatsov/rubocop/issues/785): Fix false positive on `%w` arrays in `TrailingComma`. ([@jonas054][])
+* [#782](https://github.com/bbatsov/rubocop/issues/782): Fix false positive in `AlignHash` for single line hashes. ([@jonas054][])
+
+## 0.18.0 (30/01/2014)
+
+### New features
+
+* [#714](https://github.com/bbatsov/rubocop/issues/714): New cop `RequireParentheses` checks for method calls without parentheses together with a boolean operator indicating that a mistake about precedence may have been made. ([@jonas054][])
+* [#743](https://github.com/bbatsov/rubocop/issues/743): `WordArray` cop does auto-correction. ([@jonas054][])
+* [#743](https://github.com/bbatsov/rubocop/issues/743): `Proc` cop does auto-correction. ([@bbatsov][])
+* [#743](https://github.com/bbatsov/rubocop/issues/743): `AccessModifierIndentation` cop does auto-correction. ([@jonas054][])
+* [#768](https://github.com/bbatsov/rubocop/issues/768): Rake task now supports `requires` and `options`. ([@nevir][])
+* [#759](https://github.com/bbatsov/rubocop/issues/759): New cop `EndLineConcatenation` checks for string literal concatenation with `+` at line end. ([@bbatsov][])
+
+### Changes
+
+* [#762](https://github.com/bbatsov/rubocop/issues/762): Support Rainbow gem both 1.99.x and 2.x. ([@yujinakayama][])
+* [#761](https://github.com/bbatsov/rubocop/issues/761): Relax `json` requirement to `>= 1.7.7`. ([@bbatsov][])
+* [#757](https://github.com/bbatsov/rubocop/issues/757): `Include/Exclude` supports relative globbing to some extent. ([@nevir][])
+
+### Bugs fixed
+
+* [#764](https://github.com/bbatsov/rubocop/issues/764): Handle heredocs in `TrailingComma`. ([@jonas054][])
+* Guide for contributors now points to correct issues page. ([@scottmatthewman][])
+
+## 0.17.0 (25/01/2014)
+
+### New features
+
+* New cop `ConditionPosition` checks for misplaced conditions in expressions like `if/unless/when/until`. ([@bbatsov][])
+* New cop `ElseLayout` checks for odd arrangement of code in the `else` branch of a conditional expression. ([@bbatsov][])
+* [#694](https://github.com/bbatsov/rubocop/issues/694): Support Ruby 1.9.2 until June 2014. ([@yujinakayama][])
+* [#702](https://github.com/bbatsov/rubocop/issues/702): Improve `rubocop-todo.yml` with comments about offence count, configuration parameters, and auto-correction support. ([@jonas054][])
+* Add new command-line flag `-D/--display-cop-names` to trigger the display of cop names in offence messages. ([@bbatsov][])
+* [#733](https://github.com/bbatsov/rubocop/pull/733): `NumericLiterals` cop does auto-correction. ([@dblock][])
+* [#713](https://github.com/bbatsov/rubocop/issues/713): New cop `TrailingComma` checks for comma after the last item in a hash, array, or method call parameter list. ([@jonas054][])
+
+### Changes
+
+* [#581](https://github.com/bbatsov/rubocop/pull/581): Extracted a new cop `AmbiguousOperator` from `Syntax` cop. It checks for ambiguous operators in the first argument of a method invocation without parentheses. ([@yujinakayama][])
+* Extracted a new cop `AmbiguousRegexpLiteral` from `Syntax` cop. It checks for ambiguous regexp literals in the first argument of a method invocation without parentheses. ([@yujinakayama][])
+* Extracted a new cop `UselessElseWithoutRescue` from `Syntax` cop. It checks for useless `else` in `begin..end` without `rescue`. ([@yujinakayama][])
+* Extracted a new cop `InvalidCharacterLiteral` from `Syntax` cop. It checks for invalid character literals with a non-escaped whitespace character (e.g. `? `). ([@yujinakayama][])
+* Removed `Syntax` cop from the configuration. It no longer can be disabled and it reports only invalid syntax offences. ([@yujinakayama][])
+* [#688](https://github.com/bbatsov/rubocop/issues/688): Output from `rubocop --show-cops` now looks like a YAML configuration file. The `--show-cops` option takes a comma separated list of cops as optional argument. ([@jonas054][])
+* New cop `IndentationConsistency` extracted from `IndentationWidth`, which has checked two kinds of offences until now. ([@jonas054][])
+
+### Bugs fixed
+
+* [#698](https://github.com/bbatsov/rubocop/pull/698): Support Windows paths on command-line. ([@rifraf][])
+* [#498](https://github.com/bbatsov/rubocop/issues/498): Disable terminal ANSI escape sequences when a formatter's output is not a TTY. ([@yujinakayama][])
+* [#703](https://github.com/bbatsov/rubocop/issues/703): BracesAroundHashParameters auto-correction broken with trailing comma. ([@jonas054][])
+* [#709](https://github.com/bbatsov/rubocop/issues/709): When `EndAlignment` has configuration `AlignWith: variable`, it now handles `@@a = if ...` and `a, b = if ...`. ([@jonas054][])
+* `SpaceAroundOperators` now reports an offence for `@@a=0`. ([@jonas054][])
+* [#707](https://github.com/bbatsov/rubocop/issues/707): Fix error on operator assignments in top level scope in `UselessAssignment`. ([@yujinakayama][])
+* Fix a bug where some offences were discarded when any cop that has specific target file path (by `Include` or `Exclude` under each cop configuration) had run. ([@yujinakayama][])
+* [#724](https://github.com/bbatsov/rubocop/issues/724): Accept colons denoting required keyword argument (a new feature in Ruby 2.1) without trailing space in `SpaceAfterColon`. ([@jonas054][])
+* The `--no-color` option works again. ([@jonas054][])
+* [#716](https://github.com/bbatsov/rubocop/issues/716): Fixed a regression in the auto-correction logic of `MethodDefParentheses`. ([@bbatsov][])
+* Inspected projects that lack a `.rubocop.yml` file, and therefore get their configuration from RuboCop's `config/default.yml`, no longer get configuration from RuboCop's `.rubocop.yml` and `rubocop-todo.yml`. ([@jonas054][])
+* [#730](https://github.com/bbatsov/rubocop/issues/730): `EndAlignment` now handles for example `private def some_method`, which is allowed in Ruby 2.1. It requires `end` to be aligned with `private`, not `def`, in such cases. ([@jonas054][])
+* [#744](https://github.com/bbatsov/rubocop/issues/744): Any new offences created by `--auto-correct` are now handled immediately and corrected when possible, so running `--auto-correct` once is enough. ([@jonas054][])
+* [#748](https://github.com/bbatsov/rubocop/pull/748): Auto-correction conflict between `EmptyLinesAroundBody` and `TrailingWhitespace` resolved. ([@jonas054][])
+* `ParenthesesAroundCondition` no longer crashes on parentheses around the condition in a ternary if. ([@jonas054][])
+* [#738](https://github.com/bbatsov/rubocop/issues/738): Fix a false positive in `StringLiterals`. ([@bbatsov][])
+
+## 0.16.0 (25/12/2013)
+
+### New features
+
+* [#612](https://github.com/bbatsov/rubocop/pull/612): `BracesAroundHashParameters` cop does auto-correction. ([@dblock][])
+* [#614](https://github.com/bbatsov/rubocop/pull/614): `ParenthesesAroundCondition` cop does auto-correction. ([@dblock][])
+* [#624](https://github.com/bbatsov/rubocop/pull/624): `EmptyLines` cop does auto-correction. ([@dblock][])
+* New Rails cop `DefaultScope` ensures `default_scope` is called properly with a block argument. ([@bbatsov][])
+* All cops now support the `Include` param, which specifies the files on which they should operate. ([@bbatsov][])
+* All cops now support the `Exclude` param, which specifies the files on which they should not operate. ([@bbatsov][])
+* [#631](https://github.com/bbatsov/rubocop/issues/631): `IndentationWidth` cop now detects inconsistent indentation between lines that should have the same indentation. ([@jonas054][])
+* [#649](https://github.com/bbatsov/rubocop/pull/649): `EmptyLinesAroundBody` cop does auto-correction. ([@dblock][])
+* [#657](https://github.com/bbatsov/rubocop/pull/657): `Alias` cop does auto-correction. ([@dblock][])
+* Rake task now support setting formatters. ([@pmenglund][])
+* [#653](https://github.com/bbatsov/rubocop/issues/653): `CaseIndentation` cop is now configurable with parameters `IndentWhenRelativeTo` and `IndentOneStep`. ([@jonas054][])
+* [#654](https://github.com/bbatsov/rubocop/pull/654): `For` cop is now configurable to enforce either `each` (default) or `for`. ([@jonas054][])
+* [#661](https://github.com/bbatsov/rubocop/issues/661): `EndAlignment` cop is now configurable for alignment with `keyword` (default) or `variable`. ([@jonas054][])
+* Allow to overwrite the severity of a cop with the new `Severity` param. ([@codez][])
+* New cop `FlipFlop` checks for flip flops. ([@agrimm][])
+* [#577](https://github.com/bbatsov/rubocop/issues/577): Introduced `MethodDefParentheses` to allow for for requiring either parentheses or no parentheses in method definitions. Replaces `DefWithoutParentheses`. ([@skanev][])
+* [#693](https://github.com/bbatsov/rubocop/pull/693): Generation of parameter values (i.e., not only `Enabled: false`) in `rubocop-todo.yml` by the `--auto-gen-config` option is now supported for some cops. ([@jonas054][])
+* New cop `AccessorMethodName` checks accessor method names for non-idiomatic names like `get_attribute` and `set_attribute`. ([@bbatsov][])
+* New cop `PredicateName` checks the names of predicate methods for non-idiomatic names like `is_something`, `has_something`, etc. ([@bbatsov][])
+* Support Ruby 2.1 with Parser 2.1. ([@yujinakayama][])
+
+### Changes
+
+* Removed `SymbolNames` as it was generating way too many false positives. ([@bbatsov][])
+* Renamed `ReduceArguments` to `SingleLineBlockParams` and made it configurable. ([@bbatsov][])
+
+### Bugs fixed
+
+* Handle properly heredocs in `StringLiterals` cop. ([@bbatsov][])
+* Fix `SpaceAroundOperators` to not report missing space around operator for `def self.method *args`. ([@jonas054][])
+* Properly handle `['AllCops']['Includes']` and `['AllCops']['Excludes']` when passing config via `-c`. ([@fancyremarker][], [@codez][])
+* [#611](https://github.com/bbatsov/rubocop/pull/611): Fix crash when loading an empty config file. ([@sinisterchipmunk][])
+* Fix `DotPosition` cop with `trailing` style for method calls on same line. ([@vonTronje][])
+* [#627](https://github.com/bbatsov/rubocop/pull/627): Fix counting of slashes in complicated regexps in `RegexpLiteral` cop. ([@jonas054][])
+* [#638](https://github.com/bbatsov/rubocop/issues/638): Fix bug in auto-correct that changes `each{ |x|` to `each d o |x|`. ([@jonas054][])
+* [#418](https://github.com/bbatsov/rubocop/issues/418): Stop searching for configuration files above the work directory of the isolated environment when running specs. ([@jonas054][])
+* Fix error on implicit match conditionals (e.g. `if /pattern/; end`) in `MultilineIfThen`. ([@agrimm][])
+* [#651](https://github.com/bbatsov/rubocop/issues/651): Handle properly method arguments in `RedundantSelf`. ([@bbatsov][])
+* [#628](https://github.com/bbatsov/rubocop/issues/628): Allow `self.Foo` in `RedundantSelf` cop. ([@chulkilee][])
+* [#668](https://github.com/bbatsov/rubocop/issues/668): Fix crash in `EndOfLine` that occurs when default encoding is `US_ASCII` and an inspected file has non-ascii characters. ([@jonas054][])
+* [#664](https://github.com/bbatsov/rubocop/issues/664): Accept oneline while when condition has local variable assignment. ([@emou][])
+* Fix auto-correct for `MethodDefParentheses` when parentheses are required. ([@skanev][])
+
+## 0.15.0 (06/11/2013)
+
+### New features
+
+* New cop `Output` checks for calls to print, puts, etc. in Rails. ([@daviddavis][])
+* New cop `EmptyLinesAroundBody` checks for empty lines around the bodies of class, method and module definitions. ([@bbatsov][])
+* `LeadingCommentSpace` cop does auto-correction. ([@jonas054][])
+* `SpaceAfterControlKeyword` cop does auto-correction. ([@jonas054][])
+* `SpaceAfterColon` cop does auto-correction. ([@jonas054][])
+* `SpaceAfterComma` cop does auto-correction. ([@jonas054][])
+* `SpaceAfterSemicolon` cop does auto-correction. ([@jonas054][])
+* `SpaceAfterMethodName` cop does auto-correction. ([@jonas054][])
+* `SpaceAroundBlockBraces` cop does auto-correction. ([@jonas054][])
+* `SpaceAroundEqualsInParameterDefault` cop does auto-correction. ([@jonas054][])
+* `SpaceAroundOperators` cop does auto-correction. ([@jonas054][])
+* `SpaceBeforeModifierKeyword` cop does auto-correction. ([@jonas054][])
+* `SpaceInsideHashLiteralBraces` cop does auto-correction. ([@jonas054][])
+* `SpaceInsideBrackets` cop does auto-correction. ([@jonas054][])
+* `SpaceInsideParens` cop does auto-correction. ([@jonas054][])
+* `TrailingWhitespace` cop does auto-correction. ([@jonas054][])
+* `TrailingBlankLines` cop does auto-correction. ([@jonas054][])
+* `FinalNewline` cop does auto-correction. ([@jonas054][])
+* New cop `CyclomaticComplexity` checks the cyclomatic complexity of methods against a configurable max value. ([@jonas054][])
+* [#594](https://github.com/bbatsov/rubocop/pull/594): New parameter `EnforcedStyleForEmptyBraces` with values `space` and `no_space` (default) added to `SpaceAroundBlockBraces`. ([@jonas054][])
+* [#603](https://github.com/bbatsov/rubocop/pull/603): New parameter `MinSize` added to `WordArray` to allow small string arrays, retaining the default (0). ([@claco][])
+
+### Changes
+
+* [#557](https://github.com/bbatsov/rubocop/pull/557): Configuration files for excluded files are no longer loaded. ([@jonas054][])
+* [#571](https://github.com/bbatsov/rubocop/pull/571): The default rake task now runs RuboCop over itself! ([@nevir][])
+* Encoding errors are reported as fatal offences rather than printed with red text. ([@jonas054][])
+* `AccessControl` cop is now configurable with the `EnforcedStyle` option. ([@sds][])
+* Split `AccessControl` cop to `AccessModifierIndentation` and `EmptyLinesAroundAccessModifier`. ([@bbatsov][])
+* [#594](https://github.com/bbatsov/rubocop/pull/594): Add configuration parameter `EnforcedStyleForEmptyBraces` to `SpaceInsideHashLiteralBraces` cop, and change `EnforcedStyleIsWithSpaces` (values `true`, `false`) to `EnforcedStyle` (values `space`, `no_space`). ([@jonas054][])
+* Coverage builds linked from the README page are enabled again. ([@jonas054][])
+
+### Bugs fixed
+
+* [#561](https://github.com/bbatsov/rubocop/pull/561): Handle properly negative literals in `NumericLiterals` cop. ([@bbatsov][])
+* [#567](https://github.com/bbatsov/rubocop/pull/567): Register an offence when the last hash parameter has braces in `BracesAroundHashParameters` cop. ([@dblock][])
+* `StringLiterals` cop no longer reports errors for character literals such as ?/. That should be done only by the `CharacterLiterals` cop. ([@jonas054][])
+* Made auto-correct much less likely to crash due to conflicting corrections ("clobbering"). ([@jonas054][])
+* [#565](https://github.com/bbatsov/rubocop/pull/565): `$GLOBAL_VAR from English library` should no longer be inserted when autocorrecting short-form global variables like `$!`. ([@nevir][])
+* [#566](https://github.com/bbatsov/rubocop/pull/566): Methods that just assign a splat to an ivar are no longer considered trivial writers. ([@nevir][])
+* [#585](https://github.com/bbatsov/rubocop/pull/585): `MethodCallParentheses` should allow methods starting with uppercase letter. ([@bbatsov][])
+* [#574](https://github.com/bbatsov/rubocop/issues/574): Fix error on multiple-assignment with non-array right hand side in `UselessSetterCall`. ([@yujinakayama][])
+* [#576](https://github.com/bbatsov/rubocop/issues/576): Output config validation warning to STDERR so that it won't be mixed up with formatter's output. ([@yujinakayama][])
+* [#599](https://github.com/bbatsov/rubocop/pull/599): `EndOfLine` cop is operational again. ([@jonas054][])
+* [#604](https://github.com/bbatsov/rubocop/issues/604): Fix error on implicit match conditionals (e.g. `if /pattern/; end`) in `FavorModifier`. ([@yujinakayama][])
+* [#600](https://github.com/bbatsov/rubocop/pull/600): Don't require an empty line for access modifiers at the beginning of class/module body. ([@bbatsov][])
+* [#608](https://github.com/bbatsov/rubocop/pull/608): `RescueException` no longer crashes when the namespace of a rescued class is in a local variable. ([@jonas054][])
+* [#173](https://github.com/bbatsov/rubocop/issues/173): Allow the use of `alias` in the body of an `instance_exec`. ([@bbatsov][])
+* [#554](https://github.com/bbatsov/rubocop/issues/554): Handle properly multi-line arrays with comments in them in `WordArray`. ([@bbatsov][])
+
+## 0.14.1 (10/10/2013)
+
+### New features
+
+* [#551](https://github.com/bbatsov/rubocop/pull/551): New cop `BracesAroundHashParameters` checks for braces in function calls with hash parameters. ([@dblock][])
+* New cop `SpaceAfterNot` tracks redundant space after the `!` operator. ([@bbatsov][])
+
+### Bugs fixed
+
+* Fix bug concerning table and separator alignment of multi-line hash with multiple keys on the same line. ([@jonas054][])
+* [#550](https://github.com/bbatsov/rubocop/pull/550): Fix a bug where `ClassLength` counted lines of inner classes/modules. ([@yujinakayama][])
+* [#550](https://github.com/bbatsov/rubocop/pull/550): Fix a false positive for namespace class in `Documentation`. ([@yujinakayama][])
+* [#556](https://github.com/bbatsov/rubocop/pull/556): Fix "Parser::Source::Range spans more than one line" bug in clang formatter. ([@yujinakayama][])
+* [#552](https://github.com/bbatsov/rubocop/pull/552): `RaiseArgs` allows exception constructor calls with more than one 1 argument. ([@bbatsov][])
+
+## 0.14.0 (07/10/2013)
+
+### New features
+
+* [#491](https://github.com/bbatsov/rubocop/issues/491): New cop `MethodCalledOnDoEndBlock` keeps track of methods called on `do`...`end` blocks.
+* [#456](https://github.com/bbatsov/rubocop/issues/456): New configuration parameter `AllCops`/`RunRailsCops` can be set to `true` for a project, removing the need to give the `-R`/`--rails` option with every invocation of `rubocop`.
+* [#501](https://github.com/bbatsov/rubocop/issues/501): `simple`/`clang`/`progress`/`emacs` formatters now print `[Corrected]` along with offence message when the offence is automatically corrected.
+* [#501](https://github.com/bbatsov/rubocop/issues/501): `simple`/`clang`/`progress` formatters now print count of auto-corrected offences in the final summary.
+* [#501](https://github.com/bbatsov/rubocop/issues/501): `json` formatter now outputs `corrected` key with boolean value in offence objects whether the offence is automatically corrected.
+* New cop `ClassLength` checks for overly long class definitions.
+* New cop `Debugger` checks for forgotten calls to debugger or pry.
+* New cop `RedundantException` checks for code like `raise RuntimeError, message`.
+* [#526](https://github.com/bbatsov/rubocop/issues/526): New cop `RaiseArgs` checks the args passed to `raise/fail`.
+
+### Changes
+
+* Cop `MethodAndVariableSnakeCase` replaced by `MethodName` and `VariableName`, both having the configuration parameter `EnforcedStyle` with values `snake_case` (default) and `camelCase`.
+* [#519](https://github.com/bbatsov/rubocop/issues/519): `HashSyntax` cop is now configurable and can enforce the use of the classic hash rockets syntax.
+* [#520](https://github.com/bbatsov/rubocop/issues/520): `StringLiterals` cop is now configurable and can enforce either single-quoted or double-quoted strings.
+* [#528](https://github.com/bbatsov/rubocop/issues/528): Added a config option to `RedundantReturn` to allow a `return` with multiple values.
+* [#524](https://github.com/bbatsov/rubocop/issues/524): Added a config option to `Semicolon` to allow the use of `;` as an expression separator.
+* [#525](https://github.com/bbatsov/rubocop/issues/525): `SignalException` cop is now configurable and can enforce the semantic rule or an exclusive use of `raise` or `fail`.
+* `LambdaCall` is now configurable and enforce either `Proc#call` or `Proc#()`.
+* [#529](https://github.com/bbatsov/rubocop/issues/529): Added config option `EnforcedStyle` to `SpaceAroundBraces`.
+* [#529](https://github.com/bbatsov/rubocop/issues/529): Changed config option `NoSpaceBeforeBlockParameters` to `SpaceBeforeBlockParameters`.
+* Support Parser 2.0.0 (non-beta).
+
+### Bugs fixed
+
+* [#514](https://github.com/bbatsov/rubocop/issues/514): Fix alignment of the hash containing different key lengths in one line.
+* [#496](https://github.com/bbatsov/rubocop/issues/496): Fix corner case crash in `AlignHash` cop: single key/value pair when configuration is `table` for '=>' and `separator` for `:`.
+* [#502](https://github.com/bbatsov/rubocop/issues/502): Don't check non-decimal literals with `NumericLiterals`.
+* [#448](https://github.com/bbatsov/rubocop/issues/448): Fix auto-correction of parameters spanning more than one line in `AlignParameters` cop.
+* [#493](https://github.com/bbatsov/rubocop/issues/493): Support disabling `Syntax` offences with `warning` severity.
+* Fix bug appearing when there were different values for the `AllCops`/`RunRailsCops` configuration parameter in different directories.
+* [#512](https://github.com/bbatsov/rubocop/issues/512): Fix bug causing crash in `AndOr` auto-correction.
+* [#515](https://github.com/bbatsov/rubocop/issues/515): Fix bug causing `AlignParameters` and `AlignArray` auto-correction to destroy code.
+* [#516](https://github.com/bbatsov/rubocop/issues/516): Fix bug causing `RedundantReturn` auto-correction to produce invalid code.
+* [#527](https://github.com/bbatsov/rubocop/issues/527): Handle `!=` expressions in `EvenOdd` cop.
+* `SignalException` cop now finds `raise` calls anywhere, not only in `begin` sections.
+* [#538](https://github.com/bbatsov/rubocop/issues/538): Fix bug causing `Blocks` auto-correction to produce invalid code.
+
+## 0.13.1 (19/09/2013)
+
+### New features
+
+* `HashSyntax` cop does auto-correction.
+* [#484](https://github.com/bbatsov/rubocop/pull/484): Allow calls to self to fix name clash with argument.
+* Renamed `SpaceAroundBraces` to `SpaceAroundBlockBraces`.
+* `SpaceAroundBlockBraces` now has a `NoSpaceBeforeBlockParameters` config option to enforce a style for blocks with parameters like `{|foo| puts }`.
+* New cop `LambdaCall` tracks uses of the obscure `lambda.(...)` syntax.
+
+### Bugs fixed
+
+* Fix crash on empty input file in `FinalNewline`.
+* [#485](https://github.com/bbatsov/rubocop/issues/485): Fix crash on multiple-assignment and op-assignment in `UselessSetterCall`.
+* [#497](https://github.com/bbatsov/rubocop/issues/497): Fix crash in `UselessComparison` and `NilComparison`.
+
+## 0.13.0 (13/09/2013)
+
+### New features
+
+* New configuration parameter `AllowAdjacentOneLineDefs` for `EmptyLineBetweenDefs`.
+* New cop `MultilineBlockChain` keeps track of chained blocks spanning multiple lines.
+* `RedundantSelf` cop does auto-correction.
+* `AvoidPerlBackrefs` cop does auto-correction.
+* `AvoidPerlisms` cop does auto-correction.
+* `RedundantReturn` cop does auto-correction.
+* `Blocks` cop does auto-correction.
+* New cop `TrailingBlankLines` keeps track of extra blanks lines at the end of source file.
+* New cop `AlignHash` keeps track of bad alignment in multi-line hash literals.
+* New cop `AlignArray` keeps track of bad alignment in multi-line array literals.
+* New cop `SpaceBeforeModifierKeyword` keeps track of missing space before a modifier keyword (`if`, `unless`, `while`, `until`).
+* New cop `FinalNewline` keeps tracks of the required final newline in a source file.
+* Highlightling corrected in `SpaceInsideHashLiteralBraces` and `SpaceAroundBraces` cops.
+
+### Changes
+
+* [#447](https://github.com/bbatsov/rubocop/issues/447): `BlockAlignment` cop now allows `end` to be aligned with the start of the line containing `do`.
+* `SymbolName` now has an `AllowDots` config option to allow symbols like `:'whatever.submit_button'`.
+* [#469](https://github.com/bbatsov/rubocop/issues/469): Extracted useless setter call tracking part of `UselessAssignment` cop to `UselessSetterCall`.
+* [#469](https://github.com/bbatsov/rubocop/issues/469): Merged `UnusedLocalVariable` cop into `UselessAssignment`.
+* [#458](https://github.com/bbatsov/rubocop/issues/458): The merged `UselessAssignment` cop now has advanced logic that tracks not only assignment at the end of the method but also every assignment in every scope.
+* [#466](https://github.com/bbatsov/rubocop/issues/466): Allow built-in JRuby global vars in `AvoidGlobalVars`.
+* Added a config option `AllowedVariables` to `AvoidGlobalVars` to allow users to whitelist certain global variables.
+* Renamed `AvoidGlobalVars` to `GlobalVars`.
+* Renamed `AvoidPerlisms` to `SpecialGlobalVars`.
+* Renamed `AvoidFor` to `For`.
+* Renamed `AvoidClassVars` to `ClassVars`.
+* Renamed `AvoidPerlBackrefs` to `PerlBackrefs`.
+* `NumericLiterals` now accepts a config param `MinDigits` - the minimal number of digits in the integer portion of number for the cop to check it.
+
+### Bugs fixed
+
+* [#449](https://github.com/bbatsov/rubocop/issues/449): Remove whitespaces between condition and `do` with `WhileUntilDo` auto-correction.
+* Continue with file inspection after parser warnings. Give up only on syntax errors.
+* Don't trigger the HashSyntax cop on digit-starting keys.
+* Fix crashes while inspecting class definition subclassing another class stored in a local variable in `UselessAssignment` (formerly of `UnusedLocalVariable`) and `ShadowingOuterLocalVariable` (like `clazz = Array; class SomeClass < clazz; end`).
+* [#463](https://github.com/bbatsov/rubocop/issues/463): Do not warn if using destructuring in second `reduce` argument (`ReduceArguments`).
+
+## 0.12.0 (23/08/2013)
+
+### New features
+
+* [#439](https://github.com/bbatsov/rubocop/issues/439): Added formatter 'OffenceCount' which outputs a summary list of cops and their offence count.
+* [#395](https://github.com/bbatsov/rubocop/issues/395): Added `--show-cops` option to show available cops.
+* New cop `NilComparison` keeps track of comparisons like `== nil`.
+* New cop `EvenOdd` keeps track of occasions where `Fixnum#even?` or `Fixnum#odd?` should have been used (like `x % 2 == 0`).
+* New cop `IndentationWidth` checks for files using indentation that is not two spaces.
+* New cop `SpaceAfterMethodName` keeps track of method definitions with a space between the method name and the opening parenthesis.
+* New cop `ParenthesesAsGroupedExpression` keeps track of method calls with a space before the opening parenthesis.
+* New cop `HashMethods` keeps track of uses of deprecated `Hash` methods.
+* New Rails cop `HasAndBelongsToMany` checks for uses of `has_and_belongs_to_many`.
+* New Rails cop `ReadAttribute` tracks uses of `read_attribute`.
+* `Attr` cop does auto-correction.
+* `CollectionMethods` cop does auto-correction.
+* `SignalException` cop does auto-correction.
+* `EmptyLiteral` cop does auto-correction.
+* `MethodCallParentheses` cop does auto-correction.
+* `DefWithParentheses` cop does auto-correction.
+* `DefWithoutParentheses` cop does auto-correction.
+
+### Changes
+
+* Dropped `-s`/`--silent` option. Now `progress`/`simple`/`clang` formatters always report summary and `emacs`/`files` formatters no longer report.
+* Dropped the `LineContinuation` cop.
+
+### Bugs fixed
+
+* [#432](https://github.com/bbatsov/rubocop/issues/432): Fix false positive for constant assignments when rhs is a method call with block in `ConstantName`.
+* [#434](https://github.com/bbatsov/rubocop/issues/434): Support classes and modules defined with `Class.new`/`Module.new` in `AccessControl`.
+* Fix which ranges are highlighted in reports from IfUnlessModifier, WhileUntilModifier, and MethodAndVariableSnakeCase cop.
+* [#438](https://github.com/bbatsov/rubocop/issues/438): Accept setting attribute on method argument in `UselessAssignment`.
+
+## 0.11.1 (12/08/2013)
+
+### Changes
+
+* [#425](https://github.com/bbatsov/rubocop/issues/425): `ColonMethodCalls` now allows constructor methods (like `Nokogiri::HTML()` to be called with double colon.
+
+### Bugs fixed
+
+* [#427](https://github.com/bbatsov/rubocop/issues/427): FavorUnlessOverNegatedIf triggered when using elsifs.
+* [#429](https://github.com/bbatsov/rubocop/issues/429): Fix `LeadingCommentSpace` offence reporting.
+* Fixed `AsciiComments` offence reporting.
+* Fixed `BlockComments` offence reporting.
+
+## 0.11.0 (09/08/2013)
+
+### New features
+
+* [#421](https://github.com/bbatsov/rubocop/issues/421): `TrivialAccessors` now ignores methods on user-configurable whitelist (such as `to_s` and `to_hash`).
+* [#369](https://github.com/bbatsov/rubocop/issues/369): New option `--auto-gen-config` outputs RuboCop configuration that disables all cops that detect any offences.
+* The list of annotation keywords recognized by the `CommentAnnotation` cop is now configurable.
+* Configuration file names are printed as they are loaded in `--debug` mode.
+* Auto-correct support added in `AlignParameters` cop.
+* New cop `UselessComparison` checks for comparisons of the same arguments.
+* New cop `UselessAssignment` checks for useless assignments to local variables.
+* New cop `SignalException` checks for proper usage of `fail` and `raise`.
+* New cop `ModuleFunction` checks for usage of `extend self` in modules.
+
+### Bugs fixed
+
+* [#374](https://github.com/bbatsov/rubocop/issues/374): Fixed error at post condition loop (`begin-end-while`, `begin-end-until`) in `UnusedLocalVariable` and `ShadowingOuterLocalVariable`.
+* [#373](https://github.com/bbatsov/rubocop/issues/373) and [#376](https://github.com/bbatsov/rubocop/issues/376): Allow braces around multi-line blocks if `do`-`end` would change the meaning of the code.
+* `RedundantSelf` now allows `self.` followed by any ruby keyword.
+* [#391](https://github.com/bbatsov/rubocop/issues/391): Fix bug in counting slashes in a regexp.
+* [#394](https://github.com/bbatsov/rubocop/issues/394): `DotPosition` cop handles correctly code like `l.(1)`.
+* [#390](https://github.com/bbatsov/rubocop/issues/390): `CommentAnnotation` cop allows keywords (e.g. Review, Optimize) if they just begin a sentence.
+* [#400](https://github.com/bbatsov/rubocop/issues/400): Fix bug concerning nested defs in `EmptyLineBetweenDefs` cop.
+* [#399](https://github.com/bbatsov/rubocop/issues/399): Allow assignment inside blocks in `AssignmentInCondition` cop.
+* Fix bug in favor_modifier.rb regarding missed offences after else etc.
+* [#393](https://github.com/bbatsov/rubocop/issues/393): Retract support for multiline chaining of blocks (which fixed [#346](https://github.com/bbatsov/rubocop/issues/346)), thus rejecting issue 346.
+* [#389](https://github.com/bbatsov/rubocop/issues/389): Ignore symbols that are arguments to Module#private_constant in `SymbolName` cop.
+* [#387](https://github.com/bbatsov/rubocop/issues/387): Do autocorrect in `AndOr` cop only if it does not change the meaning of the code.
+* [#398](https://github.com/bbatsov/rubocop/issues/398): Don't display blank lines in the output of the clang formatter.
+* [#283](https://github.com/bbatsov/rubocop/issues/283): Refine `StringLiterals` string content check.
+
+## 0.10.0 (17/07/2013)
+
+### New features
+
+* New cop `RedundantReturn` tracks redundant `return`s in method bodies.
+* New cop `RedundantBegin` tracks redundant `begin` blocks in method definitions.
+* New cop `RedundantSelf` tracks redundant uses of `self`.
+* New cop `EmptyEnsure` tracks empty `ensure` blocks.
+* New cop `CommentAnnotation` tracks formatting of annotation comments such as TODO.
+* Added custom rake task.
+* New formatter `FileListFormatter` outputs just a list of files with offences in them (related to [#357](https://github.com/bbatsov/rubocop/issues/357)).
+
+### Changes
+
+* `TrivialAccessors` now has an `ExactNameMatch` config option (related to [#308](https://github.com/bbatsov/rubocop/issues/308)).
+* `TrivialAccessors` now has an `ExcludePredicates` config option (related to [#326](https://github.com/bbatsov/rubocop/issues/326)).
+* Cops don't inherit from `Parser::AST::Rewriter` anymore. All 3rd party Cops should remove the call to `super` in their callbacks. If you implement your own processing you need to define the `#investigate` method instead of `#inspect`. Refer to the documentation of `Cop::Commissioner` and `Cop::Cop` classes for more information.
+* `EndAlignment` cop split into `EndAlignment` and `BlockAlignment` cops.
+
+### Bugs fixed
+
+* [#288](https://github.com/bbatsov/rubocop/issues/288): Work with absolute Excludes paths internally (2nd fix for this issue).
+* `TrivialAccessors` now detects class attributes as well as instance attributes.
+* [#338](https://github.com/bbatsov/rubocop/issues/338): Fix end alignment of blocks in chained assignments.
+* [#345](https://github.com/bbatsov/rubocop/issues/345): Add `$SAFE` to the list of built-in global variables.
+* [#340](https://github.com/bbatsov/rubocop/issues/340): Override config parameters rather than merging them.
+* [#349](https://github.com/bbatsov/rubocop/issues/349): Fix false positive for `CharacterLiteral` (`%w(?)`).
+* [#346](https://github.com/bbatsov/rubocop/issues/346): Support method chains for block end alignment checks.
+* [#350](https://github.com/bbatsov/rubocop/issues/350): Support line breaks between variables on left hand side for block end alignment checks.
+* [#356](https://github.com/bbatsov/rubocop/issues/356): Allow safe assignment in `ParenthesesAroundCondition`.
+
+### Misc
+
+* Improved performance on Ruby 1.9 by about 20%.
+* Improved overall performance by about 35%.
+
+## 0.9.1 (05/07/2013)
+
+### New features
+
+* Added `-l/--lint` option to allow doing only linting with no style checks (similar to running `ruby -wc`).
+
+### Changes
+
+* Removed the `BlockAlignSchema` configuration option from `EndAlignment`. We now support only the default alignment schema - `StartOfAssignment`.
+* Made the preferred collection methods in `CollectionMethods` configurable.
+* Made the `DotPosition` cop configurable - now both `leading` and `trailing` styles are supported.
+
+### Bugs fixed
+
+* [#318](https://github.com/bbatsov/rubocop/issues/318): Correct some special cases of block end alignment.
+* [#317](https://github.com/bbatsov/rubocop/issues/317): Fix a false positive in `LiteralInCondition`.
+* [#321](https://github.com/bbatsov/rubocop/issues/321): Ignore variables whose name start with `_` in `ShadowingOuterLocalVariable`.
+* [#322](https://github.com/bbatsov/rubocop/issues/322): Fix exception of `UnusedLocalVariable` and `ShadowingOuterLocalVariable` when inspecting keyword splat argument.
+* [#316](https://github.com/bbatsov/rubocop/issues/316): Correct nested postfix unless in `MultilineIfThen`.
+* [#327](https://github.com/bbatsov/rubocop/issues/327): Fix false offences for block expression that span on two lines in `EndAlignment`.
+* [#332](https://github.com/bbatsov/rubocop/issues/332): Fix exception of `UnusedLocalVariable` and `ShadowingOuterLocalVariable` when inspecting named captures.
+* [#333](https://github.com/bbatsov/rubocop/issues/333): Fix a case that `EnsureReturn` throws an exception when ensure has no body.
+
+## 0.9.0 (01/07/2013)
+
+### New features
+
+* Introduced formatter feature, enables custom formatted output and multiple outputs.
+* Added progress formatter and now it's the default. (`--format progress`).
+* Added JSON formatter. (`--format json`).
+* Added clang style formatter showing the offending source. code. (`--format clang`). The `clang` formatter marks a whole range rather than just the starting position, to indicate more clearly where the problem is.
+* Added `-f`/`--format` option to specify formatter.
+* Added `-o`/`--out` option to specify output file for each formatter.
+* Added `-r/--require` option to inject external Ruby code into RuboCop.
+* Added `-V/--verbose-version` option that displays Parser version and Ruby version as well.
+* Added `-R/--rails` option that enables extra Rails-specific cops.
+* Added support for auto-correction of some offences with `-a`/`--auto-correct`.
+* New cop `CaseEquality` checks for explicit use of `===`.
+* New cop `AssignmentInCondition` checks for assignment in conditions.
+* New cop `EndAlignment` tracks misaligned `end` keywords.
+* New cop `Void` tracks uses of literals/variables/operators in possibly void context.
+* New cop `Documentation` checks for top level class/module doc comments.
+* New cop `UnreachableCode` tracks unreachable code segments.
+* New cop `MethodCallParentheses` tracks unwanted braces in method calls.
+* New cop `UnusedLocalVariable` tracks unused local variables for each scope.
+* New cop `ShadowingOuterLocalVariable` tracks use of the same name as outer local variables for block arguments or block local variables.
+* New cop `WhileUntilDo` tracks uses of `do` with multi-line `while/until`.
+* New cop `CharacterLiteral` tracks uses of character literals (`?x`).
+* New cop `EndInMethod` tracks uses of `END` in method definitions.
+* New cop `LiteralInCondition` tracks uses of literals in the conditions of `if/while/until`.
+* New cop `BeginBlock` tracks uses of `BEGIN` blocks.
+* New cop `EndBlock` tracks uses of `END` blocks.
+* New cop `DotPosition` tracks the dot position in multi-line method calls.
+* New cop `Attr` tracks uses of `Module#attr`.
+* Add support for auto-correction of some offences with `-a`/`--auto-correct`.
+
+### Changes
+
+* Deprecated `-e`/`--emacs` option. (Use `--format emacs` instead).
+* Made `progress` formatter the default.
+* Most formatters (`progress`, `simple` and `clang`) now print relative file paths if the paths are under the current working directory.
+* Migrate all cops to new namespaces. `Rubocop::Cop::Lint` is for cops that emit warnings. `Rubocop::Cop::Style` is for cops that do not belong in other namespaces.
+* Merge `FavorPercentR` and `PercentR` into one cop called `RegexpLiteral`, and add configuration parameter `MaxSlashes`.
+* Add `CountKeywordArgs` configuration option to `ParameterLists` cop.
+
+### Bugs fixed
+
+* [#239](https://github.com/bbatsov/rubocop/issues/239): Fixed double quotes false positives.
+* [#233](https://github.com/bbatsov/rubocop/issues/233): Report syntax cop offences.
+* Fix off-by-one error in favor_modifier.
+* [#229](https://github.com/bbatsov/rubocop/issues/229): Recognize a line with CR+LF as a blank line in AccessControl cop.
+* [#235](https://github.com/bbatsov/rubocop/issues/235): Handle multiple constant assignment in ConstantName cop.
+* [#246](https://github.com/bbatsov/rubocop/issues/246): Correct handling of unicode escapes within double quotes.
+* Fix crashes in Blocks, CaseEquality, CaseIndentation, ClassAndModuleCamelCase, ClassMethods, CollectionMethods, and ColonMethodCall.
+* [#263](https://github.com/bbatsov/rubocop/issues/263): Do not check for space around operators called with method syntax.
+* [#271](https://github.com/bbatsov/rubocop/issues/271): Always allow line breaks inside hash literal braces.
+* [#270](https://github.com/bbatsov/rubocop/issues/270): Fixed a false positive in ParenthesesAroundCondition.
+* [#288](https://github.com/bbatsov/rubocop/issues/288): Get config parameter AllCops/Excludes from highest config file in path.
+* [#276](https://github.com/bbatsov/rubocop/issues/276): Let columns start at 1 instead of 0 in all output of column numbers.
+* [#292](https://github.com/bbatsov/rubocop/issues/292): Don't check non-regular files (like sockets, etc).
+* Fix crashes in WordArray on arrays of character literals such as `[?\r, ?\n]`.
+* Fix crashes in Documentation on empty modules.
+
+## 0.8.3 (18/06/2013)
+
+### Bug fixes
+
+* Lock Parser dependency to version 2.0.0.beta5.
+
+## 0.8.2 (06/05/2013)
+
+### New features
+
+* New cop `BlockNesting` checks for excessive block nesting.
+
+### Bug fixes
+
+* Correct calculation of whether a modifier version of a conditional statement will fit.
+* Fix an error in `MultilineIfThen` cop that occurred in some special cases.
+* [#231](https://github.com/bbatsov/rubocop/issues/231): Fix a false positive for modifier if.
+
+## 0.8.1 (05/30/2013)
+
+### New features
+
+* New cop `Proc` tracks uses of `Proc.new`.
+
+### Changes
+
+* Renamed `NewLambdaLiteral` to `Lambda`.
+* Aligned the `Lambda` cop more closely to the style guide - it now allows the use of `lambda` for multi-line blocks.
+
+### Bugs fixed
+
+* [#210](https://github.com/bbatsov/rubocop/issues/210): Fix a false positive for double quotes in regexp literals.
+* [#211](https://github.com/bbatsov/rubocop/issues/211): Fix a false positive for `initialize` method looking like a trivial writer.
+* [#215](https://github.com/bbatsov/rubocop/issues/215): Fixed a lot of modifier `if/unless/while/until` issues.
+* [#213](https://github.com/bbatsov/rubocop/issues/213): Make sure even disabled cops get their configuration set.
+* [#214](https://github.com/bbatsov/rubocop/issues/214): Fix SpaceInsideHashLiteralBraces to handle string interpolation right.
+
+## 0.8.0 (05/28/2013)
+
+### Changes
+
+* Folded `ArrayLiteral` and `HashLiteral` into `EmptyLiteral` cop.
+* The maximum number of params `ParameterLists` accepts in now configurable.
+* Reworked `SymbolSnakeCase` into `SymbolName`, which has an option `AllowCamelCase` enabled by default.
+* Migrated from `Ripper` to the portable [Parser](https://github.com/whitequark/parser).
+
+### New features
+
+* New cop `ConstantName` checks for constant which are not using `SCREAMING_SNAKE_CASE`.
+* New cop `AccessControl` checks private/protected indentation and surrounding blank lines.
+* New cop `Loop` checks for `begin/end/while(until)` and suggests the use of `Kernel#loop`.
+
+## 0.7.2 (05/13/2013)
+
+### Bugs fixed
+
+* [#155](https://github.com/bbatsov/rubocop/issues/155): 'Do not use semicolons to terminate expressions.' is not implemented correctly.
+* `OpMethod` now handles definition of unary operators without crashing.
+* `SymbolSnakeCase` now handles aliasing of operators without crashing.
+* `RescueException` now handles the splat operator `*` in a `rescue` clause without crashing.
+* [#159](https://github.com/bbatsov/rubocop/issues/159): AvoidFor cop misses many violations.
+
+## 0.7.1 (05/11/2013)
+
+### Bugs fixed
+
+* Added missing files to the gemspec.
+
+## 0.7.0 (05/11/2013)
+
+### New features
+
+* Added ability to include or exclude files/directories through `.rubocop.yml`.
+* Added option --only for running a single cop.
+* Relax semicolon rule for one line methods, classes and modules.
+* Configuration files, such as `.rubocop.yml`, can now include configuration from other files through the `inherit_from` directive. All configuration files implicitly inherit from `config/default.yml`.
+* New cop `ClassMethods` checks for uses for class/module names in definitions of class/module methods.
+* New cop `SingleLineMethods` checks for methods implemented on a single line.
+* New cop `FavorJoin` checks for usages of `Array#*` with a string argument.
+* New cop `BlockComments` tracks uses of block comments(`=begin/=end` comments).
+* New cop `EmptyLines` tracks consecutive blank lines.
+* New cop `WordArray` tracks arrays of words.
+* [#108](https://github.com/bbatsov/rubocop/issues/108): New cop `SpaceInsideHashLiteralBraces` checks for spaces inside hash literal braces - style is configurable.
+* New cop `LineContinuation` tracks uses of the line continuation character (`\`).
+* New cop `SymbolArray` tracks arrays of symbols.
+* Print warnings for unrecognized names in configuration files.
+* New cop `TrivialAccessors` tracks method definitions that could be automatically generated with `attr_*` methods.
+* New cop `LeadingCommentSpace` checks for missing space after `#` in comments.
+* New cop `ColonMethodCall` tracks uses of `::` for method calls.
+* New cop `AvoidGlobalVars` tracks uses of non built-in global variables.
+* New cop `SpaceAfterControlKeyword` tracks missing spaces after `if/elsif/case/when/until/unless/while`.
+* New cop `Not` tracks uses of the `not` keyword.
+* New cop `Eval` tracks uses of the `eval` function.
+
+### Bugs fixed
+
+* [#101](https://github.com/bbatsov/rubocop/issues/101): `SpaceAroundEqualsInParameterDefault` doesn't work properly with empty string.
+* Fix `BraceAfterPercent` for `%W`, `%i` and `%I` and added more tests.
+* Fix a false positive in the `Alias` cop. `:alias` is no longer treated as keyword.
+* `ArrayLiteral` now properly detects `Array.new`.
+* `HashLiteral` now properly detects `Hash.new`.
+* `VariableInterpolation` now detects regexp back references and doesn't crash.
+* Don't generate pathnames like some/project//some.rb.
+* [#151](https://github.com/bbatsov/rubocop/issues/151): Don't print the unrecognized cop warning several times for the same `.rubocop.yml`.
+
+### Misc
+
+* Renamed `Indentation` cop to `CaseIndentation` to avoid confusion.
+* Renamed `EmptyLines` cop to `EmptyLineBetweenDefs` to avoid confusion.
+
+## 0.6.1 (04/28/2013)
+
+### New features
+
+* Split `AsciiIdentifiersAndComments` cop in two separate cops.
+
+### Bugs fixed
+
+* [#90](https://github.com/bbatsov/rubocop/issues/90): Two cops crash when scanning code using `super`.
+* [#93](https://github.com/bbatsov/rubocop/issues/93): Issue with `whitespace?': undefined method`.
+* [#97](https://github.com/bbatsov/rubocop/issues/97): Build fails.
+* [#100](https://github.com/bbatsov/rubocop/issues/100): `OpMethod` cop doesn't work if method arg is not in braces.
+* `SymbolSnakeCase` now tracks Ruby 1.9 hash labels as well as regular symbols.
+
+### Misc
+
+* [#88](https://github.com/bbatsov/rubocop/issues/88): Abort gracefully when interrupted with Ctrl-C.
+* No longer crashes on bugs within cops. Now problematic checks are skipped and a message is displayed.
+* Replaced `Term::ANSIColor` with `Rainbow`.
+* Add an option to disable colors in the output.
+* Cop names are now displayed alongside messages when `-d/--debug` is passed.
+
+## 0.6.0 (04/23/2013)
+
+### New features
+
+* New cop `ReduceArguments` tracks argument names in reduce calls.
+* New cop `MethodLength` tracks number of LOC (lines of code) in methods.
+* New cop `RescueModifier` tracks uses of `rescue` in modifier form.
+* New cop `PercentLiterals` tracks uses of `%q`, `%Q`, `%s` and `%x`.
+* New cop `BraceAfterPercent` tracks uses of % literals with delimiters other than ().
+* Support for disabling cops locally in a file with rubocop:disable comments.
+* New cop `EnsureReturn` tracks usages of `return` in `ensure` blocks.
+* New cop `HandleExceptions` tracks suppressed exceptions.
+* New cop `AsciiIdentifiersAndComments` tracks uses of non-ascii characters in identifiers and comments.
+* New cop `RescueException` tracks uses of rescuing the `Exception` class.
+* New cop `ArrayLiteral` tracks uses of Array.new.
+* New cop `HashLiteral` tracks uses of Hash.new.
+* New cop `OpMethod` tracks the argument name in operator methods.
+* New cop `PercentR` tracks uses of %r literals with zero or one slash in the regexp.
+* New cop `FavorPercentR` tracks uses of // literals with more than one slash in the regexp.
+
+### Bugs fixed
+
+* [#62](https://github.com/bbatsov/rubocop/issues/62): Config files in ancestor directories are ignored if another exists in home directory.
+* [#65](https://github.com/bbatsov/rubocop/issues/65): Suggests to convert symbols `:==`, `:<=>` and the like to snake_case.
+* [#66](https://github.com/bbatsov/rubocop/issues/66): Does not crash on unreadable or unparseable files.
+* [#70](https://github.com/bbatsov/rubocop/issues/70): Support `alias` with bareword arguments.
+* [#64](https://github.com/bbatsov/rubocop/issues/64): Performance issue with Bundler.
+* [#75](https://github.com/bbatsov/rubocop/issues/75): Make it clear that some global variables require the use of the English library.
+* [#79](https://github.com/bbatsov/rubocop/issues/79): Ternary operator missing whitespace detection.
+
+### Misc
+
+* Dropped Jeweler for gem release management since it's no longer actively maintained.
+* Handle pluralization properly in the final summary.
+
+## 0.5.0 (04/17/2013)
+
+### New features
+
+* New cop `FavorSprintf` that checks for usages of `String#%`.
+* New cop `Semicolon` that checks for usages of `;` as expression separator.
+* New cop `VariableInterpolation` that checks for variable interpolation in double quoted strings.
+* New cop `Alias` that checks for uses of the keyword `alias`.
+* Automatically detect extensionless Ruby files with shebangs when search for Ruby source files in a directory.
+
+### Bugs fixed
+
+* [#59](https://github.com/bbatsov/rubocop/issues/59): Interpolated variables not enclosed in braces are not noticed.
+* [#42](https://github.com/bbatsov/rubocop/issues/42): Received malformed format string ArgumentError from rubocop.
+
+[@bbatsov]: https://github.com/bbatsov
+[@jonas054]: https://github.com/jonas054
+[@yujinakayama]: https://github.com/yujinakayama
+[@dblock]: https://github.com/dblock
+[@nevir]: https://github.com/nevir
+[@daviddavis]: https://github.com/daviddavis
+[@sds]: https://github.com/sds
+[@fancyremarker]: https://github.com/fancyremarker
+[@sinisterchipmunk]: https://github.com/sinisterchipmunk
+[@vonTronje]: https://github.com/vonTronje
+[@agrimm]: https://github.com/agrimm
+[@pmenglund]: https://github.com/pmenglund
+[@chulkilee]: https://github.com/chulkilee
+[@codez]: https://github.com/codez
+[@emou]: https://github.com/emou
+[@skanev]: http://github.com/skanev
+[@claco]: http://github.com/claco
+[@rifraf]: http://github.com/rifraf
+[@scottmatthewman]: https://github.com/scottmatthewman
+[@ma2gedev]: http://github.com/ma2gedev
+[@jeremyolliver]: https://github.com/jeremyolliver
+[@hannestyden]: https://github.com/hannestyden
+[@geniou]: https://github.com/geniou
+[@jkogara]: https://github.com/jkogara
+[@tmorris-fiksu]: https://github.com/tmorris-fiksu
+[@mockdeep]: https://github.com/mockdeep
+[@hiroponz]: https://github.com/hiroponz
+[@tamird]: https://github.com/tamird
+[@fshowalter]: https://github.com/fshowalter
+[@cschramm]: https://github.com/cschramm
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..f2d0dab
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,68 @@
+# Contributing
+
+If you discover issues, have ideas for improvements or new features,
+please report them to the [issue tracker][1] of the repository or
+submit a pull request. Please, try to follow these guidelines when you
+do so.
+
+## Issue reporting
+
+* Check that the issue has not already been reported.
+* Check that the issue has not already been fixed in the latest code
+  (a.k.a. `master`).
+* Be clear, concise and precise in your description of the problem.
+* Open an issue with a descriptive title and a summary in grammatically correct,
+  complete sentences.
+* Include the output of `rubocop -V`:
+
+```
+$ rubocop -V
+0.16.0 (using Parser 2.1.2, running on ruby 2.0.0 x86_64-darwin12.4.0)
+```
+
+* Include any relevant code to the issue summary.
+
+## Pull requests
+
+* Read [how to properly contribute to open source projects on Github][2].
+* Fork the project.
+* Use a topic/feature branch to easily amend a pull request later, if necessary.
+* Write [good commit messages][3].
+* Use the same coding conventions as the rest of the project.
+* Commit and push until you are happy with your contribution.
+* Make sure to add tests for it. This is important so I don't break it
+  in a future version unintentionally.
+* Add an entry to the [Changelog](CHANGELOG.md) accordingly. See [changelog entry format](#changelog-entry-format).
+* Please try not to mess with the Rakefile, version, or history. If
+  you want to have your own version, or is otherwise necessary, that
+  is fine, but please isolate to its own commit so I can cherry-pick
+  around it.
+* Make sure the test suite is passing ([including rbx and jruby][7]) and the code you wrote doesn't produce
+  RuboCop offences.
+* [Squash related commits together][5].
+* Open a [pull request][4] that relates to *only* one subject with a clear title
+  and description in grammatically correct, complete sentences.
+
+### Changelog entry format
+
+Here are a few examples:
+
+```
+* [#716](https://github.com/bbatsov/rubocop/issues/716): Fixed a regression in the auto-correction logic of `MethodDefParentheses`. ([@bbatsov][])
+* New cop `ElseLayout` checks for odd arrangement of code in the `else` branch of a conditional expression. ([@bbatsov][])
+```
+
+* Mark it up in [Markdown syntax][6].
+* The entry line should start with `* ` (an asterisk and a space).
+* If the change has a related GitHub issue (e.g. a bug fix for a reported issue), put a link to the issue as `[#123](https://github.com/bbatsov/rubocop/issues/123): `.
+* Describe the brief of the change. The sentence should end with a punctuation.
+* At the end of the entry, add an implicit link to your GitHub user page as `([@username][])`.
+* If this is your first contribution to RuboCop project, add a link definition for the implicit link to the bottom of the changelog as `[@username]: https://github.com/username`.
+
+[1]: https://github.com/bbatsov/rubocop/issues
+[2]: http://gun.io/blog/how-to-github-fork-branch-and-pull-request
+[3]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
+[4]: https://help.github.com/articles/using-pull-requests
+[5]: http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html
+[6]: http://daringfireball.net/projects/markdown/syntax
+[7]: http://blog.stwrt.ca/2013/09/06/installing-rubinius-with-rbenv
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000..5e145af
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,13 @@
+source 'http://rubygems.org'
+
+gemspec
+
+group :test do
+  gem 'coveralls', require: false
+end
+
+local_gemfile = 'Gemfile.local'
+
+if File.exist?(local_gemfile)
+  eval(File.read(local_gemfile)) # rubocop:disable Eval
+end
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..c07ee63
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,20 @@
+Copyright (c) 2012-14 Bozhidar Batsov
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..0660b3d
--- /dev/null
+++ b/README.md
@@ -0,0 +1,725 @@
+[![Gem Version](https://badge.fury.io/rb/rubocop.png)](http://badge.fury.io/rb/rubocop)
+[![Dependency Status](https://gemnasium.com/bbatsov/rubocop.png)](https://gemnasium.com/bbatsov/rubocop)
+[![Build Status](https://travis-ci.org/bbatsov/rubocop.png?branch=master)](https://travis-ci.org/bbatsov/rubocop)
+[![Coverage Status](https://coveralls.io/repos/bbatsov/rubocop/badge.png?branch=master)](https://coveralls.io/r/bbatsov/rubocop)
+[![Code Climate](https://codeclimate.com/github/bbatsov/rubocop.png)](https://codeclimate.com/github/bbatsov/rubocop)
+[![Inline docs](http://inch-pages.github.io/github/bbatsov/rubocop.png)](http://inch-pages.github.io/github/bbatsov/rubocop)
+
+# RuboCop
+
+> Role models are important. <br/>
+> -- Officer Alex J. Murphy / RoboCop
+
+**RuboCop** is a Ruby static code analyzer. Out of the box it will
+enforce many of the guidelines outlined in the community
+[Ruby Style Guide](https://github.com/bbatsov/ruby-style-guide).
+
+Most aspects of its behavior can be tweaked via various
+[configuration options](https://github.com/bbatsov/rubocop/blob/master/config/default.yml).
+
+Apart from reporting problems in your code, RuboCop can also
+automatically fix some of the problems for you.
+
+- [Installation](#installation)
+- [Basic Usage](#basic-usage)
+    - [Cops](#cops)
+        - [Style](#style)
+        - [Lint](#lint)
+        - [Rails](#rails)
+- [Configuration](#configuration)
+    - [Inheritance](#inheritance)
+    - [Defaults](#defaults)
+    - [Including/Excluding files](#includingexcluding-files)
+    - [Automatically Generated Configuration](#automatically-generated-configuration)
+- [Disabling Cops within Source Code](#disabling-cops-within-source-code)
+- [Formatters](#formatters)
+    - [Progress Formatter (default)](#progress-formatter-default)
+    - [Clang Style Formatter](#clang-style-formatter)
+    - [Fuubar Style Formatter](#fuubar-style-formatter)
+    - [Emacs Style Formatter](#emacs-style-formatter)
+    - [Simple Formatter](#simple-formatter)
+    - [File List Formatter](#file-list-formatter)
+    - [JSON Formatter](#json-formatter)
+    - [Offense Count Formatter](#offense-count-formatter)
+    - [Custom Formatters](#custom-formatters)
+        - [Creating Custom Formatter](#creating-custom-formatter)
+        - [Using Custom Formatter in Command Line](#using-custom-formatter-in-command-line)
+- [Compatibility](#compatibility)
+- [Editor integration](#editor-integration)
+    - [Emacs](#emacs)
+    - [Vim](#vim)
+    - [Sublime Text](#sublime-text)
+    - [Brackets](#brackets)
+    - [TextMate2](#textmate2)
+    - [Atom](#atom)
+    - [LightTable](#lighttable)
+    - [Other Editors](#other-editors)
+- [Guard integration](#guard-integration)
+- [Rake integration](#rake-integration)
+- [Team](#team)
+- [Contributors](#contributors)
+- [Mailing List](#mailing-list)
+- [Changelog](#changelog)
+- [Copyright](#copyright)
+
+## Installation
+
+**RuboCop**'s installation is pretty standard:
+
+```
+$ gem install rubocop
+```
+
+If you'd rather install RuboCop using `bundler`, don't require it in your `Gemfile`:
+
+```
+gem 'rubocop', require: false
+```
+
+## Basic Usage
+
+Running `rubocop` with no arguments will check all Ruby source files
+in the current directory:
+
+```
+$ rubocop
+```
+
+Alternatively you can pass `rubocop` a list of files and directories to check:
+
+```
+$ rubocop app spec lib/something.rb
+```
+
+Here's RuboCop in action. Consider the following Ruby source code:
+
+```ruby
+def badName
+  if something
+    test
+    end
+end
+```
+
+Running RuboCop on it (assuming it's in a file named `test.rb`) would produce the following report:
+
+```
+Offenses:
+
+test.rb:1:5: C: Use snake_case for methods and variables.
+def badName
+    ^^^^^^^
+test.rb:2:3: C: Favor modifier if/unless usage when you have a single-line body. Another good alternative is the usage of control flow &&/||.
+  if something
+  ^^
+test.rb:4:5: W: end at 4, 4 is not aligned with if at 2, 2
+    end
+    ^^^
+
+1 file inspected, 3 offenses detected
+```
+
+For more details check the available command-line options:
+
+```
+$ rubocop -h
+```
+
+Command flag              | Description
+--------------------------|------------------------------------------------------------
+`-v/--version`            | Displays the current version and exits
+`-V/--verbose-version`    | Displays the current version plus the version of Parser and Ruby
+`-d/--debug`              | Displays some extra debug output
+`-D/--display-cop-names`  | Displays cop names in offense messages.
+`-c/--config`             | Run with specified config file
+`-f/--format`             | Choose a formatter
+`-o/--out`                | Write output to a file instead of STDOUT
+`-r/--require`            | Require Ruby file
+`-R/--rails`              | Run extra Rails cops
+`-l/--lint`               | Run only lint cops
+`-a/--auto-correct`       | Auto-correct certain offenses *Note:* Experimental - use with caution
+`--only`                  | Run only the specified cop
+`--auto-gen-config`       | Generate a configuration file acting as a TODO list
+`--show-cops`             | Shows available cops and their configuration
+`--fail-level`            | Minimum severity for exit with error code
+
+### Cops
+
+In RuboCop lingo the various checks performed on the code are called cops. There are several cop departments.
+
+#### Style
+
+Most of the cops in RuboCop are so called style cops that check for
+stylistics problems in your code. Almost all of the them are based on
+the Ruby Style Guide. Many of the style cops have configurations
+options allowing them to support different popular coding
+conventions.
+
+#### Lint
+
+Lint cops check for possible errors and very bad practices in your
+code. RuboCop implements in a portable way all built-in MRI lint
+checks (`ruby -wc`) and adds a lot of extra lint checks of its
+own. You can run only the lint cops like this:
+
+```
+$ rubocop -l
+```
+
+Disabling any of the lint cops is generally a bad idea.
+
+#### Rails
+
+Rails cops are specific to the Ruby on Rails framework. Unlike style
+and lint cops they are not used by default and you have to request them
+specifically:
+
+```
+$ rubocop -R
+```
+
+## Configuration
+
+The behavior of RuboCop can be controlled via the
+[.rubocop.yml](https://github.com/bbatsov/rubocop/blob/master/.rubocop.yml)
+configuration file. It makes it possible to enable/disable certain cops
+(checks) and to alter their behavior if they accept any parameters. The file
+can be placed either in your home directory or in some project directory.
+
+RuboCop will start looking for the configuration file in the directory
+where the inspected file is and continue its way up to the root directory.
+
+The file has the following format:
+
+```yaml
+inherit_from: ../.rubocop.yml
+
+Encoding:
+  Enabled: false
+
+LineLength:
+  Max: 99
+```
+
+### Inheritance
+
+The optional `inherit_from` directive is used to include configuration
+from one or more files. This makes it possible to have the common
+project settings in the `.rubocop.yml` file at the project root, and
+then only the deviations from those rules in the subdirectories. The
+files can be given with absolute paths or paths relative to the file
+where they are referenced. The settings after an `inherit_from`
+directive override any settings in the file(s) inherited from. When
+multiple files are included, the first file in the list has the lowest
+precedence and the last one has the highest. The format for multiple
+inheritance is:
+
+```yaml
+inherit_from:
+  - ../.rubocop.yml
+  - ../conf/.rubocop.yml
+```
+
+### Defaults
+
+The file
+[config/default.yml](https://github.com/bbatsov/rubocop/blob/master/config/default.yml)
+under the RuboCop home directory contains the default settings that
+all configurations inherit from. Project and personal `.rubocop.yml`
+files need only make settings that are different from the default
+ones. If there is no `.rubocop.yml` file in the project or home
+directory, `config/default.yml` will be used.
+
+### Including/Excluding files
+
+RuboCop checks all files recursively within the directory it is run
+on.  However, it only recognizes files ending with `.rb` or
+extensionless files with a `#!.*ruby` declaration as Ruby files. If
+you'd like it to check other files you'll need to manually pass them
+in, or to add entries for them under `AllCops`/`Include`.  Files and
+directories can also be ignored through `AllCops`/`Exclude`.
+
+Here is an example that might be used for a Rails project:
+
+```yaml
+AllCops:
+  Include:
+    - Rakefile
+    - config.ru
+  Exclude:
+    - db/**
+    - config/**
+    - script/**
+    - !ruby/regexp /old_and_unused\.rb$/
+
+# other configuration
+# ...
+```
+
+Files and directories are specified relative to the `.rubocop.yml` file.
+
+**Note**: The `Exclude` parameter is special. It is valid for the
+directory tree starting where it is defined. It is not shadowed by the
+setting of `Exclude` in other `.rubocop.yml` files in
+subdirectories. This is different from all other parameters, who
+follow RuboCop's general principle that configuration for an inspected
+file is taken from the nearest `.rubocop.yml`, searching upwards.
+
+Cops can be run only on specific sets of files when that's needed (for
+instance you might want to run some Rails model checks only on files whose
+paths match `app/models/*.rb`). All cops support the
+`Include` param.
+
+```yaml
+DefaultScope:
+  Include:
+    - app/models/*.rb
+```
+
+Cops can also exclude only specific sets of files when that's needed (for
+instance you might want to run some cop only on a specific file). All cops support the
+`Exclude` param.
+
+```yaml
+DefaultScope:
+  Exclude:
+    - app/models/problematic.rb
+```
+
+Specific cops can be disabled by setting `Enabled` to `false` for that specific cop.
+
+```yaml
+LineLength:
+  Enabled: false
+```
+
+Cops can customize their severity level. All cops support the `Severity` param.
+Allowed params are `refactor`, `convention`, `warning`, `error` and `fatal`.
+
+```yaml
+CyclomaticComplexity:
+  Severity: warning
+```
+
+### Automatically Generated Configuration
+
+If you have a code base with an overwhelming amount of offenses, it can be a
+good idea to use `rubocop --auto-gen-config` and add an `inherit_from:
+rubocop-todo.yml` in your `.rubocop.yml`. The generated file `rubocop-todo.yml`
+contains configuration to disable all cops that currently detect an offense in
+the code. Then you can start removing the entries in the generated file one by
+one as you work through all the offenses in the code.
+
+## Disabling Cops within Source Code
+
+One or more individual cops can be disabled locally in a section of a
+file by adding a comment such as
+
+```ruby
+# rubocop:disable LineLength, StringLiterals
+[...]
+# rubocop:enable LineLength, StringLiterals
+```
+
+You can also disable *all* cops with
+
+```ruby
+# rubocop:disable all
+[...]
+# rubocop:enable all
+```
+
+One or more cops can be disabled on a single line with an end-of-line
+comment.
+
+```ruby
+for x in (0..19) # rubocop:disable AvoidFor
+```
+
+## Formatters
+
+You can change the output format of RuboCop by specifying formatters with the `-f/--format` option.
+RuboCop ships with several built-in formatters, and also you can create your custom formatter.
+
+Additionaly the output can be redirected to a file instead of `$stdout` with the `-o/--out` option.
+
+Some of the built-in formatters produce **machine-parsable** output
+and they are considered public APIs.
+The rest of the formatters are for humans, so parsing their outputs is discouraged.
+
+You can enable multiple formatters at the same time by specifying `-f/--format` multiple times.
+The `-o/--out` option applies to the previously specified `-f/--format`,
+or the default `progress` format if no `-f/--format` is specified before the `-o/--out` option.
+
+```bash
+# Simple format to $stdout.
+$ rubocop --format simple
+
+# Progress (default) format to the file result.txt.
+$ rubocop --out result.txt
+
+# Both progress and offense count formats to $stdout.
+# The offense count formatter outputs only the final summary,
+# so you'll mostly see the outputs from the progress formatter,
+# and at the end the offense count summary will be outputted.
+$ rubocop --format progress --format offenses
+
+# Progress format to $stdout, and JSON format to the file rubocop.json.
+$ rubocop --format progress --format json --out rubocop.json
+#         ~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~
+#                 |               |_______________|
+#              $stdout
+
+# Progress format to result.txt, and simple format to $stdout.
+$ rubocop --output result.txt --format simple
+#         ~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~
+#                  |                 |
+#           default format        $stdout
+```
+
+### Progress Formatter (default)
+
+The default `progress` formatter outputs a character for each inspected file,
+and at the end it displays all detected offenses in the `clang` format.
+A `.` represents a clean file, and each of the capital letters means
+the severest offense (convention, warning, error or fatal) found in a file.
+
+```
+$ rubocop
+Inspecting 26 files
+..W.C....C..CWCW.C...WC.CC
+
+Offenses:
+
+lib/foo.rb:6:5: C: Missing top-level class documentation comment.
+    class Foo
+    ^^^^^
+
+...
+
+26 files inspected, 46 offenses detected
+```
+
+### Clang Style Formatter
+
+The `clang` formatter displays the offenses in a manner similar to `clang`:
+
+```
+$ rubocop test.rb
+test.rb:1:1: C: Use snake_case for methods and variables.
+def badName
+    ^^^^^^^
+test.rb:2:3: C: Favor modifier if/unless usage when you have a single-line body. Another good alternative is the usage of control flow &&/||.
+  if something
+  ^^
+test.rb:4:5: W: end at 4, 4 is not aligned with if at 2, 2
+    end
+    ^^^
+
+1 file inspected, 3 offenses detected
+```
+
+### Fuubar Style Formatter
+
+The `fuubar` style formatter displays a progress bar
+and shows details of offenses in the `clang` format as soon as they are detected.
+This is inspired by the [Fuubar](https://github.com/jeffkreeftmeijer/fuubar) formatter for RSpec.
+
+```
+$ rubocop --format fuubar
+lib/foo.rb.rb:1:1: C: Use snake_case for methods and variables.
+def badName
+    ^^^^^^^
+lib/bar.rb:13:14: W: File.exists? is deprecated in favor of File.exist?.
+        File.exists?(path)
+             ^^^^^^^
+ 22/53 files |======== 43 ========>                           |  ETA: 00:00:02
+```
+
+### Emacs Style Formatter
+
+**Machine-parsable**
+
+The `emacs` formatter displays the offenses in a format suitable for consumption by `Emacs` (and possibly other tools).
+
+```
+$ rubocop --format emacs test.rb
+/Users/bozhidar/projects/test.rb:1:1: C: Use snake_case for methods and variables.
+/Users/bozhidar/projects/test.rb:2:3: C: Favor modifier if/unless usage when you have a single-line body. Another good alternative is the usage of control flow &&/||.
+/Users/bozhidar/projects/test.rb:4:5: W: end at 4, 4 is not aligned with if at 2, 2
+```
+
+### Simple Formatter
+
+The name of the formatter says it all :-)
+
+```
+$ rubocop --format simple test.rb
+== test.rb ==
+C:  1:  1: Use snake_case for methods and variables.
+C:  2:  3: Favor modifier if/unless usage when you have a single-line body. Another good alternative is the usage of control flow &&/||.
+W:  4:  5: end at 4, 4 is not aligned with if at 2, 2
+
+1 file inspected, 3 offenses detected
+```
+
+### File List Formatter
+
+ **Machine-parsable**
+
+Sometimes you might want to just open all files with offenses in your
+favorite editor. This formatter outputs just the names of the files
+with offenses in them and makes it possible to do something like:
+
+```
+$ rubocop --format files | xargs vim
+```
+
+### JSON Formatter
+
+**Machine-parsable**
+
+You can get RuboCop's inspection result in JSON format by passing `--format json` option in command line.
+The JSON structure is like the following example:
+
+```javascript
+{
+  "metadata": {
+    "rubocop_version": "0.9.0",
+    "ruby_engine": "ruby",
+    "ruby_version": "2.0.0",
+    "ruby_patchlevel": "195",
+    "ruby_platform": "x86_64-darwin12.3.0"
+  },
+  "files": [{
+      "path": "lib/foo.rb",
+      "offenses": []
+    }, {
+      "path": "lib/bar.rb",
+      "offenses": [{
+          "severity": "convention",
+          "message": "Line is too long. [81/79]",
+          "cop_name": "LineLength",
+          "corrected": true,
+          "location": {
+            "line": 546,
+            "column": 80,
+            "length": 4
+          }
+        }, {
+          "severity": "warning",
+          "message": "Unreachable code detected.",
+          "cop_name": "UnreachableCode",
+          "corrected": false,
+          "location": {
+            "line": 15,
+            "column": 9,
+            "length": 10
+          }
+        }
+      ]
+    }
+  ],
+  "summary": {
+    "offense_count": 2,
+    "target_file_count": 2,
+    "inspected_file_count": 2
+  }
+}
+```
+
+### Offense Count Formatter
+
+Sometimes when first applying RuboCop to a codebase, it's nice to be able to
+see where most of your style cleanup is going to be spent.
+
+With this in mind, you can use the offense count formatter to outline the offended
+cops and the number of offenses found for each by running:
+
+```
+$ rubocop --format offenses
+
+87   Documentation
+12   DotPosition
+8    AvoidGlobalVars
+7    EmptyLines
+6    AssignmentInCondition
+4    Blocks
+4    CommentAnnotation
+3    BlockAlignment
+1    IndentationWidth
+1    AvoidPerlBackrefs
+1    ColonMethodCall
+--
+134  Total
+```
+
+### Custom Formatters
+
+You can customize RuboCop's output format with custom formatter.
+
+#### Creating Custom Formatter
+
+To implement a custom formatter, you need to subclass
+`Rubocop::Formatter::BaseFormatter` and override some methods,
+or implement all formatter API methods by duck typing.
+
+Please see the documents below for more formatter API details.
+
+* [Rubocop::Formatter::BaseFormatter](http://rubydoc.info/gems/rubocop/Rubocop/Formatter/BaseFormatter)
+* [Rubocop::Cop::Offense](http://rubydoc.info/gems/rubocop/Rubocop/Cop/Offense)
+* [Parser::Source::Range](http://rubydoc.info/github/whitequark/parser/Parser/Source/Range)
+
+#### Using Custom Formatter in Command Line
+
+You can tell RuboCop to use your custom formatter with a combination of
+`--format` and `--require` option.
+For example, when you have defined `MyCustomFormatter` in
+`./path/to/my_custom_formatter.rb`, you would type this command:
+
+```
+$ rubocop --require ./path/to/my_custom_formatter --format MyCustomFormatter
+```
+
+Note: The path passed to `--require` is directly passed to `Kernel.require`.
+If your custom formatter file is not in `$LOAD_PATH`,
+you need to specify the path as relative path prefixed with `./` explicitly,
+or absolute path.
+
+## Compatibility
+
+RuboCop supports the following Ruby implementations:
+
+* MRI 1.9.2 ([until June 2014](https://www.ruby-lang.org/en/news/2013/12/17/maintenance-of-1-8-7-and-1-9-2/))
+* MRI 1.9.3
+* MRI 2.0
+* MRI 2.1
+* JRuby in 1.9 mode
+* Rubinius 2.0+
+
+## Editor integration
+
+### Emacs
+
+[rubocop.el](https://github.com/bbatsov/rubocop-emacs) is a simple
+Emacs interface for RuboCop. It allows you to run RuboCop inside Emacs
+and quickly jump between problems in your code.
+
+[flycheck](https://github.com/lunaryorn/flycheck) > 0.9 also supports
+RuboCop and uses it by default when available.
+
+### Vim
+
+The [vim-rubocop](https://github.com/ngmy/vim-rubocop) plugin runs
+RuboCop and displays the results in Vim.
+
+There's also a RuboCop checker in
+[syntastic](https://github.com/scrooloose/syntastic).
+
+### Sublime Text
+
+If you're a ST user you might find the
+[Sublime RuboCop plugin](https://github.com/pderichs/sublime_rubocop)
+useful.
+
+### Brackets
+
+The [brackets-rubocop](https://github.com/smockle/brackets-rubocop)
+extension displays RuboCop results in Brackets.
+It can be installed via the extension manager in Brackets.
+
+### TextMate2
+
+The [textmate2-rubocop](https://github.com/mrdougal/textmate2-rubocop)
+bundle displays formatted RuboCop results in a new window.
+Installation instructions can be found [here](https://github.com/mrdougal/textmate2-rubocop#installation).
+
+### Atom
+
+The [atom-lint](https://github.com/yujinakayama/atom-lint) package
+runs RuboCop and highlights the offenses in Atom.
+
+### LightTable
+
+The [lt-rubocop](https://github.com/seancaffery/lt-rubocop) plugin
+provides LightTable integration.
+
+### Other Editors
+
+Here's one great opportunity to contribute to RuboCop - implement
+RuboCop integration for your favorite editor.
+
+## Guard integration
+
+If you're fond of [Guard](https://github.com/guard/guard) you might
+like
+[guard-rubocop](https://github.com/yujinakayama/guard-rubocop). It
+allows you to automatically check Ruby code style with RuboCop when
+files are modified.
+
+
+## Rake integration
+
+To use RuboCop in your `Rakefile` add the following:
+
+```ruby
+require 'rubocop/rake_task'
+
+Rubocop::RakeTask.new
+```
+
+The above will use default values
+
+```ruby
+require 'rubocop/rake_task'
+
+desc 'Run RuboCop on the lib directory'
+Rubocop::RakeTask.new(:rubocop) do |task|
+  task.patterns = ['lib/**/*.rb']
+  # only show the files with failures
+  task.formatters = ['files']
+  # don't abort rake on failure
+  task.fail_on_error = false
+end
+```
+
+## Team
+
+Here's a list of RuboCop's core developers:
+
+* [Bozhidar Batsov](https://github.com/bbatsov)
+* [Jonas Arvidsson](https://github.com/jonas054)
+* [Yuji Nakayama](https://github.com/yujinakayama)
+* [Evgeni Dzhelyov](https://github.com/edzhelyov)
+
+## Contributors
+
+Here's a [list](https://github.com/bbatsov/rubocop/contributors) of
+all the people who have contributed to the development of RuboCop.
+
+I'm extremely grateful to each and every one of them!
+
+If you'd like to contribute to RuboCop, please take the time to go
+through our short
+[contribution guidelines](CONTRIBUTING.md).
+
+Converting more of the Ruby Style Guide into RuboCop cops is our top
+priority right now. Writing a new cop is a great way to dive into RuboCop!
+
+Of course, bug reports and suggestions for improvements are always
+welcome. GitHub pull requests are even better! :-)
+
+## Mailing List
+
+If you're interested in everything regarding RuboCop's development,
+consider joining its
+[Google Group](https://groups.google.com/forum/?fromgroups#!forum/rubocop).
+
+## Changelog
+
+RuboCop's changelog is available [here](CHANGELOG.md).
+
+## Copyright
+
+Copyright (c) 2012-2014 Bozhidar Batsov. See [LICENSE.txt](LICENSE.txt) for
+further details.
diff --git a/Rakefile b/Rakefile
new file mode 100644
index 0000000..5cfdabd
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1,43 @@
+# encoding: utf-8
+
+require 'rubygems'
+require 'bundler'
+require 'bundler/gem_tasks'
+begin
+  Bundler.setup(:default, :development)
+rescue Bundler::BundlerError => e
+  $stderr.puts e.message
+  $stderr.puts 'Run `bundle install` to install missing gems'
+  exit e.status_code
+end
+require 'rake'
+require 'rspec/core'
+require 'rspec/core/rake_task'
+require 'rubocop/rake_task'
+RSpec::Core::RakeTask.new(:spec) do |spec|
+  spec.pattern = FileList['spec/**/*_spec.rb']
+end
+
+desc 'Run RSpec with code coverage'
+task :coverage do
+  ENV['COVERAGE'] = 'true'
+  Rake::Task['spec'].execute
+end
+
+desc 'Run RuboCop over itself'
+Rubocop::RakeTask.new(:internal_investigation)
+
+task default: [:spec, :internal_investigation]
+
+require 'yard'
+YARD::Rake::YardocTask.new
+
+Rubocop::RakeTask.new
+
+task :console do
+  require 'irb'
+  require 'irb/completion'
+  require 'rubocop'
+  ARGV.clear
+  IRB.start
+end
diff --git a/bin/rubocop b/bin/rubocop
new file mode 100755
index 0000000..d6291d2
--- /dev/null
+++ b/bin/rubocop
@@ -0,0 +1,22 @@
+#!/usr/bin/env ruby
+# encoding: utf-8
+
+if RUBY_VERSION >= '1.9.2'
+  $LOAD_PATH.unshift(File.dirname(File.realpath(__FILE__)) + '/../lib')
+
+  require 'rubocop'
+  require 'benchmark'
+
+  cli = Rubocop::CLI.new
+  result = 0
+
+  time = Benchmark.realtime do
+    result = cli.run
+  end
+
+  puts "Finished in #{time} seconds" if cli.options[:debug]
+  exit result
+else
+  puts 'RuboCop supports only Ruby 1.9.2+'
+  exit(-1)
+end
diff --git a/config/default.yml b/config/default.yml
new file mode 100644
index 0000000..57cba10
--- /dev/null
+++ b/config/default.yml
@@ -0,0 +1,451 @@
+# This is the default configuration file. Enabling and disabling is configured
+# in separate files. This file adds all other parameters apart from Enabled.
+
+inherit_from:
+  - enabled.yml
+  - disabled.yml
+
+# Common configuration.
+AllCops:
+  # Include gemspec and Rakefile
+  Include:
+    - '**/*.gemspec'
+    - '**/Rakefile'
+  Exclude:
+    - 'vendor/**'
+  # By default, the rails cops are not run. Override in project or home
+  # directory .rubocop.yml files, or by giving the -R/--rails option.
+  RunRailsCops: false
+
+# Indent private/protected/public as deep as method definitions
+AccessModifierIndentation:
+  EnforcedStyle: indent
+  SupportedStyles:
+    - outdent
+    - indent
+
+# Align the elements of a hash literal if they span more than one line.
+AlignHash:
+  # Alignment of entries using hash rocket as separator. Valid values are:
+  #
+  # key - left alignment of keys
+  #   'a' => 2
+  #   'bb' => 3
+  # separator - alignment of hash rockets, keys are right aligned
+  #    'a' => 2
+  #   'bb' => 3
+  # table - left alignment of keys, hash rockets, and values
+  #   'a'  => 2
+  #   'bb' => 3
+  EnforcedHashRocketStyle: key
+  # Alignment of entries using colon as separator. Valid values are:
+  #
+  # key - left alignment of keys
+  #   a: 0
+  #   bb: 1
+  # separator - alignment of colons, keys are right aligned
+  #    a: 0
+  #   bb: 1
+  # table - left alignment of keys and values
+  #   a:  0
+  #   bb: 1
+  EnforcedColonStyle: key
+  # Select whether hashes that are the last argument in a method call should be
+  # inspected? Valid values are:
+  #
+  # always_inspect - Inspect both implicit and explicit hashes.
+  #   Registers and offence for:
+  #     function(a: 1,
+  #       b: 2)
+  #   Registers an offence for:
+  #     function({a: 1,
+  #       b: 2})
+  # always_ignore - Ignore both implicit and explicit hashes.
+  #   Accepts:
+  #     function(a: 1,
+  #       b: 2)
+  #   Accepts:
+  #     function({a: 1,
+  #       b: 2})
+  # ignore_implicit - Ingore only implicit hashes.
+  #   Accepts:
+  #     function(a: 1,
+  #       b: 2)
+  #   Registers an offence for:
+  #     function({a: 1,
+  #       b: 2})
+  # ignore_explicit - Ingore only explicit hashes.
+  #   Accepts:
+  #     function({a: 1,
+  #       b: 2})
+  #   Registers an offence for:
+  #     function(a: 1,
+  #       b: 2)
+  EnforcedLastArgumentHashStyle: always_inspect
+  SupportedLastArgumentHashStyles:
+    - always_inspect
+    - always_ignore
+    - ignore_implicit
+    - ignore_explicit
+
+AlignParameters:
+  # Alignment of parameters in multi-line method calls.
+  #
+  # The `with_first_parameter` style aligns the following lines along the same column
+  # as the first parameter.
+  #
+  #     method_call(a,
+  #                 b)
+  #
+  # The `with_fixed_indentation` style alignes the following lines with one
+  # level of indenation relative to the start of the line with the method call.
+  #
+  #     method_call(a,
+  #       b)
+  EnforcedStyle: with_first_parameter
+  SupportedStyles:
+    - with_first_parameter
+    - with_fixed_indentation
+
+# Allow safe assignment in conditions.
+AssignmentInCondition:
+  AllowSafeAssignment: true
+
+BlockNesting:
+  Max: 3
+
+BracesAroundHashParameters:
+  EnforcedStyle: no_braces
+  SupportedStyles:
+    - braces
+    - no_braces
+
+# Indentation of `when`.
+CaseIndentation:
+  IndentWhenRelativeTo: case
+  SupportedStyles:
+    - case
+    - end
+  IndentOneStep: false
+
+ClassAndModuleChildren:
+  # Checks the style of children definitions at classes and modules.
+  #
+  # Basically there are two different styles:
+  #
+  # `nested` - have each child on a separat line
+  #   class Foo
+  #     class Bar
+  #     end
+  #   end
+  #
+  # `compact` - combine definitions as much as possible
+  #   class Foo::Bar
+  #   end
+  #
+  # The compact style is only forced, for classes / modules with one child.
+  EnforcedStyle: nested
+  SupportedStyles:
+    - nested
+    - compact
+
+ClassLength:
+  CountComments: false  # count full line comments?
+  Max: 100
+
+# Align with the style guide.
+CollectionMethods:
+  PreferredMethods:
+    collect: 'map'
+    collect!: 'map!'
+    inject: 'reduce'
+    detect: 'find'
+    find_all: 'select'
+
+# Checks formatting of special comments
+CommentAnnotation:
+  Keywords:
+    - TODO
+    - FIXME
+    - OPTIMIZE
+    - HACK
+    - REVIEW
+
+# Avoid complex methods.
+CyclomaticComplexity:
+  Max: 6
+
+# Multi-line method chaining should be done with leading dots.
+DotPosition:
+  EnforcedStyle: leading
+  SupportedStyles:
+    - leading
+    - trailing
+
+# Use empty lines between defs.
+EmptyLineBetweenDefs:
+  # If true, this parameter means that single line method definitions don't
+  # need an empty line between them.
+  AllowAdjacentOneLineDefs: false
+
+# Align ends correctly.
+EndAlignment:
+  # The value `keyword` means that `end` should be aligned with the matching
+  # keyword (if, while, etc.).
+  # The value `variable` means that in assignments, `end` should be aligned
+  # with the start of the variable on the left hand side of `=`. In all other
+  # situations, `end` should still be aligned with the keyword.
+  AlignWith: keyword
+  SupportedStyles:
+    - keyword
+    - variable
+
+FileName:
+  Exclude:
+    - Rakefile
+    - Gemfile
+    - Capfile
+
+# Checks use of for or each in multiline loops.
+For:
+  EnforcedStyle: each
+  SupportedStyles:
+    - for
+    - each
+
+# Enforce the method used for string formatting.
+FormatString:
+  EnforcedStyle: format
+  SupportedStyles:
+    - format
+    - sprintf
+    - percent
+
+# Built-in global variables are allowed by default.
+GlobalVars:
+  AllowedVariables: []
+
+HashSyntax:
+  EnforcedStyle: ruby19
+  SupportedStyles:
+    - ruby19
+    - hash_rockets
+
+IfUnlessModifier:
+  MaxLineLength: 79
+
+# Checks the indentation of the first key in a hash literal.
+IndentHash:
+  # The value `special_inside_parentheses` means that hash literals with braces
+  # that have their opening brace on the same line as a surrounding opening
+  # round parenthesis, shall have their first key indented relative to the
+  # first position inside the parenthesis.
+  # The value `consistent` means that the indentation of the first key shall
+  # always be relative to the first position of the line where the opening
+  # brace is.
+  EnforcedStyle: special_inside_parentheses
+  SupportedStyles:
+    - special_inside_parentheses
+    - consistent
+
+LambdaCall:
+  EnforcedStyle: call
+  SupportedStyles:
+    - call
+    - braces
+
+LineLength:
+  Max: 79
+
+MethodDefParentheses:
+  EnforcedStyle: require_parentheses
+  SupportedStyles:
+    - require_parentheses
+    - require_no_parentheses
+
+MethodLength:
+  CountComments: false  # count full line comments?
+  Max: 10
+
+MethodName:
+  EnforcedStyle: snake_case
+  SupportedStyles:
+    - snake_case
+    - camelCase
+
+NumericLiterals:
+  MinDigits: 5
+
+ParameterLists:
+  Max: 5
+  CountKeywordArgs: true
+
+# Allow safe assignment in conditions.
+ParenthesesAroundCondition:
+  AllowSafeAssignment: true
+
+PercentLiteralDelimiters:
+  PreferredDelimiters:
+    '%':  ()
+    '%i': ()
+    '%q': ()
+    '%Q': ()
+    '%r': '{}'
+    '%s': ()
+    '%w': ()
+    '%W': ()
+    '%x': ()
+
+PredicateName:
+  NamePrefixBlacklist:
+    - is_
+    - has_
+    - have_
+
+RaiseArgs:
+  EnforcedStyle: exploded
+  SupportedStyles:
+    - compact # raise Exception.new(msg)
+    - exploded # raise Exception, msg
+
+
+RedundantReturn:
+  # When true allows code like `return x, y`.
+  AllowMultipleReturnValues: false
+
+RegexpLiteral:
+  # The maximum number of (escaped) slashes that a slash-delimited regexp is
+  # allowed to have. If there are more slashes, a %r regexp shall be used.
+  MaxSlashes: 1
+
+Semicolon:
+  # Allow ; to separate several expressions on the same line.
+  AllowAsExpressionSeparator: false
+
+SignalException:
+  EnforcedStyle: semantic
+  SupportedStyles:
+    - only_raise
+    - only_fail
+    - semantic
+
+
+SingleLineBlockParams:
+  Methods:
+    - reduce:
+        - a
+        - e
+    - inject:
+        - a
+        - e
+
+SingleLineMethods:
+  AllowIfMethodIsEmpty: true
+
+StringLiterals:
+  EnforcedStyle: single_quotes
+  SupportedStyles:
+    - single_quotes
+    - double_quotes
+
+SpaceAroundEqualsInParameterDefault:
+  EnforcedStyle: space
+  SupportedStyles:
+    - space
+    - no_space
+
+SpaceBeforeBlockBraces:
+  EnforcedStyle: space
+  SupportedStyles:
+    - space
+    - no_space
+
+SpaceInsideBlockBraces:
+  EnforcedStyle: space
+  SupportedStyles:
+    - space
+    - no_space
+  # Valid values are: space, no_space
+  EnforcedStyleForEmptyBraces: no_space
+  # Space between { and |. Overrides EnforcedStyle if there is a conflict.
+  SpaceBeforeBlockParameters: true
+
+SpaceInsideHashLiteralBraces:
+  EnforcedStyle: space
+  EnforcedStyleForEmptyBraces: no_space
+  SupportedStyles:
+    - space
+    - no_space
+
+TrailingComma:
+  EnforcedStyleForMultiline: no_comma
+  SupportedStyles:
+    - comma
+    - no_comma
+
+# TrivialAccessors doesn't require exact name matches and doesn't allow
+# predicated methods by default.
+TrivialAccessors:
+  ExactNameMatch: false
+  AllowPredicates: false
+  Whitelist:
+    - to_ary
+    - to_a
+    - to_c
+    - to_enum
+    - to_h
+    - to_hash
+    - to_i
+    - to_int
+    - to_io
+    - to_open
+    - to_path
+    - to_proc
+    - to_r
+    - to_regexp
+    - to_str
+    - to_s
+    - to_sym
+
+VariableName:
+  EnforcedStyle: snake_case
+  SupportedStyles:
+    - snake_case
+    - camelCase
+
+WhileUntilModifier:
+  MaxLineLength: 79
+
+WordArray:
+  MinSize: 0
+
+##################### Rails ##################################
+
+ActionFilter:
+  EnforcedStyle: action
+  SupportedStyles:
+    - action
+    - filter
+  Include:
+    - app/controllers/*.rb
+
+DefaultScope:
+  Include:
+    - app/models/*.rb
+
+HasAndBelongsToMany:
+  Include:
+    - app/models/*.rb
+
+ReadWriteAttribute:
+  Include:
+    - app/models/*.rb
+
+ScopeArgs:
+  Include:
+    - app/models/*.rb
+
+Validation:
+  Include:
+    - app/models/*.rb
+
diff --git a/config/disabled.yml b/config/disabled.yml
new file mode 100644
index 0000000..66fdb7d
--- /dev/null
+++ b/config/disabled.yml
@@ -0,0 +1,13 @@
+# These are all the cops that are disabled in the default configuration.
+
+GuardClause:
+  Description: 'Check for conditionals that can be replaced with guard clauses'
+  Enabled: false
+
+MethodCalledOnDoEndBlock:
+  Description: 'Avoid chaining a method call on a do...end block.'
+  Enabled: false
+
+SymbolArray:
+  Description: 'Use %i or %I for arrays of symbols.'
+  Enabled: false
diff --git a/config/enabled.yml b/config/enabled.yml
new file mode 100644
index 0000000..5cb6051
--- /dev/null
+++ b/config/enabled.yml
@@ -0,0 +1,729 @@
+# These are all the cops that are enabled in the default configuration.
+
+AccessModifierIndentation:
+  Description: Check indentation of private/protected visibility modifiers.
+  Enabled: true
+
+AccessorMethodName:
+  Description: Check the naming of accessor methods for get_/set_.
+  Enabled: true
+
+Alias:
+  Description: 'Use alias_method instead of alias.'
+  Enabled: true
+
+AlignArray:
+  Description: >-
+                 Align the elements of an array literal if they span more than
+                 one line.
+  Enabled: true
+
+AlignHash:
+  Description: >-
+                 Align the elements of a hash literal if they span more than
+                 one line.
+  Enabled: true
+
+AlignParameters:
+  Description: >-
+                 Align the parameters of a method call if they span more
+                 than one line.
+  Enabled: true
+
+AndOr:
+  Description: 'Use &&/|| instead of and/or.'
+  Enabled: true
+
+ArrayJoin:
+  Description: 'Use Array#join instead of Array#*.'
+  Enabled: true
+
+AsciiComments:
+  Description: 'Use only ascii symbols in comments.'
+  Enabled: true
+
+AsciiIdentifiers:
+  Description: 'Use only ascii symbols in identifiers.'
+  Enabled: true
+
+Attr:
+  Description: 'Checks for uses of Module#attr.'
+  Enabled: true
+
+BeginBlock:
+  Description: 'Avoid the use of BEGIN blocks.'
+  Enabled: true
+
+BlockComments:
+  Description: 'Do not use block comments.'
+  Enabled: true
+
+BlockNesting:
+  Description: 'Avoid excessive block nesting'
+  Enabled: true
+
+Blocks:
+  Description: >-
+                Avoid using {...} for multi-line blocks (multiline chaining is
+                always ugly).
+                Prefer {...} over do...end for single-line blocks.
+  Enabled: true
+
+BracesAroundHashParameters:
+  Description: 'Enforce braces style inside hash parameters.'
+  Enabled: true
+
+CaseEquality:
+  Description: 'Avoid explicit use of the case equality operator(===).'
+  Enabled: true
+
+CaseIndentation:
+  Description: 'Indentation of when in a case/when/[else/]end.'
+  Enabled: true
+
+CharacterLiteral:
+  Description: 'Checks for uses of character literals.'
+  Enabled: true
+
+ClassAndModuleCamelCase:
+  Description: 'Use CamelCase for classes and modules.'
+  Enabled: true
+
+ClassAndModuleChildren:
+  Description: 'Checks style of children classes and modules.'
+  Enabled: true
+
+ClassLength:
+  Description: 'Avoid classes longer than 100 lines of code.'
+  Enabled: true
+
+ClassMethods:
+  Description: 'Use self when defining module/class methods.'
+  Enabled: true
+
+ClassVars:
+  Description: 'Avoid the use of class variables.'
+  Enabled: true
+
+CollectionMethods:
+  Description: 'Preferred collection methods.'
+  Enabled: true
+
+ColonMethodCall:
+  Description: 'Do not use :: for method call.'
+  Enabled: true
+
+CommentAnnotation:
+  Description: >-
+                 Checks formatting of special comments
+                 (TODO, FIXME, OPTIMIZE, HACK, REVIEW).
+  Enabled: true
+
+ConstantName:
+  Description: 'Constants should use SCREAMING_SNAKE_CASE.'
+  Enabled: true
+
+CyclomaticComplexity:
+  Description: 'Avoid complex methods.'
+  Enabled: true
+
+DefWithParentheses:
+  Description: 'Use def with parentheses when there are arguments.'
+  Enabled: true
+
+DeprecatedHashMethods:
+  Description: 'Checks for use of deprecated Hash methods.'
+  Enabled: true
+
+Documentation:
+  Description: 'Document classes and non-namespace modules.'
+  Enabled: true
+
+DotPosition:
+  Description: 'Checks the position of the dot in multi-line method calls.'
+  Enabled: true
+
+DoubleNegation:
+  Description: 'Checks for uses of double negation (!!).'
+  Enabled: true
+
+EmptyLineBetweenDefs:
+  Description: 'Use empty lines between defs.'
+  Enabled: true
+
+EmptyLines:
+  Description: "Don't use several empty lines in a row."
+  Enabled: true
+
+EmptyLinesAroundAccessModifier:
+  Description: "Keep blank lines around access modifiers."
+  Enabled: true
+
+EmptyLinesAroundBody:
+  Description: "Keeps track of empty lines around expression bodies."
+  Enabled: true
+
+EmptyLiteral:
+  Description: 'Prefer literals to Array.new/Hash.new/String.new.'
+  Enabled: true
+
+Encoding:
+  Description: 'Use UTF-8 as the source file encoding.'
+  Enabled: true
+
+EndBlock:
+  Description: 'Avoid the use of END blocks.'
+  Enabled: true
+
+EndOfLine:
+  Description: 'Use Unix-style line endings.'
+  Enabled: true
+
+EvenOdd:
+  Description: 'Favor the use of Fixnum#even? && Fixnum#odd?'
+  Enabled: true
+
+FileName:
+  Description: 'Use snake_case for source file names.'
+  Enabled: true
+
+FinalNewline:
+  Description: 'Checks for a final newline in a source file.'
+  Enabled: true
+
+FlipFlop:
+  Description: 'Checks for flip flops'
+  Enabled: true
+
+For:
+  Description: 'Checks use of for or each in multiline loops.'
+  Enabled: true
+
+FormatString:
+  Description: 'Enforce the use of Kernel#sprintf, Kernel#format or String#%.'
+  Enabled: true
+
+GlobalVars:
+  Description: 'Do not introduce global variables.'
+  Enabled: true
+
+HashSyntax:
+  Description: >-
+                 Prefer Ruby 1.9 hash syntax { a: 1, b: 2 } over 1.8 syntax
+                 { :a => 1, :b => 2 }.
+  Enabled: true
+
+IfUnlessModifier:
+  Description: >-
+                 Favor modifier if/unless usage when you have a
+                 single-line body.
+  Enabled: true
+
+IfWithSemicolon:
+  Description: 'Never use if x; .... Use the ternary operator instead.'
+  Enabled: true
+
+IndentationConsistency:
+  Description: 'Keep indentation straight.'
+  Enabled: true
+
+IndentationWidth:
+  Description: 'Use 2 spaces for indentation.'
+  Enabled: true
+
+IndentArray:
+  Description: >-
+                 Checks the indentation of the first element in an array
+                 literal.
+  Enabled: true
+
+IndentHash:
+  Description: 'Checks the indentation of the first key in a hash literal.'
+  Enabled: true
+
+Lambda:
+  Description: 'Use the new lambda literal syntax for single-line blocks.'
+  Enabled: true
+
+LambdaCall:
+  Description: 'Use lambda.call(...) instead of lambda.(...).'
+  Enabled: true
+
+LeadingCommentSpace:
+  Description: 'Comments should start with a space.'
+  Enabled: true
+
+LineEndConcatenation:
+  Description: 'Use \\ instead of + to concatenate two string literals at line end.'
+  Enabled: true
+
+LineLength:
+  Description: 'Limit lines to 79 characters.'
+  Enabled: true
+
+MethodCallParentheses:
+  Description: 'Do not use parentheses for method calls with no arguments.'
+  Enabled: true
+
+MethodDefParentheses:
+  Description: >-
+                 Checks if the method definitions have or don't have
+                 parentheses.
+  Enabled: true
+
+MethodLength:
+  Description: 'Avoid methods longer than 10 lines of code.'
+  Enabled: true
+
+MethodName:
+  Description: 'Use the configured style when naming methods.'
+  Enabled: true
+
+ModuleFunction:
+  Description: 'Checks for usage of `extend self` in modules.'
+  Enabled: true
+
+MultilineBlockChain:
+  Description: 'Avoid multi-line chains of blocks.'
+  Enabled: true
+
+MultilineIfThen:
+  Description: 'Never use then for multi-line if/unless.'
+  Enabled: true
+
+MultilineTernaryOperator:
+  Description: >-
+                 Avoid multi-line ?: (the ternary operator);
+                 use if/unless instead.
+  Enabled: true
+
+NegatedIf:
+  Description: >-
+                 Favor unless over if for negative conditions
+                 (or control flow or).
+  Enabled: true
+
+NegatedWhile:
+  Description: 'Favor until over while for negative conditions.'
+  Enabled: true
+
+NestedTernaryOperator:
+  Description: 'Use one expression per branch in a ternary operator.'
+  Enabled: true
+
+NilComparison:
+  Description: 'Prefer x.nil? to x == nil.'
+  Enabled: true
+
+NonNilCheck:
+  Description: 'Checks for redundant nil checks.'
+  Enabled: true
+
+Not:
+  Description: 'Use ! instead of not.'
+  Enabled: true
+
+NumericLiterals:
+  Description: >-
+                 Add underscores to large numeric literals to improve their
+                 readability.
+  Enabled: true
+
+OneLineConditional:
+  Description: >-
+                 Favor the ternary operator(?:) over
+                 if/then/else/end constructs.
+  Enabled: true
+
+OpMethod:
+  Description: 'When defining binary operators, name the argument other.'
+  Enabled: true
+
+ParameterLists:
+  Description: 'Avoid parameter lists longer than three or four parameters.'
+  Enabled: true
+
+ParenthesesAroundCondition:
+  Description: >-
+                 Don't use parentheses around the condition of an
+                 if/unless/while.
+  Enabled: true
+
+PercentLiteralDelimiters:
+  Description: 'Use `%`-literal delimiters consistently'
+  Enabled: true
+
+PerlBackrefs:
+  Description: 'Avoid Perl-style regex back references.'
+  Enabled: true
+
+PredicateName:
+  Description: 'Check the names of predicate methods.'
+  Enabled: true
+
+Proc:
+  Description: 'Use proc instead of Proc.new.'
+  Enabled: true
+
+RaiseArgs:
+  Description: 'Checks the arguments passed to raise/fail.'
+  Enabled: true
+
+RedundantBegin:
+  Description: "Don't use begin blocks when they are not needed."
+  Enabled: true
+
+RedundantException:
+  Description: "Checks for an obsolete RuntimeException argument in raise/fail."
+  Enabled: true
+
+RedundantReturn:
+  Description: "Don't use return where it's not required."
+  Enabled: true
+
+RedundantSelf:
+  Description: "Don't use self where it's not needed."
+  Enabled: true
+
+RegexpLiteral:
+  Description: >-
+                 Use %r for regular expressions matching more than
+                 `MaxSlashes` '/' characters.
+                 Use %r only for regular expressions matching more than
+                 `MaxSlashes` '/' character.
+  Enabled: true
+
+RescueModifier:
+  Description: 'Avoid using rescue in its modifier form.'
+  Enabled: true
+
+SelfAssignment:
+  Description: 'Checks for places where self-assignment shorthand should have been used.'
+  Enabled: true
+
+Semicolon:
+  Description: "Don't use semicolons to terminate expressions."
+  Enabled: true
+
+SignalException:
+  Description: 'Checks for proper usage of fail and raise.'
+  Enabled: true
+
+SingleLineBlockParams:
+  Description: 'Enforces the names of some block params.'
+  Enabled: true
+
+SingleLineMethods:
+  Description: 'Avoid single-line methods.'
+  Enabled: true
+
+SingleSpaceBeforeFirstArg:
+  Description: >-
+                 Checks that exactly one space is used between a method name
+                 and the first argument for method calls without parentheses.
+  Enabled: true
+
+SpaceAfterColon:
+  Description: 'Use spaces after colons.'
+  Enabled: true
+
+SpaceAfterComma:
+  Description: 'Use spaces after commas.'
+  Enabled: true
+
+SpaceAfterControlKeyword:
+  Description: 'Use spaces after if/elsif/unless/while/until/case/when.'
+  Enabled: true
+
+SpaceAfterMethodName:
+  Description: >-
+                 Never put a space between a method name and the opening
+                 parenthesis in a method definition.
+  Enabled: true
+
+SpaceAfterNot:
+  Description: Tracks redundant space after the ! operator.
+  Enabled: true
+
+SpaceAfterSemicolon:
+  Description: 'Use spaces after semicolons.'
+  Enabled: true
+
+SpaceBeforeBlockBraces:
+  Description: >-
+                 Checks that the left block brace has or doesn't have space
+                 before it.
+  Enabled: true
+
+SpaceInsideBlockBraces:
+  Description: >-
+                 Checks that block braces have or don't have surrounding space.
+                 For blocks taking parameters, checks that the left brace has
+                 or doesn't have trailing space.
+  Enabled: true
+
+SpaceAroundEqualsInParameterDefault:
+  Description: >-
+                 Checks that the equals signs in parameter default assignments
+                 have or don't have surrounding space depending on
+                 configuration.
+  Enabled: true
+
+SpaceAroundOperators:
+  Description: 'Use spaces around operators.'
+  Enabled: true
+
+SpaceBeforeModifierKeyword:
+  Description: 'Put a space before the modifier keyword.'
+  Enabled: true
+
+SpaceInsideBrackets:
+  Description: 'No spaces after [ or before ].'
+  Enabled: true
+
+SpaceInsideHashLiteralBraces:
+  Description: "Use spaces inside hash literal braces - or don't."
+  Enabled: true
+
+SpaceInsideParens:
+  Description: 'No spaces after ( or before ).'
+  Enabled: true
+
+SpecialGlobalVars:
+  Description: 'Avoid Perl-style global variables.'
+  Enabled: true
+
+StringLiterals:
+  Description: 'Checks if uses of quotes match the configured preference.'
+  Enabled: true
+
+Tab:
+  Description: 'No hard tabs.'
+  Enabled: true
+
+TrailingBlankLines:
+  Description: 'Checks for superfluous trailing blank lines.'
+  Enabled: true
+
+TrailingComma:
+  Description: 'Checks for trailing comma in parameter lists and literals.'
+  Enabled: true
+
+TrailingWhitespace:
+  Description: 'Avoid trailing whitespace.'
+  Enabled: true
+
+TrivialAccessors:
+  Description: 'Prefer attr_* methods to trivial readers/writers.'
+  Enabled: true
+
+UnlessElse:
+  Description: >-
+                 Never use unless with else. Rewrite these with the positive
+                 case first.
+  Enabled: true
+
+VariableInterpolation:
+  Description: >-
+                 Don't interpolate global, instance and class variables
+                 directly in strings.
+  Enabled: true
+
+VariableName:
+  Description: 'Use the configured style when naming variables.'
+  Enabled: true
+
+WhenThen:
+  Description: 'Use when x then ... for one-line cases.'
+  Enabled: true
+
+WhileUntilDo:
+  Description: 'Checks for redundant do after while or until.'
+  Enabled: true
+
+WhileUntilModifier:
+  Description: >-
+                 Favor modifier while/until usage when you have a
+                 single-line body.
+  Enabled: true
+
+WordArray:
+  Description: 'Use %w or %W for arrays of words.'
+  Enabled: true
+
+#################### Lint ################################
+### Warnings
+
+AmbiguousOperator:
+  Description: >-
+                 Checks for ambiguous operators in the first argument of a
+                 method invocation without parentheses.
+  Enabled: true
+
+AmbiguousRegexpLiteral:
+  Description: >-
+                 Checks for ambiguous regexp literals in the first argument of
+                 a method invocation without parenthesis.
+  Enabled: true
+
+AssignmentInCondition:
+  Description: "Don't use assignment in conditions."
+  Enabled: true
+
+BlockAlignment:
+  Description: 'Align block ends correctly.'
+  Enabled: true
+
+ConditionPosition:
+  Description: 'Checks for condition placed in a confusing position relative to the keyword.'
+  Enabled: true
+
+Debugger:
+  Description: 'Check for debugger calls.'
+  Enabled: true
+
+DeprecatedClassMethods:
+  Description: 'Check for deprecated class method calls.'
+  Enabled: true
+
+ElseLayout:
+  Description: 'Check for odd code arrangement in an else block.'
+  Enabled: true
+
+EmptyEnsure:
+  Description: 'Checks for empty ensure block.'
+  Enabled: true
+
+EmptyInterpolation:
+  Description: 'Checks for empty string interpolation.'
+  Enabled: true
+
+EndAlignment:
+  Description: 'Align ends correctly.'
+  Enabled: true
+
+EndInMethod:
+  Description: 'END blocks should not be placed inside method definitions.'
+  Enabled: true
+
+EnsureReturn:
+  Description: 'Never use return in an ensure block.'
+  Enabled: true
+
+Eval:
+  Description: 'The use of eval represents a serious security risk.'
+  Enabled: true
+
+HandleExceptions:
+  Description: "Don't suppress exception."
+  Enabled: true
+
+InvalidCharacterLiteral:
+  Description: >-
+                 Checks for invalid character literals with a non-escaped
+                 whitespace character.
+  Enabled: true
+
+LiteralInCondition:
+  Description: 'Checks of literals used in conditions.'
+  Enabled: true
+
+LiteralInInterpolation:
+  Description: 'Checks for literals used in interpolation.'
+  Enabled: true
+
+Loop:
+  Description: >-
+                 Use Kernel#loop with break rather than begin/end/until or
+                 begin/end/while for post-loop tests.
+  Enabled: true
+
+ParenthesesAsGroupedExpression:
+  Description: >-
+                 Checks for method calls with a space before the opening
+                 parenthesis.
+  Enabled: true
+
+RequireParentheses:
+  Description: >-
+                 Use parentheses in the method call to avoid confusion
+                 about precedence.
+  Enabled: true
+
+RescueException:
+  Description: 'Avoid rescuing the Exception class.'
+  Enabled: true
+
+ShadowingOuterLocalVariable:
+  Description: >-
+                 Do not use the same name as outer local variable
+                 for block arguments or block local variables.
+  Enabled: true
+
+SpaceBeforeFirstArg:
+  Description: >-
+                 Put a space between a method name and the first argument
+                 in a method call wihtout parentheses.
+  Enabled: true
+
+StringConversionInInterpolation:
+  Description: 'Checks for Object#to_s usage in string interpolation.'
+  Enabled: true
+
+UnreachableCode:
+  Description: 'Unreachable code.'
+  Enabled: true
+
+UselessAccessModifier:
+  Description: 'Checks for useless access modifiers.'
+  Enabled: true
+
+UselessAssignment:
+  Description: 'Checks for useless assignment to a local variable.'
+  Enabled: true
+
+UselessComparison:
+  Description: 'Checks for comparison of something with itself.'
+  Enabled: true
+
+UselessElseWithoutRescue:
+  Description: 'Checks for useless `else` in `begin..end` without `rescue`.'
+  Enabled: true
+
+UselessSetterCall:
+  Description: 'Checks for useless setter call to a local variable.'
+  Enabled: true
+
+Void:
+  Description: 'Possible use of operator/literal/variable in void context.'
+  Enabled: true
+
+##################### Rails ##################################
+
+ActionFilter:
+  Description: 'Enforces consistent use of action filter methods.'
+  Enabled: true
+
+DefaultScope:
+  Description: 'Checks if the argument passed to default_scope is a block.'
+  Enabled: true
+
+HasAndBelongsToMany:
+  Description: 'Prefer has_many :through to has_and_belongs_to_many.'
+  Enabled: true
+
+Output:
+  Description: 'Checks for calls to puts, print, etc.'
+  Enabled: true
+
+ReadWriteAttribute:
+  Description: 'Checks for read_attribute(:attr) and write_attribute(:attr, val).'
+  Enabled: true
+
+ScopeArgs:
+  Description: 'Checks the arguments of ActiveRecord scopes.'
+  Enabled: true
+
+Validation:
+  Description: 'Use sexy validations.'
+  Enabled: true
diff --git a/lib/rubocop.rb b/lib/rubocop.rb
new file mode 100644
index 0000000..0caaf40
--- /dev/null
+++ b/lib/rubocop.rb
@@ -0,0 +1,262 @@
+# encoding: utf-8
+
+# Try to load the latest parser and fall back to the latest supported version,
+# if parser does not yet support the current Ruby version.
+# This should only be problem when using development Ruby builds.
+begin
+  require 'parser/current'
+rescue NotImplementedError => error
+  warn "Falling back to Ruby 2.1 parser: #{error.message}"
+  require 'parser/ruby21'
+  Parser::CurrentRuby = Parser::Ruby21
+end
+
+require 'rainbow'
+# Rainbow 2.0 does not load the monkey-patch for String by default.
+require 'rainbow/ext/string' unless String.method_defined?(:color)
+
+require 'English'
+require 'set'
+require 'ast/sexp'
+require 'powerpack/enumerable/drop_last'
+require 'powerpack/hash/symbolize_keys'
+require 'powerpack/string/blank'
+require 'powerpack/string/strip_indent'
+
+require 'rubocop/version'
+
+require 'rubocop/path_util'
+
+require 'rubocop/cop/util'
+require 'rubocop/cop/offense'
+require 'rubocop/cop/ignored_node'
+require 'rubocop/cop/cop'
+require 'rubocop/cop/commissioner'
+require 'rubocop/cop/corrector'
+require 'rubocop/cop/team'
+require 'rubocop/cop/severity'
+
+require 'rubocop/cop/variable_inspector'
+require 'rubocop/cop/variable_inspector/locatable'
+require 'rubocop/cop/variable_inspector/variable'
+require 'rubocop/cop/variable_inspector/assignment'
+require 'rubocop/cop/variable_inspector/reference'
+require 'rubocop/cop/variable_inspector/scope'
+require 'rubocop/cop/variable_inspector/variable_table'
+
+require 'rubocop/cop/mixin/annotation_comment'
+require 'rubocop/cop/mixin/array_syntax'
+require 'rubocop/cop/mixin/autocorrect_alignment'
+require 'rubocop/cop/mixin/autocorrect_unless_changing_ast'
+require 'rubocop/cop/mixin/check_assignment'
+require 'rubocop/cop/mixin/check_methods'
+require 'rubocop/cop/mixin/configurable_max'
+require 'rubocop/cop/mixin/code_length'
+require 'rubocop/cop/mixin/configurable_enforced_style'
+require 'rubocop/cop/mixin/configurable_naming'
+require 'rubocop/cop/mixin/if_node'
+require 'rubocop/cop/mixin/if_then_else'
+require 'rubocop/cop/mixin/negative_conditional'
+require 'rubocop/cop/mixin/parser_diagnostic'
+require 'rubocop/cop/mixin/safe_assignment'
+require 'rubocop/cop/mixin/surrounding_space'
+require 'rubocop/cop/mixin/space_inside'
+require 'rubocop/cop/mixin/space_after_punctuation'
+require 'rubocop/cop/mixin/statement_modifier'
+require 'rubocop/cop/mixin/string_help'
+
+require 'rubocop/cop/lint/ambiguous_operator'
+require 'rubocop/cop/lint/ambiguous_regexp_literal'
+require 'rubocop/cop/lint/assignment_in_condition'
+require 'rubocop/cop/lint/block_alignment'
+require 'rubocop/cop/lint/condition_position'
+require 'rubocop/cop/lint/debugger'
+require 'rubocop/cop/lint/deprecated_class_methods'
+require 'rubocop/cop/lint/else_layout'
+require 'rubocop/cop/lint/empty_ensure'
+require 'rubocop/cop/lint/empty_interpolation'
+require 'rubocop/cop/lint/end_alignment'
+require 'rubocop/cop/lint/end_in_method'
+require 'rubocop/cop/lint/ensure_return'
+require 'rubocop/cop/lint/eval'
+require 'rubocop/cop/lint/handle_exceptions'
+require 'rubocop/cop/lint/invalid_character_literal'
+require 'rubocop/cop/lint/literal_in_condition'
+require 'rubocop/cop/lint/literal_in_interpolation'
+require 'rubocop/cop/lint/loop'
+require 'rubocop/cop/lint/parentheses_as_grouped_expression'
+require 'rubocop/cop/lint/require_parentheses'
+require 'rubocop/cop/lint/rescue_exception'
+require 'rubocop/cop/lint/shadowing_outer_local_variable'
+require 'rubocop/cop/lint/space_before_first_arg'
+require 'rubocop/cop/lint/string_conversion_in_interpolation'
+require 'rubocop/cop/lint/syntax'
+require 'rubocop/cop/lint/unreachable_code'
+require 'rubocop/cop/lint/useless_access_modifier'
+require 'rubocop/cop/lint/useless_assignment'
+require 'rubocop/cop/lint/useless_comparison'
+require 'rubocop/cop/lint/useless_else_without_rescue'
+require 'rubocop/cop/lint/useless_setter_call'
+require 'rubocop/cop/lint/void'
+
+require 'rubocop/cop/style/access_modifier_indentation'
+require 'rubocop/cop/style/accessor_method_name'
+require 'rubocop/cop/style/alias'
+require 'rubocop/cop/style/align_array'
+require 'rubocop/cop/style/align_hash'
+require 'rubocop/cop/style/align_parameters'
+require 'rubocop/cop/style/and_or'
+require 'rubocop/cop/style/array_join'
+require 'rubocop/cop/style/ascii_comments'
+require 'rubocop/cop/style/ascii_identifiers'
+require 'rubocop/cop/style/attr'
+require 'rubocop/cop/style/begin_block'
+require 'rubocop/cop/style/block_comments'
+require 'rubocop/cop/style/block_nesting'
+require 'rubocop/cop/style/blocks'
+require 'rubocop/cop/style/braces_around_hash_parameters'
+require 'rubocop/cop/style/case_equality'
+require 'rubocop/cop/style/case_indentation'
+require 'rubocop/cop/style/character_literal'
+require 'rubocop/cop/style/class_and_module_camel_case'
+require 'rubocop/cop/style/class_and_module_children'
+require 'rubocop/cop/style/class_length'
+require 'rubocop/cop/style/class_methods'
+require 'rubocop/cop/style/class_vars'
+require 'rubocop/cop/style/collection_methods'
+require 'rubocop/cop/style/colon_method_call'
+require 'rubocop/cop/style/comment_annotation'
+require 'rubocop/cop/style/constant_name'
+require 'rubocop/cop/style/cyclomatic_complexity'
+require 'rubocop/cop/style/def_with_parentheses'
+require 'rubocop/cop/style/deprecated_hash_methods'
+require 'rubocop/cop/style/documentation'
+require 'rubocop/cop/style/dot_position'
+require 'rubocop/cop/style/double_negation'
+require 'rubocop/cop/style/empty_line_between_defs'
+require 'rubocop/cop/style/empty_lines'
+require 'rubocop/cop/style/empty_lines_around_access_modifier'
+require 'rubocop/cop/style/empty_lines_around_body'
+require 'rubocop/cop/style/empty_literal'
+require 'rubocop/cop/style/encoding'
+require 'rubocop/cop/style/end_block'
+require 'rubocop/cop/style/end_of_line'
+require 'rubocop/cop/style/even_odd'
+require 'rubocop/cop/style/file_name'
+require 'rubocop/cop/style/final_newline'
+require 'rubocop/cop/style/flip_flop'
+require 'rubocop/cop/style/for'
+require 'rubocop/cop/style/format_string'
+require 'rubocop/cop/style/global_vars'
+require 'rubocop/cop/style/guard_clause'
+require 'rubocop/cop/style/hash_syntax'
+require 'rubocop/cop/style/if_unless_modifier'
+require 'rubocop/cop/style/if_with_semicolon'
+require 'rubocop/cop/style/indent_array'
+require 'rubocop/cop/style/indent_hash'
+require 'rubocop/cop/style/indentation_consistency'
+require 'rubocop/cop/style/indentation_width'
+require 'rubocop/cop/style/lambda'
+require 'rubocop/cop/style/lambda_call'
+require 'rubocop/cop/style/leading_comment_space'
+require 'rubocop/cop/style/line_end_concatenation'
+require 'rubocop/cop/style/line_length'
+require 'rubocop/cop/style/method_call_parentheses'
+require 'rubocop/cop/style/method_called_on_do_end_block'
+require 'rubocop/cop/style/method_def_parentheses'
+require 'rubocop/cop/style/method_length'
+require 'rubocop/cop/style/method_name'
+require 'rubocop/cop/style/module_function'
+require 'rubocop/cop/style/multiline_block_chain'
+require 'rubocop/cop/style/multiline_if_then'
+require 'rubocop/cop/style/multiline_ternary_operator'
+require 'rubocop/cop/style/negated_if'
+require 'rubocop/cop/style/negated_while'
+require 'rubocop/cop/style/nested_ternary_operator'
+require 'rubocop/cop/style/nil_comparison'
+require 'rubocop/cop/style/non_nil_check'
+require 'rubocop/cop/style/not'
+require 'rubocop/cop/style/numeric_literals'
+require 'rubocop/cop/style/one_line_conditional'
+require 'rubocop/cop/style/op_method'
+require 'rubocop/cop/style/parameter_lists'
+require 'rubocop/cop/style/parentheses_around_condition'
+require 'rubocop/cop/style/percent_literal_delimiters'
+require 'rubocop/cop/style/perl_backrefs'
+require 'rubocop/cop/style/predicate_name'
+require 'rubocop/cop/style/proc'
+require 'rubocop/cop/style/raise_args'
+require 'rubocop/cop/style/redundant_begin'
+require 'rubocop/cop/style/redundant_exception'
+require 'rubocop/cop/style/redundant_return'
+require 'rubocop/cop/style/redundant_self'
+require 'rubocop/cop/style/regexp_literal'
+require 'rubocop/cop/style/rescue_modifier'
+require 'rubocop/cop/style/self_assignment'
+require 'rubocop/cop/style/semicolon'
+require 'rubocop/cop/style/signal_exception'
+require 'rubocop/cop/style/single_line_block_params'
+require 'rubocop/cop/style/single_line_methods'
+require 'rubocop/cop/style/single_space_before_first_arg'
+require 'rubocop/cop/style/space_after_colon'
+require 'rubocop/cop/style/space_after_comma'
+require 'rubocop/cop/style/space_after_control_keyword'
+require 'rubocop/cop/style/space_after_method_name'
+require 'rubocop/cop/style/space_after_not'
+require 'rubocop/cop/style/space_after_semicolon'
+require 'rubocop/cop/style/space_around_equals_in_parameter_default'
+require 'rubocop/cop/style/space_around_operators'
+require 'rubocop/cop/style/space_before_block_braces'
+require 'rubocop/cop/style/space_before_modifier_keyword'
+require 'rubocop/cop/style/space_inside_block_braces'
+require 'rubocop/cop/style/space_inside_brackets'
+require 'rubocop/cop/style/space_inside_hash_literal_braces'
+require 'rubocop/cop/style/space_inside_parens'
+require 'rubocop/cop/style/special_global_vars'
+require 'rubocop/cop/style/string_literals'
+require 'rubocop/cop/style/symbol_array'
+require 'rubocop/cop/style/tab'
+require 'rubocop/cop/style/trailing_blank_lines'
+require 'rubocop/cop/style/trailing_comma'
+require 'rubocop/cop/style/trailing_whitespace'
+require 'rubocop/cop/style/trivial_accessors'
+require 'rubocop/cop/style/unless_else'
+require 'rubocop/cop/style/variable_interpolation'
+require 'rubocop/cop/style/variable_name'
+require 'rubocop/cop/style/when_then'
+require 'rubocop/cop/style/while_until_do'
+require 'rubocop/cop/style/while_until_modifier'
+require 'rubocop/cop/style/word_array'
+
+require 'rubocop/cop/rails/action_filter'
+require 'rubocop/cop/rails/default_scope'
+require 'rubocop/cop/rails/has_and_belongs_to_many'
+require 'rubocop/cop/rails/output'
+require 'rubocop/cop/rails/read_write_attribute'
+require 'rubocop/cop/rails/scope_args'
+require 'rubocop/cop/rails/validation'
+
+require 'rubocop/formatter/base_formatter'
+require 'rubocop/formatter/simple_text_formatter'
+require 'rubocop/formatter/disabled_lines_formatter'
+require 'rubocop/formatter/disabled_config_formatter'
+require 'rubocop/formatter/emacs_style_formatter'
+require 'rubocop/formatter/clang_style_formatter'
+require 'rubocop/formatter/progress_formatter'
+require 'rubocop/formatter/fuubar_style_formatter'
+require 'rubocop/formatter/json_formatter'
+require 'rubocop/formatter/file_list_formatter'
+require 'rubocop/formatter/offense_count_formatter'
+require 'rubocop/formatter/formatter_set'
+
+require 'rubocop/config'
+require 'rubocop/config_loader'
+require 'rubocop/config_store'
+require 'rubocop/target_finder'
+require 'rubocop/token'
+require 'rubocop/comment_config'
+require 'rubocop/processed_source'
+require 'rubocop/source_parser'
+require 'rubocop/file_inspector'
+require 'rubocop/cli'
+require 'rubocop/options'
diff --git a/lib/rubocop/cli.rb b/lib/rubocop/cli.rb
new file mode 100644
index 0000000..dba81aa
--- /dev/null
+++ b/lib/rubocop/cli.rb
@@ -0,0 +1,109 @@
+# encoding: utf-8
+
+module Rubocop
+  # The CLI is a class responsible of handling all the command line interface
+  # logic.
+  class CLI
+    # If set true while running,
+    # RuboCop will abort processing and exit gracefully.
+    attr_accessor :wants_to_quit
+    attr_reader :options, :config_store
+
+    alias_method :wants_to_quit?, :wants_to_quit
+
+    def initialize
+      @options = {}
+      @config_store = ConfigStore.new
+    end
+
+    # Entry point for the application logic. Here we
+    # do the command line arguments processing and inspect
+    # the target files
+    # @return [Fixnum] UNIX exit code
+    def run(args = ARGV)
+      trap_interrupt
+
+      @options, remaining_args = Options.new.parse(args)
+      act_on_options(remaining_args)
+      target_files = target_finder.find(remaining_args)
+
+      inspector = FileInspector.new(@options)
+      any_failed = inspector.process_files(target_files, @config_store) do
+        wants_to_quit?
+      end
+      inspector.display_error_summary
+
+      !any_failed && !wants_to_quit ? 0 : 1
+    rescue => e
+      $stderr.puts e.message
+      $stderr.puts e.backtrace
+      return 1
+    end
+
+    def trap_interrupt
+      Signal.trap('INT') do
+        exit!(1) if wants_to_quit?
+        self.wants_to_quit = true
+        $stderr.puts
+        $stderr.puts 'Exiting... Interrupt again to exit immediately.'
+      end
+    end
+
+    private
+
+    def act_on_options(args)
+      handle_exiting_options
+
+      ConfigLoader.debug = @options[:debug]
+      ConfigLoader.auto_gen_config = @options[:auto_gen_config]
+
+      @config_store.options_config = @options[:config] if @options[:config]
+
+      Rainbow.enabled = false unless @options[:color]
+    end
+
+    def handle_exiting_options
+      return unless Options::EXITING_OPTIONS.any? { |o| @options.key? o }
+
+      puts Rubocop::Version.version(false) if @options[:version]
+      puts Rubocop::Version.version(true) if @options[:verbose_version]
+      print_available_cops if @options[:show_cops]
+      exit(0)
+    end
+
+    def print_available_cops
+      cops = Cop::Cop.all
+      show_all = @options[:show_cops].empty?
+
+      if show_all
+        puts "# Available cops (#{cops.length}) + config for #{Dir.pwd}: "
+      end
+
+      cops.types.sort!.each { |type| print_cops_of_type(cops, type, show_all) }
+    end
+
+    def print_cops_of_type(cops, type, show_all)
+      cops_of_this_type = cops.with_type(type).sort_by!(&:cop_name)
+
+      if show_all
+        puts "# Type '#{type.to_s.capitalize}' (#{cops_of_this_type.size}):"
+      end
+
+      selected_cops = cops_of_this_type.select do |cop|
+        show_all || @options[:show_cops].include?(cop.cop_name)
+      end
+
+      selected_cops.each do |cop|
+        puts '# Supports --auto-correct' if cop.new.support_autocorrect?
+        puts "#{cop.cop_name}:"
+        cnf = @config_store.for(Dir.pwd.to_s).for_cop(cop)
+        puts cnf.to_yaml.lines.to_a[1..-1].map { |line| '  ' + line }
+        puts
+      end
+    end
+
+    def target_finder
+      @target_finder ||= TargetFinder.new(@config_store, @options)
+    end
+  end
+end
diff --git a/lib/rubocop/comment_config.rb b/lib/rubocop/comment_config.rb
new file mode 100644
index 0000000..02bf7f7
--- /dev/null
+++ b/lib/rubocop/comment_config.rb
@@ -0,0 +1,99 @@
+# encoding: utf-8
+
+module Rubocop
+  # This class parses the special `rubocop:disable` comments in a source
+  # and provides a way to check if each cop is enabled at arbitrary line.
+  class CommentConfig
+    COMMENT_DIRECTIVE_REGEXP = Regexp.new(
+      '\A# rubocop : ((?:dis|en)able)\b ((?:\w+,? )+)'.gsub(' ', '\s*')
+    )
+
+    attr_reader :processed_source
+
+    def initialize(processed_source)
+      @processed_source = processed_source
+    end
+
+    def cop_enabled_at_line?(cop, line_number)
+      cop = cop.cop_name if cop.respond_to?(:cop_name)
+      disabled_line_ranges = cop_disabled_line_ranges[cop]
+      disabled_line_ranges.none? { |range| range.include?(line_number) }
+    end
+
+    def cop_disabled_line_ranges
+      @cop_disabled_line_ranges ||= analyze
+    end
+
+    private
+
+    def analyze
+      disabled_line_ranges = Hash.new { |hash, key| hash[key] = [] }
+      disablement_start_line_numbers = {}
+
+      each_mentioned_cop do |cop_name, disabled, line, single_line|
+        if single_line
+          next unless disabled
+          disabled_line_ranges[cop_name] << (line..line)
+        else
+          if disabled
+            disablement_start_line_numbers[cop_name] = line
+          else
+            start_line = disablement_start_line_numbers.delete(cop_name)
+            next unless start_line
+            disabled_line_ranges[cop_name] << (start_line..line)
+          end
+        end
+      end
+
+      disablement_start_line_numbers.each do |cop_name, start_line|
+        disabled_line_ranges[cop_name] << (start_line..Float::INFINITY)
+      end
+
+      disabled_line_ranges
+    end
+
+    def each_mentioned_cop
+      all_cop_names = nil # For performance improvement
+
+      return if processed_source.comments.nil?
+
+      processed_source.comments.each do |comment|
+        match = comment.text.match(COMMENT_DIRECTIVE_REGEXP)
+        next unless match
+
+        switch, cops_string = match.captures
+
+        if cops_string == 'all'
+          all_cop_names ||= Cop::Cop.all.map(&:cop_name)
+          cop_names = all_cop_names
+        else
+          cop_names = cops_string.split(/,\s*/)
+        end
+
+        disabled = (switch == 'disable')
+        comment_line_number = comment.loc.expression.line
+        single_line = !comment_only_line?(comment_line_number)
+
+        cop_names.each do |cop_name|
+          yield cop_name, disabled, comment_line_number, single_line
+        end
+      end
+    end
+
+    def comment_only_line?(line_number)
+      non_comment_token_line_numbers.none? do |non_comment_line_number|
+        non_comment_line_number == line_number
+      end
+    end
+
+    def non_comment_token_line_numbers
+      @non_comment_token_line_numbers ||= begin
+        non_comment_tokens = processed_source.tokens.reject do |token|
+          token.type == :tCOMMENT
+        end
+
+        non_comment_tokens.map { |token| token.pos.line }.uniq
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/config.rb b/lib/rubocop/config.rb
new file mode 100644
index 0000000..bfa9d33
--- /dev/null
+++ b/lib/rubocop/config.rb
@@ -0,0 +1,106 @@
+# encoding: utf-8
+
+require 'delegate'
+require 'pathname'
+
+module Rubocop
+  # This class represents the configuration of the RuboCop application
+  # and all its cops. A Config is associated with a YAML configuration
+  # file from which it was read. Several different Configs can be used
+  # during a run of the rubocop program, if files in several
+  # directories are inspected.
+  class Config < DelegateClass(Hash)
+    include PathUtil
+
+    class ValidationError < StandardError; end
+
+    COMMON_PARAMS = %w(Exclude Include Severity)
+
+    attr_reader :loaded_path
+
+    def initialize(hash = {}, loaded_path = nil)
+      @hash = hash
+      @loaded_path = loaded_path
+      super(@hash)
+    end
+
+    def for_cop(cop)
+      cop = cop.cop_name if cop.respond_to?(:cop_name)
+      self[cop]
+    end
+
+    def cop_enabled?(cop)
+      for_cop(cop).nil? || for_cop(cop)['Enabled']
+    end
+
+    def warn_unless_valid
+      validate
+    rescue Config::ValidationError => e
+      warn "Warning: #{e.message}".color(:red)
+    end
+
+    # TODO: This should be a private method
+    def validate
+      # Don't validate RuboCop's own files. Avoids inifinite recursion.
+      return if @loaded_path.start_with?(ConfigLoader::RUBOCOP_HOME)
+
+      default_config = ConfigLoader.default_configuration
+
+      valid_cop_names, invalid_cop_names = @hash.keys.partition do |key|
+        default_config.key?(key)
+      end
+
+      invalid_cop_names.each do |name|
+        fail ValidationError,
+             "unrecognized cop #{name} found in #{loaded_path || self}"
+      end
+
+      valid_cop_names.each do |name|
+        @hash[name].each_key do |param|
+          unless COMMON_PARAMS.include?(param) ||
+                 default_config[name].key?(param)
+            fail ValidationError,
+                 "unrecognized parameter #{name}:#{param} found " \
+                 "in #{loaded_path || self}"
+          end
+        end
+      end
+    end
+
+    def file_to_include?(file)
+      relative_file_path = path_relative_to_config(file)
+      patterns_to_include.any? do |pattern|
+        match_path?(pattern, relative_file_path)
+      end
+    end
+
+    def file_to_exclude?(file)
+      file = File.join(Dir.pwd, file) unless file.start_with?('/')
+      patterns_to_exclude.any? { |pattern| match_path?(pattern, file) }
+    end
+
+    def patterns_to_include
+      @hash['AllCops']['Include']
+    end
+
+    def patterns_to_exclude
+      @hash['AllCops']['Exclude']
+    end
+
+    def path_relative_to_config(path)
+      relative_path(path, base_dir_for_path_parameters)
+    end
+
+    # Paths specified in .rubocop.yml files are relative to the directory where
+    # that file is. Paths in other config files are relative to the current
+    # directory. This is so that paths in config/default.yml, for example, are
+    # not relative to RuboCop's config directory since that wouldn't work.
+    def base_dir_for_path_parameters
+      if File.basename(loaded_path) == ConfigLoader::DOTFILE
+        File.dirname(loaded_path)
+      else
+        Dir.pwd
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/config_loader.rb b/lib/rubocop/config_loader.rb
new file mode 100644
index 0000000..90f3980
--- /dev/null
+++ b/lib/rubocop/config_loader.rb
@@ -0,0 +1,161 @@
+# encoding: utf-8
+
+require 'yaml'
+require 'pathname'
+
+module Rubocop
+  # This class represents the configuration of the RuboCop application
+  # and all its cops. A Config is associated with a YAML configuration
+  # file from which it was read. Several different Configs can be used
+  # during a run of the rubocop program, if files in several
+  # directories are inspected.
+  class ConfigLoader
+    DOTFILE = '.rubocop.yml'
+    RUBOCOP_HOME = File.realpath(File.join(File.dirname(__FILE__), '..', '..'))
+    DEFAULT_FILE = File.join(RUBOCOP_HOME, 'config', 'default.yml')
+    AUTO_GENERATED_FILE = 'rubocop-todo.yml'
+
+    class << self
+      attr_accessor :debug, :auto_gen_config
+      attr_writer :root_level # The upwards search is stopped at this level.
+
+      alias_method :debug?, :debug
+      alias_method :auto_gen_config?, :auto_gen_config
+
+      def load_file(path)
+        path = File.absolute_path(path)
+        hash = YAML.load_file(path) || {}
+        puts "configuration from #{path}" if debug?
+
+        resolve_inheritance(path, hash)
+
+        hash.delete('inherit_from')
+        config = Config.new(hash, path)
+        deprecation_check(config)
+        config.warn_unless_valid
+        make_excludes_absolute(config)
+        config
+      end
+
+      def deprecation_check(config)
+        return unless config['AllCops']
+        if config['AllCops']['Excludes']
+          warn('AllCops/Excludes was renamed to AllCops/Exclude')
+          exit(-1)
+        elsif config['AllCops']['Includes']
+          warn('AllCops/Includes was renamed to AllCops/Include')
+          exit(-1)
+        end
+      end
+
+      def make_excludes_absolute(config)
+        if config['AllCops'] && config['AllCops']['Exclude']
+          config['AllCops']['Exclude'].map! do |exclude_elem|
+            if exclude_elem.is_a?(String) && !exclude_elem.start_with?('/')
+              File.join(config.base_dir_for_path_parameters, exclude_elem)
+            else
+              exclude_elem
+            end
+          end
+        end
+      end
+
+      # Return a recursive merge of two hashes. That is, a normal hash merge,
+      # with the addition that any value that is a hash, and occurs in both
+      # arguments, will also be merged. And so on.
+      def merge(base_hash, derived_hash)
+        result = base_hash.merge(derived_hash)
+        keys_appearing_in_both = base_hash.keys & derived_hash.keys
+        keys_appearing_in_both.each do |key|
+          if base_hash[key].is_a?(Hash)
+            result[key] = merge(base_hash[key], derived_hash[key])
+          end
+        end
+        result
+      end
+
+      def base_configs(path, inherit_from)
+        configs = Array(inherit_from).map do |f|
+          f = File.join(File.dirname(path), f) unless f.start_with?('/')
+          unless auto_gen_config? && f.include?(AUTO_GENERATED_FILE)
+            print 'Inheriting ' if debug?
+            load_file(f)
+          end
+        end
+
+        configs.compact
+      end
+
+      # Returns the path of .rubocop.yml searching upwards in the
+      # directory structure starting at the given directory where the
+      # inspected file is. If no .rubocop.yml is found there, the
+      # user's home directory is checked. If there's no .rubocop.yml
+      # there either, the path to the default file is returned.
+      def configuration_file_for(target_dir)
+        config_files_in_path(target_dir).first || DEFAULT_FILE
+      end
+
+      def configuration_from_file(config_file)
+        config = load_file(config_file)
+        return config if config_file == DEFAULT_FILE
+
+        found_files = config_files_in_path(config_file)
+        if found_files.any? && found_files.last != config_file
+          print 'AllCops/Exclude ' if debug?
+          add_excludes_from_higher_level(config, load_file(found_files.last))
+        end
+        merge_with_default(config, config_file)
+      end
+
+      def add_excludes_from_higher_level(config, highest_config)
+        if highest_config['AllCops'] && highest_config['AllCops']['Exclude']
+          config['AllCops'] ||= {}
+          excludes = config['AllCops']['Exclude'] ||= []
+          highest_config['AllCops']['Exclude'].each do |path|
+            unless path.is_a?(Regexp) || path.start_with?('/')
+              path = File.join(File.dirname(highest_config.loaded_path), path)
+            end
+            excludes << path unless excludes.include?(path)
+          end
+        end
+      end
+
+      def default_configuration
+        @default_configuration ||= begin
+                                     print 'Default ' if debug?
+                                     load_file(DEFAULT_FILE)
+                                   end
+      end
+
+      def merge_with_default(config, config_file)
+        Config.new(merge(default_configuration, config), config_file)
+      end
+
+      private
+
+      def resolve_inheritance(path, hash)
+        base_configs(path, hash['inherit_from']).reverse_each do |base_config|
+          base_config.each do |k, v|
+            hash[k] = hash.key?(k) ? merge(v, hash[k]) : v if v.is_a?(Hash)
+          end
+        end
+      end
+
+      def config_files_in_path(target)
+        possible_config_files = dirs_to_search(target).map do |dir|
+          File.join(dir, DOTFILE)
+        end
+        possible_config_files.select { |config_file| File.exist?(config_file) }
+      end
+
+      def dirs_to_search(target_dir)
+        dirs_to_search = []
+        Pathname.new(File.expand_path(target_dir)).ascend do |dir_pathname|
+          break if dir_pathname.to_s == @root_level
+          dirs_to_search << dir_pathname.to_s
+        end
+        dirs_to_search << Dir.home
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/config_store.rb b/lib/rubocop/config_store.rb
new file mode 100644
index 0000000..faa25cb
--- /dev/null
+++ b/lib/rubocop/config_store.rb
@@ -0,0 +1,45 @@
+# encoding: utf-8
+
+module Rubocop
+  # Handles caching of configurations and association of inspected
+  # ruby files to configurations.
+  class ConfigStore
+    def initialize
+      # @options_config stores a config that is specified in the command line.
+      # This takes precedence over configs located in any directories
+      @options_config = nil
+
+      # @path_cache maps directories to configuration paths. We search
+      # for .rubocop.yml only if we haven't already found it for the
+      # given directory.
+      @path_cache = {}
+
+      # @object_cache maps configuration file paths to
+      # configuration objects so we only need to load them once.
+      @object_cache = {}
+    end
+
+    def options_config=(options_config)
+      loaded_config = ConfigLoader.load_file(options_config)
+      ConfigLoader.make_excludes_absolute(loaded_config)
+      @options_config = ConfigLoader.merge_with_default(loaded_config,
+                                                        options_config)
+    end
+
+    def for(file_or_dir)
+      return @options_config if @options_config
+
+      dir = if File.directory?(file_or_dir)
+              file_or_dir
+            else
+              File.dirname(file_or_dir)
+            end
+      @path_cache[dir] ||= ConfigLoader.configuration_file_for(dir)
+      path = @path_cache[dir]
+      @object_cache[path] ||= begin
+                                print "For #{dir}: " if ConfigLoader.debug?
+                                ConfigLoader.configuration_from_file(path)
+                              end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/commissioner.rb b/lib/rubocop/cop/commissioner.rb
new file mode 100644
index 0000000..ffe0cbb
--- /dev/null
+++ b/lib/rubocop/cop/commissioner.rb
@@ -0,0 +1,105 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    # Commissioner class is responsible for processing the AST and delegating
+    # work to the specified cops.
+    class Commissioner < Parser::AST::Processor
+      attr_reader :errors
+
+      METHODS_NOT_DEFINED_IN_PARSER_PROCESSOR = [
+        :on_sym, :on_str, :on_int, :on_float
+      ]
+
+      def self.callback_methods
+        Parser::AST::Processor.instance_methods.select do |method|
+          method.to_s =~ /^on_/
+        end + METHODS_NOT_DEFINED_IN_PARSER_PROCESSOR
+      end
+
+      # Methods that are not defined in Parser::AST::Processor
+      # won't have a `super` to call. So we should not attempt
+      # to invoke `super` when defining them.
+      def self.call_super(callback)
+        if METHODS_NOT_DEFINED_IN_PARSER_PROCESSOR.include?(callback)
+          ''
+        else
+          'super'
+        end
+      end
+
+      def initialize(cops, options = {})
+        @cops = cops
+        @options = options
+        reset_errors
+      end
+
+      callback_methods.each do |callback|
+        class_eval <<-EOS
+          def #{callback}(node)
+            @cops.each do |cop|
+              next unless cop.respond_to?(:#{callback})
+              with_cop_error_handling(cop) do
+                cop.send(:#{callback}, node)
+              end
+            end
+
+            #{call_super(callback)}
+          end
+        EOS
+      end
+
+      def investigate(processed_source)
+        reset_errors
+        prepare(processed_source)
+        invoke_cops_callback(processed_source)
+        process(processed_source.ast) if processed_source.ast
+        @cops.each_with_object([]) do |cop, offenses|
+          filename = processed_source.buffer.name
+          # ignore files that are of no interest to the cop in question
+          offenses.concat(cop.offenses) if cop.relevant_file?(filename)
+        end
+      end
+
+      private
+
+      def reset_errors
+        @errors = Hash.new { |hash, k| hash[k] = [] }
+      end
+
+      # TODO: Bad design.
+      def prepare(processed_source)
+        @cops.each { |cop| cop.processed_source = processed_source }
+      end
+
+      # There are cops that require their own custom processing.
+      # If they define the #investigate method, all input parameters passed
+      # to the commissioner will be passed to the cop too in order to do
+      # its own processing.
+      def invoke_cops_callback(processed_source)
+        @cops.each do |cop|
+          next unless cop.respond_to?(:investigate)
+
+          filename = processed_source.buffer.name
+
+          # ignore files that are of no interest to the cop in question
+          next unless cop.relevant_file?(filename)
+
+          with_cop_error_handling(cop) do
+            cop.investigate(processed_source)
+          end
+        end
+      end
+
+      def with_cop_error_handling(cop)
+        yield
+      rescue => e
+        if @options[:raise_error]
+          raise e
+        else
+          @errors[cop] << e
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/cop.rb b/lib/rubocop/cop/cop.rb
new file mode 100644
index 0000000..603a01a
--- /dev/null
+++ b/lib/rubocop/cop/cop.rb
@@ -0,0 +1,192 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    # Store for all cops with helper functions
+    class CopStore < ::Array
+      # @return [Array<String>] list of types for current cops.
+      def types
+        @types = map(&:cop_type).uniq! unless defined? @types
+        @types
+      end
+
+      # @return [Array<Cop>] Cops for that specific type.
+      def with_type(type)
+        select { |c| c.cop_type == type }
+      end
+
+      # @return [Array<Cop>] Cops not for a specific type.
+      def without_type(type)
+        reject { |c| c.cop_type == type }
+      end
+    end
+
+    # A scaffold for concrete cops.
+    #
+    # The Cop class is meant to be extended.
+    #
+    # Cops track offenses and can autocorrect them of the fly.
+    #
+    # A commissioner object is responsible for traversing the AST and invoking
+    # the specific callbacks on each cop.
+    # If a cop needs to do its own processing of the AST or depends on
+    # something else, it should define the `#investigate` method and do
+    # the processing there.
+    #
+    # @example
+    #
+    #   class CustomCop < Cop
+    #     def investigate(processed_source)
+    #       # Do custom processing
+    #     end
+    #   end
+    class Cop
+      extend AST::Sexp
+      include Util
+      include IgnoredNode
+
+      attr_reader :config, :offenses, :corrections
+      attr_accessor :processed_source # TODO: Bad design.
+
+      @all = CopStore.new
+
+      def self.all
+        @all.clone
+      end
+
+      def self.non_rails
+        @all.without_type(:rails)
+      end
+
+      def self.inherited(subclass)
+        @all << subclass
+      end
+
+      def self.cop_name
+        name.to_s.split('::').last
+      end
+
+      def self.cop_type
+        name.to_s.split('::')[-2].downcase.to_sym
+      end
+
+      def self.lint?
+        cop_type == :lint
+      end
+
+      def self.rails?
+        cop_type == :rails
+      end
+
+      def initialize(config = nil, options = nil)
+        @config = config || Config.new
+        @options = options || { auto_correct: false, debug: false }
+
+        @offenses = []
+        @corrections = []
+      end
+
+      def cop_config
+        @config.for_cop(self)
+      end
+
+      def autocorrect?
+        @options[:auto_correct] && support_autocorrect?
+      end
+
+      def debug?
+        @options[:debug]
+      end
+
+      def display_cop_names?
+        debug? || @options[:display_cop_names]
+      end
+
+      def message(node = nil)
+        self.class::MSG
+      end
+
+      def support_autocorrect?
+        respond_to?(:autocorrect, true)
+      end
+
+      def add_offense(node, loc, message = nil, severity = nil)
+        location = loc.is_a?(Symbol) ? node.loc.send(loc) : loc
+
+        return unless enabled_line?(location.line)
+
+        # Don't include the same location twice for one cop.
+        return if @offenses.find { |o| o.location == location }
+
+        severity = custom_severity || severity || default_severity
+
+        message ||= message(node)
+        message = display_cop_names? ? "#{name}: #{message}" : message
+
+        autocorrect(node) if autocorrect?
+        @offenses << Offense.new(severity, location, message, name,
+                                 autocorrect?)
+        yield if block_given?
+      end
+
+      def config_to_allow_offenses
+        Formatter::DisabledConfigFormatter.config_to_allow_offenses[cop_name]
+      end
+
+      def config_to_allow_offenses=(hash)
+        Formatter::DisabledConfigFormatter.config_to_allow_offenses[cop_name] =
+          hash
+      end
+
+      def cop_name
+        self.class.cop_name
+      end
+
+      alias_method :name, :cop_name
+
+      def include_file?(file)
+        file_name_matches_any?(file, 'Include', true)
+      end
+
+      def exclude_file?(file)
+        file_name_matches_any?(file, 'Exclude', false)
+      end
+
+      def relevant_file?(file)
+        include_file?(file) && !exclude_file?(file)
+      end
+
+      private
+
+      def file_name_matches_any?(file, parameter, default_result)
+        patterns = cop_config && cop_config[parameter]
+        return default_result unless patterns
+        path = config.path_relative_to_config(file)
+        patterns.any? { |pattern| match_path?(pattern, path) }
+      end
+
+      def enabled_line?(line_number)
+        return true unless @processed_source
+        @processed_source.comment_config
+          .cop_enabled_at_line?(self, line_number)
+      end
+
+      def default_severity
+        self.class.lint? ? :warning : :convention
+      end
+
+      def custom_severity
+        severity = cop_config && cop_config['Severity']
+        if severity
+          if Severity::NAMES.include?(severity.to_sym)
+            severity.to_sym
+          else
+            warn "Warning: Invalid severity '#{severity}'. " +
+                 "Valid severities are #{Severity::NAMES.join(', ')}."
+                 .color(:red)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/corrector.rb b/lib/rubocop/cop/corrector.rb
new file mode 100644
index 0000000..4742661
--- /dev/null
+++ b/lib/rubocop/cop/corrector.rb
@@ -0,0 +1,84 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    # This class takes a source buffer and rewrite its source
+    # based on the different correction rules supplied.
+    #
+    # Important!
+    # The nodes modified by the corrections should be part of the
+    # AST of the source_buffer.
+    class Corrector
+      #
+      # @param source_buffer [Parser::Source::Buffer]
+      # @param corrections [Array(#call)]
+      #   Array of Objects that respond to #call. They will receive the
+      #   corrector itself and should use its method to modify the source.
+      #
+      # @example
+      #
+      # class AndOrCorrector
+      #   def initialize(node)
+      #     @node = node
+      #   end
+      #
+      #   def call(corrector)
+      #     replacement = (@node.type == :and ? '&&' : '||')
+      #     corrector.replace(@node.loc.operator, replacement)
+      #   end
+      # end
+      #
+      # corrections = [AndOrCorrector.new(node)]
+      # corrector = Corrector.new(source_buffer, corrections)
+      def initialize(source_buffer, corrections)
+        @source_buffer = source_buffer
+        @corrections = corrections
+        @source_rewriter = Parser::Source::Rewriter.new(source_buffer)
+      end
+
+      # Does the actual rewrite and returns string corresponding to
+      # the rewritten source.
+      #
+      # @return [String]
+      # TODO: Handle conflict exceptions raised from the Source::Rewriter
+      def rewrite
+        @corrections.each do |correction|
+          correction.call(self)
+        end
+
+        @source_rewriter.process
+      end
+
+      # Removes the source range.
+      #
+      # @param [Parser::Source::Range] range
+      def remove(range)
+        @source_rewriter.remove(range)
+      end
+
+      # Inserts new code before the given source range.
+      #
+      # @param [Parser::Source::Range] range
+      # @param [String] content
+      def insert_before(range, content)
+        @source_rewriter.insert_before(range, content)
+      end
+
+      # Inserts new code after the given source range.
+      #
+      # @param [Parser::Source::Range] range
+      # @param [String] content
+      def insert_after(range, content)
+        @source_rewriter.insert_after(range, content)
+      end
+
+      # Replaces the code of the source range `range` with `content`.
+      #
+      # @param [Parser::Source::Range] range
+      # @param [String] content
+      def replace(range, content)
+        @source_rewriter.replace(range, content)
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/ignored_node.rb b/lib/rubocop/cop/ignored_node.rb
new file mode 100644
index 0000000..a7b7664
--- /dev/null
+++ b/lib/rubocop/cop/ignored_node.rb
@@ -0,0 +1,31 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    # Handles adding and checking ignored nodes.
+    module IgnoredNode
+      def ignore_node(node)
+        @ignored_nodes ||= []
+        @ignored_nodes << node
+      end
+
+      def part_of_ignored_node?(node)
+        return false unless @ignored_nodes
+        expression = node.loc.expression
+        @ignored_nodes.each do |ignored_node|
+          if ignored_node.loc.expression.begin_pos <= expression.begin_pos &&
+            ignored_node.loc.expression.end_pos >= expression.end_pos
+            return true
+          end
+        end
+
+        false
+      end
+
+      def ignored_node?(node)
+        # Same object found in array?
+        @ignored_nodes && @ignored_nodes.any? { |n| n.eql?(node) }
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/ambiguous_operator.rb b/lib/rubocop/cop/lint/ambiguous_operator.rb
new file mode 100644
index 0000000..954b61a
--- /dev/null
+++ b/lib/rubocop/cop/lint/ambiguous_operator.rb
@@ -0,0 +1,50 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # This cop checks for ambiguous operators in the first argument of a
+      # method invocation without parentheses.
+      #
+      # @example
+      #   array = [1, 2, 3]
+      #
+      #   # The `*` is interpreted as a splat operator but it could possibly be
+      #   # a `*` method invocation (i.e. `do_something.*(array)`).
+      #   do_something *array
+      #
+      #   # With parentheses, there's no ambiguity.
+      #   do_something(*array)
+      class AmbiguousOperator < Cop
+        include ParserDiagnostic
+
+        AMBIGUITIES = {
+          '+'  => { actual: 'positive number', possible: 'addition' },
+          '-'  => { actual: 'negative number', possible: 'subtraction' },
+          '*'  => { actual: 'splat',           possible: 'multiplication' },
+          '&'  => { actual: 'block',           possible: 'binary AND' },
+          '**' => { actual: 'keyword splat',   possible: 'exponent' }
+        }.each do |key, hash|
+          hash[:operator] = key
+        end
+
+        MSG_FORMAT = 'Ambiguous %{actual} operator. Parenthesize the method ' \
+                     "arguments if it's surely a %{actual} operator, or add " \
+                     'a whitespace to the right of the %{operator} if it ' \
+                     'should be a %{possible}.'
+
+        private
+
+        def relevant_diagnostic?(diagnostic)
+          diagnostic.reason == :ambiguous_prefix
+        end
+
+        def alternative_message(diagnostic)
+          operator = diagnostic.location.source
+          hash = AMBIGUITIES[operator]
+          format(MSG_FORMAT, hash)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb b/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb
new file mode 100644
index 0000000..845bf7b
--- /dev/null
+++ b/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb
@@ -0,0 +1,36 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # This cop checks for ambiguous regexp literals in the first argument of
+      # a method invocation without parentheses.
+      #
+      # @example
+      #   # This is interpreted as a method invocation with a regexp literal,
+      #   # but it could possibly be `/` method invocations.
+      #   # (i.e. `do_something./(pattern)./(i)`)
+      #   do_something /pattern/i
+      #
+      #   # With parentheses, there's no ambiguity.
+      #   do_something(/pattern/i)
+      class AmbiguousRegexpLiteral < Cop
+        include ParserDiagnostic
+
+        MSG = 'Ambiguous regexp literal. Parenthesize the method arguments ' \
+              "if it's surely a regexp literal, or add a whitespace to the " \
+              'right of the / if it should be a division.'
+
+        private
+
+        def relevant_diagnostic?(diagnostic)
+          diagnostic.reason == :ambiguous_literal
+        end
+
+        def alternative_message(diagnostic)
+          MSG
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/assignment_in_condition.rb b/lib/rubocop/cop/lint/assignment_in_condition.rb
new file mode 100644
index 0000000..35f7cb8
--- /dev/null
+++ b/lib/rubocop/cop/lint/assignment_in_condition.rb
@@ -0,0 +1,46 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # This cop checks for assignments in the conditions of
+      # if/while/until.
+      class AssignmentInCondition < Cop
+        include SafeAssignment
+
+        MSG = 'Assignment in condition - you probably meant to use `==`.'
+
+        def on_if(node)
+          check(node)
+        end
+
+        def on_while(node)
+          check(node)
+        end
+
+        def on_until(node)
+          check(node)
+        end
+
+        private
+
+        def check(node)
+          condition, = *node
+
+          # assignments inside blocks are not what we're looking for
+          return if condition.type == :block
+
+          on_node([:begin, *EQUALS_ASGN_NODES], condition) do |asgn_node|
+            # skip safe assignment nodes if safe assignment is allowed
+            return if safe_assignment_allowed? && safe_assignment?(asgn_node)
+
+            # assignment nodes from shorthand ops like ||= don't have operator
+            if asgn_node.type != :begin && asgn_node.loc.operator
+              add_offense(asgn_node, :operator)
+            end
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/block_alignment.rb b/lib/rubocop/cop/lint/block_alignment.rb
new file mode 100644
index 0000000..ad4b5af
--- /dev/null
+++ b/lib/rubocop/cop/lint/block_alignment.rb
@@ -0,0 +1,151 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # This cop checks whether the end keywords are aligned properly for do
+      # end blocks.
+      #
+      # @example
+      #
+      #   variable = lambda do |i|
+      #     i
+      #   end
+      class BlockAlignment < Cop
+        include CheckAssignment
+
+        MSG = 'end at %d, %d is not aligned with %s at %d, %d%s'
+
+        def initialize(config = nil, options = nil)
+          super
+          @inspected_blocks = []
+        end
+
+        def on_block(node)
+          return if already_processed_node?(node)
+          check_block_alignment(node, node)
+        end
+
+        def on_and(node)
+          return if already_processed_node?(node)
+
+          _left, right = *node
+          if right.type == :block
+            check_block_alignment(node, right)
+            @inspected_blocks << right
+          end
+        end
+
+        alias_method :on_or, :on_and
+
+        def on_op_asgn(node)
+          variable, _op, args = *node
+          check_assignment(variable, args)
+        end
+
+        def on_send(node)
+          _receiver, _method, *args = *node
+          check_assignment(node, args.last)
+        end
+
+        def on_masgn(node)
+          variables, args = *node
+          check_assignment(variables, args)
+        end
+
+        private
+
+        def check_assignment(begin_node, other_node)
+          return unless other_node
+
+          block_node = find_block_node(other_node)
+          return unless block_node.type == :block
+
+          # If the block is an argument in a function call, align end with
+          # the block itself, and not with the function.
+          if begin_node.type == :send
+            _receiver, method, *_args = *begin_node
+            begin_node = block_node if method.to_s =~ /^\w+$/
+          end
+
+          # Align with the expression that is on the same line
+          # where the block is defined
+          if begin_node.type != :mlhs && block_is_on_next_line?(begin_node,
+                                                                block_node)
+            return
+          end
+          return if already_processed_node?(block_node)
+
+          @inspected_blocks << block_node
+          check_block_alignment(begin_node, block_node)
+        end
+
+        def find_block_node(node)
+          while [:send, :lvasgn].include?(node.type)
+            n = case node.type
+                when :send
+                  find_block_or_send_node(node) || break
+                when :lvasgn
+                  _variable, value = *node
+                  value
+                end
+            node = n if n
+          end
+          node
+        end
+
+        def find_block_or_send_node(send_node)
+          receiver, _method, args = *send_node
+          [receiver, args].find do |subnode|
+            subnode && [:block, :send].include?(subnode.type)
+          end
+        end
+
+        def check_block_alignment(start_node, block_node)
+          start_loc = start_node.loc.expression
+          end_loc = block_node.loc.end
+          do_loc = block_node.loc.begin # Actually it's either do or {.
+          return if do_loc.line == end_loc.line # One-liner, not interesting.
+          if start_loc.column != end_loc.column
+            # We've found that "end" is not aligned with the start node (which
+            # can be a block, a variable assignment, etc). But we also allow
+            # the "end" to be aligned with the start of the line where the "do"
+            # is, which is a style some people use in multi-line chains of
+            # blocks.
+            match = /\S.*/.match(do_loc.source_line)
+            indentation_of_do_line = match.begin(0)
+            if end_loc.column != indentation_of_do_line
+              add_offense(nil,
+                          end_loc,
+                          format(MSG, end_loc.line, end_loc.column,
+                                 start_loc.source.lines.to_a.first.chomp,
+                                 start_loc.line, start_loc.column,
+                                 alt_start_msg(match, start_loc, do_loc,
+                                               indentation_of_do_line)))
+            end
+          end
+        end
+
+        def alt_start_msg(match, start_loc, do_loc, indentation_of_do_line)
+          if start_loc.line == do_loc.line &&
+              start_loc.column == indentation_of_do_line
+            ''
+          else
+            " or #{match[0]} at #{do_loc.line}, #{indentation_of_do_line}"
+          end
+        end
+
+        def message
+        end
+
+        def already_processed_node?(node)
+          @inspected_blocks.include?(node)
+        end
+
+        def block_is_on_next_line?(begin_node, block_node)
+          begin_node.loc.line != block_node.loc.line
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/condition_position.rb b/lib/rubocop/cop/lint/condition_position.rb
new file mode 100644
index 0000000..05e7b91
--- /dev/null
+++ b/lib/rubocop/cop/lint/condition_position.rb
@@ -0,0 +1,52 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # This cop checks for conditions that are not on the same line as
+      # if/while/until.
+      #
+      # @example
+      #
+      #   if
+      #     some_condition
+      #     do_something
+      #   end
+      class ConditionPosition < Cop
+        def on_if(node)
+          return if node.loc.respond_to?(:question)
+
+          check(node)
+        end
+
+        def on_while(node)
+          check(node)
+        end
+
+        def on_until(node)
+          check(node)
+        end
+
+        private
+
+        def check(node)
+          condition, = *node
+
+          if on_different_line?(node.loc.keyword.line,
+                                condition.loc.expression.line)
+            add_offense(condition, :expression,
+                        message(node.loc.keyword.source))
+          end
+        end
+
+        def message(keyword)
+          "Place the condition on the same line as `#{keyword}`."
+        end
+
+        def on_different_line?(keyword_line, cond_line)
+          keyword_line != cond_line
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/debugger.rb b/lib/rubocop/cop/lint/debugger.rb
new file mode 100644
index 0000000..0eacb1b
--- /dev/null
+++ b/lib/rubocop/cop/lint/debugger.rb
@@ -0,0 +1,35 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # This cop checks for calls to debugger or pry.
+      class Debugger < Cop
+        MSG = 'Remove calls to `debugger`.'
+
+        # debugger call node
+        #
+        # (send nil :debugger)
+        DEBUGGER_NODE = s(:send, nil, :debugger)
+
+        # binding.pry node
+        #
+        # (send
+        #   (send nil :binding) :pry)
+        PRY_NODE = s(:send, s(:send, nil, :binding), :pry)
+
+        # binding.remote_pry node
+        #
+        # (send
+        #   (send nil :binding) :remote_pry)
+        REMOTE_PRY_NODE = s(:send, s(:send, nil, :binding), :remote_pry)
+
+        DEBUGGER_NODES = [DEBUGGER_NODE, PRY_NODE, REMOTE_PRY_NODE]
+
+        def on_send(node)
+          add_offense(node, :selector) if DEBUGGER_NODES.include?(node)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/deprecated_class_methods.rb b/lib/rubocop/cop/lint/deprecated_class_methods.rb
new file mode 100644
index 0000000..2127452
--- /dev/null
+++ b/lib/rubocop/cop/lint/deprecated_class_methods.rb
@@ -0,0 +1,62 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # This cop checks for uses of the deprecated class method usages.
+      class DeprecatedClassMethods < Cop
+        include AST::Sexp
+
+        MSG = '`%s` is deprecated in favor of `%s`.'
+
+        DEPRECATED_METHODS = [
+          [:File, :exists?, :exist?],
+          [:Dir, :exists?, :exist?]
+        ]
+
+        def on_send(node)
+          receiver, method_name, *_args = *node
+
+          DEPRECATED_METHODS.each do |data|
+            next unless class_nodes(data).include?(receiver)
+            next unless method_name == data[1]
+
+            add_offense(node, :selector,
+                        format(MSG,
+                               deprecated_method(data),
+                               replacement_method(data)))
+          end
+        end
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            receiver, method_name, *_args = *node
+
+            DEPRECATED_METHODS.each do |data|
+              next unless class_nodes(data).include?(receiver)
+              next unless method_name == data[1]
+
+              corrector.replace(node.loc.selector,
+                                data[2].to_s)
+            end
+          end
+        end
+
+        private
+
+        def class_nodes(data)
+          [s(:const, nil, data[0]),
+           s(:const, s(:cbase), data[0])]
+        end
+
+        def deprecated_method(data)
+          format('%s.%s', data[0], data[1])
+        end
+
+        def replacement_method(data)
+          format('%s.%s', data[0], data[2])
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/else_layout.rb b/lib/rubocop/cop/lint/else_layout.rb
new file mode 100644
index 0000000..8deaf0c
--- /dev/null
+++ b/lib/rubocop/cop/lint/else_layout.rb
@@ -0,0 +1,57 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # This cop checks for odd else block layout - like
+      # having an expression on the same line as the else keyword,
+      # which is usually a mistake.
+      #
+      # @example
+      #
+      #   if something
+      #     ...
+      #   else do_this
+      #     do_that
+      #   end
+      class ElseLayout < Cop
+        def on_if(node)
+          # ignore ternary ops
+          return if node.loc.respond_to?(:question)
+          # ignore modifier ops & elsif nodes
+          return unless node.loc.end
+
+          check(node)
+        end
+
+        private
+
+        def check(node)
+          return unless node
+
+          if node.loc.respond_to?(:else) &&
+             node.loc.else &&
+             node.loc.else.is?('else')
+            _cond, _if_branch, else_branch = *node
+
+            return unless else_branch && else_branch.type == :begin
+
+            first_else_expr = else_branch.children.first
+
+            if first_else_expr.loc.expression.line == node.loc.else.line
+              add_offense(first_else_expr, :expression, message)
+            end
+          elsif node.loc.respond_to?(:keyword) &&
+                %w(if elsif).include?(node.loc.keyword.source)
+            _cond, _if_branch, else_branch = *node
+            check(else_branch)
+          end
+        end
+
+        def message
+          'Odd `else` layout detected. Did you mean to use `elsif`?'
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/empty_ensure.rb b/lib/rubocop/cop/lint/empty_ensure.rb
new file mode 100644
index 0000000..b64276a
--- /dev/null
+++ b/lib/rubocop/cop/lint/empty_ensure.rb
@@ -0,0 +1,18 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # This cop checks for empty `ensure` blocks
+      class EmptyEnsure < Cop
+        MSG = 'Empty `ensure` block detected.'
+
+        def on_ensure(node)
+          _body, ensure_body = *node
+
+          add_offense(node, :keyword) unless ensure_body
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/empty_interpolation.rb b/lib/rubocop/cop/lint/empty_interpolation.rb
new file mode 100644
index 0000000..81cf4bb
--- /dev/null
+++ b/lib/rubocop/cop/lint/empty_interpolation.rb
@@ -0,0 +1,22 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # This cop checks for empty interpolation.
+      #
+      # @example
+      #
+      #   "result is #{}"
+      class EmptyInterpolation < Cop
+        MSG = 'Empty interpolation detected.'
+
+        def on_dstr(node)
+          node.children.select { |n| n.type == :begin }.each do |begin_node|
+            add_offense(begin_node, :expression) if begin_node.children.empty?
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/end_alignment.rb b/lib/rubocop/cop/lint/end_alignment.rb
new file mode 100644
index 0000000..bf013f3
--- /dev/null
+++ b/lib/rubocop/cop/lint/end_alignment.rb
@@ -0,0 +1,129 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # This cop checks whether the end keywords are aligned properly.
+      #
+      # Two modes are supported through the AlignWith configuration
+      # parameter. If it's set to `keyword` (which is the default), the `end`
+      # shall be aligned with the start of the keyword (if, def, etc.). If it's
+      # set to `variable` the `end` shall be aligned with the left-hand-side of
+      # the variable assignment, if there is one.
+      #
+      # @example
+      #
+      #   variable = if true
+      #              end
+      class EndAlignment < Cop
+        include CheckMethods
+        include CheckAssignment
+        include ConfigurableEnforcedStyle
+
+        MSG = 'end at %d, %d is not aligned with %s at %d, %d'
+
+        def on_class(node)
+          check(node)
+        end
+
+        def on_module(node)
+          check(node)
+        end
+
+        def on_if(node)
+          check(node) if node.loc.respond_to?(:end)
+        end
+
+        def on_while(node)
+          check(node)
+        end
+
+        def on_until(node)
+          check(node)
+        end
+
+        def on_send(node)
+          receiver, method_name, *args = *node
+          if visibility_and_def_on_same_line?(receiver, method_name, args)
+            expr = node.loc.expression
+            method_def = args.first
+            range = Parser::Source::Range.new(expr.source_buffer,
+                                              expr.begin_pos,
+                                              method_def.loc.keyword.end_pos)
+            check_offset(method_def, range.source,
+                         method_def.loc.keyword.begin_pos - expr.begin_pos)
+            ignore_node(method_def) # Don't check the same `end` again.
+          end
+        end
+
+        private
+
+        # Returns true for constructs such as
+        # private def my_method
+        # which are allowed in Ruby 2.1 and later.
+        def visibility_and_def_on_same_line?(receiver, method_name, args)
+          !receiver &&
+            [:public, :protected, :private,
+             :module_function].include?(method_name) &&
+            args.size == 1 && [:def, :defs].include?(args.first.type)
+        end
+
+        def check_assignment(node, rhs)
+          # If there are method calls chained to the right hand side of the
+          # assignment, we let rhs be the receiver of those method calls before
+          # we check if it's an if/unless/while/until.
+          rhs = first_part_of_call_chain(rhs)
+
+          return unless rhs
+
+          case rhs.type
+          when :if, :while, :until
+            return if rhs.loc.respond_to?(:question) # ternary
+
+            if style == :variable
+              expr = node.loc.expression
+              range = Parser::Source::Range.new(expr.source_buffer,
+                                                expr.begin_pos,
+                                                rhs.loc.keyword.end_pos)
+              offset = rhs.loc.keyword.column - node.loc.expression.column
+            else
+              range = rhs.loc.keyword
+              offset = 0
+            end
+
+            check_offset(rhs, range.source, offset)
+            ignore_node(rhs) # Don't check again.
+          end
+        end
+
+        def check(node, *_)
+          check_offset(node, node.loc.keyword.source, 0)
+        end
+
+        def check_offset(node, alignment_base, offset)
+          return if ignored_node?(node)
+
+          end_loc = node.loc.end
+          return unless end_loc # Discard modifier forms of if/while/until.
+
+          kw_loc = node.loc.keyword
+
+          if kw_loc.line != end_loc.line &&
+              kw_loc.column != end_loc.column + offset
+            add_offense(nil, end_loc,
+                        format(MSG, end_loc.line, end_loc.column,
+                               alignment_base, kw_loc.line, kw_loc.column)) do
+              opposite_style_detected
+            end
+          else
+            correct_style_detected
+          end
+        end
+
+        def parameter_name
+          'AlignWith'
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/end_in_method.rb b/lib/rubocop/cop/lint/end_in_method.rb
new file mode 100644
index 0000000..de03a17
--- /dev/null
+++ b/lib/rubocop/cop/lint/end_in_method.rb
@@ -0,0 +1,22 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # This cop checks for END blocks in method definitions.
+      class EndInMethod < Cop
+        include CheckMethods
+
+        MSG = '`END` found in method definition. Use `at_exit` instead.'
+
+        private
+
+        def check(node, *_)
+          on_node(:postexe, node) do |end_node|
+            add_offense(end_node, :keyword)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/ensure_return.rb b/lib/rubocop/cop/lint/ensure_return.rb
new file mode 100644
index 0000000..8e79a0f
--- /dev/null
+++ b/lib/rubocop/cop/lint/ensure_return.rb
@@ -0,0 +1,22 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # This cop checks for *return* from an *ensure* block.
+      class EnsureReturn < Cop
+        MSG = 'Never return from an `ensure` block.'
+
+        def on_ensure(node)
+          _body, ensure_body = *node
+
+          return unless ensure_body
+
+          on_node(:return, ensure_body) do |e|
+            add_offense(e, :expression)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/eval.rb b/lib/rubocop/cop/lint/eval.rb
new file mode 100644
index 0000000..8d0efad
--- /dev/null
+++ b/lib/rubocop/cop/lint/eval.rb
@@ -0,0 +1,18 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # This cop checks for the use of *Kernel#eval*.
+      class Eval < Cop
+        MSG = 'The use of `eval` is a serious security risk.'
+
+        def on_send(node)
+          receiver, method_name, = *node
+
+          add_offense(node, :selector) if receiver.nil? && method_name == :eval
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/handle_exceptions.rb b/lib/rubocop/cop/lint/handle_exceptions.rb
new file mode 100644
index 0000000..f603ecc
--- /dev/null
+++ b/lib/rubocop/cop/lint/handle_exceptions.rb
@@ -0,0 +1,18 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # This cop checks for *rescue* blocks with no body.
+      class HandleExceptions < Cop
+        MSG = 'Do not suppress exceptions.'
+
+        def on_resbody(node)
+          _exc_list_node, _exc_var_node, body_node = *node
+
+          add_offense(node, :expression) unless body_node
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/invalid_character_literal.rb b/lib/rubocop/cop/lint/invalid_character_literal.rb
new file mode 100644
index 0000000..434ee8c
--- /dev/null
+++ b/lib/rubocop/cop/lint/invalid_character_literal.rb
@@ -0,0 +1,37 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # This cop checks for invalid character literals with a non-escaped
+      # whitespace character (e.g. `? `).
+      # However, currently it's unclear whether there's a way to emit this
+      # warning without syntax errors.
+      #
+      #     $ ruby -w
+      #     p(? )
+      #     -:1: warning: invalid character syntax; use ?\s
+      #     -:1: syntax error, unexpected '?', expecting ')'
+      #     p(? )
+      #        ^
+      #
+      # @example
+      #   p(? )
+      class InvalidCharacterLiteral < Cop
+        include ParserDiagnostic
+
+        private
+
+        def relevant_diagnostic?(diagnostic)
+          diagnostic.reason == :invalid_escape_use
+        end
+
+        def alternative_message(diagnostic)
+          diagnostic.message
+            .capitalize
+            .gsub('character syntax', 'character literal')
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/literal_in_condition.rb b/lib/rubocop/cop/lint/literal_in_condition.rb
new file mode 100644
index 0000000..e1ffc50
--- /dev/null
+++ b/lib/rubocop/cop/lint/literal_in_condition.rb
@@ -0,0 +1,138 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # This cop checks for literals used as the conditions or as
+      # operands in and/or expressions serving as the conditions of
+      # if/while/until.
+      #
+      # @example
+      #
+      #   if 20
+      #     do_something
+      #   end
+      #
+      #   if some_var && true
+      #     do_something
+      #   end
+      #
+      class LiteralInCondition < Cop
+        MSG = 'Literal `%s` appeared in a condition.'
+
+        LITERALS = [:str, :dstr, :int, :float, :array,
+                    :hash, :regexp, :nil, :true, :false]
+
+        BASIC_LITERALS = LITERALS - [:dstr, :array, :hash]
+
+        def on_if(node)
+          check_for_literal(node)
+        end
+
+        def on_while(node)
+          check_for_literal(node)
+        end
+
+        def on_while_post(node)
+          check_for_literal(node)
+        end
+
+        def on_until(node)
+          check_for_literal(node)
+        end
+
+        def on_until_post(node)
+          check_for_literal(node)
+        end
+
+        def on_case(node)
+          cond, *whens, _else = *node
+
+          if cond
+            check_case_cond(cond)
+          else
+            whens.each do |when_node|
+              check_for_literal(when_node)
+            end
+          end
+        end
+
+        def message(node)
+          format(MSG, node.loc.expression.source)
+        end
+
+        private
+
+        def check_for_literal(node)
+          cond, = *node
+
+          # if the cond node is literal we obviously have a problem
+          if literal?(cond)
+            add_offense(cond, :expression)
+          else
+            # alternatively we have to consider a logical node with a
+            # literal argument
+            check_node(cond)
+          end
+        end
+
+        def not?(node)
+          return false unless node && node.type == :send
+
+          _receiver, method_name, *_args = *node
+
+          method_name == :!
+        end
+
+        def literal?(node)
+          LITERALS.include?(node.type)
+        end
+
+        def basic_literal?(node)
+          if node && node.type == :array
+            primitive_array?(node)
+          else
+            BASIC_LITERALS.include?(node.type)
+          end
+        end
+
+        def primitive_array?(node)
+          node.children.all? { |n| basic_literal?(n) }
+        end
+
+        def check_node(node)
+          return unless node
+
+          if not?(node)
+            receiver, = *node
+
+            handle_node(receiver)
+          elsif [:and, :or].include?(node.type)
+            *operands = *node
+            operands.each do |op|
+              handle_node(op)
+            end
+          elsif node.type == :begin && node.children.size == 1
+            child_node = node.children.first
+            handle_node(child_node)
+          end
+        end
+
+        def handle_node(node)
+          if literal?(node)
+            add_offense(node, :expression)
+          elsif [:send, :and, :or, :begin].include?(node.type)
+            check_node(node)
+          end
+        end
+
+        def check_case_cond(node)
+          return if node.type == :array && !primitive_array?(node)
+          return if node.type == :dstr
+
+          handle_node(node)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/literal_in_interpolation.rb b/lib/rubocop/cop/lint/literal_in_interpolation.rb
new file mode 100644
index 0000000..8152981
--- /dev/null
+++ b/lib/rubocop/cop/lint/literal_in_interpolation.rb
@@ -0,0 +1,37 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # This cop checks for interpolated literals.
+      #
+      # @example
+      #
+      #   "result is #{10}"
+      class LiteralInInterpolation < Cop
+        LITERALS = [:str, :dstr, :int, :float, :array,
+                    :hash, :regexp, :nil, :true, :false]
+
+        MSG = 'Literal interpolation detected.'
+
+        def on_dstr(node)
+          node.children.select { |n| n.type == :begin }.each do |begin_node|
+            final_node = begin_node.children.last
+            next unless final_node
+            # handle strings like __FILE__
+            return if special_string?(final_node)
+            next unless LITERALS.include?(final_node.type)
+
+            add_offense(final_node, :expression)
+          end
+        end
+
+        private
+
+        def special_string?(node)
+          node.type == :str && !node.loc.respond_to?(:begin)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/loop.rb b/lib/rubocop/cop/lint/loop.rb
new file mode 100644
index 0000000..8ed8397
--- /dev/null
+++ b/lib/rubocop/cop/lint/loop.rb
@@ -0,0 +1,27 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # This cop checks for uses of *begin...end while/until something*.
+      class Loop < Cop
+        MSG = 'Use `Kernel#loop` with `break` rather than ' \
+              '`begin/end/until`(or `while`).'
+
+        def on_while_post(node)
+          register_offense(node)
+        end
+
+        def on_until_post(node)
+          register_offense(node)
+        end
+
+        private
+
+        def register_offense(node)
+          add_offense(node, :keyword)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb b/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb
new file mode 100644
index 0000000..91cba61
--- /dev/null
+++ b/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb
@@ -0,0 +1,52 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # Checks for space between a the name of a called method and a left
+      # parenthesis.
+      #
+      # @example
+      #
+      # puts (x + y)
+      class ParenthesesAsGroupedExpression < Cop
+        MSG = '(...) interpreted as grouped expression.'
+
+        def on_send(node)
+          _receiver, method_name, args = *node
+          return if operator?(method_name) || method_name.to_s.end_with?('=')
+
+          if args && args.loc.expression.source.start_with?('(')
+            space_length = spaces_before_left_parenthesis(node)
+            if space_length > 0
+              expr = args.loc.expression
+              space_range =
+                Parser::Source::Range.new(expr.source_buffer,
+                                          expr.begin_pos - space_length,
+                                          expr.begin_pos)
+              add_offense(nil, space_range)
+            end
+          end
+        end
+
+        private
+
+        def spaces_before_left_parenthesis(node)
+          receiver, method_name, _args = *node
+          receiver_length = if receiver
+                              receiver.loc.expression.source.length
+                            else
+                              0
+                            end
+          without_receiver = node.loc.expression.source[receiver_length..-1]
+
+          # Escape question mark if any.
+          method_regexp = Regexp.escape(method_name)
+
+          match = without_receiver.match(/^\s*\.?\s*#{method_regexp}(\s+)\(/)
+          match ? match.captures[0].length : 0
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/require_parentheses.rb b/lib/rubocop/cop/lint/require_parentheses.rb
new file mode 100644
index 0000000..cface14
--- /dev/null
+++ b/lib/rubocop/cop/lint/require_parentheses.rb
@@ -0,0 +1,68 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # This cop checks for expressions where there is a call to a predicate
+      # method with at least one argument, where no parentheses are used around
+      # the parameter list, and a boolean operator, && or ||, is used in the
+      # last argument.
+      #
+      # The idea behind warning for these constructs is that the user might
+      # be under the impression that the return value from the method call is
+      # an operand of &&/||.
+      #
+      # @example
+      #
+      # if day.is? :tuesday && month == :jan
+      #   ...
+      # end
+      class RequireParentheses < Cop
+        include IfNode
+
+        MSG = 'Use parentheses in the method call to avoid confusion about ' \
+              'precedence.'
+
+        def on_send(node)
+          _receiver, method_name, *args = *node
+
+          return if parentheses?(node)
+          return if args.empty?
+
+          if ternary_op?(args.first)
+            check_ternary(args.first, node)
+          else
+            # We're only checking predicate methods. There would be false
+            # positives otherwise.
+            check_send(args.last, node) if predicate?(method_name)
+          end
+        end
+
+        private
+
+        def check_ternary(arg, node)
+          condition, _, _ = *arg
+          if offense?(condition)
+            expr = node.loc.expression
+            range = Parser::Source::Range.new(expr.source_buffer,
+                                              expr.begin_pos,
+                                              condition.loc.expression.end_pos)
+            add_offense(range, range)
+          end
+        end
+
+        def check_send(arg, node)
+          add_offense(node, :expression) if offense?(arg)
+        end
+
+        def predicate?(method_name)
+          method_name =~ /\w\?$/
+        end
+
+        def offense?(node)
+          [:and, :or].include?(node.type)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/rescue_exception.rb b/lib/rubocop/cop/lint/rescue_exception.rb
new file mode 100644
index 0000000..a66121a
--- /dev/null
+++ b/lib/rubocop/cop/lint/rescue_exception.rb
@@ -0,0 +1,24 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # This cop checks for *rescue* blocks targeting the Exception class.
+      class RescueException < Cop
+        MSG = 'Avoid rescuing the `Exception` class.'
+
+        def on_resbody(node)
+          return unless node.children.first
+          rescue_args = node.children.first.children
+          if rescue_args.any? { |a| targets_exception?(a) }
+            add_offense(node, :expression)
+          end
+        end
+
+        def targets_exception?(rescue_arg_node)
+          Util.const_name(rescue_arg_node) == 'Exception'
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb b/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb
new file mode 100644
index 0000000..cd06f5a
--- /dev/null
+++ b/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb
@@ -0,0 +1,31 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # This cop looks for use of the same name as outer local variables
+      # for block arguments or block local variables.
+      # This is a mimic of the warning
+      # "shadowing outer local variable - foo" from `ruby -cw`.
+      class ShadowingOuterLocalVariable < Cop
+        include VariableInspector
+
+        MSG = 'Shadowing outer local variable - `%s`'
+
+        def investigate(processed_source)
+          inspect_variables(processed_source.ast)
+        end
+
+        def before_declaring_variable(variable)
+          return if variable.name.to_s.start_with?('_')
+
+          outer_local_variable = variable_table.find_variable(variable.name)
+          return unless outer_local_variable
+
+          message = format(MSG, variable.name)
+          add_offense(variable.declaration_node, :expression, message)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/space_before_first_arg.rb b/lib/rubocop/cop/lint/space_before_first_arg.rb
new file mode 100644
index 0000000..8729d1d
--- /dev/null
+++ b/lib/rubocop/cop/lint/space_before_first_arg.rb
@@ -0,0 +1,37 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # Checks for space between a method name and the first argument for
+      # method calls without parentheses.
+      #
+      # @example
+      #
+      #   something?x
+      #   something!x
+      #
+      class SpaceBeforeFirstArg < Cop
+        MSG = 'Put space between the method name and the first argument.'
+
+        def on_send(node)
+          return if parentheses?(node)
+
+          _receiver, method_name, *args = *node
+          return if args.empty?
+          return if operator?(method_name)
+          return if method_name.to_s.end_with?('=')
+
+          # Setter calls with parentheses are parsed this way. The parentheses
+          # belong to the argument, not the send node.
+          return if args.first.type == :begin
+
+          arg1 = args.first.loc.expression
+          arg1_with_space = range_with_surrounding_space(arg1, :left)
+
+          add_offense(nil, arg1) if arg1_with_space.source =~ /\A\S/
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/string_conversion_in_interpolation.rb b/lib/rubocop/cop/lint/string_conversion_in_interpolation.rb
new file mode 100644
index 0000000..bd63b27
--- /dev/null
+++ b/lib/rubocop/cop/lint/string_conversion_in_interpolation.rb
@@ -0,0 +1,51 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # This cop checks for string conversion in string interpolation,
+      # which is redundant.
+      #
+      # @example
+      #
+      #   "result is #{something.to_s}"
+      class StringConversionInInterpolation < Cop
+        MSG_DEFAULT = 'Redundant use of `Object#to_s` in interpolation.'
+        MSG_SELF = 'Use `self` instead of `Object#to_s` in interpolation.'
+
+        def on_dstr(node)
+          node.children.select { |n| n.type == :begin }.each do |begin_node|
+            final_node = begin_node.children.last
+            next unless final_node && final_node.type == :send
+
+            receiver, method_name, *args = *final_node
+
+            if method_name == :to_s && args.empty?
+              add_offense(
+                final_node,
+                :selector,
+                receiver ? MSG_DEFAULT : MSG_SELF
+              )
+            end
+          end
+        end
+
+        private
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            receiver, _method_name, *_args = *node
+            corrector.replace(
+              node.loc.expression,
+              if receiver
+                receiver.loc.expression.source
+              else
+                'self'
+              end
+            )
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/syntax.rb b/lib/rubocop/cop/lint/syntax.rb
new file mode 100644
index 0000000..a090230
--- /dev/null
+++ b/lib/rubocop/cop/lint/syntax.rb
@@ -0,0 +1,28 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # This is actually not a cop and inspects nothing. It just provides
+      # methods to repack Parser's diagnostics into RuboCop's offenses.
+      module Syntax
+        COP_NAME = 'Syntax'.freeze
+
+        def self.offenses_from_diagnostics(diagnostics)
+          diagnostics.map do |diagnostic|
+            offense_from_diagnostic(diagnostic)
+          end
+        end
+
+        def self.offense_from_diagnostic(diagnostic)
+          Offense.new(
+            diagnostic.level,
+            diagnostic.location,
+            diagnostic.message,
+            COP_NAME
+          )
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/unreachable_code.rb b/lib/rubocop/cop/lint/unreachable_code.rb
new file mode 100644
index 0000000..cae2bc2
--- /dev/null
+++ b/lib/rubocop/cop/lint/unreachable_code.rb
@@ -0,0 +1,33 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # This cop checks for unreachable code.
+      # The check are based on the presence of flow of control
+      # statement in non-final position in *begin*(implicit) blocks.
+      class UnreachableCode < Cop
+        MSG = 'Unreachable code detected.'
+
+        NODE_TYPES = [:return, :next, :break, :retry, :redo]
+        FLOW_COMMANDS = [:throw, :raise, :fail]
+
+        def on_begin(node)
+          expressions = *node
+
+          expressions.each_cons(2) do |e1, e2|
+            if NODE_TYPES.include?(e1.type) || flow_command?(e1)
+              add_offense(e2, :expression)
+            end
+          end
+        end
+
+        private
+
+        def flow_command?(node)
+          FLOW_COMMANDS.any? { |c| command?(c, node) }
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/useless_access_modifier.rb b/lib/rubocop/cop/lint/useless_access_modifier.rb
new file mode 100644
index 0000000..843df7b
--- /dev/null
+++ b/lib/rubocop/cop/lint/useless_access_modifier.rb
@@ -0,0 +1,58 @@
+# encoding: utf-8
+module Rubocop
+  module Cop
+    module Lint
+      # This cop checks for access modifiers without any code.
+      #
+      # @example
+      #   class Foo
+      #     private # This is useless
+      #
+      #     def self.some_method
+      #     end
+      #   end
+      class UselessAccessModifier < Cop
+        MSG = 'Useless `%s` access modifier.'
+
+        def on_class(node)
+          _name, _base_class, body = *node
+          return unless body
+
+          body_nodes = body.type == :begin ? body.children : [body]
+
+          body_nodes.each do |child_node|
+            check_for_access_modifier(child_node) ||
+            check_for_instance_method(child_node)
+          end
+
+          add_offense_for_access_modifier
+        end
+
+        private
+
+        def add_offense_for_access_modifier
+          return unless @access_modifier_node
+
+          _, modifier = *@access_modifier_node
+          message = format(MSG, modifier)
+          add_offense(@access_modifier_node, :expression, message)
+        end
+
+        def check_for_instance_method(node)
+          return unless node.type == :def ||
+            node.type == :send
+
+          @access_modifier_node = nil
+        end
+
+        def check_for_access_modifier(node)
+          return unless Style::AccessModifierIndentation
+            .modifier_node?(node)
+
+          add_offense_for_access_modifier
+          @access_modifier_node = node
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/useless_assignment.rb b/lib/rubocop/cop/lint/useless_assignment.rb
new file mode 100644
index 0000000..412bd53
--- /dev/null
+++ b/lib/rubocop/cop/lint/useless_assignment.rb
@@ -0,0 +1,88 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # This cop checks for every useless assignment to local variable in every
+      # scope.
+      # The basic idea for this cop was from the warning of `ruby -cw`:
+      #
+      #   assigned but unused variable - foo
+      #
+      # Currently this cop has advanced logic that detects unreferenced
+      # reassignments and properly handles varied cases such as branch, loop,
+      # rescue, ensure, etc.
+      class UselessAssignment < Cop
+        include VariableInspector
+
+        MSG = 'Useless assignment to variable - %s'
+
+        def investigate(processed_source)
+          inspect_variables(processed_source.ast)
+        end
+
+        def after_leaving_scope(scope)
+          scope.variables.each_value do |variable|
+            check_for_unused_assignments(variable)
+            check_for_unused_block_local_variable(variable)
+          end
+        end
+
+        def check_for_unused_assignments(variable)
+          return if variable.name.to_s.start_with?('_')
+
+          variable.assignments.each do |assignment|
+            next if assignment.used?
+
+            message = message_for_useless_assignment(assignment)
+
+            location = if assignment.regexp_named_capture?
+                         assignment.node.children.first.loc.expression
+                       else
+                         assignment.node.loc.name
+                       end
+
+            add_offense(nil, location, message)
+          end
+        end
+
+        def message_for_useless_assignment(assignment)
+          variable = assignment.variable
+
+          message = format(MSG, variable.name)
+
+          if assignment.multiple_assignment?
+            message << ". Use _ or _#{variable.name} as a variable name " \
+                       "to indicate that it won't be used."
+          elsif assignment.operator_assignment?
+            return_value_node = return_value_node_of_scope(variable.scope)
+            if assignment.meta_assignment_node.equal?(return_value_node)
+              non_assignment_operator = assignment.operator.sub(/=$/, '')
+              message << ". Use just operator #{non_assignment_operator}."
+            end
+          end
+
+          message
+        end
+
+        # TODO: More precise handling (rescue, ensure, nested begin, etc.)
+        def return_value_node_of_scope(scope)
+          body_node = scope.body_node
+
+          if body_node.type == :begin
+            body_node.children.last
+          else
+            body_node
+          end
+        end
+
+        def check_for_unused_block_local_variable(variable)
+          return unless variable.block_local_variable?
+          return unless variable.assignments.empty?
+          message = format(MSG, variable.name)
+          add_offense(variable.declaration_node, :expression, message)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/useless_comparison.rb b/lib/rubocop/cop/lint/useless_comparison.rb
new file mode 100644
index 0000000..f400b35
--- /dev/null
+++ b/lib/rubocop/cop/lint/useless_comparison.rb
@@ -0,0 +1,30 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # This cop checks for comparison of something with itself.
+      #
+      # @example
+      #
+      #  x.top >= x.top
+      class UselessComparison < Cop
+        MSG = 'Comparison of something with itself detected.'
+
+        OPS = %w(== === != < > <= >= <=>)
+
+        def on_send(node)
+          # lambda.() does not have a selector
+          return unless node.loc.selector
+          op = node.loc.selector.source
+
+          if OPS.include?(op)
+            receiver, _method, args = *node
+
+            add_offense(node, :selector) if receiver == args
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/useless_else_without_rescue.rb b/lib/rubocop/cop/lint/useless_else_without_rescue.rb
new file mode 100644
index 0000000..54291c3
--- /dev/null
+++ b/lib/rubocop/cop/lint/useless_else_without_rescue.rb
@@ -0,0 +1,25 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # This cop checks for useless `else` in `begin..end` without `rescue`.
+      #
+      # @example
+      #   begin
+      #     do_something
+      #   else
+      #     handle_errors # This will never be run.
+      #   end
+      class UselessElseWithoutRescue < Cop
+        include ParserDiagnostic
+
+        private
+
+        def relevant_diagnostic?(diagnostic)
+          diagnostic.reason == :useless_else
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/useless_setter_call.rb b/lib/rubocop/cop/lint/useless_setter_call.rb
new file mode 100644
index 0000000..6348a73
--- /dev/null
+++ b/lib/rubocop/cop/lint/useless_setter_call.rb
@@ -0,0 +1,150 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # This cop checks for setter call to local variable as the final
+      # expression of a function definition.
+      #
+      # @example
+      #
+      #  def something
+      #    x = Something.new
+      #    x.attr = 5
+      #  end
+      class UselessSetterCall < Cop
+        include CheckMethods
+
+        MSG = 'Useless setter call to local variable %s.'
+        ASSIGNMENT_TYPES = [:lvasgn, :ivasgn, :cvasgn, :gvasgn].freeze
+
+        private
+
+        def check(_node, _method_name, args, body)
+          return unless body
+
+          if body.type == :begin
+            expression = body.children
+          else
+            expression = body
+          end
+
+          last_expr = expression.is_a?(Array) ? expression.last : expression
+
+          return unless setter_call_to_local_variable?(last_expr)
+
+          tracker = MethodVariableTracker.new(args, body)
+          receiver, = *last_expr
+          var_name, = *receiver
+          return if tracker.contain_object_passed_as_argument?(var_name)
+
+          add_offense(receiver,
+                      :name,
+                      format(MSG, receiver.loc.name.source))
+        end
+
+        def setter_call_to_local_variable?(node)
+          return unless node && node.type == :send
+          receiver, method, _args = *node
+          return unless receiver && receiver.type == :lvar
+          method =~ /\w=$/
+        end
+
+        # This class tracks variable assignments in a method body
+        # and if a variable contains object passed as argument at the end of
+        # the method.
+        class MethodVariableTracker
+          def initialize(args_node, body_node)
+            @args_node = args_node
+            @body_node = body_node
+          end
+
+          def contain_object_passed_as_argument?(variable_name)
+            return @table[variable_name] if @table
+
+            @table = {}
+
+            @args_node.children.each do |arg_node|
+              arg_name, = *arg_node
+              @table[arg_name] = true
+            end
+
+            scan(@body_node) do |node|
+              case node.type
+              when :masgn
+                process_multiple_assignment(node)
+              when :or_asgn, :and_asgn
+                process_logical_operator_assignment(node)
+              when :op_asgn
+                process_binary_operator_assignment(node)
+              when *ASSIGNMENT_TYPES
+                _, rhs_node = *node
+                process_assignment(node, rhs_node)
+              end
+            end
+
+            @table[variable_name]
+          end
+
+          def scan(node, &block)
+            catch(:skip_children) do
+              yield node
+
+              node.children.each do |child|
+                next unless child.is_a?(Parser::AST::Node)
+                scan(child, &block)
+              end
+            end
+          end
+
+          def process_multiple_assignment(masgn_node)
+            mlhs_node, mrhs_node = *masgn_node
+
+            mlhs_node.children.each_with_index do |lhs_node, index|
+              next unless ASSIGNMENT_TYPES.include?(lhs_node.type)
+
+              lhs_variable_name, = *lhs_node
+              rhs_node = mrhs_node.children[index]
+
+              if mrhs_node.type == :array && rhs_node
+                process_assignment(lhs_variable_name, rhs_node)
+              else
+                @table[lhs_variable_name] = false
+              end
+            end
+
+            throw :skip_children
+          end
+
+          def process_logical_operator_assignment(asgn_node)
+            lhs_node, rhs_node = *asgn_node
+            return unless ASSIGNMENT_TYPES.include?(lhs_node.type)
+            process_assignment(lhs_node, rhs_node)
+
+            throw :skip_children
+          end
+
+          def process_binary_operator_assignment(op_asgn_node)
+            lhs_node, = *op_asgn_node
+            return unless ASSIGNMENT_TYPES.include?(lhs_node.type)
+            lhs_variable_name, = *lhs_node
+            @table[lhs_variable_name] = false
+
+            throw :skip_children
+          end
+
+          def process_assignment(asgn_node, rhs_node)
+            lhs_variable_name, = *asgn_node
+
+            if [:lvar, :ivar, :cvar, :gvar].include?(rhs_node.type)
+              rhs_variable_name, = *rhs_node
+              @table[lhs_variable_name] = @table[rhs_variable_name]
+            else
+              @table[lhs_variable_name] = false
+            end
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/lint/void.rb b/lib/rubocop/cop/lint/void.rb
new file mode 100644
index 0000000..755ef61
--- /dev/null
+++ b/lib/rubocop/cop/lint/void.rb
@@ -0,0 +1,54 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Lint
+      # This cop checks for operators, variables and literals used
+      # in void context.
+      class Void < Cop
+        OP_MSG = 'Operator `%s` used in void context.'
+        VAR_MSG = 'Variable `%s` used in void context.'
+        LIT_MSG = 'Literal `%s` used in void context'
+
+        OPS = %w(* / % + - == === != < > <= >= <=>)
+        VARS = [:ivar, :lvar, :cvar, :const]
+        LITERALS = [:str, :dstr, :int, :float, :array,
+                    :hash, :regexp, :nil, :true, :false]
+
+        def on_begin(node)
+          expressions = *node
+
+          expressions.drop_last(1).each do |expr|
+            check_for_void_op(expr)
+            check_for_literal(expr)
+            check_for_var(expr)
+          end
+        end
+
+        private
+
+        def check_for_void_op(node)
+          return unless node.type == :send
+
+          op = node.loc.selector.source
+
+          add_offense(node, :selector, format(OP_MSG, op)) if OPS.include?(op)
+        end
+
+        def check_for_var(node)
+          if VARS.include?(node.type)
+            add_offense(node, :name,
+                        format(VAR_MSG, node.loc.name.source))
+          end
+        end
+
+        def check_for_literal(node)
+          if LITERALS.include?(node.type)
+            add_offense(node, :expression,
+                        format(LIT_MSG, node.loc.expression.source))
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/mixin/annotation_comment.rb b/lib/rubocop/cop/mixin/annotation_comment.rb
new file mode 100644
index 0000000..6d41f54
--- /dev/null
+++ b/lib/rubocop/cop/mixin/annotation_comment.rb
@@ -0,0 +1,37 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # Common functionality related to annotation comments.
+      module AnnotationComment
+        private
+
+        def annotation?(comment)
+          _margin, first_word, colon, space, note = split_comment(comment)
+          keyword_appearance?(first_word, colon, space) &&
+            !just_first_word_of_sentence?(first_word, colon, space, note)
+        end
+
+        def split_comment(comment)
+          match = comment.text.match(/^(# ?)([A-Za-z]+)(\s*:)?(\s+)?(\S+)?/)
+          return false unless match
+          margin, first_word, colon, space, note = *match.captures
+          [margin, first_word, colon, space, note]
+        end
+
+        def keyword_appearance?(first_word, colon, space)
+          first_word && keyword?(first_word.upcase) && (colon || space)
+        end
+
+        def just_first_word_of_sentence?(first_word, colon, space, note)
+          first_word == first_word.capitalize && !colon && space && note
+        end
+
+        def keyword?(word)
+          config.for_cop('CommentAnnotation')['Keywords'].include?(word)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/mixin/array_syntax.rb b/lib/rubocop/cop/mixin/array_syntax.rb
new file mode 100644
index 0000000..e94f3a3
--- /dev/null
+++ b/lib/rubocop/cop/mixin/array_syntax.rb
@@ -0,0 +1,24 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    # Common code for ordinary arrays with [] that can be written with %
+    # syntax.
+    module ArraySyntax
+      def array_of?(element_type, node)
+        return false unless square_brackets?(node)
+
+        array_elems = node.children
+
+        # no need to check empty arrays
+        return false unless array_elems && array_elems.size > 1
+
+        array_elems.all? { |e| e.type == element_type }
+      end
+
+      def square_brackets?(node)
+        node.loc.begin && node.loc.begin.is?('[')
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/mixin/autocorrect_alignment.rb b/lib/rubocop/cop/mixin/autocorrect_alignment.rb
new file mode 100644
index 0000000..aacd0ba
--- /dev/null
+++ b/lib/rubocop/cop/mixin/autocorrect_alignment.rb
@@ -0,0 +1,79 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    # This module does auto-correction of nodes that should just be moved to
+    # the left or to the right, amount being determined by the instance
+    # variable @column_delta.
+    module AutocorrectAlignment
+      def check_alignment(items, base_column = nil)
+        base_column ||= items.first.loc.column unless items.empty?
+        items.each_cons(2) do |prev, current|
+          if current.loc.line > prev.loc.line && start_of_line?(current.loc)
+            @column_delta = base_column - current.loc.column
+            add_offense(current, :expression) if @column_delta != 0
+          end
+        end
+      end
+
+      def start_of_line?(loc)
+        loc.expression.source_line[0...loc.column] =~ /^\s*$/
+      end
+
+      def autocorrect(node)
+        # We can't use the instance variable inside the lambda. That would
+        # just give each lambda the same reference and they would all get
+        # the last value of @column_delta. A local variable fixes the
+        # problem.
+        column_delta = @column_delta
+
+        @corrections << lambda do |corrector|
+          expr = node.loc.expression
+          each_line(expr) do |line_begin_pos, line|
+            range = calculate_range(expr, line_begin_pos, column_delta)
+            if column_delta > 0
+              unless range.source == "\n"
+                corrector.insert_before(range, ' ' * column_delta)
+              end
+            else
+              remove(range, corrector) if range.source =~ /^[ \t]+$/
+            end
+          end
+        end
+      end
+
+      def calculate_range(expr, line_begin_pos, column_delta)
+        starts_with_space = expr.source_buffer.source[line_begin_pos] =~ / /
+        pos_to_remove = if column_delta > 0 || starts_with_space
+                          line_begin_pos
+                        else
+                          line_begin_pos - column_delta.abs
+                        end
+        Parser::Source::Range.new(expr.source_buffer, pos_to_remove,
+                                  pos_to_remove + column_delta.abs)
+      end
+
+      def remove(range, corrector)
+        original_stderr = $stderr
+        $stderr = StringIO.new # Avoid error messages on console
+        corrector.remove(range)
+      rescue RuntimeError
+        range = Parser::Source::Range.new(range.source_buffer,
+                                          range.begin_pos + 1,
+                                          range.end_pos + 1)
+        retry if range.source =~ /^ +$/
+      ensure
+        $stderr = original_stderr
+      end
+
+      def each_line(expr)
+        offset = 0
+        expr.source.each_line do |line|
+          line_begin_pos = expr.begin_pos + offset
+          yield line_begin_pos, line
+          offset += line.length
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/mixin/autocorrect_unless_changing_ast.rb b/lib/rubocop/cop/mixin/autocorrect_unless_changing_ast.rb
new file mode 100644
index 0000000..1e4ffb9
--- /dev/null
+++ b/lib/rubocop/cop/mixin/autocorrect_unless_changing_ast.rb
@@ -0,0 +1,24 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    # This module does auto-correction of nodes that could become grammatically
+    # different after the correction. If the code change would alter the
+    # abstract syntax tree, it is not done.
+    module AutocorrectUnlessChangingAST
+      def autocorrect(node)
+        c = correction(node)
+        new_source = rewrite_node(node, c)
+
+        # Make the correction only if it doesn't change the AST.
+        @corrections << c if node == SourceParser.parse(new_source).ast
+      end
+
+      def rewrite_node(node, correction)
+        processed_source = SourceParser.parse(node.loc.expression.source)
+        c = correction(processed_source.ast)
+        Corrector.new(processed_source.buffer, [c]).rewrite
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/mixin/check_assignment.rb b/lib/rubocop/cop/mixin/check_assignment.rb
new file mode 100644
index 0000000..65b99f3
--- /dev/null
+++ b/lib/rubocop/cop/mixin/check_assignment.rb
@@ -0,0 +1,26 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    # Common functionality for checking assignment nodes.
+    module CheckAssignment
+      TYPES = Util::ASGN_NODES - [:casgn, :op_asgn]
+      TYPES.each do |type|
+        define_method("on_#{type}") do |node|
+          _lhs, rhs = *node
+          check_assignment(node, rhs)
+        end
+      end
+
+      def on_casgn(node)
+        _scope, _lhs, rhs = *node
+        check_assignment(node, rhs)
+      end
+
+      def on_op_asgn(node)
+        _lhs, _op, rhs = *node
+        check_assignment(node, rhs)
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/mixin/check_methods.rb b/lib/rubocop/cop/mixin/check_methods.rb
new file mode 100644
index 0000000..273ccb4
--- /dev/null
+++ b/lib/rubocop/cop/mixin/check_methods.rb
@@ -0,0 +1,18 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    # Common functionality for checking instance methods and singeton methods.
+    module CheckMethods
+      def on_def(node)
+        method_name, args, body = *node
+        check(node, method_name, args, body)
+      end
+
+      def on_defs(node)
+        _scope, method_name, args, body = *node
+        check(node, method_name, args, body)
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/mixin/code_length.rb b/lib/rubocop/cop/mixin/code_length.rb
new file mode 100644
index 0000000..66d7b40
--- /dev/null
+++ b/lib/rubocop/cop/mixin/code_length.rb
@@ -0,0 +1,33 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    # Common functionality for checking length of code segments.
+    module CodeLength
+      include ConfigurableMax
+
+      def max_length
+        cop_config['Max']
+      end
+
+      def count_comments?
+        cop_config['CountComments']
+      end
+
+      def check(node, *_)
+        length = code_length(node)
+        if length > max_length
+          add_offense(node, :keyword, format(message, length,
+                                             max_length)) do
+            self.max = length
+          end
+        end
+      end
+
+      # Returns true for lines that shall not be included in the count.
+      def irrelevant_line(source_line)
+        source_line.blank? || !count_comments? && comment_line?(source_line)
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/mixin/configurable_enforced_style.rb b/lib/rubocop/cop/mixin/configurable_enforced_style.rb
new file mode 100644
index 0000000..ffe8372
--- /dev/null
+++ b/lib/rubocop/cop/mixin/configurable_enforced_style.rb
@@ -0,0 +1,53 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    # Handles `EnforcedStyle` configuration parameters.
+    module ConfigurableEnforcedStyle
+      def opposite_style_detected
+        self.config_to_allow_offenses ||=
+          { parameter_name => alternative_style.to_s }
+        both_styles_detected if config_to_allow_offenses['Enabled']
+      end
+
+      def correct_style_detected
+        # Enabled:true indicates, later when the opposite style is detected,
+        # that the correct style is used somewhere.
+        self.config_to_allow_offenses ||= { 'Enabled' => true }
+        both_styles_detected if config_to_allow_offenses[parameter_name]
+      end
+
+      def both_styles_detected
+        # Both correct and opposite styles exist.
+        self.config_to_allow_offenses = { 'Enabled' => false }
+      end
+
+      def unrecognized_style_detected
+        # All we can do is to disable.
+        self.config_to_allow_offenses = { 'Enabled' => false }
+      end
+
+      def style
+        s = cop_config[parameter_name]
+        if cop_config['SupportedStyles'].include?(s)
+          s.to_sym
+        else
+          fail "Unknown style #{s} selected!"
+        end
+      end
+
+      def alternative_style
+        a = cop_config['SupportedStyles'].map(&:to_sym)
+        if a.size != 2
+          fail 'alternative_style can only be used when there are exactly ' \
+               '2 SupportedStyles'
+        end
+        style == a.first ? a.last : a.first
+      end
+
+      def parameter_name
+        'EnforcedStyle'
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/mixin/configurable_max.rb b/lib/rubocop/cop/mixin/configurable_max.rb
new file mode 100644
index 0000000..91b9ead
--- /dev/null
+++ b/lib/rubocop/cop/mixin/configurable_max.rb
@@ -0,0 +1,19 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    # Handles `Max` configuration parameters, especially setting them to an
+    # appropriate value with --auto-gen-config.
+    module ConfigurableMax
+      def max=(value)
+        cfg = self.config_to_allow_offenses ||= {}
+        value = [cfg[parameter_name], value].max if cfg[parameter_name]
+        cfg[parameter_name] = value
+      end
+
+      def parameter_name
+        'Max'
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/mixin/configurable_naming.rb b/lib/rubocop/cop/mixin/configurable_naming.rb
new file mode 100644
index 0000000..e7cfe9a
--- /dev/null
+++ b/lib/rubocop/cop/mixin/configurable_naming.rb
@@ -0,0 +1,45 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    # This module provides functionality for checking if names match the
+    # configured EnforcedStyle.
+    module ConfigurableNaming
+      include ConfigurableEnforcedStyle
+
+      SNAKE_CASE = /^@?[\da-z_]+[!?=]?$/
+      CAMEL_CASE = /^@?[a-z][\da-zA-Z]+[!?=]?$/
+
+      def check(node, range)
+        return unless range
+
+        name = range.source.to_sym
+        return if operator?(name)
+
+        if matches_config?(name)
+          correct_style_detected
+        else
+          add_offense(node, range, message(style)) do
+            opposite_style_detected
+          end
+        end
+      end
+
+      def matches_config?(name)
+        name =~ (style == :snake_case ? SNAKE_CASE : CAMEL_CASE)
+      end
+
+      # Returns a range containing the method name after the given regexp and
+      # a dot.
+      def after_dot(node, method_name_length, regexp)
+        expr = node.loc.expression
+        match = /\A#{regexp}\s*\.\s*/.match(expr.source)
+        return unless match
+        offset = match[0].length
+        begin_pos = expr.begin_pos + offset
+        Parser::Source::Range.new(expr.source_buffer, begin_pos,
+                                  begin_pos + method_name_length)
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/mixin/if_node.rb b/lib/rubocop/cop/mixin/if_node.rb
new file mode 100644
index 0000000..8dba070
--- /dev/null
+++ b/lib/rubocop/cop/mixin/if_node.rb
@@ -0,0 +1,25 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    # Common functionality for checking if nodes.
+    module IfNode
+      def modifier_if?(node)
+        node.loc.end.nil?
+      end
+
+      def ternary_op?(node)
+        node.loc.respond_to?(:question)
+      end
+
+      def elsif?(node)
+        node.loc.respond_to?(:keyword) && node.loc.keyword &&
+          node.loc.keyword.is?('elsif')
+      end
+
+      def if_else?(node)
+        node.loc.respond_to?(:else) && node.loc.else
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/mixin/if_then_else.rb b/lib/rubocop/cop/mixin/if_then_else.rb
new file mode 100644
index 0000000..3b27c12
--- /dev/null
+++ b/lib/rubocop/cop/mixin/if_then_else.rb
@@ -0,0 +1,23 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    # Common functionality for cops checking if and unless statements.
+    module IfThenElse
+      def on_if(node)
+        check(node)
+      end
+
+      def on_unless(node)
+        check(node)
+      end
+
+      def check(node)
+        # We won't check modifier or ternary conditionals.
+        return unless node.loc.expression.source =~ /\A(if|unless)\b/
+        return unless offending_line(node)
+        add_offense(node, :expression, error_message(node))
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/mixin/negative_conditional.rb b/lib/rubocop/cop/mixin/negative_conditional.rb
new file mode 100644
index 0000000..d382247
--- /dev/null
+++ b/lib/rubocop/cop/mixin/negative_conditional.rb
@@ -0,0 +1,24 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    # Some common code shared between FavorUnlessOverNegatedIf and
+    # FavorUntilOverNegatedWhile.
+    module NegativeConditional
+      def check(node)
+        condition, _body, _rest = *node
+
+        # Look at last expression of contents if there's a parenthesis
+        # around condition.
+        condition = condition.children.last while condition.type == :begin
+
+        if condition.type == :send
+          _object, method = *condition
+          if method == :! && !(node.loc.respond_to?(:else) && node.loc.else)
+            add_offense(node, :expression)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/mixin/parser_diagnostic.rb b/lib/rubocop/cop/mixin/parser_diagnostic.rb
new file mode 100644
index 0000000..abc37a5
--- /dev/null
+++ b/lib/rubocop/cop/mixin/parser_diagnostic.rb
@@ -0,0 +1,34 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    # Common functionality for cops which processes Parser's diagnostics.
+    # This mixin requires its user class to define `#relevant_diagnostic?`.
+    #
+    #     def relevant_diagnostic?(diagnostic)
+    #       diagnostic.reason == :my_interested_diagnostic_type
+    #     end
+    #
+    # If you want to use an alternative offense message rather than the one in
+    # Parser's diagnostic, define `#alternative_message`.
+    #
+    #     def alternative_message(diagnostic)
+    #       'My custom message'
+    #     end
+    module ParserDiagnostic
+      def investigate(processed_source)
+        processed_source.diagnostics.each do |d|
+          next unless relevant_diagnostic?(d)
+
+          message = if respond_to?(:alternative_message, true)
+                      alternative_message(d)
+                    else
+                      d.message.capitalize
+                    end
+
+          add_offense(nil, d.location, message, d.level)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/mixin/safe_assignment.rb b/lib/rubocop/cop/mixin/safe_assignment.rb
new file mode 100644
index 0000000..7e06a97
--- /dev/null
+++ b/lib/rubocop/cop/mixin/safe_assignment.rb
@@ -0,0 +1,19 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    # Common functionality for safe assignment. By safe assignment we mean
+    # putting parentheses around an assignment to indicate "I know I'm using an
+    # assignment as a condition. It's not a mistake."
+    module SafeAssignment
+      def safe_assignment?(node)
+        node.type == :begin && node.children.size == 1 &&
+          Util::EQUALS_ASGN_NODES.include?(node.children[0].type)
+      end
+
+      def safe_assignment_allowed?
+        cop_config['AllowSafeAssignment']
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/mixin/space_after_punctuation.rb b/lib/rubocop/cop/mixin/space_after_punctuation.rb
new file mode 100644
index 0000000..03b6041
--- /dev/null
+++ b/lib/rubocop/cop/mixin/space_after_punctuation.rb
@@ -0,0 +1,33 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    # Common functionality for cops checking for missing space after
+    # punctuation.
+    module SpaceAfterPunctuation
+      MSG = 'Space missing after %s.'
+
+      def investigate(processed_source)
+        processed_source.tokens.each_cons(2) do |t1, t2|
+          if kind(t1) && t1.pos.line == t2.pos.line &&
+              t2.pos.column == t1.pos.column + offset(t1) &&
+              ![:tRPAREN, :tRBRACK].include?(t2.type)
+            add_offense(t1, t1.pos, format(MSG, kind(t1)))
+          end
+        end
+      end
+
+      # The normal offset, i.e., the distance from the punctuation
+      # token where a space should be, is 1.
+      def offset(token)
+        1
+      end
+
+      def autocorrect(token)
+        @corrections << lambda do |corrector|
+          corrector.replace(token.pos, token.pos.source + ' ')
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/mixin/space_inside.rb b/lib/rubocop/cop/mixin/space_inside.rb
new file mode 100644
index 0000000..2bcef82
--- /dev/null
+++ b/lib/rubocop/cop/mixin/space_inside.rb
@@ -0,0 +1,35 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    # Common functionality for checking for spaces inside various
+    # kinds of parentheses.
+    module SpaceInside
+      include SurroundingSpace
+      MSG = 'Space inside %s detected.'
+
+      def investigate(processed_source)
+        @processed_source = processed_source
+        left, right, kind = specifics
+        processed_source.tokens.each_cons(2) do |t1, t2|
+          if t1.type == left || t2.type == right
+            # If the second token is a comment, that means that a line break
+            # follows, and that the rules for space inside don't apply.
+            next if t2.type == :tCOMMENT
+
+            if t2.pos.line == t1.pos.line && space_between?(t1, t2)
+              range = Parser::Source::Range.new(processed_source.buffer,
+                                                t1.pos.end_pos,
+                                                t2.pos.begin_pos)
+              add_offense(range, range, format(MSG, kind))
+            end
+          end
+        end
+      end
+
+      def autocorrect(range)
+        @corrections << ->(corrector) { corrector.remove(range) }
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/mixin/statement_modifier.rb b/lib/rubocop/cop/mixin/statement_modifier.rb
new file mode 100644
index 0000000..f1bba3e
--- /dev/null
+++ b/lib/rubocop/cop/mixin/statement_modifier.rb
@@ -0,0 +1,60 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    # Common functionality for modifier cops.
+    module StatementModifier
+      include IfNode
+
+      # TODO: Extremely ugly solution that needs lots of polish.
+      def check(sexp, comments)
+        case sexp.loc.keyword.source
+        when 'if'     then cond, body, _else = *sexp
+        when 'unless' then cond, _else, body = *sexp
+        else               cond, body = *sexp
+        end
+
+        return false if length(sexp) > 3
+
+        body_length = body_length(body)
+
+        return false if body_length == 0
+
+        on_node(:lvasgn, cond) do
+          return false
+        end
+
+        indentation = sexp.loc.keyword.column
+        kw_length = sexp.loc.keyword.size
+        cond_length = cond.loc.expression.size
+        space = 1
+        total = indentation + body_length + space + kw_length + space +
+          cond_length
+        total <= max_line_length && !body_has_comment?(body, comments)
+      end
+
+      def max_line_length
+        cop_config && cop_config['MaxLineLength'] ||
+        config.for_cop('LineLength')['Max']
+      end
+
+      def length(sexp)
+        sexp.loc.expression.source.lines.to_a.size
+      end
+
+      def body_length(body)
+        if body && body.loc.expression
+          body.loc.expression.size
+        else
+          0
+        end
+      end
+
+      def body_has_comment?(body, comments)
+        comment_lines = comments.map(&:location).map(&:line)
+        body_line = body.loc.expression.line
+        comment_lines.include?(body_line)
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/mixin/string_help.rb b/lib/rubocop/cop/mixin/string_help.rb
new file mode 100644
index 0000000..75ae1ef
--- /dev/null
+++ b/lib/rubocop/cop/mixin/string_help.rb
@@ -0,0 +1,32 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    # Classes that include this module just implement functions to determine
+    # what is an offense and how to do auto-correction. They get help with
+    # adding offenses for the faulty string nodes, and with filtering out
+    # nodes.
+    module StringHelp
+      def on_str(node)
+        # Constants like __FILE__ are handled as strings,
+        # but don't respond to begin.
+        return unless node.loc.respond_to?(:begin) && node.loc.begin
+        return if part_of_ignored_node?(node)
+
+        if offense?(node)
+          add_offense(node, :expression) { opposite_style_detected }
+        else
+          correct_style_detected
+        end
+      end
+
+      def on_dstr(node)
+        ignore_node(node)
+      end
+
+      def on_regexp(node)
+        ignore_node(node)
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/mixin/surrounding_space.rb b/lib/rubocop/cop/mixin/surrounding_space.rb
new file mode 100644
index 0000000..11563c8
--- /dev/null
+++ b/lib/rubocop/cop/mixin/surrounding_space.rb
@@ -0,0 +1,42 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    # Common functionality for checking surrounding space.
+    module SurroundingSpace
+      def space_between?(t1, t2)
+        char_preceding_2nd_token =
+          @processed_source[t2.pos.line - 1][t2.pos.column - 1]
+        if char_preceding_2nd_token == '+' && t1.type != :tPLUS
+          # Special case. A unary plus is not present in the tokens.
+          char_preceding_2nd_token =
+            @processed_source[t2.pos.line - 1][t2.pos.column - 2]
+        end
+        t2.pos.line > t1.pos.line || char_preceding_2nd_token =~ /[ \t]/
+      end
+
+      def index_of_first_token(node)
+        b = node.loc.expression.begin
+        token_table[[b.line, b.column]]
+      end
+
+      def index_of_last_token(node)
+        e = node.loc.expression.end
+        (0...e.column).to_a.reverse.find do |c|
+          ix = token_table[[e.line, c]]
+          return ix if ix
+        end
+      end
+
+      def token_table
+        @token_table ||= begin
+          table = {}
+          @processed_source.tokens.each_with_index do |t, ix|
+            table[[t.pos.line, t.pos.column]] = ix
+          end
+          table
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/offense.rb b/lib/rubocop/cop/offense.rb
new file mode 100644
index 0000000..ae619bf
--- /dev/null
+++ b/lib/rubocop/cop/offense.rb
@@ -0,0 +1,119 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    # An offense represents a style violation detected by RuboCop.
+    class Offense
+      include Comparable
+
+      # @api public
+      #
+      # @!attribute [r] severity
+      #
+      # @return [Rubocop::Cop::Severity]
+      attr_reader :severity
+
+      # @api public
+      #
+      # @!attribute [r] location
+      #
+      # @return [Parser::Source::Range]
+      #   the location where the violation is detected.
+      #
+      # @see http://rubydoc.info/github/whitequark/parser/Parser/Source/Range
+      #   Parser::Source::Range
+      attr_reader :location
+
+      # @api public
+      #
+      # @!attribute [r] message
+      #
+      # @return [String]
+      #   human-readable message
+      #
+      # @example
+      #   'Line is too long. [90/79]'
+      attr_reader :message
+
+      # @api public
+      #
+      # @!attribute [r] cop_name
+      #
+      # @return [String]
+      #   a cop class name without namespace.
+      #   i.e. type of the violation.
+      #
+      # @example
+      #   'LineLength'
+      attr_reader :cop_name
+
+      # @api public
+      #
+      # @!attribute [r] corrected
+      #
+      # @return [Boolean]
+      #   whether this offense is automatically corrected.
+      attr_reader :corrected
+      alias_method :corrected?, :corrected
+
+      # @api private
+      attr_reader :line
+
+      # @api private
+      attr_reader :column
+
+      # @api private
+      def initialize(severity, location, message, cop_name, corrected = false)
+        @severity = Rubocop::Cop::Severity.new(severity)
+        @location = location.freeze
+        @line = location.line.freeze
+        @column = location.column.freeze
+        @message = message.freeze
+        @cop_name = cop_name.freeze
+        @corrected = corrected.freeze
+        freeze
+      end
+
+      # @api private
+      # This is just for debugging purpose.
+      def to_s
+        format('%s:%3d:%3d: %s',
+               severity.code, line, real_column, message)
+      end
+
+      # @api private
+      #
+      # Internally we use column number that start at 0, but when
+      # outputting column numbers, we want them to start at 1. One
+      # reason is that editors, such as Emacs, expect this.
+      def real_column
+        column + 1
+      end
+
+      # @api public
+      #
+      # @return [Boolean]
+      #   returns `true` if two offenses contain same attributes
+      def ==(other)
+        severity == other.severity && line == other.line &&
+          column == other.column && message == other.message &&
+          cop_name == other.cop_name
+      end
+
+      # @api public
+      #
+      # Returns `-1`, `0` or `+1`
+      # if this offense is less than, equal to, or greater than `other`.
+      #
+      # @return [Integer]
+      #   comparison result
+      def <=>(other)
+        [:line, :column, :cop_name, :message].each do |attribute|
+          result = send(attribute) <=> other.send(attribute)
+          return result unless result == 0
+        end
+        0
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/rails/action_filter.rb b/lib/rubocop/cop/rails/action_filter.rb
new file mode 100644
index 0000000..f534f80
--- /dev/null
+++ b/lib/rubocop/cop/rails/action_filter.rb
@@ -0,0 +1,73 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Rails
+      # This cop enforces the consistent use of action filters methods.
+      #
+      # The cop is configurable and the enforce the use of older
+      # something_filter methods or the newer something_action methods.
+      class ActionFilter < Cop
+        include ConfigurableEnforcedStyle
+
+        MSG = 'Prefer `%s` over `%s`.'
+
+        FILTER_METHODS = [:before_filter, :skip_before_filter,
+                          :after_filter, :around_filter]
+
+        ACTION_METHODS = [:before_action, :skip_before_action,
+                          :after_action, :around_action]
+
+        def on_block(node)
+          method, _args, _body = *node
+
+          check_method_node(method)
+        end
+
+        def on_send(node)
+          receiver, _method_name, *_args = *node
+
+          check_method_node(node) if receiver.nil?
+        end
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            corrector.replace(node.loc.selector,
+                              preferred_method(node.loc.selector.source).to_s)
+          end
+        end
+
+        private
+
+        def check_method_node(node)
+          _receiver, method_name, *_args = *node
+
+          if offending_method?(method_name)
+            add_offense(
+              node, :selector,
+              format(MSG,
+                     preferred_method(method_name),
+                     method_name)
+            )
+          end
+        end
+
+        def offending_method?(method_name)
+          bad_methods.include?(method_name)
+        end
+
+        def bad_methods
+          style == :action ? FILTER_METHODS : ACTION_METHODS
+        end
+
+        def good_methods
+          style == :action ? ACTION_METHODS : FILTER_METHODS
+        end
+
+        def preferred_method(method)
+          good_methods[bad_methods.index(method.to_sym)]
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/rails/default_scope.rb b/lib/rubocop/cop/rails/default_scope.rb
new file mode 100644
index 0000000..2556db3
--- /dev/null
+++ b/lib/rubocop/cop/rails/default_scope.rb
@@ -0,0 +1,35 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Rails
+      # This cop checks for default_scope calls when it was passed
+      # a lambda or a proc instead of a block.
+      #
+      # @example
+      #
+      #   # incorrect
+      #   default_scope -> { something }
+      #
+      #   # correct
+      #   default_scope { something }
+      class DefaultScope < Cop
+        MSG = '`default_scope` expects a block as its sole argument.'
+
+        def on_send(node)
+          return unless command?(:default_scope, node)
+
+          _receiver, _method_name, *args = *node
+
+          return unless args.size == 1
+
+          first_arg = args[0]
+
+          if first_arg.type != :block || lambda_or_proc?(first_arg)
+            add_offense(first_arg, :expression)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/rails/has_and_belongs_to_many.rb b/lib/rubocop/cop/rails/has_and_belongs_to_many.rb
new file mode 100644
index 0000000..6dd1b5d
--- /dev/null
+++ b/lib/rubocop/cop/rails/has_and_belongs_to_many.rb
@@ -0,0 +1,18 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Rails
+      # This cop checks for the use of the has_and_belongs_to_many macro.
+      class HasAndBelongsToMany < Cop
+        MSG = 'Prefer `has_many :through` to `has_and_belongs_to_many`.'
+
+        def on_send(node)
+          if command?(:has_and_belongs_to_many, node)
+            add_offense(node, :selector)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/rails/output.rb b/lib/rubocop/cop/rails/output.rb
new file mode 100644
index 0000000..49d5a50
--- /dev/null
+++ b/lib/rubocop/cop/rails/output.rb
@@ -0,0 +1,26 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Rails
+      # This cop checks for the use of output calls like puts and print
+      class Output < Cop
+        MSG = 'Do not write to stdout. Use Rails\' logger if you want to log.'
+
+        BLACKLIST = [:puts,
+                     :print,
+                     :p,
+                     :pp,
+                     :pretty_print]
+
+        def on_send(node)
+          receiver, method_name, *_args = *node
+
+          if receiver.nil? && BLACKLIST.include?(method_name)
+            add_offense(node, :selector)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/rails/read_write_attribute.rb b/lib/rubocop/cop/rails/read_write_attribute.rb
new file mode 100644
index 0000000..34e8a9b
--- /dev/null
+++ b/lib/rubocop/cop/rails/read_write_attribute.rb
@@ -0,0 +1,43 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Rails
+      # This cop checks for the use of the read_attribute or
+      # write_attribute methods.
+      #
+      # @example
+      #
+      #   # bad
+      #   x = read_attributed(:attr)
+      #   write_attribute(:attr, val)
+      #
+      #   # good
+      #   x = self[:attr]
+      #   self[:attr] = val
+      class ReadWriteAttribute < Cop
+        MSG = 'Prefer `%s` over `%s`.'
+
+        def on_send(node)
+          receiver, method_name, *_args = *node
+
+          return if receiver
+
+          if [:read_attribute, :write_attribute].include?(method_name)
+            add_offense(node, :selector)
+          end
+        end
+
+        def message(node)
+          _receiver, method_name, *_args = *node
+
+          if method_name == :read_attribute
+            format(MSG, 'self[:attr]', 'read_attribute(:attr)')
+          else
+            format(MSG, 'self[:attr] = val', 'write_attribute(:attr, var)')
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/rails/scope_args.rb b/lib/rubocop/cop/rails/scope_args.rb
new file mode 100644
index 0000000..3d44938
--- /dev/null
+++ b/lib/rubocop/cop/rails/scope_args.rb
@@ -0,0 +1,33 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Rails
+      # This cop checks for scope calls where it was passed
+      # a method (usually a scope) instead of a lambda/proc.
+      #
+      # @example
+      #
+      #   # bad
+      #   scope :something, where(something: true)
+      #
+      #   # good
+      #   scope :something, -> { where(something: true) }
+      class ScopeArgs < Cop
+        MSG = 'Use `lambda`/`proc` instead of a plain method call.'
+
+        def on_send(node)
+          return unless command?(:scope, node)
+
+          _receiver, _method_name, *args = *node
+
+          return unless args.size == 2
+
+          second_arg = args[1]
+
+          add_offense(second_arg, :expression) if second_arg.type == :send
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/rails/validation.rb b/lib/rubocop/cop/rails/validation.rb
new file mode 100644
index 0000000..c2c85a4
--- /dev/null
+++ b/lib/rubocop/cop/rails/validation.rb
@@ -0,0 +1,31 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Rails
+      # This cop checks for the use of old-style attribute validation macros.
+      class Validation < Cop
+        MSG = 'Use the new "sexy" validations (`validates` ...).'
+
+        BLACKLIST = [:validates_acceptance_of,
+                     :validates_confirmation_of,
+                     :validates_exclusion_of,
+                     :validates_format_of,
+                     :validates_inclusion_of,
+                     :validates_length_of,
+                     :validates_numericality_of,
+                     :validates_presence_of,
+                     :validates_size_of,
+                     :validates_uniqueness_of]
+
+        def on_send(node)
+          receiver, method_name, *_args = *node
+
+          if receiver.nil? && BLACKLIST.include?(method_name)
+            add_offense(node, :selector)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/severity.rb b/lib/rubocop/cop/severity.rb
new file mode 100644
index 0000000..d991308
--- /dev/null
+++ b/lib/rubocop/cop/severity.rb
@@ -0,0 +1,76 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    # Severity class is simple value object about severity
+    class Severity
+      include Comparable
+
+      # @api private
+      NAMES = [:refactor, :convention, :warning, :error, :fatal]
+
+      # @api private
+      CODE_TABLE = { R: :refactor, C: :convention,
+                     W: :warning, E: :error, F: :fatal }
+
+      # @api public
+      #
+      # @!attribute [r] name
+      #
+      # @return [Symbol]
+      #   severity.
+      #   any of `:refactor`, `:convention`, `:warning`, `:error` or `:fatal`.
+      attr_reader :name
+
+      # @api private
+      def self.name_from_code(code)
+        name = code.to_sym
+        CODE_TABLE[name] || name
+      end
+
+      # @api private
+      def initialize(name_or_code)
+        name = Severity.name_from_code(name_or_code)
+        unless NAMES.include?(name)
+          fail ArgumentError, "Unknown severity: #{name}"
+        end
+        @name = name.freeze
+        freeze
+      end
+
+      # @api private
+      def to_s
+        @name.to_s
+      end
+
+      # @api private
+      def code
+        @name.to_s[0].upcase
+      end
+
+      # @api private
+      def level
+        NAMES.index(name) + 1
+      end
+
+      # @api private
+      def ==(other)
+        if other.is_a?(Symbol)
+          @name == other
+        else
+          @name == other.name
+        end
+      end
+
+      # @api private
+      def hash
+        @name.hash
+      end
+
+      # @api private
+      def <=>(other)
+        level <=> other.level
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/access_modifier_indentation.rb b/lib/rubocop/cop/style/access_modifier_indentation.rb
new file mode 100644
index 0000000..76d525a
--- /dev/null
+++ b/lib/rubocop/cop/style/access_modifier_indentation.rb
@@ -0,0 +1,94 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # Modifiers should be indented as deep as method definitions, or as deep
+      # as the class/module keyword, depending on configuration.
+      class AccessModifierIndentation < Cop
+        include AutocorrectAlignment
+        include ConfigurableEnforcedStyle
+
+        MSG = '%s access modifiers like `%s`.'
+
+        PRIVATE_NODE = s(:send, nil, :private)
+        PROTECTED_NODE = s(:send, nil, :protected)
+        PUBLIC_NODE = s(:send, nil, :public)
+
+        def on_class(node)
+          _name, _base_class, body = *node
+          check_body(body, node)
+        end
+
+        def on_sclass(node)
+          _name, body = *node
+          check_body(body, node)
+        end
+
+        def on_module(node)
+          _name, body = *node
+          check_body(body, node)
+        end
+
+        def on_block(node)
+          _method, _args, body = *node
+          check_body(body, node) if class_constructor?(node)
+        end
+
+        def self.modifier_node?(node)
+          [PRIVATE_NODE, PROTECTED_NODE, PUBLIC_NODE].include?(node)
+        end
+
+        private
+
+        def check_body(body, node)
+          return if body.nil? # Empty class etc.
+
+          modifiers = body.children.select { |c| self.class.modifier_node?(c) }
+          class_column = node.loc.expression.column
+
+          modifiers.each { |modifier| check_modifier(modifier, class_column) }
+        end
+
+        def check_modifier(send_node, class_start_col)
+          access_modifier_start_col = send_node.loc.expression.column
+          offset = access_modifier_start_col - class_start_col
+
+          @column_delta = expected_indent_offset - offset
+          if @column_delta == 0
+            correct_style_detected
+          else
+            add_offense(send_node, :expression) do
+              if offset == unexpected_indent_offset
+                opposite_style_detected
+              else
+                unrecognized_style_detected
+              end
+            end
+          end
+        end
+
+        def message(node)
+          format(MSG, style.capitalize, node.loc.selector.source)
+        end
+
+        def class_constructor?(block_node)
+          send_node = block_node.children.first
+          receiver_node, method_name, *_ = *send_node
+          return false unless method_name == :new
+          %w(Class Module).include?(Util.const_name(receiver_node))
+        end
+
+        def expected_indent_offset
+          style == :outdent ? 0 : IndentationWidth::CORRECT_INDENTATION
+        end
+
+        # An offset that is not expected, but correct if the configuration is
+        # changed.
+        def unexpected_indent_offset
+          IndentationWidth::CORRECT_INDENTATION - expected_indent_offset
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/accessor_method_name.rb b/lib/rubocop/cop/style/accessor_method_name.rb
new file mode 100644
index 0000000..86e5882
--- /dev/null
+++ b/lib/rubocop/cop/style/accessor_method_name.rb
@@ -0,0 +1,45 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop makes sure that accessor methods are named properly.
+      #
+      # @example
+      #   # bad
+      #   def set_attribute(value) ...
+      #
+      #   # good
+      #   def attribute=(value)
+      #
+      #   # bad
+      #   def get_attribute ...
+      #
+      #   # good
+      #   def attribute ...
+      class AccessorMethodName < Cop
+        include CheckMethods
+
+        private
+
+        def check(node, method_name, args, _body)
+          if bad_reader_name?(method_name.to_s, args)
+            add_offense(node, :name,
+                        'Do not prefix reader method names with `get_`.')
+          elsif bad_writer_name?(method_name.to_s, args)
+            add_offense(node, :name,
+                        'Do not prefix writer method names with `set_`.')
+          end
+        end
+
+        def bad_reader_name?(method_name, args)
+          method_name.start_with?('get_') && args.to_a.empty?
+        end
+
+        def bad_writer_name?(method_name, args)
+          method_name.start_with?('set_') && args.to_a.one?
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/alias.rb b/lib/rubocop/cop/style/alias.rb
new file mode 100644
index 0000000..3ac7e48
--- /dev/null
+++ b/lib/rubocop/cop/style/alias.rb
@@ -0,0 +1,48 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # The purpose of the this cop is advise the use of
+      # alias_method over the alias keyword whenever possible.
+      class Alias < Cop
+        MSG = 'Use `alias_method` instead of `alias`.'
+
+        def on_block(node)
+          method, _args, body = *node
+          _receiver, method_name = *method
+
+          # using alias is the only option in certain scenarios
+          # in such scenarios we don't want to report an offense
+          if method_name == :instance_exec
+            on_node(:alias, body) { |n| ignore_node(n) }
+          end
+        end
+
+        def on_alias(node)
+          return if ignored_node?(node)
+
+          # alias_method can't be used with global variables
+          new, old = *node
+
+          return if new.type == :gvar && old.type == :gvar
+
+          add_offense(node, :keyword)
+        end
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            # replace alias with alias_method
+            corrector.replace(node.loc.keyword, 'alias_method')
+            # insert a comma
+            new, old = *node
+            corrector.insert_after(new.loc.expression, ',')
+            # convert bareword arguments to symbols
+            corrector.replace(new.loc.expression, ":#{new.children.first}")
+            corrector.replace(old.loc.expression, ":#{old.children.first}")
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/align_array.rb b/lib/rubocop/cop/style/align_array.rb
new file mode 100644
index 0000000..bd117c0
--- /dev/null
+++ b/lib/rubocop/cop/style/align_array.rb
@@ -0,0 +1,20 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # Here we check if the elements of a multi-line array literal are
+      # aligned.
+      class AlignArray < Cop
+        include AutocorrectAlignment
+
+        MSG = 'Align the elements of an array literal if they span more ' \
+              'than one line.'
+
+        def on_array(node)
+          check_alignment(node.children)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/align_hash.rb b/lib/rubocop/cop/style/align_hash.rb
new file mode 100644
index 0000000..5649e26
--- /dev/null
+++ b/lib/rubocop/cop/style/align_hash.rb
@@ -0,0 +1,257 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # Here we check if the keys, separators, and values of a multi-line hash
+      # literal are aligned.
+      class AlignHash < Cop
+        include IgnoredNode
+
+        # Handles calculation of deltas (deviations from correct alignment)
+        # when the enforced style is 'key'.
+        class KeyAlignment
+          def checkable_layout(_node)
+            true
+          end
+
+          def deltas_for_first_pair(*_)
+            {} # The first pair is always considered correct.
+          end
+
+          def deltas(first_pair, prev_pair, current_pair)
+            if current_pair.loc.line == prev_pair.loc.line
+              {}
+            else
+              { key: first_pair.loc.column - current_pair.loc.column }
+            end
+          end
+        end
+
+        # Common functionality for the styles where not only keys, but also
+        # values are aligned.
+        class AlignmentOfValues
+          def checkable_layout(node)
+            !any_pairs_on_the_same_line?(node) && all_have_same_sparator?(node)
+          end
+
+          def deltas(first_pair, prev_pair, current_pair)
+            key_delta = key_delta(first_pair, current_pair)
+            current_separator = current_pair.loc.operator
+            separator_delta = separator_delta(first_pair, current_separator,
+                                              key_delta)
+            value_delta = value_delta(first_pair, current_pair) -
+              key_delta - separator_delta
+
+            { key: key_delta, separator: separator_delta, value: value_delta }
+          end
+
+          private
+
+          def separator_delta(first_pair, current_separator, key_delta)
+            if current_separator.is?(':')
+              0 # Colon follows directly after key
+            else
+              hash_rocket_delta(first_pair, current_separator) - key_delta
+            end
+          end
+
+          def any_pairs_on_the_same_line?(node)
+            lines_of_the_children = node.children.map do |pair|
+              key, _value = *pair
+              key.loc.line
+            end
+            lines_of_the_children.uniq.size < lines_of_the_children.size
+          end
+
+          def all_have_same_sparator?(node)
+            first_separator = node.children.first.loc.operator.source
+            node.children[1..-1].all? do |pair|
+              pair.loc.operator.is?(first_separator)
+            end
+          end
+        end
+
+        # Handles calculation of deltas when the enforced style is 'table'.
+        class TableAlignment < AlignmentOfValues
+          # The table style is the only one where the first key-value pair can
+          # be considered to have bad alignment.
+          def deltas_for_first_pair(first_pair, node)
+            key_widths = node.children.map do |pair|
+              key, _value = *pair
+              key.loc.expression.source.length
+            end
+            @max_key_width = key_widths.max
+
+            separator_delta = separator_delta(first_pair,
+                                              first_pair.loc.operator, 0)
+            {
+              separator: separator_delta,
+              value:     value_delta(first_pair, first_pair) - separator_delta
+            }
+          end
+
+          private
+
+          def key_delta(first_pair, current_pair)
+            first_pair.loc.column - current_pair.loc.column
+          end
+
+          def hash_rocket_delta(first_pair, current_separator)
+            first_pair.loc.column + @max_key_width + 1 -
+              current_separator.column
+          end
+
+          def value_delta(first_pair, current_pair)
+            first_key, _ = *first_pair
+            _, current_value = *current_pair
+            correct_value_column = first_key.loc.column +
+              spaced_separator(current_pair).length + @max_key_width
+            correct_value_column - current_value.loc.column
+          end
+
+          def spaced_separator(node)
+            node.loc.operator.is?('=>') ? ' => ' : ': '
+          end
+        end
+
+        # Handles calculation of deltas when the enforced style is 'separator'.
+        class SeparatorAlignment < AlignmentOfValues
+          def deltas_for_first_pair(first_pair, node)
+            {} # The first pair is always considered correct.
+          end
+
+          private
+
+          def key_delta(first_pair, current_pair)
+            key_end_column(first_pair) - key_end_column(current_pair)
+          end
+
+          def key_end_column(pair)
+            key, _value = *pair
+            key.loc.column + key.loc.expression.source.length
+          end
+
+          def hash_rocket_delta(first_pair, current_separator)
+            first_pair.loc.operator.column - current_separator.column
+          end
+
+          def value_delta(first_pair, current_pair)
+            _, first_value = *first_pair
+            _, current_value = *current_pair
+            first_value.loc.column - current_value.loc.column
+          end
+        end
+
+        MSG = 'Align the elements of a hash literal if they span more than ' \
+              'one line.'
+
+        def on_send(node)
+          if (last_child = node.children.last) && hash?(last_child) &&
+              ignore_last_argument_hash?(last_child)
+            ignore_node(last_child)
+          end
+        end
+
+        def on_hash(node)
+          return if ignored_node?(node)
+          return if node.children.empty?
+          return unless multiline?(node)
+
+          @alignment_for_hash_rockets ||=
+            new_alignment('EnforcedHashRocketStyle')
+          @alignment_for_colons ||= new_alignment('EnforcedColonStyle')
+
+          first_pair = node.children.first
+
+          unless @alignment_for_hash_rockets.checkable_layout(node) &&
+              @alignment_for_colons.checkable_layout(node)
+            return
+          end
+
+          @column_deltas = alignment_for(first_pair)
+            .deltas_for_first_pair(first_pair, node)
+          add_offense(first_pair, :expression) unless good_alignment?
+
+          node.children.each_cons(2) do |prev, current|
+            @column_deltas = alignment_for(current).deltas(first_pair, prev,
+                                                           current)
+            add_offense(current, :expression) unless good_alignment?
+          end
+        end
+
+        private
+
+        def ignore_last_argument_hash?(node)
+          case cop_config['EnforcedLastArgumentHashStyle']
+          when 'always_inspect'  then false
+          when 'always_ignore'   then true
+          when 'ignore_explicit' then explicit_hash?(node)
+          when 'ignore_implicit' then !explicit_hash?(node)
+          end
+        end
+
+        def hash?(node)
+          node.respond_to?(:type) && node.type == :hash
+        end
+
+        def explicit_hash?(node)
+          node.loc.begin
+        end
+
+        def multiline?(node)
+          node.loc.expression.source.include?("\n")
+        end
+
+        def alignment_for(pair)
+          if pair.loc.operator.is?('=>')
+            @alignment_for_hash_rockets
+          else
+            @alignment_for_colons
+          end
+        end
+
+        def autocorrect(node)
+          # We can't use the instance variable inside the lambda. That would
+          # just give each lambda the same reference and they would all get the
+          # last value of each. Some local variables fix the problem.
+          key_delta       = @column_deltas[:key] || 0
+          separator_delta = @column_deltas[:separator] || 0
+          value_delta     = @column_deltas[:value] || 0
+
+          key, value = *node
+
+          @corrections << lambda do |corrector|
+            adjust(corrector, key_delta, key.loc.expression)
+            adjust(corrector, separator_delta, node.loc.operator)
+            adjust(corrector, value_delta, value.loc.expression)
+          end
+        end
+
+        def new_alignment(key)
+          case cop_config[key]
+          when 'key'       then KeyAlignment.new
+          when 'table'     then TableAlignment.new
+          when 'separator' then SeparatorAlignment.new
+          else fail "Unknown #{key}: #{cop_config[key]}"
+          end
+        end
+
+        def adjust(corrector, delta, range)
+          if delta > 0
+            corrector.insert_before(range, ' ' * delta)
+          elsif delta < 0
+            range = Parser::Source::Range.new(range.source_buffer,
+                                              range.begin_pos - delta.abs,
+                                              range.begin_pos)
+            corrector.remove(range)
+          end
+        end
+
+        def good_alignment?
+          @column_deltas.values.compact.none? { |v| v != 0 }
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/align_parameters.rb b/lib/rubocop/cop/style/align_parameters.rb
new file mode 100644
index 0000000..37d7957
--- /dev/null
+++ b/lib/rubocop/cop/style/align_parameters.rb
@@ -0,0 +1,39 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # Here we check if the parameters on a multi-line method call are
+      # aligned.
+      class AlignParameters < Cop
+        include AutocorrectAlignment
+
+        MSG = 'Align the parameters of a method call if they span ' \
+              'more than one line.'
+
+        def on_send(node)
+          _receiver, method, *args = *node
+
+          return if method == :[]=
+          return if args.size <= 1
+
+          check_alignment(args, base_column(node, args))
+        end
+
+        private
+
+        def fixed_indentation?
+          cop_config['EnforcedStyle'] == 'with_fixed_indentation'
+        end
+
+        def base_column(node, args)
+          if fixed_indentation?
+            node.loc.column + 2
+          else
+            args.first.loc.column
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/and_or.rb b/lib/rubocop/cop/style/and_or.rb
new file mode 100644
index 0000000..5c6d615
--- /dev/null
+++ b/lib/rubocop/cop/style/and_or.rb
@@ -0,0 +1,44 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for uses of *and* and *or*.
+      class AndOr < Cop
+        include AutocorrectUnlessChangingAST
+
+        MSG = 'Use `%s` instead of `%s`.'
+
+        OPS = { 'and' => '&&', 'or' => '||' }
+
+        def on_and(node)
+          process_logical_op(node)
+        end
+
+        def on_or(node)
+          process_logical_op(node)
+        end
+
+        private
+
+        def process_logical_op(node)
+          op = node.loc.operator.source
+          op_type = node.type.to_s
+
+          if op == op_type
+            add_offense(node,
+                        :operator,
+                        format(MSG, OPS[op], op))
+          end
+        end
+
+        def correction(node)
+          lambda do |corrector|
+            replacement = (node.type == :and ? '&&' : '||')
+            corrector.replace(node.loc.operator, replacement)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/array_join.rb b/lib/rubocop/cop/style/array_join.rb
new file mode 100644
index 0000000..78bb487
--- /dev/null
+++ b/lib/rubocop/cop/style/array_join.rb
@@ -0,0 +1,25 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for uses of "*" as a substitute for *join*.
+      #
+      # Not all cases can reliably checked, due to Ruby's dynamic
+      # types, so we consider only cases when the first argument is an
+      # array literal or the second is a string literal.
+      class ArrayJoin < Cop
+        MSG = 'Favor `Array#join` over `Array#*`.'
+
+        def on_send(node)
+          receiver_node, method_name, *arg_nodes = *node
+
+          if receiver_node && receiver_node.type == :array &&
+              method_name == :* && arg_nodes[0].type == :str
+            add_offense(node, :selector)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/ascii_comments.rb b/lib/rubocop/cop/style/ascii_comments.rb
new file mode 100644
index 0000000..4dbe3e2
--- /dev/null
+++ b/lib/rubocop/cop/style/ascii_comments.rb
@@ -0,0 +1,19 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for non-ascii (non-English) characters
+      # in comments.
+      class AsciiComments < Cop
+        MSG = 'Use only ascii symbols in comments.'
+
+        def investigate(processed_source)
+          processed_source.comments.each do |comment|
+            add_offense(comment, :expression) unless comment.text.ascii_only?
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/ascii_identifiers.rb b/lib/rubocop/cop/style/ascii_identifiers.rb
new file mode 100644
index 0000000..b4337c3
--- /dev/null
+++ b/lib/rubocop/cop/style/ascii_identifiers.rb
@@ -0,0 +1,20 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for non-ascii characters in indentifier names.
+      class AsciiIdentifiers < Cop
+        MSG = 'Use only ascii symbols in identifiers.'
+
+        def investigate(processed_source)
+          processed_source.tokens.each do |t|
+            if t.type == :tIDENTIFIER && !t.text.ascii_only?
+              add_offense(nil, t.pos)
+            end
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/attr.rb b/lib/rubocop/cop/style/attr.rb
new file mode 100644
index 0000000..0dd6f78
--- /dev/null
+++ b/lib/rubocop/cop/style/attr.rb
@@ -0,0 +1,22 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for uses of Module#attr.
+      class Attr < Cop
+        MSG = 'Do not use `attr`. Use `attr_reader` instead.'
+
+        def on_send(node)
+          add_offense(node, :selector) if command?(:attr, node)
+        end
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            corrector.replace(node.loc.selector, 'attr_reader')
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/begin_block.rb b/lib/rubocop/cop/style/begin_block.rb
new file mode 100644
index 0000000..5106b13
--- /dev/null
+++ b/lib/rubocop/cop/style/begin_block.rb
@@ -0,0 +1,16 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for BEGIN blocks.
+      class BeginBlock < Cop
+        MSG = 'Avoid the use of `BEGIN` blocks.'
+
+        def on_preexe(node)
+          add_offense(node, :keyword)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/block_comments.rb b/lib/rubocop/cop/style/block_comments.rb
new file mode 100644
index 0000000..2eeaad7
--- /dev/null
+++ b/lib/rubocop/cop/style/block_comments.rb
@@ -0,0 +1,20 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop looks for uses of block comments (=begin...=end).
+      class BlockComments < Cop
+        MSG = 'Do not use block comments.'
+
+        def investigate(processed_source)
+          processed_source.comments.each do |comment|
+            if comment.text.start_with?('=begin')
+              add_offense(comment, :expression)
+            end
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/block_nesting.rb b/lib/rubocop/cop/style/block_nesting.rb
new file mode 100644
index 0000000..da61733
--- /dev/null
+++ b/lib/rubocop/cop/style/block_nesting.rb
@@ -0,0 +1,55 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for excessive nesting of conditional and looping
+      # constructs. Despite the cop's name, blocks are not considered as an
+      # extra level of nesting.
+      #
+      # The maximum level of nesting allowed is configurable.
+      class BlockNesting < Cop
+        include ConfigurableMax
+
+        NESTING_BLOCKS = [
+          :case, :if, :while, :while_post,
+          :until, :until_post, :for, :resbody
+        ]
+
+        def investigate(processed_source)
+          return unless processed_source.ast
+          max = cop_config['Max']
+          check_nesting_level(processed_source.ast, max, 0)
+        end
+
+        private
+
+        def check_nesting_level(node, max, current_level)
+          if NESTING_BLOCKS.include?(node.type)
+            unless node.loc.respond_to?(:keyword) &&
+                   node.loc.keyword.is?('elsif')
+              current_level += 1
+            end
+            if current_level > max
+              self.max = current_level
+              unless part_of_ignored_node?(node)
+                add_offense(node, :expression, message(max)) do
+                  ignore_node(node)
+                end
+              end
+            end
+          end
+          node.children.each do |child|
+            if child.is_a?(Parser::AST::Node)
+              check_nesting_level(child, max, current_level)
+            end
+          end
+        end
+
+        def message(max)
+          "Avoid more than #{max} levels of block nesting."
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/blocks.rb b/lib/rubocop/cop/style/blocks.rb
new file mode 100644
index 0000000..0f795c6
--- /dev/null
+++ b/lib/rubocop/cop/style/blocks.rb
@@ -0,0 +1,80 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # Check for uses of braces or do/end around single line or
+      # multi-line blocks.
+      class Blocks < Cop
+        include AutocorrectUnlessChangingAST
+
+        MULTI_LINE_MSG = 'Avoid using {...} for multi-line blocks.'
+        SINGLE_LINE_MSG = 'Prefer {...} over do...end for single-line blocks.'
+
+        def on_send(node)
+          _receiver, method_name, *args = *node
+          if args.any?
+            block = get_block(args.last)
+            if block && !parentheses?(node) && !operator?(method_name)
+              # If there are no parentheses around the arguments, then braces
+              # and do-end have different meaning due to how they bind, so we
+              # allow either.
+              ignore_node(block)
+            end
+          end
+        end
+
+        def on_block(node)
+          return if ignored_node?(node)
+
+          block_length = Util.block_length(node)
+          block_begin = node.loc.begin.source
+
+          if block_length > 0 && block_begin == '{'
+            add_offense(node, :begin, MULTI_LINE_MSG)
+          elsif block_length == 0 && block_begin != '{'
+            add_offense(node, :begin, SINGLE_LINE_MSG)
+          end
+        end
+
+        private
+
+        def correction(node)
+          lambda do |corrector|
+            b, e = node.loc.begin, node.loc.end
+            if b.is?('{')
+              # If the left brace is immediately preceded by a word character,
+              # then we need a space before `do` to get valid Ruby code.
+              if b.source_buffer.source[b.begin_pos - 1, 1] =~ /\w/
+                corrector.insert_before(b, ' ')
+              end
+              corrector.replace(b, 'do')
+              corrector.replace(e, 'end')
+            else
+              corrector.replace(b, '{')
+              corrector.replace(e, '}')
+            end
+          end
+        end
+
+        def get_block(node)
+          case node.type
+          when :block
+            node
+          when :send
+            receiver, _method_name, *_args = *node
+            get_block(receiver) if receiver
+          end
+        end
+
+        def parentheses?(send_node)
+          send_node.loc.begin
+        end
+
+        def operator?(method_name)
+          method_name =~ /^\W/
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/braces_around_hash_parameters.rb b/lib/rubocop/cop/style/braces_around_hash_parameters.rb
new file mode 100644
index 0000000..0af7b22
--- /dev/null
+++ b/lib/rubocop/cop/style/braces_around_hash_parameters.rb
@@ -0,0 +1,87 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for braces in method calls with hash parameters.
+      class BracesAroundHashParameters < Cop
+        include ConfigurableEnforcedStyle
+
+        def on_send(node)
+          _receiver, method_name, *args = *node
+
+          # Discard attr writer methods.
+          return if method_name.to_s.end_with?('=')
+          # Discard operator methods.
+          return if operator?(method_name)
+
+          # We care only for the last argument.
+          arg = args.last
+
+          check(arg, args) if non_empty_hash?(arg)
+        end
+
+        private
+
+        def check(arg, args)
+          if style == :no_braces
+            if !braces?(arg) || all_hashes?(args)
+              correct_style_detected
+            else
+              add_offense(arg, :expression,
+                          'Redundant curly braces around a hash parameter.') do
+                opposite_style_detected
+              end
+            end
+          elsif braces?(arg)
+            correct_style_detected
+          else
+            add_offense(arg, :expression,
+                        'Missing curly braces around a hash parameter.') do
+              opposite_style_detected
+            end
+          end
+        end
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            if style == :no_braces
+              corrector.remove(node.loc.begin)
+              corrector.remove(node.loc.end)
+              remove_trailing_comma(node, corrector)
+            elsif style == :braces
+              corrector.insert_before(node.loc.expression, '{')
+              corrector.insert_after(node.loc.expression, '}')
+            end
+          end
+        end
+
+        def remove_trailing_comma(node, corrector)
+          sb = node.loc.end.source_buffer
+          pos_after_last_pair = node.children.last.loc.expression.end_pos
+          range_after_last_pair =
+            Parser::Source::Range.new(sb, pos_after_last_pair,
+                                      node.loc.end.begin_pos)
+          trailing_comma_offset = range_after_last_pair.source =~ /,/
+          if trailing_comma_offset
+            comma_begin = pos_after_last_pair + trailing_comma_offset
+            corrector.remove(Parser::Source::Range.new(sb, comma_begin,
+                                                       comma_begin + 1))
+          end
+        end
+
+        def non_empty_hash?(arg)
+          arg && arg.type == :hash && arg.children.any?
+        end
+
+        def braces?(arg)
+          arg.loc.begin
+        end
+
+        def all_hashes?(args)
+          args.length > 1 && args.all? { |a| a.type == :hash }
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/case_equality.rb b/lib/rubocop/cop/style/case_equality.rb
new file mode 100644
index 0000000..99e1650
--- /dev/null
+++ b/lib/rubocop/cop/style/case_equality.rb
@@ -0,0 +1,18 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for uses of the case equality operator(===).
+      class CaseEquality < Cop
+        MSG = 'Avoid the use of the case equality operator `===`.'
+
+        def on_send(node)
+          _receiver, method_name, *_args = *node
+
+          add_offense(node, :selector) if method_name == :===
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/case_indentation.rb b/lib/rubocop/cop/style/case_indentation.rb
new file mode 100644
index 0000000..6720e6d
--- /dev/null
+++ b/lib/rubocop/cop/style/case_indentation.rb
@@ -0,0 +1,62 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks how the *when*s of a *case* expression
+      # are indented in relation to its *case* or *end* keyword.
+      #
+      # It will register a separate offense for each misaligned *when*.
+      class CaseIndentation < Cop
+        include ConfigurableEnforcedStyle
+
+        def on_case(case_node)
+          _condition, *whens, _else = *case_node
+
+          base = style
+          indent = cop_config['IndentOneStep']
+          base_column = base_column(case_node, base)
+
+          whens.each do |when_node|
+            check_when(when_node, case_node, base, indent, base_column)
+          end
+        end
+
+        private
+
+        def check_when(when_node, case_node, base, indent, base_column)
+          pos = when_node.loc.keyword
+          expected_column = base_column +
+            (indent ? IndentationWidth::CORRECT_INDENTATION : 0)
+          if pos.column == expected_column
+            correct_style_detected
+          else
+            msg = 'Indent `when` ' + if indent
+                                       "one step more than `#{base}`."
+                                     else
+                                       "as deep as `#{base}`."
+                                     end
+            add_offense(when_node, pos, msg) do
+              if pos.column == base_column(case_node, alternative_style)
+                opposite_style_detected
+              else
+                unrecognized_style_detected
+              end
+            end
+          end
+        end
+
+        def parameter_name
+          'IndentWhenRelativeTo'
+        end
+
+        def base_column(case_node, base)
+          case base
+          when :case then case_node.location.keyword.column
+          when :end  then case_node.location.end.column
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/character_literal.rb b/lib/rubocop/cop/style/character_literal.rb
new file mode 100644
index 0000000..1a02631
--- /dev/null
+++ b/lib/rubocop/cop/style/character_literal.rb
@@ -0,0 +1,42 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # Checks for uses of the character literal ?x.
+      class CharacterLiteral < Cop
+        include StringHelp
+
+        MSG = 'Do not use the character literal - use string literal instead.'
+
+        def offense?(node)
+          # we don't register an offense for things like ?\C-\M-d
+          node.loc.begin.is?('?') &&
+            node.loc.expression.source.size.between?(2, 3)
+        end
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            string = node.loc.expression.source[1..-1]
+
+            if string.length == 1 # normal character
+              corrector.replace(node.loc.expression, "'#{string}'")
+            elsif string.length == 2 # special character like \n
+              corrector.replace(node.loc.expression, %Q("#{string}"))
+            end
+          end
+        end
+
+        # Dummy implementation of method in ConfigurableEnforcedStyle that is
+        # called from StringHelp.
+        def opposite_style_detected
+        end
+
+        # Dummy implementation of method in ConfigurableEnforcedStyle that is
+        # called from StringHelp.
+        def correct_style_detected
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/class_and_module_camel_case.rb b/lib/rubocop/cop/style/class_and_module_camel_case.rb
new file mode 100644
index 0000000..dcc3b15
--- /dev/null
+++ b/lib/rubocop/cop/style/class_and_module_camel_case.rb
@@ -0,0 +1,29 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cops checks for class and module names with
+      # an underscore in them.
+      class ClassAndModuleCamelCase < Cop
+        MSG = 'Use CamelCase for classes and modules.'
+
+        def on_class(node)
+          check_name(node)
+        end
+
+        def on_module(node)
+          check_name(node)
+        end
+
+        private
+
+        def check_name(node)
+          name = node.loc.name.source
+
+          add_offense(node, :name) if name =~ /_/
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/class_and_module_children.rb b/lib/rubocop/cop/style/class_and_module_children.rb
new file mode 100644
index 0000000..d90318d
--- /dev/null
+++ b/lib/rubocop/cop/style/class_and_module_children.rb
@@ -0,0 +1,69 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks the style of children definitions at classes and
+      # modules. Basically there are two different styles:
+      #
+      # nested - have each child on its own line
+      #   class Foo
+      #     class Bar
+      #     end
+      #   end
+      #
+      # compact - combine definitions as much as possible
+      #   class Foo::Bar
+      #   end
+      #
+      # The compact style is only forced, for classes / modules with one child.
+      class ClassAndModuleChildren < Cop
+        include ConfigurableEnforcedStyle
+
+        NESTED_MSG = 'Use nested module/class definitions instead of ' \
+                     'compact style.'
+
+        COMPACT_MSG = 'Use compact module/class definition instead of ' \
+                      'nested style.'
+
+        def on_class(node)
+          _name, _superclass, body = *node
+          check_style(node, body)
+        end
+
+        def on_module(node)
+          _name, body = *node
+          check_style(node, body)
+        end
+
+        private
+
+        def check_style(node, body)
+          if style == :nested
+            check_nested_style(node)
+          else
+            check_compact_style(node, body)
+          end
+        end
+
+        def check_nested_style(node)
+          return unless compact_node_name?(node)
+          add_offense(node, :name, NESTED_MSG)
+        end
+
+        def check_compact_style(node, body)
+          return unless one_child?(node, body) && !compact_node_name?(node)
+          add_offense(node, :name, COMPACT_MSG)
+        end
+
+        def one_child?(node, body)
+          body && body.type != :begin
+        end
+
+        def compact_node_name?(node)
+          node.loc.name.source =~ /::/
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/class_length.rb b/lib/rubocop/cop/style/class_length.rb
new file mode 100644
index 0000000..fc8e344
--- /dev/null
+++ b/lib/rubocop/cop/style/class_length.rb
@@ -0,0 +1,49 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks if the length a class exceeds some maximum value.
+      # Comment lines can optionally be ignored.
+      # The maximum allowed length is configurable.
+      class ClassLength < Cop
+        include CodeLength
+
+        def on_class(node)
+          check(node)
+        end
+
+        private
+
+        def message
+          'Class definition is too long. [%d/%d]'
+        end
+
+        def code_length(node)
+          class_body_line_numbers = line_range(node).to_a[1...-1]
+
+          target_line_numbers = class_body_line_numbers -
+                                  line_numbers_of_inner_classes(node)
+
+          target_line_numbers.reduce(0) do |length, line_number|
+            source_line = processed_source[line_number]
+            next length if irrelevant_line(source_line)
+            length + 1
+          end
+        end
+
+        def line_numbers_of_inner_classes(node)
+          line_numbers = Set.new
+
+          on_node([:class, :module], node) do |inner_node|
+            next if inner_node.eql?(node)
+            line_range = line_range(inner_node)
+            line_numbers.merge(line_range)
+          end
+
+          line_numbers.to_a
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/class_methods.rb b/lib/rubocop/cop/style/class_methods.rb
new file mode 100644
index 0000000..7afd978
--- /dev/null
+++ b/lib/rubocop/cop/style/class_methods.rb
@@ -0,0 +1,56 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for uses of the class/module name instead of
+      # self, when defining class/module methods.
+      class ClassMethods < Cop
+        MSG = 'Use `self.%s` instead of `%s.%s`.'
+
+        def on_class(node)
+          _name, _superclass, body = *node
+          check(body)
+        end
+
+        def on_module(node)
+          _name, body = *node
+          check(body)
+        end
+
+        private
+
+        def check(node)
+          return unless node
+
+          if node.type == :defs
+            check_defs(node)
+          elsif node.type == :begin
+            defs_nodes = node.children.compact.select { |n| n.type == :defs }
+            defs_nodes.each { |n| check_defs(n) }
+          end
+        end
+
+        def check_defs(node)
+          definee, method_name, _args, _body = *node
+
+          if definee.type == :const
+            _, class_name = *definee
+            add_offense(definee, :name,
+                        message(class_name, method_name))
+          end
+        end
+
+        def message(class_name, method_name)
+          format(MSG, method_name, class_name, method_name)
+        end
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            corrector.replace(node.loc.name, 'self')
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/class_vars.rb b/lib/rubocop/cop/style/class_vars.rb
new file mode 100644
index 0000000..725b677
--- /dev/null
+++ b/lib/rubocop/cop/style/class_vars.rb
@@ -0,0 +1,23 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for uses of class variables. Offenses
+      # are signaled only on assignment to class variables to
+      # reduced the number of offenses that would be reported.
+      class ClassVars < Cop
+        MSG = 'Replace class var %s with a class instance var.'
+
+        def on_cvasgn(node)
+          add_offense(node, :name)
+        end
+
+        def message(node)
+          class_var, = *node
+          format(MSG, class_var)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/collection_methods.rb b/lib/rubocop/cop/style/collection_methods.rb
new file mode 100644
index 0000000..b86348d
--- /dev/null
+++ b/lib/rubocop/cop/style/collection_methods.rb
@@ -0,0 +1,73 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for uses of unidiomatic method names
+      # from the Enumerable module.
+      #
+      # The current definition of the check is flawed and should be
+      # enhanced by check for by blocks & procs as arguments of the
+      # methods.
+      class CollectionMethods < Cop
+        MSG = 'Prefer `%s` over `%s`.'
+
+        def on_block(node)
+          method, _args, _body = *node
+
+          check_method_node(method)
+        end
+
+        def on_send(node)
+          _receiver, _method_name, *args = *node
+
+          if args.size == 1 && args.first.type == :block_pass
+            check_method_node(node)
+          end
+        end
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            corrector.replace(node.loc.selector,
+                              preferred_method(node.loc.selector.source))
+          end
+        end
+
+        private
+
+        def check_method_node(node)
+          _receiver, method_name, *_args = *node
+
+          if preferred_methods[method_name]
+            add_offense(
+              node, :selector,
+              format(MSG,
+                     preferred_method(method_name),
+                     method_name)
+            )
+          end
+        end
+
+        def preferred_method(method)
+          preferred_methods[method.to_sym]
+        end
+
+        def preferred_methods
+          @preferred_methods ||=
+            begin
+              # Make sure default configuration 'foo' => 'bar' is removed from
+              # the total configuration if there is a 'bar' => 'foo' override.
+              default = default_cop_config['PreferredMethods']
+              merged = cop_config['PreferredMethods']
+              overrides = merged.values - default.values
+              merged.reject { |key, _| overrides.include?(key) }.symbolize_keys
+            end
+        end
+
+        def default_cop_config
+          ConfigLoader.default_configuration[cop_name]
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/colon_method_call.rb b/lib/rubocop/cop/style/colon_method_call.rb
new file mode 100644
index 0000000..7b3123c
--- /dev/null
+++ b/lib/rubocop/cop/style/colon_method_call.rb
@@ -0,0 +1,33 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for methods invoked via the :: operator instead
+      # of the . operator (like FileUtils::rmdir instead of FileUtils.rmdir).
+      class ColonMethodCall < Cop
+        MSG = 'Do not use `::` for method calls.'
+
+        def on_send(node)
+          receiver, _method_name, *_args = *node
+
+          # discard methods with nil receivers and op methods(like [])
+          return unless receiver && node.loc.dot && node.loc.dot.is?('::')
+          return if allowed_name(_method_name.to_s)
+
+          add_offense(node, :dot)
+        end
+
+        def allowed_name(method_name)
+          method_name.match(/^[A-Z]/)
+        end
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            corrector.replace(node.loc.dot, '.')
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/comment_annotation.rb b/lib/rubocop/cop/style/comment_annotation.rb
new file mode 100644
index 0000000..49c0c88
--- /dev/null
+++ b/lib/rubocop/cop/style/comment_annotation.rb
@@ -0,0 +1,37 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks that comment annotation keywords are written according
+      # to guidelines.
+      class CommentAnnotation < Cop
+        include AnnotationComment
+
+        MSG = 'Annotation keywords should be all upper case, followed by a ' \
+              'colon and a space, then a note describing the problem.'
+
+        def investigate(processed_source)
+          processed_source.comments.each do |comment|
+            margin, first_word, colon, space, note = split_comment(comment)
+            if annotation?(comment) && !correct_annotation?(first_word, colon,
+                                                            space, note)
+              start = comment.loc.expression.begin_pos + margin.length
+              length = first_word.length + (colon || '').length
+              range = Parser::Source::Range.new(processed_source.buffer,
+                                                start,
+                                                start + length)
+              add_offense(nil, range)
+            end
+          end
+        end
+
+        private
+
+        def correct_annotation?(first_word, colon, space, note)
+          keyword?(first_word) && (colon && space && note || !colon && !note)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/constant_name.rb b/lib/rubocop/cop/style/constant_name.rb
new file mode 100644
index 0000000..96e6ca1
--- /dev/null
+++ b/lib/rubocop/cop/style/constant_name.rb
@@ -0,0 +1,29 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks whether constant names are written using
+      # SCREAMING_SNAKE_CASE.
+      #
+      # To avoid false positives, it ignores cases in which we cannot know
+      # for certain the type of value that would be assigned to a constant.
+      class ConstantName < Cop
+        MSG = 'Use SCREAMING_SNAKE_CASE for constants.'
+        SNAKE_CASE = /^[\dA-Z_]+$/
+
+        def on_casgn(node)
+          _scope, const_name, value = *node
+
+          # We cannot know the result of method calls like
+          # NewClass = something_that_returns_a_class
+          # It's also ok to assign a class constant another class constant
+          # SomeClass = SomeOtherClass
+          unless value && [:send, :block, :const].include?(value.type)
+            add_offense(node, :name) if const_name !~ SNAKE_CASE
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/cyclomatic_complexity.rb b/lib/rubocop/cop/style/cyclomatic_complexity.rb
new file mode 100644
index 0000000..0e029b0
--- /dev/null
+++ b/lib/rubocop/cop/style/cyclomatic_complexity.rb
@@ -0,0 +1,41 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks that the cyclomatic complexity of methods is not higher
+      # than the configured maximum. The cyclomatic complexity is the number of
+      # linearly independent paths through a method. The algorithm counts
+      # decision points and adds one.
+      #
+      # An if statement (or unless or ?:) increases the complexity by one. An
+      # else branch does not, since it doesn't add a decision point. The &&
+      # operator (or keyword and) can be converted to a nested if statement,
+      # and ||/or is shorthand for a sequence of ifs, so they also add one.
+      # Loops can be said to have an exit condition, so they add one.
+      class CyclomaticComplexity < Cop
+        include CheckMethods
+        include ConfigurableMax
+
+        MSG = 'Cyclomatic complexity for %s is too high. [%d/%d]'
+        DECISION_POINT_NODES = [:if, :while, :until, :for, :rescue, :when,
+                                :and, :or]
+
+        private
+
+        def check(node, method_name, *_)
+          complexity = 1
+          on_node(DECISION_POINT_NODES, node) { complexity += 1 }
+
+          max = cop_config['Max']
+          if complexity > max
+            add_offense(node, :keyword,
+                        format(MSG, method_name, complexity, max)) do
+              self.max = complexity
+            end
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/def_with_parentheses.rb b/lib/rubocop/cop/style/def_with_parentheses.rb
new file mode 100644
index 0000000..51215bd
--- /dev/null
+++ b/lib/rubocop/cop/style/def_with_parentheses.rb
@@ -0,0 +1,33 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for parentheses in the definition of a method,
+      # that does not take any arguments. Both instance and
+      # class/singleton methods are checked.
+      class DefWithParentheses < Cop
+        include CheckMethods
+
+        MSG = "Omit the parentheses in defs when the method doesn't accept " \
+              'any arguments.'
+
+        def check(node, _method_name, args, _body)
+          start_line = node.loc.keyword.line
+          end_line = node.loc.end.line
+
+          return if start_line == end_line
+
+          add_offense(args, :begin) if args.children == [] && args.loc.begin
+        end
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            corrector.remove(node.loc.begin)
+            corrector.remove(node.loc.end)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/deprecated_hash_methods.rb b/lib/rubocop/cop/style/deprecated_hash_methods.rb
new file mode 100644
index 0000000..fd582a1
--- /dev/null
+++ b/lib/rubocop/cop/style/deprecated_hash_methods.rb
@@ -0,0 +1,39 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for uses of the deprecated methods Hash#has_key?
+      # and Hash#has_value?
+      class DeprecatedHashMethods < Cop
+        MSG = '`Hash#%s` is deprecated in favor of `Hash#%s`.'
+
+        DEPRECATED_METHODS = [:has_key?, :has_value?]
+
+        def on_send(node)
+          _receiver, method_name, *args = *node
+
+          if args.size == 1 && DEPRECATED_METHODS.include?(method_name)
+            add_offense(node, :selector,
+                        format(MSG,
+                               method_name,
+                               proper_method_name(method_name)))
+          end
+        end
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            corrector.replace(node.loc.selector,
+                              proper_method_name(node.loc.selector.source))
+          end
+        end
+
+        private
+
+        def proper_method_name(method_name)
+          method_name.to_s.sub(/has_/, '')
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/documentation.rb b/lib/rubocop/cop/style/documentation.rb
new file mode 100644
index 0000000..b8ad29d
--- /dev/null
+++ b/lib/rubocop/cop/style/documentation.rb
@@ -0,0 +1,74 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for missing top-level documentation of
+      # classes and modules. Classes with no body are exempt from the
+      # check and so are namespace modules - modules that have nothing in
+      # their bodies except classes or other other modules.
+      class Documentation < Cop
+        include AnnotationComment
+
+        MSG = 'Missing top-level %s documentation comment.'
+
+        def investigate(processed_source)
+          ast = processed_source.ast
+          return unless ast
+
+          ast_with_comments = Parser::Source::Comment.associate(
+            ast,
+            processed_source.comments
+          )
+
+          check(ast, ast_with_comments)
+        end
+
+        private
+
+        def check(ast, ast_with_comments)
+          on_node([:class, :module], ast) do |node|
+            case node.type
+            when :class
+              _name, _superclass, body = *node
+            when :module
+              _name, body = *node
+            end
+
+            next if node.type == :class && !body
+            next if namespace?(body)
+            next if associated_comment?(node, ast_with_comments)
+            add_offense(node, :keyword, format(MSG, node.type.to_s))
+          end
+        end
+
+        def namespace?(body_node)
+          return false unless body_node
+
+          case body_node.type
+          when :begin
+            body_node.children.all? do |node|
+              [:class, :module].include?(node.type)
+            end
+          when :class, :module
+            true
+          else
+            false
+          end
+        end
+
+        # Returns true if the node has a comment on the line above it that
+        # isn't an annotation.
+        def associated_comment?(node, ast_with_comments)
+          return false if ast_with_comments[node].empty?
+
+          preceding_comment = ast_with_comments[node].last
+          distance = node.loc.keyword.line - preceding_comment.loc.line
+          return false if distance > 1
+
+          !annotation?(preceding_comment)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/dot_position.rb b/lib/rubocop/cop/style/dot_position.rb
new file mode 100644
index 0000000..cca9ebd
--- /dev/null
+++ b/lib/rubocop/cop/style/dot_position.rb
@@ -0,0 +1,57 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks the . position in multi-line method calls.
+      class DotPosition < Cop
+        include ConfigurableEnforcedStyle
+
+        def on_send(node)
+          return unless node.loc.dot
+
+          if proper_dot_position?(node)
+            correct_style_detected
+          else
+            add_offense(node, :dot) { opposite_style_detected }
+          end
+        end
+
+        private
+
+        def message(node)
+          'Place the . on the ' +
+            case style
+            when :leading
+              'next line, together with the method name.'
+            when :trailing
+              'previous line, together with the method call receiver.'
+            end
+        end
+
+        def proper_dot_position?(node)
+          receiver, _method_name, *_args = *node
+
+          receiver_line = receiver.loc.expression.end.line
+
+          if node.loc.selector
+            selector_line = node.loc.selector.line
+          else
+            # l.(1) has no selector, so we use the opening parenthesis instead
+            selector_line = node.loc.begin.line
+          end
+
+          # receiver and selector are on the same line
+          return true if selector_line == receiver_line
+
+          dot_line = node.loc.dot.line
+
+          case style
+          when :leading then dot_line == selector_line
+          when :trailing then dot_line != selector_line
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/double_negation.rb b/lib/rubocop/cop/style/double_negation.rb
new file mode 100644
index 0000000..e5416d0
--- /dev/null
+++ b/lib/rubocop/cop/style/double_negation.rb
@@ -0,0 +1,40 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for uses of double negation (!!) to convert something
+      # to a boolean value. As this is both cryptic and usually redundant it
+      # should be avoided.
+      #
+      # @example
+      #
+      #   # bad
+      #   !!something
+      #
+      #   # good
+      #   !something.nil?
+      class DoubleNegation < Cop
+        MSG = 'Avoid the use of double negation (`!!`).'
+
+        def on_send(node)
+          return unless not_node?(node)
+
+          receiver, _method_name, *_args = *node
+
+          add_offense(node, :selector) if not_node?(receiver)
+        end
+
+        private
+
+        def not_node?(node)
+          _receiver, method_name, *args = *node
+
+          # ! does not take any arguments
+          args.empty? && method_name == :! &&
+            node.loc.selector.is?('!')
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/empty_line_between_defs.rb b/lib/rubocop/cop/style/empty_line_between_defs.rb
new file mode 100644
index 0000000..d160987
--- /dev/null
+++ b/lib/rubocop/cop/style/empty_line_between_defs.rb
@@ -0,0 +1,46 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks whether method definitions are
+      # separated by empty lines.
+      class EmptyLineBetweenDefs < Cop
+        MSG = 'Use empty lines between defs.'
+
+        def on_def(node)
+          if @prev_def_end && (def_start(node) - @prev_def_end) == 1
+            unless @prev_was_single_line && singe_line_def?(node) &&
+                cop_config['AllowAdjacentOneLineDefs']
+              add_offense(node, :keyword)
+            end
+          end
+
+          @prev_def_end = def_end(node)
+          @prev_was_single_line = singe_line_def?(node)
+        end
+
+        private
+
+        def singe_line_def?(node)
+          def_start(node) == def_end(node)
+        end
+
+        def def_start(node)
+          node.loc.keyword.line
+        end
+
+        def def_end(node)
+          node.loc.end.line
+        end
+
+        def autocorrect(node)
+          range = range_with_surrounding_space(node.loc.expression, :left)
+          @corrections << lambda do |corrector|
+            corrector.insert_before(range, "\n")
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/empty_lines.rb b/lib/rubocop/cop/style/empty_lines.rb
new file mode 100644
index 0000000..d3238f1
--- /dev/null
+++ b/lib/rubocop/cop/style/empty_lines.rb
@@ -0,0 +1,47 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cops checks for two or more consecutive blank lines.
+      class EmptyLines < Cop
+        MSG = 'Extra blank line detected.'
+        LINE_OFFSET = 2
+
+        def investigate(processed_source)
+          return if processed_source.tokens.empty?
+
+          prev_line = 1
+
+          processed_source.tokens.sort_by { |t| t.pos.line }.each do |token|
+            cur_line = token.pos.line
+
+            line_diff = cur_line - prev_line
+
+            if line_diff > LINE_OFFSET
+              # we need to be wary of comments since they
+              # don't show up in the tokens
+              ((prev_line + 1)...cur_line).each do |line|
+                # we check if the prev and current lines are empty
+                if processed_source[line - 2].empty? &&
+                    processed_source[line - 1].empty?
+                  range = source_range(processed_source.buffer,
+                                       processed_source[0...(line - 1)],
+                                       0,
+                                       1)
+                  add_offense(range, range)
+                end
+              end
+            end
+
+            prev_line = cur_line
+          end
+        end
+
+        def autocorrect(range)
+          @corrections << ->(corrector) { corrector.remove(range) }
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/empty_lines_around_access_modifier.rb b/lib/rubocop/cop/style/empty_lines_around_access_modifier.rb
new file mode 100644
index 0000000..ab689e8
--- /dev/null
+++ b/lib/rubocop/cop/style/empty_lines_around_access_modifier.rb
@@ -0,0 +1,48 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # Access modifiers should be surrounded by blank lines.
+      class EmptyLinesAroundAccessModifier < Cop
+        MSG = 'Keep a blank line before and after `%s`.'
+
+        PRIVATE_NODE = s(:send, nil, :private)
+        PROTECTED_NODE = s(:send, nil, :protected)
+        PUBLIC_NODE = s(:send, nil, :public)
+
+        def on_send(node)
+          return unless modifier_node?(node)
+
+          return if empty_lines_around?(node)
+
+          add_offense(node, :expression)
+        end
+
+        private
+
+        def empty_lines_around?(node)
+          send_line = node.loc.line
+          previous_line = processed_source[send_line - 2]
+          next_line = processed_source[send_line]
+
+          (class_def?(previous_line.lstrip) ||
+           previous_line.blank?) &&
+            next_line.blank?
+        end
+
+        def class_def?(line)
+          %w(class module).any? { |keyword| line.start_with?(keyword) }
+        end
+
+        def message(node)
+          format(MSG, node.loc.selector.source)
+        end
+
+        def modifier_node?(node)
+          [PRIVATE_NODE, PROTECTED_NODE, PUBLIC_NODE].include?(node)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/empty_lines_around_body.rb b/lib/rubocop/cop/style/empty_lines_around_body.rb
new file mode 100644
index 0000000..72a51bd
--- /dev/null
+++ b/lib/rubocop/cop/style/empty_lines_around_body.rb
@@ -0,0 +1,74 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cops checks redundant empty lines around the bodies of classes,
+      # modules & methods.
+      #
+      # @example
+      #
+      #   class Test
+      #
+      #      def something
+      #        ...
+      #      end
+      #
+      #   end
+      #
+      #   def something(arg)
+      #
+      #     ...
+      #   end
+      #
+      class EmptyLinesAroundBody < Cop
+        include CheckMethods
+
+        MSG_BEG = 'Extra empty line detected at body beginning.'
+        MSG_END = 'Extra empty line detected at body end.'
+
+        def on_class(node)
+          check(node)
+        end
+
+        def on_module(node)
+          check(node)
+        end
+
+        def on_sclass(node)
+          check(node)
+        end
+
+        def autocorrect(range)
+          @corrections << ->(corrector) { corrector.remove(range) }
+        end
+
+        private
+
+        def check(node, *_)
+          start_line = node.loc.keyword.line
+          end_line = node.loc.end.line
+
+          return if start_line == end_line
+
+          check_source(start_line, end_line)
+        end
+
+        def check_source(start_line, end_line)
+          check_line(start_line, MSG_BEG)
+          check_line(end_line - 2, MSG_END) unless end_line - 2 == start_line
+        end
+
+        def check_line(line, msg)
+          if processed_source.lines[line].empty?
+            range = source_range(processed_source.buffer,
+                                 processed_source[0...line],
+                                 0,
+                                 1)
+            add_offense(range, range, msg)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/empty_literal.rb b/lib/rubocop/cop/style/empty_literal.rb
new file mode 100644
index 0000000..1108145
--- /dev/null
+++ b/lib/rubocop/cop/style/empty_literal.rb
@@ -0,0 +1,60 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for the use of a method, the result of which
+      # would be a literal, like an empty array, hash or string.
+      class EmptyLiteral < Cop
+        ARR_MSG = 'Use array literal [] instead of Array.new.'
+        HASH_MSG = 'Use hash literal {} instead of Hash.new.'
+        STR_MSG = "Use string literal '' instead of String.new."
+
+        # Empty array node
+        #
+        # (send
+        #   (const nil :Array) :new)
+        ARRAY_NODE = s(:send, s(:const, nil, :Array), :new)
+
+        # Empty hash node
+        #
+        # (send
+        #   (const nil :Hash) :new)
+        HASH_NODE = s(:send, s(:const, nil, :Hash), :new)
+
+        # Empty string node
+        #
+        # (send
+        #   (const nil :String) :new)
+        STR_NODE = s(:send, s(:const, nil, :String), :new)
+
+        def on_send(node)
+          return if part_of_ignored_node?(node)
+
+          case node
+          when ARRAY_NODE
+            add_offense(node, :expression, ARR_MSG)
+          when HASH_NODE
+            add_offense(node, :expression, HASH_MSG)
+          when STR_NODE
+            add_offense(node, :expression, STR_MSG)
+          end
+        end
+
+        # TODO: Check block contents as well.
+        alias_method :on_block, :ignore_node
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            name = case node
+                   when ARRAY_NODE then '[]'
+                   when HASH_NODE then '{}'
+                   when STR_NODE then "''"
+                   end
+            corrector.replace(node.loc.expression, name)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/encoding.rb b/lib/rubocop/cop/style/encoding.rb
new file mode 100644
index 0000000..de95a5e
--- /dev/null
+++ b/lib/rubocop/cop/style/encoding.rb
@@ -0,0 +1,30 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks whether the source file has a
+      # utf-8 encoding comment. This check makes sense only
+      # in Ruby 1.9, since in 2.0+ utf-8 is the default source file
+      # encoding.
+      class Encoding < Cop
+        MSG = 'Missing utf-8 encoding comment.'
+
+        def investigate(processed_source)
+          unless RUBY_VERSION >= '2.0.0'
+            line_number = 0
+            line_number += 1 if processed_source[line_number] =~ /^#!/
+            line = processed_source[line_number]
+            unless line =~ /#.*coding\s?[:=]\s?(UTF|utf)-8/
+              add_offense(nil,
+                          source_range(processed_source.buffer,
+                                       processed_source[0...line_number],
+                                       0, 1),
+                          MSG)
+            end
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/end_block.rb b/lib/rubocop/cop/style/end_block.rb
new file mode 100644
index 0000000..e219224
--- /dev/null
+++ b/lib/rubocop/cop/style/end_block.rb
@@ -0,0 +1,16 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for END blocks.
+      class EndBlock < Cop
+        MSG = 'Avoid the use of `END` blocks. Use `Kernel#at_exit` instead.'
+
+        def on_postexe(node)
+          add_offense(node, :keyword)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/end_of_line.rb b/lib/rubocop/cop/style/end_of_line.rb
new file mode 100644
index 0000000..d3085a8
--- /dev/null
+++ b/lib/rubocop/cop/style/end_of_line.rb
@@ -0,0 +1,30 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for Windows-style line endings in the source code.
+      class EndOfLine < Cop
+        MSG = 'Carriage return character detected.'
+
+        def investigate(processed_source)
+          buffer = processed_source.buffer
+          original_source = IO.read(buffer.name,
+                                    encoding: buffer.source.encoding)
+          original_source.lines.each_with_index do |line, index|
+            if line =~ /\r$/
+              add_offense(nil,
+                          source_range(buffer,
+                                       processed_source[0...index],
+                                       0, line.length),
+                          MSG)
+              # Usually there will be carriage return characters on all or none
+              # of the lines in a file, so we report only one offense.
+              break
+            end
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/even_odd.rb b/lib/rubocop/cop/style/even_odd.rb
new file mode 100644
index 0000000..357196c
--- /dev/null
+++ b/lib/rubocop/cop/style/even_odd.rb
@@ -0,0 +1,60 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for places where Fixnum#even? or Fixnum#odd?
+      # should have been used.
+      #
+      # @example
+      #
+      #   # bad
+      #   if x % 2 == 0
+      #
+      #   # good
+      #   if x.even?
+      class EvenOdd < Cop
+        MSG_EVEN = 'Replace with `Fixnum#even?`.'
+        MSG_ODD = 'Replace with `Fixnum#odd?`.'
+
+        ZERO = s(:int, 0)
+        ONE = s(:int, 1)
+        TWO = s(:int, 2)
+
+        def on_send(node)
+          receiver, method, args = *node
+
+          return unless [:==, :!=].include?(method)
+          return unless div_by_2?(receiver)
+
+          if args == ZERO
+            add_offense(node,
+                        :expression,
+                        method == :== ? MSG_EVEN : MSG_ODD)
+          elsif args == ONE
+            add_offense(node,
+                        :expression,
+                        method == :== ? MSG_ODD : MSG_EVEN)
+          end
+        end
+
+        private
+
+        def div_by_2?(node)
+          return unless node
+
+          # check for scenarios like (x % 2) == 0
+          if node.type == :begin && node.children.size == 1
+            node = node.children.first
+          end
+
+          return unless node.type == :send
+
+          _receiver, method, args = *node
+
+          method == :% && args == TWO
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/file_name.rb b/lib/rubocop/cop/style/file_name.rb
new file mode 100644
index 0000000..c37f76f
--- /dev/null
+++ b/lib/rubocop/cop/style/file_name.rb
@@ -0,0 +1,29 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop makes sure that Ruby source files have snake_case names.
+      class FileName < Cop
+        MSG = 'Use snake_case for source file names.'
+
+        SNAKE_CASE = /^[\da-z_]+$/
+
+        def investigate(processed_source)
+          file_path = processed_source.buffer.name
+
+          return if config.file_to_include?(file_path)
+
+          basename = File.basename(file_path).sub(/\.[^\.]+$/, '')
+
+          unless basename.split('.').all? { |fragment| fragment =~ SNAKE_CASE }
+            add_offense(nil,
+                        source_range(processed_source.buffer,
+                                     processed_source[0..0],
+                                     0, 1))
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/final_newline.rb b/lib/rubocop/cop/style/final_newline.rb
new file mode 100644
index 0000000..af28fa9
--- /dev/null
+++ b/lib/rubocop/cop/style/final_newline.rb
@@ -0,0 +1,29 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop enforces the presence of a final newline in each source file.
+      class FinalNewline < Cop
+        MSG = 'Source files should end with a newline (\n).'
+
+        def investigate(processed_source)
+          final_line = processed_source.raw_lines.to_a.last
+
+          unless final_line.nil? || final_line.end_with?("\n")
+            range = source_range(processed_source.buffer,
+                                 processed_source[0...-1],
+                                 final_line.length - 1, 1)
+            add_offense(range, range)
+          end
+        end
+
+        def autocorrect(range)
+          @corrections << lambda do |corrector|
+            corrector.insert_after(range, "\n")
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/flip_flop.rb b/lib/rubocop/cop/style/flip_flop.rb
new file mode 100644
index 0000000..0520c91
--- /dev/null
+++ b/lib/rubocop/cop/style/flip_flop.rb
@@ -0,0 +1,20 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop looks for uses of flip flop operator
+      class FlipFlop < Cop
+        MSG = 'Avoid the use of flip flop operators.'
+
+        def on_iflipflop(node)
+          add_offense(node, :expression)
+        end
+
+        def on_eflipflop(node)
+          add_offense(node, :expression)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/for.rb b/lib/rubocop/cop/style/for.rb
new file mode 100644
index 0000000..2bea1b3
--- /dev/null
+++ b/lib/rubocop/cop/style/for.rb
@@ -0,0 +1,47 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop looks for uses of the *for* keyword, or *each* method. The
+      # preferred alternative is set in the EnforcedStyle configuration
+      # parameter. An *each* call with a block on a single line is always
+      # allowed, however.
+      class For < Cop
+        include ConfigurableEnforcedStyle
+
+        def on_for(node)
+          if style == :each
+            add_offense(node, :keyword, 'Prefer `each` over `for`.') do
+              opposite_style_detected
+            end
+          else
+            correct_style_detected
+          end
+        end
+
+        def on_block(node)
+          return if block_length(node) == 0
+
+          method, _args, _body = *node
+          return unless method.type == :send
+
+          _receiver, method_name, *args = *method
+          return unless method_name == :each && args.empty?
+
+          if style == :for
+            end_pos = method.loc.expression.end_pos
+            range = Parser::Source::Range.new(processed_source.buffer,
+                                              end_pos - 'each'.length,
+                                              end_pos)
+            add_offense(range, range, 'Prefer `for` over `each`.') do
+              opposite_style_detected
+            end
+          else
+            correct_style_detected
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/format_string.rb b/lib/rubocop/cop/style/format_string.rb
new file mode 100644
index 0000000..bab20c3
--- /dev/null
+++ b/lib/rubocop/cop/style/format_string.rb
@@ -0,0 +1,66 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop enforces the use of a single string formatting utility.
+      # Valid options include Kernel#format, Kernel#sprintf and String#%.
+      #
+      # The detection of String#% cannot be implemented in a reliable
+      # manner for all cases, so only two scenarios are considered -
+      # if the first argument is a string literal and if the second
+      # argument is an array literal.
+      class FormatString < Cop
+        include ConfigurableEnforcedStyle
+
+        def on_send(node)
+          add_offense(node, :selector) if offending_node?(node)
+        end
+
+        private
+
+        def offending_node?(node)
+          case style
+          when :format
+            sprintf?(node) || percent?(node)
+          when :sprintf
+            format?(node) || percent?(node)
+          when :percent
+            format?(node) || sprintf?(node)
+          end
+        end
+
+        def format?(node)
+          command?(:format, node)
+        end
+
+        def sprintf?(node)
+          command?(:sprintf, node)
+        end
+
+        def percent?(node)
+          receiver_node, method_name, *arg_nodes = *node
+
+          method_name == :% &&
+            ([:str, :dstr].include?(receiver_node.type) ||
+             arg_nodes[0].type == :array)
+        end
+
+        def message(node)
+          _receiver_node, method_name, *_arg_nodes = *node
+
+          preferred =
+            if style == :percent
+              'String#%'
+            else
+              style
+            end
+
+          method_name = 'String#%' if method_name == :%
+
+          "Favor `#{preferred}` over `#{method_name}`."
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/global_vars.rb b/lib/rubocop/cop/style/global_vars.rb
new file mode 100644
index 0000000..9fffbd8
--- /dev/null
+++ b/lib/rubocop/cop/style/global_vars.rb
@@ -0,0 +1,74 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cops looks for uses of global variables.
+      # It does not report offenses for built-in global variables.
+      # Built-in global variables are allowed by default. Additionally
+      # users can allow additional variables via the AllowedVariables option.
+      #
+      # Note that backreferences like $1, $2, etc are not global variables.
+      class GlobalVars < Cop
+        MSG = 'Do not introduce global variables.'
+
+        # predefined global variables their English aliases
+        # http://www.zenspider.com/Languages/Ruby/QuickRef.html
+        BUILT_IN_VARS = %w(
+          $: $LOAD_PATH
+          $" $LOADED_FEATURES
+          $0 $PROGRAM_NAME
+          $! $ERROR_INFO
+          $@ $ERROR_POSITION
+          $; $FS $FIELD_SEPARATOR
+          $, $OFS $OUTPUT_FIELD_SEPARATOR
+          $/ $RS $INPUT_RECORD_SEPARATOR
+          $\\ $ORS $OUTPUT_RECORD_SEPARATOR
+          $. $NR $INPUT_LINE_NUMBER
+          $_ $LAST_READ_LINE
+          $> $DEFAULT_OUTPUT
+          $< $DEFAULT_INPUT
+          $$ $PID $PROCESS_ID
+          $? $CHILD_STATUS
+          $~ $LAST_MATCH_INFO
+          $= $IGNORECASE
+          $* $ARGV
+          $& $MATCH
+          $` $PREMATCH
+          $' $POSTMATCH
+          $+ $LAST_PAREN_MATCH
+          $stdin $stdout $stderr
+          $DEBUG $FILENAME $VERBOSE $SAFE
+          $-0 $-a $-d $-F $-i $-I $-l $-p $-v $-w
+          $CLASSPATH $JRUBY_VERSION $JRUBY_REVISION $ENV_JAVA
+        ).map(&:to_sym)
+
+        def user_vars
+          if cop_config['AllowedVariables']
+            cop_config['AllowedVariables'].map(&:to_sym)
+          else
+            []
+          end
+        end
+
+        def allowed_var?(global_var)
+          BUILT_IN_VARS.include?(global_var) || user_vars.include?(global_var)
+        end
+
+        def on_gvar(node)
+          check(node)
+        end
+
+        def on_gvasgn(node)
+          check(node)
+        end
+
+        def check(node)
+          global_var, = *node
+
+          add_offense(node, :name) unless allowed_var?(global_var)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/guard_clause.rb b/lib/rubocop/cop/style/guard_clause.rb
new file mode 100644
index 0000000..8e21756
--- /dev/null
+++ b/lib/rubocop/cop/style/guard_clause.rb
@@ -0,0 +1,69 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop if/unless expression that can be replace with a guard clause.
+      #
+      # @example
+      #
+      #   # bad
+      #   def test
+      #     if something
+      #       work
+      #       work
+      #       work
+      #     end
+      #   end
+      #
+      #   # good
+      #   def test
+      #     return unless something
+      #     work
+      #     work
+      #     work
+      #   end
+      #
+      # It should be extended to handle methods whose body is if/else
+      # or a case expression with a default branch.
+      class GuardClause < Cop
+        include CheckMethods
+        include IfNode
+
+        MSG = 'Use a guard clause instead of wrapping ' \
+              'the code inside a conditional expression.'
+
+        private
+
+        def check(_node, _method_name, _args, body)
+          return unless body
+
+          if body.type == :if
+            check_if_node(body)
+          elsif body.type == :begin
+            expressions = *body
+            last_expr = expressions.last
+
+            check_if_node(last_expr) if last_expr && last_expr.type == :if
+          end
+        end
+
+        def check_if_node(node)
+          _cond, _body, else_body = *node
+
+          return if else_body
+          # discard modifier ifs and ternary_ops
+          return if modifier_if?(node) || ternary_op?(node)
+          # discard short ifs
+          return unless if_length(node) > 3
+
+          add_offense(node, :keyword)
+        end
+
+        def if_length(node)
+          node.loc.end.line - node.loc.keyword.line + 1
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/hash_syntax.rb b/lib/rubocop/cop/style/hash_syntax.rb
new file mode 100644
index 0000000..60f3018
--- /dev/null
+++ b/lib/rubocop/cop/style/hash_syntax.rb
@@ -0,0 +1,89 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks hash literal syntax.
+      #
+      # It can enforce either the use of the class hash rocket syntax or
+      # the use of the newer Ruby 1.9 syntax (when applicable).
+      #
+      # A separate offense is registered for each problematic pair.
+      class HashSyntax < Cop
+        include ConfigurableEnforcedStyle
+
+        MSG_19 = 'Use the new Ruby 1.9 hash syntax.'
+        MSG_HASH_ROCKETS = 'Always use hash rockets in hashes.'
+
+        def on_hash(node)
+          style == :ruby19 ? ruby19_check(node) : hash_rockets_check(node)
+        end
+
+        def ruby19_check(node)
+          pairs = *node
+
+          sym_indices = pairs.all? { |p| word_symbol_pair?(p) }
+
+          check(pairs, '=>', MSG_19) if sym_indices
+        end
+
+        def hash_rockets_check(node)
+          pairs = *node
+
+          check(pairs, ':', MSG_HASH_ROCKETS)
+        end
+
+        def autocorrect(node)
+          key = node.children.first.loc.expression
+          op = node.loc.operator
+
+          @corrections << lambda do |corrector|
+            if style == :ruby19
+              range = Parser::Source::Range.new(key.source_buffer,
+                                                key.begin_pos, op.end_pos)
+              range = range_with_surrounding_space(range, :right)
+              corrector.replace(range,
+                                range.source.sub(/^:(.*\S)\s*=>\s*$/, '\1: '))
+            else
+              corrector.insert_after(key, ' => ')
+              corrector.insert_before(key, ':')
+              corrector.remove(range_with_surrounding_space(op))
+            end
+          end
+        end
+
+        private
+
+        def space_before_operator?(op, key)
+          op.begin_pos - key.begin_pos - key.source.length > 0
+        end
+
+        def check(pairs, delim, msg)
+          pairs.each do |pair|
+            if pair.loc.operator && pair.loc.operator.is?(delim)
+              add_offense(pair,
+                          pair.loc.expression.begin.join(pair.loc.operator),
+                          msg) do
+                opposite_style_detected
+              end
+            else
+              correct_style_detected
+            end
+          end
+        end
+
+        def word_symbol_pair?(pair)
+          key, _value = *pair
+
+          if key.type == :sym
+            sym_name = key.to_a[0]
+
+            sym_name =~ /\A[A-Za-z_]\w*\z/
+          else
+            false
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/if_unless_modifier.rb b/lib/rubocop/cop/style/if_unless_modifier.rb
new file mode 100644
index 0000000..59812fd
--- /dev/null
+++ b/lib/rubocop/cop/style/if_unless_modifier.rb
@@ -0,0 +1,35 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # Checks for if and unless statements that would fit on one line
+      # if written as a modifier if/unless.
+      # The maximum line length is configurable.
+      class IfUnlessModifier < Cop
+        include StatementModifier
+
+        def error_message(keyword)
+          "Favor modifier `#{keyword}` usage when having a single-line body." \
+          ' Another good alternative is the usage of control flow `&&`/`||`.'
+        end
+
+        def investigate(processed_source)
+          return unless processed_source.ast
+          on_node(:if, processed_source.ast) do |node|
+            # discard ternary ops, if/else and modifier if/unless nodes
+            next if ternary_op?(node)
+            next if modifier_if?(node)
+            next if elsif?(node)
+            next if if_else?(node)
+
+            if check(node, processed_source.comments)
+              add_offense(node, :keyword,
+                          error_message(node.loc.keyword.source))
+            end
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/if_with_semicolon.rb b/lib/rubocop/cop/style/if_with_semicolon.rb
new file mode 100644
index 0000000..739da7d
--- /dev/null
+++ b/lib/rubocop/cop/style/if_with_semicolon.rb
@@ -0,0 +1,20 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # Checks for uses of semicolon in if statements.
+      class IfWithSemicolon < Cop
+        include IfThenElse
+
+        def offending_line(node)
+          node.loc.begin.line if node.loc.begin && node.loc.begin.is?(';')
+        end
+
+        def error_message(_node)
+          'Never use if x; Use the ternary operator instead.'
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/indent_array.rb b/lib/rubocop/cop/style/indent_array.rb
new file mode 100644
index 0000000..d5019b5
--- /dev/null
+++ b/lib/rubocop/cop/style/indent_array.rb
@@ -0,0 +1,41 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cops checks the indentation of the first element in an array
+      # literal where the opening bracket and the first element are on separate
+      # lines. The other elements' indentations are handled by the AlignArray
+      # cop.
+      #
+      # Array literals shall have their first element indented one step (2
+      # spaces) more than the start of the line where the opening bracket is.
+      class IndentArray < Cop
+        include AutocorrectAlignment
+
+        def on_array(node)
+          first_pair = node.children.first
+          return if first_pair.nil?
+
+          left_bracket = node.loc.begin
+          return if left_bracket.nil?
+
+          return if first_pair.loc.expression.line == left_bracket.line
+
+          column = first_pair.loc.expression.column
+          base_column = left_bracket.source_line =~ /\S/
+          expected_column = base_column + IndentationWidth::CORRECT_INDENTATION
+          @column_delta = expected_column - column
+
+          add_offense(first_pair, :expression) if @column_delta != 0
+        end
+
+        def message(_)
+          format('Use %d spaces for indentation in an array, relative to ' \
+                 'the start of the line where the left bracket is.',
+                 IndentationWidth::CORRECT_INDENTATION)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/indent_hash.rb b/lib/rubocop/cop/style/indent_hash.rb
new file mode 100644
index 0000000..8f0b2ab
--- /dev/null
+++ b/lib/rubocop/cop/style/indent_hash.rb
@@ -0,0 +1,144 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cops checks the indentation of the first key in a hash literal
+      # where the opening brace and the first key are on separate lines. The
+      # other keys' indentations are handled by the AlignHash cop.
+      #
+      # Hash literals that are arguments in a method call with parentheses, and
+      # where the opening curly brace of the hash is on the same line as the
+      # opening parenthesis of the method call, shall have their first key
+      # indented one step (two spaces) more than the position inside the
+      # opening parenthesis.
+      #
+      # Other hash literals shall have their first key indented one step more
+      # than the start of the line where the opening curly brace is.
+      class IndentHash < Cop
+        include AutocorrectAlignment
+        include ConfigurableEnforcedStyle
+
+        def on_hash(node)
+          left_brace = node.loc.begin
+          check(node, left_brace, nil) if left_brace
+        end
+
+        def on_send(node)
+          _receiver, _method_name, *args = *node
+          left_parenthesis = node.loc.begin
+          return unless left_parenthesis
+
+          args.each do |arg|
+            on_node(:hash, arg, :send) do |hash_node|
+              left_brace = hash_node.loc.begin
+              if left_brace && left_brace.line == left_parenthesis.line
+                check(hash_node, left_brace, left_parenthesis)
+                ignore_node(hash_node)
+              end
+            end
+          end
+        end
+
+        private
+
+        def check(hash_node, left_brace, left_parenthesis)
+          return if ignored_node?(hash_node)
+
+          first_pair = hash_node.children.first
+          return if first_pair.nil?
+
+          left_brace = hash_node.loc.begin
+          return if first_pair.loc.expression.line == left_brace.line
+
+          if separator_style?(first_pair)
+            check_based_on_longest_key(hash_node.children, left_brace,
+                                       left_parenthesis)
+          else
+            check_first_pair(first_pair, left_brace, left_parenthesis, 0)
+          end
+        end
+
+        def separator_style?(first_pair)
+          separator = first_pair.loc.operator
+          key = "Enforced#{separator.is?(':') ? 'Colon' : 'HashRocket'}Style"
+          config.for_cop('AlignHash')[key] == 'separator'
+        end
+
+        def check_based_on_longest_key(pairs, left_brace, left_parenthesis)
+          key_lengths = pairs.map do |pair|
+            pair.children.first.loc.expression.length
+          end
+          check_first_pair(pairs.first, left_brace, left_parenthesis,
+                           key_lengths.max - key_lengths.first)
+        end
+
+        def check_first_pair(first_pair, left_brace, left_parenthesis, offset)
+          column = first_pair.loc.expression.column
+          @column_delta =
+            expected_column(left_brace, left_parenthesis, offset) - column
+
+          if @column_delta == 0
+            correct_style_detected
+          else
+            add_offense(first_pair, :expression,
+                        message(base_description(left_parenthesis))) do
+              if column == unexpected_column(left_brace, left_parenthesis,
+                                             offset)
+                opposite_style_detected
+              else
+                unrecognized_style_detected
+              end
+            end
+          end
+        end
+
+        # Returns the expected, or correct indentation.
+        def expected_column(left_brace, left_parenthesis, offset)
+          base_column =
+            if left_parenthesis && style == :special_inside_parentheses
+              left_parenthesis.column + 1
+            else
+              left_brace.source_line =~ /\S/
+            end
+
+          base_column + IndentationWidth::CORRECT_INDENTATION + offset
+        end
+
+        # Returns the description of what the correct indentation is based on.
+        def base_description(left_parenthesis)
+          if left_parenthesis && style == :special_inside_parentheses
+            'the first position after the preceding left parenthesis'
+          else
+            'the start of the line where the left curly brace is'
+          end
+        end
+
+        # Returns the "unexpected column", which is the column that would be
+        # correct if the configuration was changed.
+        def unexpected_column(left_brace, left_parenthesis, offset)
+          # Set a crazy value by default, indicating that there's no other
+          # configuration that can be chosen to make the used indentation
+          # accepted.
+          unexpected_base_column = -1000
+
+          if left_parenthesis
+            unexpected_base_column = if style == :special_inside_parentheses
+                                       left_brace.source_line =~ /\S/
+                                     else
+                                       left_parenthesis.column + 1
+                                     end
+          end
+
+          unexpected_base_column + IndentationWidth::CORRECT_INDENTATION +
+            offset
+        end
+
+        def message(base_description)
+          format('Use %d spaces for indentation in a hash, relative to %s.',
+                 IndentationWidth::CORRECT_INDENTATION, base_description)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/indentation_consistency.rb b/lib/rubocop/cop/style/indentation_consistency.rb
new file mode 100644
index 0000000..29d4297
--- /dev/null
+++ b/lib/rubocop/cop/style/indentation_consistency.rb
@@ -0,0 +1,43 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cops checks for inconsistent indentation.
+      #
+      # @example
+      #
+      # class A
+      #   def test
+      #     puts 'hello'
+      #      puts 'world'
+      #   end
+      # end
+      class IndentationConsistency < Cop
+        include AutocorrectAlignment
+
+        MSG = 'Inconsistent indentation detected.'
+
+        def on_begin(node)
+          check(node)
+        end
+
+        def on_kwbegin(node)
+          check(node)
+        end
+
+        private
+
+        def check(node)
+          children_to_check = node.children.reject do |child|
+            # Don't check nodes that have special indentation and will be
+            # checked by the AccessModifierIndentation cop.
+            AccessModifierIndentation.modifier_node?(child)
+          end
+
+          check_alignment(children_to_check)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/indentation_width.rb b/lib/rubocop/cop/style/indentation_width.rb
new file mode 100644
index 0000000..803072c
--- /dev/null
+++ b/lib/rubocop/cop/style/indentation_width.rb
@@ -0,0 +1,177 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cops checks for indentation that doesn't use two spaces.
+      #
+      # @example
+      #
+      # class A
+      #  def test
+      #   puts 'hello'
+      #  end
+      # end
+      class IndentationWidth < Cop
+        include AutocorrectAlignment
+        include CheckMethods
+        include CheckAssignment
+        include IfNode
+
+        CORRECT_INDENTATION = 2
+
+        def on_kwbegin(node)
+          check_indentation(node.loc.end, node.children.first)
+        end
+
+        def on_block(node)
+          _method, _args, body = *node
+          # Check body against end/} indentation. Checking against variable
+          # assignments, etc, would be more difficult.
+          check_indentation(node.loc.end, body)
+        end
+
+        def on_module(node)
+          _module_name, *members = *node
+          members.each { |m| check_indentation(node.loc.keyword, m) }
+        end
+
+        def on_class(node)
+          _class_name, _base_class, *members = *node
+          members.each { |m| check_indentation(node.loc.keyword, m) }
+        end
+
+        def check(node, _method_name, _args, body)
+          check_indentation(node.loc.keyword, body)
+        end
+
+        def on_for(node)
+          _variable, _collection, body = *node
+          check_indentation(node.loc.keyword, body)
+        end
+
+        def on_while(node, base = node)
+          _condition, body = *node
+          if node.loc.keyword.begin_pos == node.loc.expression.begin_pos
+            check_indentation(base.loc, body)
+          end
+        end
+
+        alias_method :on_until, :on_while
+
+        def on_case(node)
+          _condition, *branches = *node
+          latest_when = nil
+          branches.compact.each do |b|
+            if b.type == :when
+              _condition, body = *b
+              # Check "when" body against "when" keyword indentation.
+              check_indentation(b.loc.keyword, body)
+              latest_when = b
+            else
+              # Since it's not easy to get the position of the "else" keyword,
+              # we check "else" body against latest "when" keyword indentation.
+              check_indentation(latest_when.loc.keyword, b)
+            end
+          end
+        end
+
+        def on_if(node, base = node)
+          return if ignored_node?(node)
+          return if ternary_op?(node)
+          return if modifier_if?(node)
+
+          case node.loc.keyword.source
+          when 'if'     then _condition, body, else_clause = *node
+          when 'unless' then _condition, else_clause, body = *node
+          else               _condition, body = *node
+          end
+
+          check_if(node, body, else_clause, base.loc) if body
+        end
+
+        private
+
+        def check_assignment(node, rhs)
+          # If there are method calls chained to the right hand side of the
+          # assignment, we let rhs be the receiver of those method calls before
+          # we check its indentation.
+          rhs = first_part_of_call_chain(rhs)
+
+          if rhs
+            end_alignment_config = config.for_cop('EndAlignment')
+            style = if end_alignment_config['Enabled']
+                      end_alignment_config['AlignWith']
+                    else
+                      'keyword'
+                    end
+            base = style == 'variable' ? node : rhs
+
+            case rhs.type
+            when :if            then on_if(rhs, base)
+            when :while, :until then on_while(rhs, base)
+            else                     return
+            end
+
+            ignore_node(rhs)
+          end
+        end
+
+        def check_if(node, body, else_clause, base_loc)
+          return if ternary_op?(node)
+
+          check_indentation(base_loc, body)
+
+          if else_clause
+            if elsif?(else_clause)
+              _condition, inner_body, inner_else_clause = *else_clause
+              check_if(else_clause, inner_body, inner_else_clause, base_loc)
+            else
+              check_indentation(node.loc.else, else_clause)
+            end
+          end
+        end
+
+        def check_indentation(base_loc, body_node)
+          return unless body_node
+
+          # Don't check if expression is on same line as "then" keyword, etc.
+          return if body_node.loc.line == base_loc.line
+
+          return if starts_with_access_modifier?(body_node)
+
+          # Don't check indentation if the line doesn't start with the body.
+          # For example lines like "else do_something".
+          first_char_pos_on_line = body_node.loc.expression.source_line =~ /\S/
+          return unless body_node.loc.column == first_char_pos_on_line
+
+          indentation = body_node.loc.column - base_loc.column
+          @column_delta = CORRECT_INDENTATION - indentation
+          return if @column_delta == 0
+
+          # This cop only auto-corrects the first statement in a def body, for
+          # example.
+          body_node = body_node.children.first if body_node.type == :begin
+
+          expr = body_node.loc.expression
+          pos = if indentation >= 0
+                  (expr.begin_pos - indentation)..expr.begin_pos
+                else
+                  expr.begin_pos..(expr.begin_pos - indentation)
+                end
+
+          add_offense(body_node,
+                      Parser::Source::Range.new(expr.source_buffer,
+                                                pos.begin, pos.end),
+                      format("Use #{CORRECT_INDENTATION} (not %d) spaces " \
+                             'for indentation.', indentation))
+        end
+
+        def starts_with_access_modifier?(body_node)
+          body_node.type == :begin &&
+            AccessModifierIndentation.modifier_node?(body_node.children.first)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/lambda.rb b/lib/rubocop/cop/style/lambda.rb
new file mode 100644
index 0000000..26c1c12
--- /dev/null
+++ b/lib/rubocop/cop/style/lambda.rb
@@ -0,0 +1,45 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for uses of the pre 1.9 lambda syntax for one-line
+      # anonymous functions and uses of the 1.9 lambda syntax for multi-line
+      # anonymous functions.
+      class Lambda < Cop
+        SINGLE_MSG = 'Use the new lambda literal syntax `->(params) {...}`.'
+        MULTI_MSG = 'Use the `lambda` method for multi-line lambdas.'
+
+        TARGET = s(:send, nil, :lambda)
+
+        def on_block(node)
+          # We're looking for
+          # (block
+          #   (send nil :lambda)
+          #   ...)
+          block_method, = *node
+
+          if block_method == TARGET
+            selector = block_method.loc.selector.source
+            lambda_length = lambda_length(node)
+
+            if selector != '->' && lambda_length == 0
+              add_offense(block_method, :expression, SINGLE_MSG)
+            elsif selector == '->' && lambda_length > 0
+              add_offense(block_method, :expression, MULTI_MSG)
+            end
+          end
+        end
+
+        private
+
+        def lambda_length(block_node)
+          start_line = block_node.loc.begin.line
+          end_line = block_node.loc.end.line
+
+          end_line - start_line
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/lambda_call.rb b/lib/rubocop/cop/style/lambda_call.rb
new file mode 100644
index 0000000..343c578
--- /dev/null
+++ b/lib/rubocop/cop/style/lambda_call.rb
@@ -0,0 +1,63 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for use of the lambda.(args) syntax.
+      #
+      # @example
+      #
+      #  # bad
+      #  lambda.(x, y)
+      #
+      #  # good
+      #  lambda.call(x, y)
+      class LambdaCall < Cop
+        include ConfigurableEnforcedStyle
+
+        def on_send(node)
+          _receiver, selector, = *node
+
+          # we care only about `call` methods
+          return unless selector == :call
+
+          if offense?(node)
+            add_offense(node, :expression) { opposite_style_detected }
+          else
+            correct_style_detected
+          end
+        end
+
+        private
+
+        def offense?(node)
+          # lambda.() does not have a selector
+          style == :call && node.loc.selector.nil? ||
+            style == :braces && node.loc.selector
+        end
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            if style == :call
+              receiver_node, = *node
+              expr = node.loc.expression
+              receiver = receiver_node.loc.expression.source
+              replacement = expr.source.sub("#{receiver}.", "#{receiver}.call")
+              corrector.replace(expr, replacement)
+            else
+              corrector.remove(node.loc.selector)
+            end
+          end
+        end
+
+        def message(node)
+          if style == :call
+            'Prefer the use of `lambda.call(...)` over `lambda.(...)`.'
+          else
+            'Prefer the use of `lambda.(...)` over `lambda.call(...)`.'
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/leading_comment_space.rb b/lib/rubocop/cop/style/leading_comment_space.rb
new file mode 100644
index 0000000..f6451d0
--- /dev/null
+++ b/lib/rubocop/cop/style/leading_comment_space.rb
@@ -0,0 +1,34 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks whether comments have a leading space
+      # after the # denoting the start of the comment. The
+      # leading space is not required for some RDoc special syntax,
+      # like #++, #--, #:nodoc, etc.
+      class LeadingCommentSpace < Cop
+        MSG = 'Missing space after #.'
+
+        def investigate(processed_source)
+          processed_source.comments.each do |comment|
+            if comment.text =~ /^#+[^#\s:+-]/
+              unless comment.text.start_with?('#!') && comment.loc.line == 1
+                add_offense(comment, :expression)
+              end
+            end
+          end
+        end
+
+        def autocorrect(comment)
+          expr = comment.loc.expression
+          b = expr.begin_pos
+          hash_mark = Parser::Source::Range.new(expr.source_buffer, b, b + 1)
+          @corrections << lambda do |corrector|
+            corrector.insert_after(hash_mark, ' ')
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/line_end_concatenation.rb b/lib/rubocop/cop/style/line_end_concatenation.rb
new file mode 100644
index 0000000..cf14078
--- /dev/null
+++ b/lib/rubocop/cop/style/line_end_concatenation.rb
@@ -0,0 +1,66 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for string literal concatenation at
+      # the end of a line.
+      #
+      # @example
+      #
+      #   # bad
+      #   some_str = 'ala' +
+      #              'bala'
+      #
+      #   some_str = 'ala' <<
+      #              'bala'
+      #
+      #   # good
+      #   some_str = 'ala' \
+      #              'bala'
+      #
+      class LineEndConcatenation < Cop
+        MSG = 'Use \\ instead of + to concatenate those strings.'
+
+        def on_send(node)
+          add_offense(node, :selector) if offending_node?(node)
+        end
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            # replace + with \
+            corrector.replace(node.loc.selector, '\\')
+          end
+        end
+
+        private
+
+        def offending_node?(node)
+          receiver, method, arg = *node
+
+          # TODO: Report Emacs bug.
+          return false unless [:+, :<<].include?(method)
+
+          return false unless string_type?(receiver)
+
+          return false unless string_type?(arg)
+
+          expression = node.loc.expression.source
+          concatenator_at_line_end?(expression)
+        end
+
+        def concatenator_at_line_end?(expression)
+          # check if the first line of the expression ends with a + or a <<
+          expression =~ /.+(\+|<<)\s*$/
+        end
+
+        def string_type?(node)
+          return false unless [:str, :dstr].include?(node.type)
+
+          # we care only about quotes-delimited literals
+          node.loc.begin && ["'", '"'].include?(node.loc.begin.source)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/line_length.rb b/lib/rubocop/cop/style/line_length.rb
new file mode 100644
index 0000000..6b82bdc
--- /dev/null
+++ b/lib/rubocop/cop/style/line_length.rb
@@ -0,0 +1,34 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks the length of lines in the source code.
+      # The maximum length is configurable.
+      class LineLength < Cop
+        include ConfigurableMax
+
+        MSG = 'Line is too long. [%d/%d]'
+
+        def investigate(processed_source)
+          processed_source.lines.each_with_index do |line, index|
+            if line.length > max
+              message = format(MSG, line.length, max)
+              add_offense(nil,
+                          source_range(processed_source.buffer,
+                                       processed_source[0...index], max,
+                                       line.length - max),
+                          message) do
+                self.max = line.length
+              end
+            end
+          end
+        end
+
+        def max
+          cop_config['Max']
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/method_call_parentheses.rb b/lib/rubocop/cop/style/method_call_parentheses.rb
new file mode 100644
index 0000000..9ecfc83
--- /dev/null
+++ b/lib/rubocop/cop/style/method_call_parentheses.rb
@@ -0,0 +1,35 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for unwanted parentheses in parameterless method calls.
+      class MethodCallParentheses < Cop
+        MSG = 'Do not use parentheses for method calls with no arguments.'
+
+        def on_send(node)
+          _receiver, method_name, *args = *node
+
+          # methods starting with a capital letter should be skipped
+          return if method_name =~ /\A[A-Z]/
+
+          add_offense(node, :begin) if args.empty? && node.loc.begin
+        end
+
+        def autocorrect(node)
+          # Bail out if the call is going to be auto-corrected by EmptyLiteral.
+          if config.for_cop('EmptyLiteral')['Enabled'] &&
+              [EmptyLiteral::HASH_NODE,
+               EmptyLiteral::ARRAY_NODE,
+               EmptyLiteral::STR_NODE].include?(node)
+            return
+          end
+          @corrections << lambda do |corrector|
+            corrector.remove(node.loc.begin)
+            corrector.remove(node.loc.end)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/method_called_on_do_end_block.rb b/lib/rubocop/cop/style/method_called_on_do_end_block.rb
new file mode 100644
index 0000000..96daf35
--- /dev/null
+++ b/lib/rubocop/cop/style/method_called_on_do_end_block.rb
@@ -0,0 +1,41 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for methods called on a do...end block. The point of
+      # this check is that it's easy to miss the call tacked on to the block
+      # when reading code.
+      #
+      # @example
+      #
+      # a do
+      #   b
+      # end.c
+      class MethodCalledOnDoEndBlock < Cop
+        MSG = 'Avoid chaining a method call on a do...end block.'
+
+        def on_block(node)
+          method, _args, _body = *node
+          # If the method that is chained on the do...end block is itself a
+          # method with a block, we allow it. It's pretty safe to assume that
+          # these calls are not missed by anyone reading code. We also want to
+          # avoid double reporting of offenses checked by the
+          # MultilineBlockChain cop.
+          ignore_node(method)
+        end
+
+        def on_send(node)
+          return if ignored_node?(node)
+          receiver, _method_name, *_args = *node
+          if receiver && receiver.type == :block && receiver.loc.end.is?('end')
+            range = Parser::Source::Range.new(receiver.loc.end.source_buffer,
+                                              receiver.loc.end.begin_pos,
+                                              node.loc.expression.end_pos)
+            add_offense(nil, range)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/method_def_parentheses.rb b/lib/rubocop/cop/style/method_def_parentheses.rb
new file mode 100644
index 0000000..c3b0393
--- /dev/null
+++ b/lib/rubocop/cop/style/method_def_parentheses.rb
@@ -0,0 +1,72 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cops checks for parentheses around the arguments in method
+      # definitions. Both instance and class/singleton methods are checked.
+      class MethodDefParentheses < Cop
+        include CheckMethods
+        include ConfigurableEnforcedStyle
+
+        def check(node, _method_name, args, _body)
+          if style == :require_parentheses
+            if arguments?(args) && !parentheses?(args)
+              add_offense(node,
+                          args.loc.expression,
+                          'Use def with parentheses when there are ' \
+                          'parameters.') do
+                opposite_style_detected
+              end
+            else
+              correct_style_detected
+            end
+          elsif parentheses?(args)
+            add_offense(args, :expression, 'Use def without parentheses.') do
+              opposite_style_detected
+            end
+          else
+            correct_style_detected
+          end
+        end
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            if style == :require_parentheses
+              args_expr = args_node(node).loc.expression
+              args_with_space = range_with_surrounding_space(args_expr, :left)
+              just_space = Parser::Source::Range.new(args_expr.source_buffer,
+                                                     args_with_space.begin_pos,
+                                                     args_expr.begin_pos)
+              corrector.replace(just_space, '(')
+              corrector.insert_after(args_expr, ')')
+            elsif style == :require_no_parentheses
+              corrector.replace(node.loc.begin, ' ')
+              corrector.remove(node.loc.end)
+            end
+          end
+        end
+
+        private
+
+        def args_node(def_node)
+          if def_node.type == :def
+            _method_name, args, _body = *def_node
+            args
+          else
+            _scope, _method_name, args, _body = *def_node
+            args
+          end
+        end
+
+        def arguments?(args)
+          args.children.size > 0
+        end
+
+        def parentheses?(args)
+          args.loc.begin
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/method_length.rb b/lib/rubocop/cop/style/method_length.rb
new file mode 100644
index 0000000..9846a90
--- /dev/null
+++ b/lib/rubocop/cop/style/method_length.rb
@@ -0,0 +1,29 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks if the length a method exceeds some maximum value.
+      # Comment lines can optionally be ignored.
+      # The maximum allowed length is configurable.
+      class MethodLength < Cop
+        include CheckMethods
+        include CodeLength
+
+        private
+
+        def message
+          'Method has too many lines. [%d/%d]'
+        end
+
+        def code_length(node)
+          lines = node.loc.expression.source.lines.to_a[1..-2] || []
+
+          lines.reject! { |line| irrelevant_line(line) }
+
+          lines.size
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/method_name.rb b/lib/rubocop/cop/style/method_name.rb
new file mode 100644
index 0000000..44636bd
--- /dev/null
+++ b/lib/rubocop/cop/style/method_name.rb
@@ -0,0 +1,42 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop makes sure that all methods use the configured style,
+      # snake_case or camelCase, for their names. Some special arrangements
+      # have to be made for operator methods.
+      class MethodName < Cop
+        include ConfigurableNaming
+
+        def on_def(node)
+          check(node, name_of_instance_method(node))
+        end
+
+        def on_defs(node)
+          check(node, name_of_singleton_method(node))
+        end
+
+        def name_of_instance_method(def_node)
+          expr = def_node.loc.expression
+          match = /^def(\s+)([\w]+[!?=]?\b)/.match(expr.source)
+          return unless match
+          space, method_name = match.captures
+          begin_pos = expr.begin_pos + 'def'.length + space.length
+          Parser::Source::Range.new(expr.source_buffer, begin_pos,
+                                    begin_pos + method_name.length)
+        end
+
+        def name_of_singleton_method(defs_node)
+          scope, method_name, _args, _body = *defs_node
+          after_dot(defs_node, method_name.length,
+                    "def\s+" + Regexp.escape(scope.loc.expression.source))
+        end
+
+        def message(style)
+          format('Use %s for methods.', style)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/module_function.rb b/lib/rubocop/cop/style/module_function.rb
new file mode 100644
index 0000000..0b47e21
--- /dev/null
+++ b/lib/rubocop/cop/style/module_function.rb
@@ -0,0 +1,32 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cops checks for use of `extend self` in a module.
+      #
+      # @example
+      #
+      # module Test
+      #   extend self
+      #
+      #   ...
+      # end
+      class ModuleFunction < Cop
+        MSG = 'Use `module_function` instead of `extend self`.'
+
+        TARGET_NODE = s(:send, nil, :extend, s(:self))
+
+        def on_module(node)
+          _name, body = *node
+
+          if body && body.type == :begin
+            body.children.each do |body_node|
+              add_offense(body_node, :expression) if body_node == TARGET_NODE
+            end
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/multiline_block_chain.rb b/lib/rubocop/cop/style/multiline_block_chain.rb
new file mode 100644
index 0000000..dd19391
--- /dev/null
+++ b/lib/rubocop/cop/style/multiline_block_chain.rb
@@ -0,0 +1,44 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for chaining of a block after another block that spans
+      # multiple lines.
+      #
+      # @example
+      #
+      #   Thread.list.find_all do |t|
+      #     t.alive?
+      #   end.map do |t|
+      #     t.object_id
+      #   end
+      class MultilineBlockChain < Cop
+        MSG = 'Avoid multi-line chains of blocks.'
+
+        def on_block(node)
+          method, _args, _body = *node
+          on_node(:send, method) do |send_node|
+            receiver, _method_name, *_args = *send_node
+            if receiver && receiver.type == :block
+              # The begin and end could also be braces, but we call the
+              # variables do... and end...
+              do_kw_loc, end_kw_loc = receiver.loc.begin, receiver.loc.end
+
+              if do_kw_loc.line != end_kw_loc.line
+                range =
+                  Parser::Source::Range.new(end_kw_loc.source_buffer,
+                                            end_kw_loc.begin_pos,
+                                            method.loc.expression.end_pos)
+                add_offense(nil, range)
+                # Done. If there are more blocks in the chain, they will be
+                # found by subsequent calls to on_block.
+                break
+              end
+            end
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/multiline_if_then.rb b/lib/rubocop/cop/style/multiline_if_then.rb
new file mode 100644
index 0000000..5b1fcbb
--- /dev/null
+++ b/lib/rubocop/cop/style/multiline_if_then.rb
@@ -0,0 +1,50 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # Checks for uses of the `then` keyword in multi-line if statements.
+      #
+      # @example This is considered bad practice:
+      #
+      #   if cond then
+      #   end
+      #
+      # @example If statements can contain `then` on the same line:
+      #
+      #   if cond then a
+      #   elsif cond then b
+      #   end
+      class MultilineIfThen < Cop
+        include IfNode
+        include IfThenElse
+
+        def offending_line(node)
+          condition, body, else_clause = *node
+          next_thing = if body && body.loc.expression
+                         body.loc.expression.begin
+                       elsif else_clause && else_clause.loc.expression
+                         else_clause.loc.expression.begin
+                       else
+                         node.loc.end # No body, use "end".
+                       end
+          right_after_cond =
+            Parser::Source::Range.new(next_thing.source_buffer,
+                                      end_position(condition),
+                                      next_thing.begin_pos)
+          if right_after_cond.source =~ /\A\s*then\s*(#.*)?\s*\n/
+            node.loc.expression.begin.line
+          end
+        end
+
+        def end_position(conditional_node)
+          conditional_node.loc.expression.end.end_pos
+        end
+
+        def error_message(node)
+          "Never use `then` for multi-line `#{node.loc.keyword.source}`."
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/multiline_ternary_operator.rb b/lib/rubocop/cop/style/multiline_ternary_operator.rb
new file mode 100644
index 0000000..0160b91
--- /dev/null
+++ b/lib/rubocop/cop/style/multiline_ternary_operator.rb
@@ -0,0 +1,22 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for multi-line ternary op expressions.
+      class MultilineTernaryOperator < Cop
+        MSG = 'Avoid multi-line ?: (the ternary operator);' \
+              ' use `if`/`unless` instead.'
+
+        def on_if(node)
+          loc = node.loc
+
+          # discard non-ternary ops
+          return unless loc.respond_to?(:question)
+
+          add_offense(node, :expression) if loc.line != loc.colon.line
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/negated_if.rb b/lib/rubocop/cop/style/negated_if.rb
new file mode 100644
index 0000000..a25e2e4
--- /dev/null
+++ b/lib/rubocop/cop/style/negated_if.rb
@@ -0,0 +1,46 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # Checks for uses of if with a negated condition. Only ifs
+      # without else are considered.
+      class NegatedIf < Cop
+        include NegativeConditional
+
+        MSG = 'Favor `%s` over `%s` for negative conditions.'
+
+        def on_if(node)
+          return unless node.loc.respond_to?(:keyword)
+          return if node.loc.keyword.is?('elsif')
+
+          check(node)
+        end
+
+        def message(node)
+          if node.loc.keyword.is?('if')
+            format(MSG, 'unless', 'if')
+          else
+            format(MSG, 'if', 'unless')
+          end
+        end
+
+        private
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            condition, _body, _rest = *node
+            # unwrap the negated portion of the condition (a send node)
+            pos_condition, _method, = *condition
+            corrector.replace(
+              node.loc.keyword,
+              node.loc.keyword.is?('if') ? 'unless' : 'if'
+            )
+            corrector.replace(condition.loc.expression,
+                              pos_condition.loc.expression.source)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/negated_while.rb b/lib/rubocop/cop/style/negated_while.rb
new file mode 100644
index 0000000..87ec820
--- /dev/null
+++ b/lib/rubocop/cop/style/negated_while.rb
@@ -0,0 +1,45 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # Checks for uses of while with a negated condition.
+      class NegatedWhile < Cop
+        include NegativeConditional
+
+        MSG = 'Favor `%s` over `%s` for negative conditions.'
+
+        def on_while(node)
+          check(node)
+        end
+
+        def on_until(node)
+          check(node)
+        end
+
+        def message(node)
+          if node.type == :while
+            format(MSG, 'until', 'while')
+          else
+            format(MSG, 'while', 'until')
+          end
+        end
+
+        private
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            condition, _body, _rest = *node
+            # unwrap the negated portion of the condition (a send node)
+            pos_condition, _method, = *condition
+            corrector.replace(
+              node.loc.keyword,
+              node.type == :while ? 'until' : 'while')
+            corrector.replace(condition.loc.expression,
+                              pos_condition.loc.expression.source)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/nested_ternary_operator.rb b/lib/rubocop/cop/style/nested_ternary_operator.rb
new file mode 100644
index 0000000..5db4e06
--- /dev/null
+++ b/lib/rubocop/cop/style/nested_ternary_operator.rb
@@ -0,0 +1,26 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for nested ternary op expressions.
+      class NestedTernaryOperator < Cop
+        MSG = 'Ternary operators must not be nested. Prefer `if`/`else` ' \
+              'constructs instead.'
+
+        def on_if(node)
+          loc = node.loc
+
+          # discard non-ternary ops
+          return unless loc.respond_to?(:question)
+
+          node.children.each do |child|
+            on_node(:if, child) do |c|
+              add_offense(c, :expression) if c.loc.respond_to?(:question)
+            end
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/nil_comparison.rb b/lib/rubocop/cop/style/nil_comparison.rb
new file mode 100644
index 0000000..efb8325
--- /dev/null
+++ b/lib/rubocop/cop/style/nil_comparison.rb
@@ -0,0 +1,42 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for comparison of something with nil using ==.
+      #
+      # @example
+      #
+      #  # bad
+      #  if x == nil
+      #
+      #  # good
+      #  if x.nil?
+      class NilComparison < Cop
+        MSG = 'Prefer the use of the `nil?` predicate.'
+
+        OPS = [:==, :===]
+
+        NIL_NODE = s(:nil)
+
+        def on_send(node)
+          _receiver, method, args = *node
+
+          if OPS.include?(method)
+            add_offense(node, :selector) if args == NIL_NODE
+          end
+        end
+
+        private
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            expr = node.loc.expression
+            new_code = expr.source.sub(/\s*={2,3}\s*nil/, '.nil?')
+            corrector.replace(expr, new_code)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/non_nil_check.rb b/lib/rubocop/cop/style/non_nil_check.rb
new file mode 100644
index 0000000..4a218d5
--- /dev/null
+++ b/lib/rubocop/cop/style/non_nil_check.rb
@@ -0,0 +1,104 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for non-nil checks, which are usually redundant.
+      #
+      # @example
+      #
+      #  # bad
+      #  if x != nil
+      #  if !x.nil?
+      #
+      #  # good
+      #  if x
+      #
+      # Non-nil checks are allowed if they are the final nodes of predicate.
+      #
+      #  # good
+      #  def signed_in?
+      #    !current_user.nil?
+      #  end
+      class NonNilCheck < Cop
+        MSG = 'Explicit non-nil checks are usually redundant.'
+
+        NIL_NODE = s(:nil)
+
+        def on_def(node)
+          method_name, _args, body = *node
+          process_method(method_name, body)
+        end
+
+        def on_defs(node)
+          _scope, method_name, _args, body = *node
+          process_method(method_name, body)
+        end
+
+        def on_send(node)
+          return if ignored_node?(node)
+          receiver, method, args = *node
+
+          return unless [:!=, :!].include?(method)
+
+          if method == :!=
+            add_offense(node, :selector) if args == NIL_NODE
+          elsif method == :!
+            add_offense(node, :expression) if nil_check?(receiver)
+          end
+        end
+
+        private
+
+        def process_method(name, body)
+          # only predicate methods are handled differently
+          return unless name.to_s.end_with?('?')
+          return unless body
+
+          if body.type != :begin
+            ignore_node(body)
+          elsif body.type == :begin
+            ignore_node(body.children.last)
+          end
+        end
+
+        def nil_check?(node)
+          return false unless node && node.type == :send
+
+          _receiver, method, *_args = *node
+          method == :nil?
+        end
+
+        def autocorrect(node)
+          receiver, method, _args = *node
+
+          if method == :!=
+            autocorrect_comparison(node)
+          elsif method == :!
+            autocorrect_non_nil(node, receiver)
+          end
+        end
+
+        def autocorrect_comparison(node)
+          @corrections << lambda do |corrector|
+            expr = node.loc.expression
+            new_code = expr.source.sub(/\s*!=\s*nil/, '')
+            corrector.replace(expr, new_code)
+          end
+        end
+
+        def autocorrect_non_nil(node, inner_node)
+          @corrections << lambda do |corrector|
+            receiver, _method, _args = *inner_node
+            if receiver
+              corrector.replace(node.loc.expression,
+                                receiver.loc.expression.source)
+            else
+              corrector.replace(node.loc.expression, 'self')
+            end
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/not.rb b/lib/rubocop/cop/style/not.rb
new file mode 100644
index 0000000..9b69013
--- /dev/null
+++ b/lib/rubocop/cop/style/not.rb
@@ -0,0 +1,34 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for uses if the keyword *not* instead of !.
+      class Not < Cop
+        include AutocorrectUnlessChangingAST
+
+        MSG = 'Use `!` instead of `not`.'
+
+        def on_send(node)
+          _receiver, method_name, *args = *node
+
+          # not does not take any arguments
+          if args.empty? && method_name == :! &&
+              node.loc.selector.is?('not')
+            add_offense(node, :selector)
+          end
+        end
+
+        private
+
+        def correction(node)
+          lambda do |corrector|
+            old_source = node.loc.expression.source
+            new_source = old_source.sub(/not\s+/, '!')
+            corrector.replace(node.loc.expression, new_source)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/numeric_literals.rb b/lib/rubocop/cop/style/numeric_literals.rb
new file mode 100644
index 0000000..185b9b0
--- /dev/null
+++ b/lib/rubocop/cop/style/numeric_literals.rb
@@ -0,0 +1,73 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for big numeric literals without _ between groups
+      # of digits in them.
+      class NumericLiterals < Cop
+        # The parameter is called MinDigits (meaning the minimum number of
+        # digits for which an offense can be registered), but essentially it's
+        # a Max parameter (the maximum number of something that's allowed).
+        include ConfigurableMax
+
+        MSG = 'Separate every 3 digits in the integer portion of a number ' \
+              'with underscores(_).'
+
+        def on_int(node)
+          check(node)
+        end
+
+        def on_float(node)
+          check(node)
+        end
+
+        private
+
+        def parameter_name
+          'MinDigits'
+        end
+
+        def check(node)
+          int = integer_part(node)
+
+          # TODO: handle non-decimal literals as well
+          return if int.start_with?('0')
+
+          if int.size >= min_digits
+            case int
+            when /^\d+$/
+              add_offense(node, :expression) { self.max = int.size + 1 }
+            when /\d{4}/, /_\d{1,2}_/
+              add_offense(node, :expression) do
+                self.config_to_allow_offenses = { 'Enabled' => false }
+              end
+            end
+          end
+        end
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            int = node.loc.expression.source.to_i
+            formatted_int = int
+              .abs
+              .to_s
+              .reverse
+              .gsub(/...(?=.)/, '\&_')
+              .reverse
+            formatted_int.insert(0, '-') if int < 0
+            corrector.replace(node.loc.expression, formatted_int)
+          end
+        end
+
+        def integer_part(node)
+          node.loc.expression.source.sub(/^[+-]/, '').split('.').first
+        end
+
+        def min_digits
+          cop_config['MinDigits']
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/one_line_conditional.rb b/lib/rubocop/cop/style/one_line_conditional.rb
new file mode 100644
index 0000000..8c6b805
--- /dev/null
+++ b/lib/rubocop/cop/style/one_line_conditional.rb
@@ -0,0 +1,21 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # TODO: Make configurable.
+      # Checks for uses of if/then/else/end on a single line.
+      class OneLineConditional < Cop
+        include IfThenElse
+
+        def offending_line(node)
+          node.loc.expression.line unless node.loc.expression.source =~ /\n/
+        end
+
+        def error_message(_node)
+          'Favor the ternary operator (?:) over if/then/else/end constructs.'
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/op_method.rb b/lib/rubocop/cop/style/op_method.rb
new file mode 100644
index 0000000..dbb951d
--- /dev/null
+++ b/lib/rubocop/cop/style/op_method.rb
@@ -0,0 +1,27 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop makes sure that certain operator methods have their sole
+      # parameter named `other`.
+      class OpMethod < Cop
+        MSG = 'When defining the `%s` operator, name its argument `other`.'
+
+        BLACKLISTED = [:+@, :-@, :[], :[]=, :<<]
+
+        TARGET_ARGS = [s(:args, s(:arg, :other)), s(:args, s(:arg, :_other))]
+
+        def on_def(node)
+          name, args, _body = *node
+
+          if name !~ /\A\w/ && !BLACKLISTED.include?(name) &&
+              args.children.size == 1 && !TARGET_ARGS.include?(args)
+            add_offense(args.children[0], :expression,
+                        format(MSG, name))
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/parameter_lists.rb b/lib/rubocop/cop/style/parameter_lists.rb
new file mode 100644
index 0000000..641c914
--- /dev/null
+++ b/lib/rubocop/cop/style/parameter_lists.rb
@@ -0,0 +1,44 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for methods with too many parameters.
+      # The maximum number of parameters in configurable.
+      # On Ruby 2.0+ keyword arguments can optionally
+      # be excluded from the total count.
+      class ParameterLists < Cop
+        include ConfigurableMax
+
+        MSG = 'Avoid parameter lists longer than %d parameters.'
+
+        def on_args(node)
+          count = args_count(node)
+          if count > max_params
+            add_offense(node, :expression, format(MSG, max_params)) do
+              self.max = count
+            end
+          end
+        end
+
+        private
+
+        def args_count(node)
+          if count_keyword_args?
+            node.children.size
+          else
+            node.children.reject { |a| a.type == :kwoptarg }.size
+          end
+        end
+
+        def max_params
+          cop_config['Max']
+        end
+
+        def count_keyword_args?
+          cop_config['CountKeywordArgs']
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/parentheses_around_condition.rb b/lib/rubocop/cop/style/parentheses_around_condition.rb
new file mode 100644
index 0000000..f44e8de
--- /dev/null
+++ b/lib/rubocop/cop/style/parentheses_around_condition.rb
@@ -0,0 +1,62 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for the presence of superfluous parentheses around the
+      # condition of if/unless/while/until.
+      class ParenthesesAroundCondition < Cop
+        include IfNode
+        include SafeAssignment
+
+        def on_if(node)
+          return if ternary_op?(node)
+          process_control_op(node)
+        end
+
+        def on_while(node)
+          process_control_op(node)
+        end
+
+        def on_until(node)
+          process_control_op(node)
+        end
+
+        private
+
+        def process_control_op(node)
+          cond, _body = *node
+
+          if cond.type == :begin
+            return if parens_required?(node)
+            # allow safe assignment
+            return if safe_assignment?(cond) && safe_assignment_allowed?
+
+            add_offense(cond, :expression, message(node))
+          end
+        end
+
+        def parens_required?(node)
+          exp = node.loc.expression
+          kw = node.loc.keyword
+          kw_offset = kw.begin_pos - exp.begin_pos
+
+          exp.source[kw_offset..-1].start_with?(kw.source + '(')
+        end
+
+        def message(node)
+          kw = node.loc.keyword.source
+          article = kw == 'while' ? 'a' : 'an'
+          "Don't use parentheses around the condition of #{article} `#{kw}`."
+        end
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            corrector.remove(node.loc.begin)
+            corrector.remove(node.loc.end)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/percent_literal_delimiters.rb b/lib/rubocop/cop/style/percent_literal_delimiters.rb
new file mode 100644
index 0000000..ee598bf
--- /dev/null
+++ b/lib/rubocop/cop/style/percent_literal_delimiters.rb
@@ -0,0 +1,153 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop enforces the consitent useage of `%`-literal delimiters.
+      class PercentLiteralDelimiters < Cop
+        def on_array(node)
+          process(node, '%w', '%W', '%i')
+        end
+
+        def on_regexp(node)
+          process(node, '%r')
+        end
+
+        def on_str(node)
+          process(node, '%', '%Q', '%q')
+        end
+        alias_method :on_dstr, :on_str
+
+        def on_sym(node)
+          process(node, '%s')
+        end
+
+        def on_xstr(node)
+          process(node, '%x')
+        end
+
+        def message(node)
+          type = type(node)
+          delimiters = preferred_delimiters(type)
+
+          "`#{type}`-literals should be delimited by " \
+          "`#{delimiters[0]}` and `#{delimiters[1]}`"
+        end
+
+        private
+
+        def autocorrect(node)
+          type = type(node)
+
+          opening_delimiter, closing_delimiter = preferred_delimiters(type)
+          opening_newline = new_line(node.loc.begin, node.children.first)
+          closing_newline = new_line(node.loc.end, node.children.last)
+
+          expression, reg_opt = *contents(node)
+          corrected_source =
+            type + opening_delimiter + opening_newline +
+            expression +
+            closing_newline + closing_delimiter + reg_opt
+
+          @corrections << lambda do |corrector|
+            corrector.replace(
+              node.loc.expression,
+              corrected_source
+            )
+          end
+        end
+
+        def process(node, *types)
+          on_percent_literal(node, types) if percent_literal?(node)
+        end
+
+        def percent_literal?(node)
+          if (begin_source = begin_source(node))
+            begin_source.start_with?('%')
+          end
+        end
+
+        def on_percent_literal(node, types)
+          type = type(node)
+          if types.include?(type) &&
+              !uses_preferred_delimiter?(node, type) &&
+              !contains_preferred_delimiter?(node, type)
+            add_offense(node, :expression)
+          end
+        end
+
+        def type(node)
+          node.loc.begin.source[0..-2]
+        end
+
+        def preferred_delimiters(type)
+          cop_config['PreferredDelimiters'][type].split(//)
+        end
+
+        def contents(node)
+          first_child, *middle, last_child = *node
+          last_child ||= first_child
+          if node.type == :regexp
+            *_, next_to_last_child = *middle
+            next_to_last_child ||= first_child
+            [
+              source(node, first_child, next_to_last_child),
+              last_child.loc.expression.source
+            ]
+          else
+            [
+              if first_child.is_a?(Parser::AST::Node)
+                source(node, first_child, last_child)
+              else
+                first_child.to_s
+              end,
+              ''
+            ]
+          end
+        end
+
+        def source(node, begin_node, end_node)
+          Parser::Source::Range.new(
+            node.loc.expression.source_buffer,
+            begin_node.loc.expression.begin_pos,
+            end_node.loc.expression.end_pos
+          ).source
+        end
+
+        def uses_preferred_delimiter?(node, type)
+          preferred_delimiters(type)[0] == begin_source(node)[-1]
+        end
+
+        def contains_preferred_delimiter?(node, type)
+          preferred_delimiters = preferred_delimiters(type)
+          node
+            .children.map { |n| string_source(n) }.compact
+            .any? { |s| preferred_delimiters.any? { |d| s.include?(d) } }
+        end
+
+        def begin_source(node)
+          if node.loc.respond_to?(:begin) && node.loc.begin
+            node.loc.begin.source
+          end
+        end
+
+        def string_source(node)
+          if node.is_a?(String)
+            node
+          elsif node.respond_to?(:type) && node.type == :str
+            node.loc.expression.source
+          end
+        end
+
+        def new_line(range, child_node)
+          same_line?(range, child_node) ? '' : "\n"
+        end
+
+        def same_line?(range, child_node)
+          !child_node.is_a?(Parser::AST::Node) ||
+            range.begin.line == child_node.loc.line
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/perl_backrefs.rb b/lib/rubocop/cop/style/perl_backrefs.rb
new file mode 100644
index 0000000..508d448
--- /dev/null
+++ b/lib/rubocop/cop/style/perl_backrefs.rb
@@ -0,0 +1,26 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop looks for uses of Perl-style regexp match
+      # backreferences like $1, $2, etc.
+      class PerlBackrefs < Cop
+        MSG = 'Avoid the use of Perl-style backrefs.'
+
+        def on_nth_ref(node)
+          add_offense(node, :expression)
+        end
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            backref, = *node
+
+            corrector.replace(node.loc.expression,
+                              "Regexp.last_match[#{backref}]")
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/predicate_name.rb b/lib/rubocop/cop/style/predicate_name.rb
new file mode 100644
index 0000000..f8da241
--- /dev/null
+++ b/lib/rubocop/cop/style/predicate_name.rb
@@ -0,0 +1,46 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop makes sure that predicates are named properly.
+      #
+      # @example
+      #   # bad
+      #   def is_even?(value) ...
+      #
+      #   # good
+      #   def even?(value)
+      #
+      #   # bad
+      #   def has_value? ...
+      #
+      #   # good
+      #   def value? ...
+      class PredicateName < Cop
+        include CheckMethods
+
+        private
+
+        def check(node, method_name, args, _body)
+          prefix_blacklist.each do |prefix|
+            if method_name.to_s.start_with?(prefix)
+              add_offense(node, :name,
+                          message(method_name.to_s, prefix))
+            end
+          end
+        end
+
+        def message(method_name, prefix)
+          new_name = method_name.sub(prefix, '')
+          new_name << '?' unless method_name.end_with?('?')
+          "Rename `#{method_name}` to `#{new_name}`."
+        end
+
+        def prefix_blacklist
+          cop_config['NamePrefixBlacklist']
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/proc.rb b/lib/rubocop/cop/style/proc.rb
new file mode 100644
index 0000000..fcc3c01
--- /dev/null
+++ b/lib/rubocop/cop/style/proc.rb
@@ -0,0 +1,32 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cops checks for uses of Proc.new where Kernel#proc
+      # would be more appropriate.
+      class Proc < Cop
+        MSG = 'Use `proc` instead of `Proc.new`.'
+
+        TARGET = s(:send, s(:const, nil, :Proc), :new)
+
+        def on_block(node)
+          # We're looking for
+          # (block
+          #   (send
+          #     (const nil :Proc) :new)
+          #   ...)
+          block_method, = *node
+
+          add_offense(block_method, :expression) if block_method == TARGET
+        end
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            corrector.replace(node.loc.expression, 'proc')
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/raise_args.rb b/lib/rubocop/cop/style/raise_args.rb
new file mode 100644
index 0000000..40d582a
--- /dev/null
+++ b/lib/rubocop/cop/style/raise_args.rb
@@ -0,0 +1,68 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks the args passed to `fail` and `raise`.
+      class RaiseArgs < Cop
+        include ConfigurableEnforcedStyle
+
+        def on_send(node)
+          return unless command?(:raise, node) || command?(:fail, node)
+
+          case style
+          when :compact
+            check_compact(node)
+          when :exploded
+            check_exploded(node)
+          end
+        end
+
+        private
+
+        def check_compact(node)
+          _receiver, selector, *args = *node
+
+          if args.size > 1
+            add_offense(node, :expression, message(selector)) do
+              opposite_style_detected
+            end
+          else
+            correct_style_detected
+          end
+        end
+
+        def check_exploded(node)
+          _receiver, selector, *args = *node
+
+          if args.size == 1
+            arg, = *args
+
+            if arg.type == :send && arg.loc.selector.is?('new')
+              _receiver, _selector, *constructor_args = *arg
+
+              # Allow code like `raise Ex.new(arg1, arg2)`.
+              if constructor_args.size <= 1
+                add_offense(node, :expression, message(selector)) do
+                  opposite_style_detected
+                end
+              end
+            end
+          else
+            correct_style_detected
+          end
+        end
+
+        def message(method)
+          case style
+          when :compact
+            "Provide an exception object as an argument to `#{method}`."
+          when :exploded
+            "Provide an exception class and message as " \
+            "arguments to `#{method}`."
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/redundant_begin.rb b/lib/rubocop/cop/style/redundant_begin.rb
new file mode 100644
index 0000000..373beb2
--- /dev/null
+++ b/lib/rubocop/cop/style/redundant_begin.rb
@@ -0,0 +1,35 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for redundant `begin` blocks.
+      #
+      # Currently it checks for code like this:
+      #
+      # @example
+      #
+      #   def test
+      #     begin
+      #       ala
+      #       bala
+      #     rescue StandardError => e
+      #       something
+      #     end
+      #   end
+      class RedundantBegin < Cop
+        include CheckMethods
+
+        MSG = 'Redundant `begin` block detected.'
+
+        private
+
+        def check(_node, _method_name, _args, body)
+          return unless body && body.type == :kwbegin
+
+          add_offense(body, :begin)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/redundant_exception.rb b/lib/rubocop/cop/style/redundant_exception.rb
new file mode 100644
index 0000000..03308fb
--- /dev/null
+++ b/lib/rubocop/cop/style/redundant_exception.rb
@@ -0,0 +1,32 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for RuntimeError as the argument of raise/fail.
+      #
+      # Currently it checks for code like this:
+      #
+      # @example
+      #
+      #   raise RuntimeError, 'message'
+      class RedundantException < Cop
+        MSG = 'Redundant `RuntimeError` argument can be removed.'
+
+        TARGET_NODE = s(:const, nil, :RuntimeError)
+
+        def on_send(node)
+          return unless command?(:raise, node) || command?(:fail, node)
+
+          _receiver, _selector, *args = *node
+
+          return unless args.size == 2
+
+          first_arg, = *args
+
+          add_offense(first_arg, :expression) if first_arg == TARGET_NODE
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/redundant_return.rb b/lib/rubocop/cop/style/redundant_return.rb
new file mode 100644
index 0000000..345751f
--- /dev/null
+++ b/lib/rubocop/cop/style/redundant_return.rb
@@ -0,0 +1,66 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for redundant `return` expressions.
+      #
+      # @example
+      #
+      #   def test
+      #     return something
+      #   end
+      #
+      #   def test
+      #     one
+      #     two
+      #     three
+      #     return something
+      #   end
+      #
+      # It should be extended to handle methods whose body is if/else
+      # or a case expression with a default branch.
+      class RedundantReturn < Cop
+        include CheckMethods
+
+        MSG = 'Redundant `return` detected.'
+
+        private
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            if node.children.size > 1
+              kids = node.children.map { |child| child.loc.expression }
+              corrector.insert_before(kids.first, '[')
+              corrector.insert_after(kids.last, ']')
+            end
+            return_kw = range_with_surrounding_space(node.loc.keyword, :right)
+            corrector.remove(return_kw)
+          end
+        end
+
+        def check(_node, _method_name, _args, body)
+          return unless body
+
+          if body.type == :return
+            check_return_node(body)
+          elsif body.type == :begin
+            expressions = *body
+            last_expr = expressions.last
+
+            if last_expr && last_expr.type == :return
+              check_return_node(last_expr)
+            end
+          end
+        end
+
+        def check_return_node(node)
+          return if cop_config['AllowMultipleReturnValues'] &&
+            node.children.size > 1
+
+          add_offense(node, :keyword)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/redundant_self.rb b/lib/rubocop/cop/style/redundant_self.rb
new file mode 100644
index 0000000..74bba6c
--- /dev/null
+++ b/lib/rubocop/cop/style/redundant_self.rb
@@ -0,0 +1,145 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for redundant uses of `self`.
+      #
+      # `self` is only needed when:
+      #
+      # * Sending a message to same object with zero arguments in
+      #   presence of a method name clash with an argument or a local
+      #   variable.
+      #
+      #   Note, with using explicit self you can only send messages
+      #   with public or protected scope, you cannot send private
+      #   messages this way.
+      #
+      #   Example:
+      #
+      #   def bar
+      #     :baz
+      #   end
+      #
+      #   def foo(bar)
+      #     self.bar # resolves name clash with argument
+      #   end
+      #
+      #   def foo2
+      #     bar = 1
+      #     self.bar # resolves name class with local variable
+      #   end
+      #
+      # * Calling an attribute writer to prevent an local variable assignment
+      #
+      #   attr_writer :bar
+      #
+      #   def foo
+      #     self.bar= 1 # Make sure above attr writer is called
+      #   end
+      #
+      # Special cases:
+      #
+      # We allow uses of `self` with operators because it would be awkward
+      # otherwise.
+      class RedundantSelf < Cop
+        MSG = 'Redundant `self` detected.'
+
+        def initialize(config = nil, options = nil)
+          super
+          @allowed_send_nodes = []
+          @local_variables = []
+        end
+
+        # Assignment of self.x
+
+        def on_or_asgn(node)
+          lhs, _rhs = *node
+          allow_self(lhs)
+        end
+
+        alias_method :on_and_asgn, :on_or_asgn
+
+        def on_op_asgn(node)
+          lhs, _op, _rhs = *node
+          allow_self(lhs)
+        end
+
+        # Using self.x to distinguish from local variable x
+
+        def on_def(node)
+          @local_variables = []
+        end
+
+        def on_defs(node)
+          @local_variables = []
+        end
+
+        def on_args(node)
+          node.children.each { |arg| on_argument(arg) }
+        end
+
+        def on_blockarg(node)
+          on_argument(node)
+        end
+
+        def on_lvasgn(node)
+          lhs, _rhs = *node
+          @local_variables << lhs
+        end
+
+        # Detect offenses
+
+        def on_send(node)
+          receiver, method_name, *_args = *node
+          if receiver && receiver.type == :self
+            unless operator?(method_name) || keyword?(method_name) ||
+                constant_name?(method_name) ||
+                @allowed_send_nodes.include?(node) ||
+                @local_variables.include?(method_name)
+              add_offense(node, :expression)
+            end
+          end
+        end
+
+        def autocorrect(node)
+          receiver, _method_name, *_args = *node
+          @corrections << lambda do |corrector|
+            corrector.remove(receiver.loc.expression)
+            corrector.remove(node.loc.dot)
+          end
+        end
+
+        private
+
+        def on_argument(node)
+          name, _ = *node
+          @local_variables << name
+        end
+
+        def operator?(method_name)
+          method_name.to_s =~ /\W/
+        end
+
+        def keyword?(method_name)
+          [:alias, :and, :begin, :break, :case, :class, :def, :defined, :do,
+           :else, :elsif, :end, :ensure, :false, :for, :if, :in, :module,
+           :next, :nil, :not, :or, :redo, :rescue, :retry, :return, :self,
+           :super, :then, :true, :undef, :unless, :until, :when, :while,
+           :yield].include?(method_name)
+        end
+
+        def constant_name?(method_name)
+          method_name.match(/^[A-Z]/)
+        end
+
+        def allow_self(node)
+          if node.type == :send
+            receiver, _method_name, *_args = *node
+            @allowed_send_nodes << node if receiver && receiver.type == :self
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/regexp_literal.rb b/lib/rubocop/cop/style/regexp_literal.rb
new file mode 100644
index 0000000..c8168ce
--- /dev/null
+++ b/lib/rubocop/cop/style/regexp_literal.rb
@@ -0,0 +1,81 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for regexp literals and reports offenses based
+      # on how many escaped slashes there are in the regexp and on the
+      # value of the configuration parameter MaxSlashes.
+      class RegexpLiteral < Cop
+        def on_regexp(node)
+          string_parts = node.children.select { |child| child.type == :str }
+          total_string = string_parts.map { |s| s.loc.expression.source }.join
+          slashes = total_string.count('/')
+          if node.loc.begin.is?('/')
+            if slashes > max_slashes
+              add_offense(node, :expression, error_message('')) do
+                self.slash_count_in_slashes_regexp = slashes
+              end
+            end
+          elsif slashes <= max_slashes
+            add_offense(node, :expression, error_message('only ')) do
+              self.slash_count_in_percent_r_regexp = slashes
+            end
+          end
+        end
+
+        private
+
+        def max_slashes
+          m = cop_config['MaxSlashes']
+          unless m.is_a?(Fixnum) && m >= 0
+            fail "Illegal value for MaxSlashes: #{m}"
+          end
+          m
+        end
+
+        # MaxSlashes must be set equal to the highest number of slashes used
+        # within // to avoid reports.
+        def slash_count_in_slashes_regexp=(value)
+          configure_slashes(value) { |current| [current, value].max }
+        end
+
+        # MaxSlashes must be set one less than the highest number of slashes
+        # used within %r{} to avoid reports.
+        def slash_count_in_percent_r_regexp=(value)
+          configure_slashes(value - 1) { |current| [current, value - 1].min }
+        end
+
+        def configure_slashes(value)
+          cfg = self.config_to_allow_offenses ||= {}
+          return if cfg.key?('Enabled')
+
+          if cfg['MaxSlashes']
+            value = yield cfg['MaxSlashes']
+            if cfg['MaxSlashes'] > max_slashes && value < max_slashes ||
+                cfg['MaxSlashes'] < max_slashes && value > max_slashes
+              # We can't both increase and decrease MaxSlashes to avoid
+              # reports. This means that the only option is to disable the cop.
+              cfg = self.config_to_allow_offenses = { 'Enabled' => false }
+              return
+            end
+          end
+
+          if value >= 0
+            cfg['MaxSlashes'] = value
+          else
+            self.config_to_allow_offenses = { 'Enabled' => false }
+          end
+        end
+
+        def error_message(word)
+          format('Use %%r %sfor regular expressions matching more ' \
+                 "than %d '/' character%s.",
+                 word,
+                 max_slashes,
+                 max_slashes == 1 ? '' : 's')
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/rescue_modifier.rb b/lib/rubocop/cop/style/rescue_modifier.rb
new file mode 100644
index 0000000..29f1612
--- /dev/null
+++ b/lib/rubocop/cop/style/rescue_modifier.rb
@@ -0,0 +1,39 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for uses of rescue in its modifier form.
+      class RescueModifier < Cop
+        include CheckMethods
+
+        MSG = 'Avoid using `rescue` in its modifier form.'
+
+        def on_rescue(node)
+          return if ignored_node?(node)
+
+          add_offense(node, :expression)
+        end
+
+        def on_kwbegin(node)
+          body, *_ = *node
+          check(nil, nil, nil, body)
+        end
+
+        def check(_node, _method_name, _args, body)
+          return unless body
+
+          case body.type
+          when :rescue
+            ignore_node(body)
+          when :ensure
+            first_child = body.children.first
+            if first_child && first_child.type == :rescue
+              ignore_node(first_child)
+            end
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/self_assignment.rb b/lib/rubocop/cop/style/self_assignment.rb
new file mode 100644
index 0000000..1e8b6d1
--- /dev/null
+++ b/lib/rubocop/cop/style/self_assignment.rb
@@ -0,0 +1,73 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop enforces the use the shorthand for self-assignment.
+      #
+      # @example
+      #
+      #   # bad
+      #   x = x + 1
+      #
+      #   # good
+      #   x += 1
+      class SelfAssignment < Cop
+        include AST::Sexp
+
+        OPS = [:+, :-, :*, :**, :/, :|, :&]
+
+        def on_lvasgn(node)
+          check(node, :lvar)
+        end
+
+        def on_ivasgn(node)
+          check(node, :ivar)
+        end
+
+        def on_cvasgn(node)
+          check(node, :cvar)
+        end
+
+        def check(node, var_type)
+          var_name, rhs = *node
+
+          return unless rhs
+
+          if rhs.type == :send
+            check_send_node(node, rhs, var_name, var_type)
+          elsif [:and, :or].include?(rhs.type)
+            check_boolean_node(node, rhs, var_name, var_type)
+          end
+        end
+
+        def check_send_node(node, rhs, var_name, var_type)
+          receiver, method_name, *_args = *rhs
+
+          return unless OPS.include?(method_name)
+
+          target_node = s(var_type, var_name)
+
+          if receiver == target_node
+            add_offense(node,
+                        :expression,
+                        "Use self-assignment shorthand `#{method_name}=`.")
+          end
+        end
+
+        def check_boolean_node(node, rhs, var_name, var_type)
+          first_operand, _second_operand = *rhs
+
+          target_node = s(var_type, var_name)
+
+          if first_operand == target_node
+            operator = rhs.loc.operator.source
+            add_offense(node,
+                        :expression,
+                        "Use self-assignment shorthand `#{operator}=`.")
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/semicolon.rb b/lib/rubocop/cop/style/semicolon.rb
new file mode 100644
index 0000000..a47c0fb
--- /dev/null
+++ b/lib/rubocop/cop/style/semicolon.rb
@@ -0,0 +1,68 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for multiple expressions placed on the same line.
+      # It also checks for lines terminated with a semicolon.
+      class Semicolon < Cop
+        MSG = 'Do not use semicolons to terminate expressions.'
+
+        def investigate(processed_source)
+          return unless processed_source.ast
+          @processed_source = processed_source
+
+          check_for_line_terminator
+        end
+
+        def on_begin(node)
+          unless cop_config['AllowAsExpressionSeparator']
+            exprs = node.children
+
+            return if exprs.size < 2
+
+            # create a map matching lines to the number of expressions on them
+            exprs_lines = exprs.map { |e| e.loc.expression.line }
+            lines = exprs_lines.group_by { |i| i }
+
+            # every line with more than 1 expression on it is an offense
+            lines.each do |line, expr_on_line|
+              if expr_on_line.size > 1
+                # TODO: Find the correct position of the semicolon. We don't
+                # know if the first semicolon on the line is a separator of
+                # expressions. It's just a guess.
+                column = @processed_source[line - 1].index(';')
+                convention_on(line, column, !:last_on_line)
+              end
+            end
+          end
+        end
+
+        private
+
+        def check_for_line_terminator
+          tokens_for_lines = @processed_source.tokens.group_by do |token|
+            token.pos.line
+          end
+
+          tokens_for_lines.each do |line, tokens|
+            if tokens.last.type == :tSEMI
+              convention_on(line, tokens.last.pos.column, :last_on_line)
+            end
+          end
+        end
+
+        def convention_on(line, column, last_on_line)
+          range = source_range(@processed_source.buffer,
+                               @processed_source[0...(line - 1)], column,
+                               1)
+          add_offense(last_on_line ? range : nil, range)
+        end
+
+        def autocorrect(range)
+          @corrections << ->(corrector) { corrector.remove(range) } if range
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/signal_exception.rb b/lib/rubocop/cop/style/signal_exception.rb
new file mode 100644
index 0000000..3160a15
--- /dev/null
+++ b/lib/rubocop/cop/style/signal_exception.rb
@@ -0,0 +1,96 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for uses of `fail` and `raise`.
+      class SignalException < Cop
+        include ConfigurableEnforcedStyle
+
+        FAIL_MSG = 'Use `fail` instead of `raise` to signal exceptions.'
+        RAISE_MSG = 'Use `raise` instead of `fail` to rethrow exceptions.'
+
+        def on_rescue(node)
+          if style == :semantic
+            begin_node, *rescue_nodes, _else_node = *node
+
+            check_for(:raise, begin_node)
+
+            rescue_nodes.each do |rescue_node|
+              check_for(:fail, rescue_node)
+              allow(:raise, rescue_node)
+            end
+          end
+        end
+
+        def on_send(node)
+          case style
+          when :semantic
+            check_for(:raise, node) unless ignored_node?(node)
+          when :only_raise
+            check_for(:raise, node)
+          when :only_fail
+            check_for(:fail, node)
+          end
+        end
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            name =
+              case style
+              when :semantic then command?(:raise, node) ? 'fail' : 'raise'
+              when :only_raise then 'raise'
+              when :only_fail then 'fail'
+              end
+
+            corrector.replace(node.loc.selector, name)
+          end
+        end
+
+        private
+
+        def message(method_name)
+          case style
+          when :semantic
+            method_name == :fail ? RAISE_MSG : FAIL_MSG
+          when :only_raise
+            'Always use `raise` to signal exceptions.'
+          when :only_fail
+            'Always use `fail` to signal exceptions.'
+          end
+        end
+
+        def check_for(method_name, node)
+          return unless node
+
+          if style == :semantic
+            each_command(method_name, node) do |send_node|
+              unless ignored_node?(send_node)
+                add_offense(send_node, :selector, message(method_name))
+                ignore_node(send_node)
+              end
+            end
+          else
+            _receiver, selector, _args = *node
+
+            if [:raise, :fail].include?(selector) && selector != method_name
+              add_offense(node, :selector, message(method_name))
+            end
+          end
+        end
+
+        def allow(method_name, node)
+          each_command(method_name, node) do |send_node|
+            ignore_node(send_node)
+          end
+        end
+
+        def each_command(method_name, node)
+          on_node(:send, node, :rescue) do |send_node|
+            yield send_node if command?(method_name, send_node)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/single_line_block_params.rb b/lib/rubocop/cop/style/single_line_block_params.rb
new file mode 100644
index 0000000..af741b8
--- /dev/null
+++ b/lib/rubocop/cop/style/single_line_block_params.rb
@@ -0,0 +1,62 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks whether the block parameters of a single-line
+      # method accepting a block match the names specified via configuration.
+      #
+      # For instance one can configure `reduce`(`inject`) to use |a, e| as
+      # parameters.
+      class SingleLineBlockParams < Cop
+        def on_block(node)
+          # we care only for single line blocks
+          return unless Util.block_length(node) == 0
+
+          method_node, args_node, _body_node = *node
+          receiver, method_name, _method_args = *method_node
+
+          # discard other scenarios
+          return unless receiver
+          return unless method_names.include?(method_name)
+
+          # discard cases with argument destructuring
+          args = *args_node
+
+          return true unless args.all? { |n| n.type == :arg }
+
+          unless args_match?(method_name, args)
+            add_offense(args_node, :expression, message(method_name))
+          end
+        end
+
+        private
+
+        def message(method_name)
+          args = target_args(method_name).join(', ')
+          "Name `#{method_name}` block params `|#{args}|`."
+        end
+
+        def methods
+          cop_config['Methods']
+        end
+
+        def method_names
+          methods.map { |e| e.keys.first.to_sym }
+        end
+
+        def target_args(method_name)
+          method_name = method_name.to_s
+          method_hash = methods.find { |m| m.keys.first == method_name }
+          method_hash[method_name]
+        end
+
+        def args_match?(method_name, args)
+          actual_args = args.flat_map { |a| a.to_a }
+
+          actual_args == target_args(method_name).map(&:to_sym)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/single_line_methods.rb b/lib/rubocop/cop/style/single_line_methods.rb
new file mode 100644
index 0000000..37475b5
--- /dev/null
+++ b/lib/rubocop/cop/style/single_line_methods.rb
@@ -0,0 +1,70 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for single-line method definitions.
+      # It can optionally accept single-line methods with no body.
+      class SingleLineMethods < Cop
+        include CheckMethods
+
+        MSG = 'Avoid single-line method definitions.'
+
+        def allow_empty?
+          cop_config['AllowIfMethodIsEmpty']
+        end
+
+        private
+
+        def check(node, _method_name, _args, body)
+          start_line = node.loc.keyword.line
+          end_line = node.loc.end.line
+
+          empty_body = body.nil?
+
+          if start_line == end_line && !(allow_empty? && empty_body)
+            @body = body
+            add_offense(node, :expression)
+          end
+        end
+
+        def autocorrect(node)
+          body = @body
+          eol_comment = processed_source.comments.find do |c|
+            c.loc.line == node.loc.expression.line
+          end
+          @corrections << lambda do |corrector|
+            if body.type == :begin
+              body.children.each do |part|
+                break_line_before(part.loc.expression, node, corrector, 1)
+              end
+            else
+              break_line_before(body.loc.expression, node, corrector, 1)
+            end
+
+            break_line_before(node.loc.end, node, corrector, 0)
+
+            move_comment(eol_comment, node, corrector) if eol_comment
+          end
+        end
+
+        def break_line_before(range, node, corrector, indent_steps)
+          corrector.insert_before(
+            range,
+            "\n" + ' ' * (node.loc.keyword.column +
+                          indent_steps *
+                          IndentationWidth::CORRECT_INDENTATION)
+          )
+        end
+
+        def move_comment(eol_comment, node, corrector)
+          text = eol_comment.loc.expression.source
+          corrector.insert_before(node.loc.expression,
+                                  text + "\n" +
+                                  ' ' * node.loc.keyword.column)
+          corrector.remove(eol_comment.loc.expression)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/single_space_before_first_arg.rb b/lib/rubocop/cop/style/single_space_before_first_arg.rb
new file mode 100644
index 0000000..de4c972
--- /dev/null
+++ b/lib/rubocop/cop/style/single_space_before_first_arg.rb
@@ -0,0 +1,41 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # Checks that exactly one space is used between a method name and the
+      # first argument for method calls without parentheses.
+      #
+      # @example
+      #
+      #   something  x
+      #   something   y, z
+      #
+      class SingleSpaceBeforeFirstArg < Cop
+        MSG = 'Put one space between the method name and the first argument.'
+
+        def on_send(node)
+          return if parentheses?(node)
+
+          _receiver, method_name, *args = *node
+          return if args.empty?
+          return if operator?(method_name)
+          return if method_name.to_s.end_with?('=')
+
+          arg1 = args.first.loc.expression
+          return if arg1.line > node.loc.line
+
+          arg1_with_space = range_with_surrounding_space(arg1, :left)
+          space = Parser::Source::Range.new(arg1.source_buffer,
+                                            arg1_with_space.begin_pos,
+                                            arg1.begin_pos)
+          add_offense(space, space) if space.length > 1
+        end
+
+        def autocorrect(range)
+          @corrections << ->(corrector) { corrector.replace(range, ' ') }
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/space_after_colon.rb b/lib/rubocop/cop/style/space_after_colon.rb
new file mode 100644
index 0000000..834ae8c
--- /dev/null
+++ b/lib/rubocop/cop/style/space_after_colon.rb
@@ -0,0 +1,36 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # Checks for colon (:) not followed by some kind of space.
+      class SpaceAfterColon < Cop
+        include IfNode
+
+        MSG = 'Space missing after colon.'
+
+        def on_pair(node)
+          oper = node.loc.operator
+          if oper.is?(':') && oper.source_buffer.source[oper.end_pos] =~ /\S/
+            add_offense(oper, oper)
+          end
+        end
+
+        def on_if(node)
+          if ternary_op?(node)
+            colon = node.loc.colon
+            if colon.source_buffer.source[colon.end_pos] =~ /\S/
+              add_offense(colon, colon)
+            end
+          end
+        end
+
+        def autocorrect(range)
+          @corrections << lambda do |corrector|
+            corrector.insert_after(range, ' ')
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/space_after_comma.rb b/lib/rubocop/cop/style/space_after_comma.rb
new file mode 100644
index 0000000..6cc2bdb
--- /dev/null
+++ b/lib/rubocop/cop/style/space_after_comma.rb
@@ -0,0 +1,16 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # Checks for comma (,) not followed by some kind of space.
+      class SpaceAfterComma < Cop
+        include SpaceAfterPunctuation
+
+        def kind(token)
+          'comma' if token.type == :tCOMMA
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/space_after_control_keyword.rb b/lib/rubocop/cop/style/space_after_control_keyword.rb
new file mode 100644
index 0000000..55877d7
--- /dev/null
+++ b/lib/rubocop/cop/style/space_after_control_keyword.rb
@@ -0,0 +1,37 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # Checks for various control keywords missing a space after them.
+      class SpaceAfterControlKeyword < Cop
+        MSG = 'Use space after control keywords.'
+        # elsif and unless are handled by on_if.
+        KEYWORDS = %w(if case when while until)
+
+        def on_keyword(node)
+          return if node.loc.is_a?(Parser::Source::Map::Ternary)
+
+          exp = node.loc.expression
+          kw = node.loc.keyword
+          kw_offset = kw.begin_pos - exp.begin_pos
+          if exp.source[kw_offset..-1].start_with?(kw.source + '(')
+            add_offense(node, kw)
+          end
+        end
+
+        KEYWORDS.each do |keyword|
+          define_method(:"on_#{keyword}") do |node|
+            on_keyword(node)
+          end
+        end
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            corrector.insert_after(node.loc.keyword, ' ')
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/space_after_method_name.rb b/lib/rubocop/cop/style/space_after_method_name.rb
new file mode 100644
index 0000000..3ddac59
--- /dev/null
+++ b/lib/rubocop/cop/style/space_after_method_name.rb
@@ -0,0 +1,40 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # Checks for space between a method name and a left parenthesis in defs.
+      #
+      # @example
+      #
+      #   # bad
+      #   def func (x) ... end
+      #
+      #   # good
+      #   def func(x) ... end
+      class SpaceAfterMethodName < Cop
+        include CheckMethods
+
+        MSG = 'Never put a space between a method name and the opening ' \
+              'parenthesis.'
+
+        def check(_node, _method_name, args, body)
+          return unless args.loc.begin && args.loc.begin.is?('(')
+          expr = args.loc.expression
+          pos_before_left_paren = Parser::Source::Range.new(expr.source_buffer,
+                                                            expr.begin_pos - 1,
+                                                            expr.begin_pos)
+          if pos_before_left_paren.source =~ /\s/
+            add_offense(pos_before_left_paren, pos_before_left_paren)
+          end
+        end
+
+        def autocorrect(pos_before_left_paren)
+          @corrections << lambda do |corrector|
+            corrector.remove(pos_before_left_paren)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/space_after_not.rb b/lib/rubocop/cop/style/space_after_not.rb
new file mode 100644
index 0000000..89ee460
--- /dev/null
+++ b/lib/rubocop/cop/style/space_after_not.rb
@@ -0,0 +1,41 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for space after `!`.
+      #
+      # @example
+      #   # bad
+      #   ! something
+      #
+      #   # good
+      #   !something
+      class SpaceAfterNot < Cop
+        MSG = 'Do not leave space between `!` and its argument.'
+
+        def on_send(node)
+          _receiver, method_name, *_args = *node
+
+          return unless method_name == :!
+
+          if node.loc.expression.source =~ /^!\s+\w+/
+            # TODO: Improve source range to highlight the redundant whitespace.
+            add_offense(node, :selector)
+          end
+        end
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            receiver, _method_name, *_args = *node
+            space_range =
+              Parser::Source::Range.new(node.loc.selector.source_buffer,
+                                        node.loc.selector.end_pos,
+                                        receiver.loc.expression.begin_pos)
+            corrector.remove(space_range)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/space_after_semicolon.rb b/lib/rubocop/cop/style/space_after_semicolon.rb
new file mode 100644
index 0000000..c89e431
--- /dev/null
+++ b/lib/rubocop/cop/style/space_after_semicolon.rb
@@ -0,0 +1,16 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # Checks for semicolon (;) not followed by some kind of space.
+      class SpaceAfterSemicolon < Cop
+        include SpaceAfterPunctuation
+
+        def kind(token)
+          'semicolon' if token.type == :tSEMI
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/space_around_equals_in_parameter_default.rb b/lib/rubocop/cop/style/space_around_equals_in_parameter_default.rb
new file mode 100644
index 0000000..0909fe9
--- /dev/null
+++ b/lib/rubocop/cop/style/space_around_equals_in_parameter_default.rb
@@ -0,0 +1,68 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # Checks that the equals signs in parameter default assignments
+      # have or don't have surrounding space depending on configuration.
+      class SpaceAroundEqualsInParameterDefault < Cop
+        include SurroundingSpace
+        include ConfigurableEnforcedStyle
+
+        def investigate(processed_source)
+          return unless processed_source.ast
+          @processed_source = processed_source
+          on_node(:optarg, processed_source.ast) do |optarg|
+            index = index_of_first_token(optarg)
+            arg, equals, value = processed_source.tokens[index, 3]
+            check_optarg(arg, equals, value)
+          end
+        end
+
+        private
+
+        def check_optarg(arg, equals, value)
+          space_on_both_sides = space_on_both_sides?(arg, equals, value)
+          no_surrounding_space = no_surrounding_space?(arg, equals, value)
+
+          if style == :space && space_on_both_sides ||
+              style == :no_space && no_surrounding_space
+            correct_style_detected
+          else
+            range = Parser::Source::Range.new(processed_source.buffer,
+                                              arg.pos.end_pos,
+                                              value.pos.begin_pos)
+            add_offense(range, range) do
+              if style == :space && no_surrounding_space ||
+                  style == :no_space && space_on_both_sides
+                opposite_style_detected
+              else
+                unrecognized_style_detected
+              end
+            end
+          end
+        end
+
+        def space_on_both_sides?(arg, equals, value)
+          space_between?(arg, equals) && space_between?(equals, value)
+        end
+
+        def no_surrounding_space?(arg, equals, value)
+          !space_between?(arg, equals) && !space_between?(equals, value)
+        end
+
+        def message(_)
+          format('Surrounding space %s in default value assignment.',
+                 style == :space ? 'missing' : 'detected')
+        end
+
+        def autocorrect(range)
+          replacement = style == :space ? ' = ' : '='
+          @corrections << lambda do |corrector|
+            corrector.replace(range, replacement)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/space_around_operators.rb b/lib/rubocop/cop/style/space_around_operators.rb
new file mode 100644
index 0000000..2cfe900
--- /dev/null
+++ b/lib/rubocop/cop/style/space_around_operators.rb
@@ -0,0 +1,82 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # Checks that operators have space around them, except for **
+      # which should not have surrounding space.
+      class SpaceAroundOperators < Cop
+        TYPES = %w(and or class) + ASGN_NODES
+
+        TYPES.each { |t| define_method(:"on_#{t}") { |node| check(node) } }
+
+        def on_pair(node)
+          check(node) if node.loc.operator.is?('=>')
+        end
+
+        def on_if(node)
+          if node.loc.respond_to?(:question)
+            check_operator(node.loc.question)
+            check_operator(node.loc.colon)
+          end
+        end
+
+        def on_resbody(node)
+          check_operator(node.loc.assoc) if node.loc.assoc
+        end
+
+        def on_send(node)
+          if node.loc.operator
+            check(node)
+          elsif !unary_operation?(node) && !called_with_dot?(node)
+            op = node.loc.selector
+            check_operator(op) if operator?(op)
+          end
+        end
+
+        private
+
+        def operator?(range)
+          range.source !~ /^\[|\w/
+        end
+
+        def unary_operation?(node)
+          whole, selector = node.loc.expression, node.loc.selector
+          operator?(selector) && whole.begin_pos == selector.begin_pos
+        end
+
+        def called_with_dot?(node)
+          node.loc.dot
+        end
+
+        def check(node)
+          check_operator(node.loc.operator) if node.loc.operator
+        end
+
+        def check_operator(op)
+          with_space = range_with_surrounding_space(op)
+          if op.is?('**')
+            unless with_space.is?('**')
+              add_offense(with_space, op, 'Space around operator ** detected.')
+            end
+          elsif with_space.source !~ /^\s.*\s$/
+            add_offense(with_space, op,
+                        'Surrounding space missing for operator' \
+                        " '#{op.source}'.")
+          end
+        end
+
+        def autocorrect(range)
+          @corrections << lambda do |corrector|
+            case range.source
+            when /\*\*/
+              corrector.replace(range, '**')
+            else
+              corrector.replace(range, " #{range.source.strip} ")
+            end
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/space_before_block_braces.rb b/lib/rubocop/cop/style/space_before_block_braces.rb
new file mode 100644
index 0000000..a9f8248
--- /dev/null
+++ b/lib/rubocop/cop/style/space_before_block_braces.rb
@@ -0,0 +1,63 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # Checks that block braces have or don't have a space before the opening
+      # brace depending on configuration.
+      class SpaceBeforeBlockBraces < Cop
+        include ConfigurableEnforcedStyle
+
+        def on_block(node)
+          return if node.loc.begin.is?('do') # No braces.
+
+          # If braces are on separate lines, and the Blocks cop is enabled,
+          # those braces will be changed to do..end by the user or by
+          # auto-correct, so reporting space issues is not useful, and it
+          # creates auto-correct conflicts.
+          if config.for_cop('Blocks')['Enabled'] && Util.block_length(node) > 0
+            return
+          end
+
+          left_brace = node.loc.begin
+          space_plus_brace = range_with_surrounding_space(left_brace)
+          used_style =
+            space_plus_brace.source.start_with?('{') ? :no_space : :space
+
+          case used_style
+          when style  then correct_style_detected
+          when :space then space_detected(left_brace, space_plus_brace)
+          else             space_missing(left_brace)
+          end
+        end
+
+        private
+
+        def space_missing(left_brace)
+          add_offense(left_brace, left_brace,
+                      'Space missing to the left of {.') do
+            opposite_style_detected
+          end
+        end
+
+        def space_detected(left_brace, space_plus_brace)
+          space = Parser::Source::Range.new(left_brace.source_buffer,
+                                            space_plus_brace.begin_pos,
+                                            left_brace.begin_pos)
+          add_offense(space, space, 'Space detected to the left of {.') do
+            opposite_style_detected
+          end
+        end
+
+        def autocorrect(range)
+          @corrections << lambda do |corrector|
+            case range.source
+            when /\s/ then corrector.remove(range)
+            else           corrector.insert_before(range, ' ')
+            end
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/space_before_modifier_keyword.rb b/lib/rubocop/cop/style/space_before_modifier_keyword.rb
new file mode 100644
index 0000000..e990bc0
--- /dev/null
+++ b/lib/rubocop/cop/style/space_before_modifier_keyword.rb
@@ -0,0 +1,40 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # Here we check if modifier keywords are preceded by a space.
+      class SpaceBeforeModifierKeyword < Cop
+        MSG = 'Put a space before the modifier keyword.'
+
+        def on_if(node)
+          if modifier?(node)
+            kw = node.loc.keyword
+            b = kw.begin_pos
+            left_of_kw = Parser::Source::Range.new(kw.source_buffer, b - 1, b)
+            add_offense(node, left_of_kw) unless left_of_kw.is?(' ')
+          end
+        end
+
+        alias_method :on_while, :on_if
+        alias_method :on_until, :on_if
+
+        private
+
+        def modifier?(node)
+          node.loc.respond_to?(:end) && node.loc.end.nil? && !elsif?(node)
+        end
+
+        def elsif?(node)
+          node.loc.keyword.is?('elsif')
+        end
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            corrector.insert_before(node.loc.keyword, ' ')
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/space_inside_block_braces.rb b/lib/rubocop/cop/style/space_inside_block_braces.rb
new file mode 100644
index 0000000..30c867a
--- /dev/null
+++ b/lib/rubocop/cop/style/space_inside_block_braces.rb
@@ -0,0 +1,151 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # Checks that block braces have or don't have surrounding space inside
+      # them on configuration. For blocks taking parameters, it checks that the
+      # left brace has or doesn't have trailing space depending on
+      # configuration.
+      class SpaceInsideBlockBraces < Cop
+        include ConfigurableEnforcedStyle
+        include SurroundingSpace
+
+        def on_block(node)
+          return if node.loc.begin.is?('do') # No braces.
+
+          # If braces are on separate lines, and the Blocks cop is enabled,
+          # those braces will be changed to do..end by the user or by
+          # auto-correct, so reporting space issues is not useful, and it
+          # creates auto-correct conflicts.
+          if config.for_cop('Blocks')['Enabled'] && Util.block_length(node) > 0
+            return
+          end
+
+          left_brace, right_brace = node.loc.begin, node.loc.end
+
+          check_inside(node, left_brace, right_brace)
+        end
+
+        private
+
+        def check_inside(node, left_brace, right_brace)
+          sb = node.loc.expression.source_buffer
+
+          if left_brace.end_pos == right_brace.begin_pos
+            if style_for_empty_braces == :space
+              offense(sb, left_brace.begin_pos, right_brace.end_pos,
+                      'Space missing inside empty braces.')
+            end
+          else
+            range = Parser::Source::Range.new(sb, left_brace.end_pos,
+                                              right_brace.begin_pos)
+            inner = range.source
+            unless inner =~ /\n/
+              if inner =~ /\S/
+                braces_with_contents_inside(node, inner, sb)
+              elsif style_for_empty_braces == :no_space
+                offense(sb, range.begin_pos, range.end_pos,
+                        'Space inside empty braces detected.')
+              end
+            end
+          end
+        end
+
+        def braces_with_contents_inside(node, inner, sb)
+          _method, args, _body = *node
+          left_brace, right_brace = node.loc.begin, node.loc.end
+          pipe = args.loc.begin
+
+          if inner =~ /^\S/
+            no_space_inside_left_brace(left_brace, pipe, sb)
+          else
+            space_inside_left_brace(left_brace, pipe, sb)
+          end
+
+          if inner =~ /\S$/
+            no_space(sb, right_brace.begin_pos, right_brace.end_pos,
+                     'Space missing inside }.')
+          else
+            space_inside_right_brace(right_brace, sb)
+          end
+        end
+
+        def no_space_inside_left_brace(left_brace, pipe, sb)
+          if pipe
+            if left_brace.end_pos == pipe.begin_pos &&
+                cop_config['SpaceBeforeBlockParameters']
+              offense(sb, left_brace.begin_pos, pipe.end_pos,
+                      'Space between { and | missing.')
+            end
+          else
+            # We indicate the position after the left brace. Otherwise it's
+            # difficult to distinguish between space missing to the left and to
+            # the right of the brace in autocorrect.
+            no_space(sb, left_brace.end_pos, left_brace.end_pos + 1,
+                     'Space missing inside {.')
+          end
+        end
+
+        def space_inside_left_brace(left_brace, pipe, sb)
+          if pipe
+            unless cop_config['SpaceBeforeBlockParameters']
+              offense(sb, left_brace.end_pos, pipe.begin_pos,
+                      'Space between { and | detected.')
+            end
+          else
+            brace_with_space = range_with_surrounding_space(left_brace, :right)
+            space(sb, brace_with_space.begin_pos + 1, brace_with_space.end_pos,
+                  'Space inside { detected.')
+          end
+        end
+
+        def space_inside_right_brace(right_brace, sb)
+          brace_with_space = range_with_surrounding_space(right_brace, :left)
+          space(sb, brace_with_space.begin_pos, brace_with_space.end_pos - 1,
+                'Space inside } detected.')
+        end
+
+        def no_space(sb, begin_pos, end_pos, msg)
+          if style == :space
+            offense(sb, begin_pos, end_pos, msg) { opposite_style_detected }
+          else
+            correct_style_detected
+          end
+        end
+
+        def space(sb, begin_pos, end_pos, msg)
+          if style == :no_space
+            offense(sb, begin_pos, end_pos, msg) { opposite_style_detected }
+          else
+            correct_style_detected
+          end
+        end
+
+        def offense(sb, begin_pos, end_pos, msg)
+          range = Parser::Source::Range.new(sb, begin_pos, end_pos)
+          add_offense(range, range, msg) { yield if block_given? }
+        end
+
+        def style_for_empty_braces
+          case cop_config['EnforcedStyleForEmptyBraces']
+          when 'space'    then :space
+          when 'no_space' then :no_space
+          else fail 'Unknown EnforcedStyleForEmptyBraces selected!'
+          end
+        end
+
+        def autocorrect(range)
+          @corrections << lambda do |corrector|
+            case range.source
+            when /\s/ then corrector.remove(range)
+            when '{}' then corrector.replace(range, '{ }')
+            when '{|' then corrector.replace(range, '{ |')
+            else           corrector.insert_before(range, ' ')
+            end
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/space_inside_brackets.rb b/lib/rubocop/cop/style/space_inside_brackets.rb
new file mode 100644
index 0000000..2d98c88
--- /dev/null
+++ b/lib/rubocop/cop/style/space_inside_brackets.rb
@@ -0,0 +1,16 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # Checks for spaces inside square brackets.
+      class SpaceInsideBrackets < Cop
+        include SpaceInside
+
+        def specifics
+          [:tLBRACK, :tRBRACK, 'square brackets']
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/space_inside_hash_literal_braces.rb b/lib/rubocop/cop/style/space_inside_hash_literal_braces.rb
new file mode 100644
index 0000000..dd87768
--- /dev/null
+++ b/lib/rubocop/cop/style/space_inside_hash_literal_braces.rb
@@ -0,0 +1,111 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # Checks that braces used for hash literals have or don't have
+      # surrounding space depending on configuration.
+      class SpaceInsideHashLiteralBraces < Cop
+        include SurroundingSpace
+        include ConfigurableEnforcedStyle
+
+        MSG = 'Space inside %s.'
+
+        def investigate(processed_source)
+          return unless processed_source.ast
+          tokens = processed_source.tokens
+
+          on_node(:hash, processed_source.ast) do |hash|
+            b_ix = index_of_first_token(hash)
+            if tokens[b_ix].type == :tLBRACE # Hash literal with braces?
+              e_ix = index_of_last_token(hash)
+              check(tokens[b_ix], tokens[b_ix + 1])
+              check(tokens[e_ix - 1], tokens[e_ix]) unless b_ix == e_ix - 1
+            end
+          end
+        end
+
+        private
+
+        def check(t1, t2)
+          # No offense if line break inside.
+          return if t1.pos.line < t2.pos.line
+          return if t2.type == :tCOMMENT # Also indicates there's a line break.
+
+          is_empty_braces = t1.text == '{' && t2.text == '}'
+          expect_space = if is_empty_braces
+                           cop_config['EnforcedStyleForEmptyBraces'] == 'space'
+                         else
+                           style == :space
+                         end
+          if offense?(t1, t2, expect_space)
+            brace = (t1.text == '{' ? t1 : t2).pos
+            range = expect_space ? brace : space_range(brace)
+            add_offense(range, range, message(brace, is_empty_braces,
+                                              expect_space)) do
+              opposite_style_detected
+            end
+          else
+            correct_style_detected
+          end
+        end
+
+        def offense?(t1, t2, expect_space)
+          has_space = space_between?(t1, t2)
+          expect_space ? !has_space : has_space
+        end
+
+        def message(brace, is_empty_braces, expect_space)
+          inside_what = if is_empty_braces
+                          'empty hash literal braces'
+                        else
+                          brace.source
+                        end
+          problem = expect_space ? 'missing' : 'detected'
+          format(MSG, "#{inside_what} #{problem}")
+        end
+
+        def autocorrect(range)
+          @corrections << lambda do |corrector|
+            # It is possible that BracesAroundHashParameters will remove the
+            # braces while this cop inserts spaces. This can lead to unwanted
+            # changes to the inspected code.  If we replace the brace with a
+            # brace plus space (rather than just inserting a space), then any
+            # removal of the same brace will give us a clobbering error. This
+            # in turn will make RuboCop fall back on cop-by-cop
+            # auto-correction.  Problem solved.
+            case range.source
+            when /\s/ then corrector.remove(range)
+            when '{' then corrector.replace(range, '{ ')
+            else corrector.replace(range, ' }')
+            end
+          end
+        end
+
+        def space_range(token_range)
+          if token_range.source == '{'
+            range_of_space_to_the_right(token_range)
+          else
+            range_of_space_to_the_left(token_range)
+          end
+        end
+
+        def range_of_space_to_the_right(range)
+          src = range.source_buffer.source
+          end_pos = range.end_pos
+          end_pos += 1 while src[end_pos] =~ /[ \t]/
+          Parser::Source::Range.new(range.source_buffer,
+                                    range.begin_pos + 1, end_pos)
+        end
+
+        def range_of_space_to_the_left(range)
+          src = range.source_buffer.source
+          begin_pos = range.begin_pos
+          begin_pos -= 1 while src[begin_pos - 1] =~ /[ \t]/
+          Parser::Source::Range.new(range.source_buffer, begin_pos,
+                                    range.end_pos - 1)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/space_inside_parens.rb b/lib/rubocop/cop/style/space_inside_parens.rb
new file mode 100644
index 0000000..f16e875
--- /dev/null
+++ b/lib/rubocop/cop/style/space_inside_parens.rb
@@ -0,0 +1,16 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # Checks for spaces inside ordinary round parentheses.
+      class SpaceInsideParens < Cop
+        include SpaceInside
+
+        def specifics
+          [:tLPAREN2, :tRPAREN, 'parentheses']
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/special_global_vars.rb b/lib/rubocop/cop/style/special_global_vars.rb
new file mode 100644
index 0000000..354c2e4
--- /dev/null
+++ b/lib/rubocop/cop/style/special_global_vars.rb
@@ -0,0 +1,84 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop looks for uses of Perl-style global variables.
+      class SpecialGlobalVars < Cop
+        MSG_BOTH = 'Prefer `%s` from the English library, or `%s` over `%s`.'
+        MSG_ENGLISH = 'Prefer `%s` from the English library over `%s`.'
+        MSG_REGULAR = 'Prefer `%s` over `%s`.'
+
+        PREFERRED_VARS = {
+          '$:' => ['$LOAD_PATH'],
+          '$"' => ['$LOADED_FEATURES'],
+          '$0' => ['$PROGRAM_NAME'],
+          '$!' => ['$ERROR_INFO'],
+          '$@' => ['$ERROR_POSITION'],
+          '$;' => ['$FIELD_SEPARATOR', '$FS'],
+          '$,' => ['$OUTPUT_FIELD_SEPARATOR', '$OFS'],
+          '$/' => ['$INPUT_RECORD_SEPARATOR', '$RS'],
+          '$\\' => ['$OUTPUT_RECORD_SEPARATOR', '$ORS'],
+          '$.' => ['$INPUT_LINE_NUMBER', '$NR'],
+          '$_' => ['$LAST_READ_LINE'],
+          '$>' => ['$DEFAULT_OUTPUT'],
+          '$<' => ['$DEFAULT_INPUT'],
+          '$$' => ['$PROCESS_ID', '$PID'],
+          '$?' => ['$CHILD_STATUS'],
+          '$~' => ['$LAST_MATCH_INFO'],
+          '$=' => ['$IGNORECASE'],
+          '$*' => ['$ARGV', 'ARGV'],
+          '$&' => ['$MATCH'],
+          '$`' => ['$PREMATCH'],
+          '$\'' => ['$POSTMATCH'],
+          '$+' => ['$LAST_PAREN_MATCH']
+        }.symbolize_keys
+
+        # Anything *not* in this set is provided by the English library.
+        NON_ENGLISH_VARS = Set.new([
+          '$LOAD_PATH',
+          '$LOADED_FEATURES',
+          '$PROGRAM_NAME',
+          'ARGV'
+        ])
+
+        def on_gvar(node)
+          global_var, = *node
+
+          add_offense(node, :expression) if PREFERRED_VARS[global_var]
+        end
+
+        def message(node)
+          global_var, = *node
+
+          regular, english = PREFERRED_VARS[global_var].partition do |var|
+            NON_ENGLISH_VARS.include? var
+          end
+
+          # For now, we assume that lists are 2 items or less.  Easy grammar!
+          regular_msg = regular.join('` or `')
+          english_msg = english.join('` or `')
+
+          if regular.length > 0 && english.length > 0
+            format(MSG_BOTH, english_msg, regular_msg, global_var)
+          elsif regular.length > 0
+            format(MSG_REGULAR, regular_msg, global_var)
+          elsif english.length > 0
+            format(MSG_ENGLISH, english_msg, global_var)
+          else
+            fail 'Bug in SpecialGlobalVars - global var w/o preferred vars!'
+          end
+        end
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            global_var, = *node
+
+            corrector.replace(node.loc.expression,
+                              PREFERRED_VARS[global_var].first)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/string_literals.rb b/lib/rubocop/cop/style/string_literals.rb
new file mode 100644
index 0000000..df47b81
--- /dev/null
+++ b/lib/rubocop/cop/style/string_literals.rb
@@ -0,0 +1,46 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # Checks if uses of quotes match the configured preference.
+      class StringLiterals < Cop
+        include ConfigurableEnforcedStyle
+        include StringHelp
+
+        private
+
+        def message(node)
+          if style == :single_quotes
+            "Prefer single-quoted strings when you don't need string " \
+            'interpolation or special symbols.'
+          else
+            'Prefer double-quoted strings unless you need single quotes to ' \
+            'avoid extra backslashes for escaping.'
+          end
+        end
+
+        def offense?(node)
+          src = node.loc.expression.source
+          return false if src =~ /^(%[qQ]?|\?|<<-)/i
+          src !~ if style == :single_quotes
+                   # regex matches IF there is a ' or there is a \\ in the
+                   # string that is not preceeded/followed by another \\
+                   # (e.g. "\\x34") but not "\\\\"
+                   /' | (?<! \\) \\{2}* \\ (?! \\)/x
+                 else
+                   /" | \\/x
+                 end
+        end
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            replacement = node.loc.begin.is?('"') ? "'" : '"'
+            corrector.replace(node.loc.begin, replacement)
+            corrector.replace(node.loc.end, replacement)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/symbol_array.rb b/lib/rubocop/cop/style/symbol_array.rb
new file mode 100644
index 0000000..ae20de5
--- /dev/null
+++ b/lib/rubocop/cop/style/symbol_array.rb
@@ -0,0 +1,24 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for array literals made up of symbols
+      # that are not using the %i() syntax.
+      #
+      # This check makes sense only on Ruby 2.0+.
+      class SymbolArray < Cop
+        include ArraySyntax
+
+        MSG = 'Use %i or %I for array of symbols.'
+
+        def on_array(node)
+          # %i and %I were introduced in Ruby 2.0
+          unless RUBY_VERSION < '2.0.0'
+            add_offense(node, :expression) if array_of?(:sym, node)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/tab.rb b/lib/rubocop/cop/style/tab.rb
new file mode 100644
index 0000000..15cefed
--- /dev/null
+++ b/lib/rubocop/cop/style/tab.rb
@@ -0,0 +1,26 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for tabs inside the source code.
+      class Tab < Cop
+        MSG = 'Tab detected.'
+
+        def investigate(processed_source)
+          processed_source.lines.each_with_index do |line, index|
+            match = line.match(/^( *)\t/)
+            if match
+              spaces = match.captures[0]
+              add_offense(nil,
+                          source_range(processed_source.buffer,
+                                       processed_source[0...index],
+                                       spaces.length, 1),
+                          MSG)
+            end
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/trailing_blank_lines.rb b/lib/rubocop/cop/style/trailing_blank_lines.rb
new file mode 100644
index 0000000..1c11c3e
--- /dev/null
+++ b/lib/rubocop/cop/style/trailing_blank_lines.rb
@@ -0,0 +1,44 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop looks for trailing blank lines in the source code.
+      class TrailingBlankLines < Cop
+        MSG = '%d trailing blank lines detected.'
+
+        def investigate(processed_source)
+          blank_lines = 0
+
+          processed_source.lines.reverse_each do |line|
+            if line.blank?
+              blank_lines += 1
+            else
+              break
+            end
+          end
+
+          if blank_lines > 0
+            range_size =
+              processed_source.raw_lines.to_a[-blank_lines..-1].join.length
+            range = source_range(processed_source.buffer,
+                                 processed_source[0...-blank_lines],
+                                 0, range_size)
+            add_offense(range, range, format(MSG, blank_lines))
+          end
+        end
+
+        def autocorrect(range)
+          # Bail out if there's also trailing whitespace, because
+          # auto-correction in the two cops would result in clobbering.
+          if range.source =~ / / &&
+              config.for_cop('TrailingWhitespace')['Enabled']
+            return
+          end
+
+          @corrections << ->(corrector) { corrector.remove(range) }
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/trailing_comma.rb b/lib/rubocop/cop/style/trailing_comma.rb
new file mode 100644
index 0000000..657e022
--- /dev/null
+++ b/lib/rubocop/cop/style/trailing_comma.rb
@@ -0,0 +1,102 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for trailing comma in parameter lists and literals.
+      class TrailingComma < Cop
+        include ArraySyntax
+        include ConfigurableEnforcedStyle
+
+        MSG = '%s comma after the last %s.'
+
+        def on_array(node)
+          check_literal(node, 'item of %s array') if square_brackets?(node)
+        end
+
+        def on_hash(node)
+          check_literal(node, 'item of %s hash')
+        end
+
+        def on_send(node)
+          _receiver, _method_name, *args = *node
+          return if args.empty?
+          # It's impossible for a method call without parentheses to have
+          # a trailing comma.
+          return unless brackets?(node)
+
+          check(node, args, 'parameter of %s method call',
+                args.last.loc.expression.end_pos, node.loc.expression.end_pos)
+        end
+
+        private
+
+        def parameter_name
+          'EnforcedStyleForMultiline'
+        end
+
+        def check_literal(node, kind)
+          return if node.children.empty?
+          # A braceless hash is the last parameter of a method call and will be
+          # checked as such.
+          return unless brackets?(node)
+
+          check(node, node.children, kind,
+                node.children.last.loc.expression.end_pos,
+                node.loc.end.begin_pos)
+        end
+
+        def check(node, items, kind, begin_pos, end_pos)
+          sb = items.first.loc.expression.source_buffer
+          after_last_item = Parser::Source::Range.new(sb, begin_pos, end_pos)
+
+          return if heredoc?(after_last_item.source)
+
+          comma_offset = after_last_item.source =~ /,/
+          should_have_comma = style == :comma && multiline?(node)
+          if comma_offset
+            unless should_have_comma
+              avoid_comma(items, kind,
+                          after_last_item.begin_pos + comma_offset, sb)
+            end
+          elsif should_have_comma
+            put_comma(items, kind, sb)
+          end
+        end
+
+        def heredoc?(source_after_last_item)
+          source_after_last_item =~ /\w/
+        end
+
+        # Returns true if the node has round/square/curly brackets.
+        def brackets?(node)
+          node.loc.end
+        end
+
+        # Returns true if the round/square/curly brackets of the given node are
+        # on different lines.
+        def multiline?(node)
+          [node.loc.begin, node.loc.end].map(&:line).uniq.size > 1
+        end
+
+        def avoid_comma(items, kind, comma_begin_pos, sb)
+          range = Parser::Source::Range.new(sb, comma_begin_pos,
+                                            comma_begin_pos + 1)
+          article = kind =~ /array/ ? 'an' : 'a'
+          add_offense(nil, range,
+                      format(MSG, 'Avoid', format(kind, article)))
+        end
+
+        def put_comma(items, kind, sb)
+          last_expr = items.last.loc.expression
+          ix = last_expr.source.rindex("\n") || 0
+          ix += last_expr.source[ix..-1] =~ /\S/
+          range = Parser::Source::Range.new(sb, last_expr.begin_pos + ix,
+                                            last_expr.end_pos)
+          add_offense(nil, range,
+                      format(MSG, 'Put a', format(kind, 'a multiline')))
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/trailing_whitespace.rb b/lib/rubocop/cop/style/trailing_whitespace.rb
new file mode 100644
index 0000000..5331a60
--- /dev/null
+++ b/lib/rubocop/cop/style/trailing_whitespace.rb
@@ -0,0 +1,28 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop looks for trailing whitespace in the source code.
+      class TrailingWhitespace < Cop
+        MSG = 'Trailing whitespace detected.'
+
+        def investigate(processed_source)
+          processed_source.lines.each_with_index do |line, index|
+            if line =~ /.*[ \t]+$/
+              range = source_range(processed_source.buffer,
+                                   processed_source[0...index],
+                                   line.rstrip.length,
+                                   line.length - line.rstrip.length)
+              add_offense(range, range)
+            end
+          end
+        end
+
+        def autocorrect(range)
+          @corrections << ->(corrector) { corrector.remove(range) }
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/trivial_accessors.rb b/lib/rubocop/cop/style/trivial_accessors.rb
new file mode 100644
index 0000000..67a3877
--- /dev/null
+++ b/lib/rubocop/cop/style/trivial_accessors.rb
@@ -0,0 +1,78 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop looks for trivial reader/writer methods, that could
+      # have been created with the attr_* family of functions automatically.
+      class TrivialAccessors < Cop
+        include CheckMethods
+
+        MSG = 'Use `attr_%s` to define trivial %s methods.'
+
+        private
+
+        def check(node, method_name, args, body)
+          kind = if trivial_reader?(method_name, args, body)
+                   'reader'
+                 elsif trivial_writer?(method_name, args, body)
+                   'writer'
+                 end
+          if kind
+            add_offense(node, :keyword,
+                        format(MSG, kind, kind))
+          end
+        end
+
+        def exact_name_match?
+          cop_config['ExactNameMatch']
+        end
+
+        def allow_predicates?
+          cop_config['AllowPredicates']
+        end
+
+        def whitelist
+          whitelist = cop_config['Whitelist']
+          Array(whitelist).map(&:to_sym) + [:initialize]
+        end
+
+        def predicate?(method_name)
+          method_name[-1] == '?'
+        end
+
+        def trivial_reader?(method_name, args, body)
+          looks_like_trivial_reader?(args, body) &&
+            !allowed_method?(method_name, body)
+        end
+
+        def looks_like_trivial_reader?(args, body)
+          args.children.size == 0 && body && body.type == :ivar
+        end
+
+        def trivial_writer?(method_name, args, body)
+          looks_like_trivial_writer?(args, body) &&
+            !allowed_method?(method_name, body)
+        end
+
+        def looks_like_trivial_writer?(args, body)
+          args.children.size == 1 && args.children[0].type != :restarg &&
+            body && body.type == :ivasgn &&
+            body.children[1] && body.children[1].type == :lvar
+        end
+
+        def allowed_method?(method_name, body)
+          allow_predicates? && predicate?(method_name) ||
+            whitelist.include?(method_name) ||
+            exact_name_match? && !names_match?(method_name, body)
+        end
+
+        def names_match?(method_name, body)
+          ivar_name, = *body
+
+          method_name.to_s.chomp('=') == ivar_name[1..-1]
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/unless_else.rb b/lib/rubocop/cop/style/unless_else.rb
new file mode 100644
index 0000000..ff477d5
--- /dev/null
+++ b/lib/rubocop/cop/style/unless_else.rb
@@ -0,0 +1,24 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop looks for *unless* expressions with *else* clauses.
+      class UnlessElse < Cop
+        MSG = 'Never use `unless` with `else`. Rewrite these with the ' \
+              'positive case first.'
+
+        def on_if(node)
+          loc = node.loc
+
+          # discard ternary ops and modifier if/unless nodes
+          return unless loc.respond_to?(:keyword) && loc.respond_to?(:else)
+
+          if loc.keyword.is?('unless') && loc.else
+            add_offense(node, :expression)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/variable_interpolation.rb b/lib/rubocop/cop/style/variable_interpolation.rb
new file mode 100644
index 0000000..fb5a374
--- /dev/null
+++ b/lib/rubocop/cop/style/variable_interpolation.rb
@@ -0,0 +1,33 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for variable interpolation (like "#@ivar").
+      class VariableInterpolation < Cop
+        MSG = 'Replace interpolated variable `%s` with expression `#{%s}`.'
+
+        def on_dstr(node)
+          var_nodes(node.children).each do |v|
+            var = v.loc.expression.source
+
+            add_offense(v, :expression, format(MSG, var, var))
+          end
+        end
+
+        private
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            expr = node.loc.expression
+            corrector.replace(expr, "{#{expr.source}}")
+          end
+        end
+
+        def var_nodes(nodes)
+          nodes.select { |n| [:ivar, :cvar, :gvar, :nth_ref].include?(n.type) }
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/variable_name.rb b/lib/rubocop/cop/style/variable_name.rb
new file mode 100644
index 0000000..9201503
--- /dev/null
+++ b/lib/rubocop/cop/style/variable_name.rb
@@ -0,0 +1,44 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop makes sure that all variables use the configured style,
+      # snake_case or camelCase, for their names.
+      class VariableName < Cop
+        include ConfigurableNaming
+
+        def on_lvasgn(node)
+          check(node, name_of_variable(node))
+        end
+
+        def on_ivasgn(node)
+          check(node, name_of_variable(node))
+        end
+
+        def on_send(node)
+          check(node, name_of_setter(node))
+        end
+
+        def name_of_variable(vasgn_node)
+          expr = vasgn_node.loc.expression
+          name = vasgn_node.children.first
+          Parser::Source::Range.new(expr.source_buffer, expr.begin_pos,
+                                    expr.begin_pos + name.length)
+        end
+
+        def name_of_setter(send_node)
+          receiver, method_name = *send_node
+          return unless receiver && receiver.type == :self
+          return unless method_name.to_s.end_with?('=')
+          after_dot(send_node, method_name.length - '='.length,
+                    Regexp.escape(receiver.loc.expression.source))
+        end
+
+        def message(style)
+          format('Use %s for variables.', style)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/when_then.rb b/lib/rubocop/cop/style/when_then.rb
new file mode 100644
index 0000000..d853a6b
--- /dev/null
+++ b/lib/rubocop/cop/style/when_then.rb
@@ -0,0 +1,24 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for *when;* uses in *case* expressions.
+      class WhenThen < Cop
+        MSG = 'Never use `when x;`. Use `when x then` instead.'
+
+        def on_when(node)
+          if node.loc.begin && node.loc.begin.is?(';')
+            add_offense(node, :begin)
+          end
+        end
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            corrector.replace(node.loc.begin, ' then')
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/while_until_do.rb b/lib/rubocop/cop/style/while_until_do.rb
new file mode 100644
index 0000000..922e740
--- /dev/null
+++ b/lib/rubocop/cop/style/while_until_do.rb
@@ -0,0 +1,45 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # Checks for uses of `do` in multi-line `while/until` statements.
+      class WhileUntilDo < Cop
+        def on_while(node)
+          handle(node)
+        end
+
+        def on_until(node)
+          handle(node)
+        end
+
+        def handle(node)
+          length = node.loc.expression.source.lines.to_a.size
+
+          if length > 1
+            if node.loc.begin && node.loc.begin.is?('do')
+              add_offense(node, :begin,
+                          error_message(node.type))
+            end
+          end
+        end
+
+        private
+
+        def error_message(node_type)
+          format('Never use `do` with multi-line `%s`.', node_type)
+        end
+
+        def autocorrect(node)
+          @corrections << lambda do |corrector|
+            condition_node, = *node
+            end_of_condition_range = condition_node.loc.expression.end
+            do_range = node.loc.begin
+            whitespaces_and_do_range = end_of_condition_range.join(do_range)
+            corrector.remove(whitespaces_and_do_range)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/while_until_modifier.rb b/lib/rubocop/cop/style/while_until_modifier.rb
new file mode 100644
index 0000000..d6af351
--- /dev/null
+++ b/lib/rubocop/cop/style/while_until_modifier.rb
@@ -0,0 +1,33 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # Checks for while and until statements that would fit on one line
+      # if written as a modifier while/until.
+      # The maximum line length is configurable.
+      class WhileUntilModifier < Cop
+        include StatementModifier
+
+        def investigate(processed_source)
+          return unless processed_source.ast
+          on_node([:while, :until], processed_source.ast) do |node|
+            # discard modifier while/until
+            next unless node.loc.end
+
+            if check(node, processed_source.comments)
+              add_offense(node, :keyword,
+                          message(node.loc.keyword.source))
+            end
+          end
+        end
+
+        private
+
+        def message(keyword)
+          "Favor modifier `#{keyword}` usage when having a single-line body."
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/style/word_array.rb b/lib/rubocop/cop/style/word_array.rb
new file mode 100644
index 0000000..2a335d7
--- /dev/null
+++ b/lib/rubocop/cop/style/word_array.rb
@@ -0,0 +1,86 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module Style
+      # This cop checks for array literals made up of word-like
+      # strings, that are not using the %w() syntax.
+      class WordArray < Cop
+        include ArraySyntax
+        # The parameter is called MinSize (meaning the minimum array size for
+        # which an offense can be registered), but essentially it's a Max
+        # parameter (the maximum number of something that's allowed).
+        include ConfigurableMax
+
+        MSG = 'Use `%w` or `%W` for array of words.'
+
+        def on_array(node)
+          array_elems = node.children
+          if array_of?(:str, node) && !complex_content?(array_elems) &&
+            array_elems.size > min_size && !comments_in_array?(node)
+            add_offense(node, :expression) { self.max = array_elems.size }
+          end
+        end
+
+        private
+
+        def parameter_name
+          'MinSize'
+        end
+
+        def comments_in_array?(node)
+          comments = processed_source.comments
+
+          array_range = node.loc.expression.to_a
+
+          comments.any? do |comment|
+            !(comment.loc.expression.to_a & array_range).empty?
+          end
+        end
+
+        def complex_content?(arr_sexp)
+          arr_sexp.each do |s|
+            source = s.loc.expression.source
+            unless source.start_with?('?') # %W(\r \n) can replace [?\r, ?\n]
+              str_content = Util.strip_quotes(source)
+              return true unless str_content =~ /\A[\w-]+\z/
+            end
+          end
+
+          false
+        end
+
+        def min_size
+          cop_config['MinSize']
+        end
+
+        def autocorrect(node)
+          sb = node.loc.expression.source_buffer
+          interpolated = false
+
+          contents = node.children.map do |n|
+            if character_literal?(n)
+              interpolated = true
+              begin_pos = n.loc.expression.begin_pos + '?'.length
+              end_pos = n.loc.expression.end_pos
+            else
+              begin_pos = n.loc.begin.end_pos
+              end_pos = n.loc.end.begin_pos
+            end
+            Parser::Source::Range.new(sb, begin_pos, end_pos).source
+          end.join(' ')
+
+          char = interpolated ? 'W' : 'w'
+
+          @corrections << lambda do |corrector|
+            corrector.replace(node.loc.expression, "%#{char}(#{contents})")
+          end
+        end
+
+        def character_literal?(node)
+          node.loc.end.nil?
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/team.rb b/lib/rubocop/cop/team.rb
new file mode 100644
index 0000000..8cc43d6
--- /dev/null
+++ b/lib/rubocop/cop/team.rb
@@ -0,0 +1,113 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    # FIXME
+    class Team
+      attr_reader :errors, :updated_source_file
+
+      alias_method :updated_source_file?, :updated_source_file
+
+      def initialize(cop_classes, config, options = nil)
+        @cop_classes = cop_classes
+        @config = config
+        @options = options || { auto_correct: false, debug: false }
+        @errors = []
+      end
+
+      def autocorrect?
+        @options[:auto_correct]
+      end
+
+      def debug?
+        @options[:debug]
+      end
+
+      def inspect_file(processed_source)
+        # If we got any syntax errors, return only the syntax offenses.
+        # Parser may return nil for AST even though there are no syntax errors.
+        # e.g. sources which contain only comments
+        unless processed_source.valid_syntax?
+          diagnostics = processed_source.diagnostics
+          return Lint::Syntax.offenses_from_diagnostics(diagnostics)
+        end
+
+        commissioner = Commissioner.new(cops)
+        offenses = commissioner.investigate(processed_source)
+        process_commissioner_errors(
+          processed_source.file_path, commissioner.errors)
+        autocorrect(processed_source.buffer, cops)
+        offenses
+      end
+
+      def cops
+        @cops ||= begin
+          @cop_classes.each_with_object([]) do |cop_class, instances|
+            if cop_enabled?(cop_class)
+              instances << cop_class.new(@config, @options)
+            end
+          end
+        end
+      end
+
+      private
+
+      def cop_enabled?(cop_class)
+        @config.cop_enabled?(cop_class) ||
+          cop_class.cop_name == @options[:only]
+      end
+
+      def autocorrect(buffer, cops)
+        @updated_source_file = false
+        return unless autocorrect?
+
+        corrections = cops.reduce([]) do |array, cop|
+          array.concat(cop.corrections)
+          array
+        end
+
+        corrector = Corrector.new(buffer, corrections)
+        new_source = begin
+                       corrector.rewrite
+                     rescue RangeError, RuntimeError
+                       autocorrect_one_cop(buffer, cops)
+                     end
+
+        unless new_source == buffer.source
+          filename = buffer.name
+          File.open(filename, 'w') { |f| f.write(new_source) }
+          @updated_source_file = true
+        end
+      end
+
+      # Does a slower but safer auto-correction run by correcting for just one
+      # cop. The re-running of auto-corrections will make sure that the full
+      # set of auto-corrections is tried again after this method has finished.
+      def autocorrect_one_cop(buffer, cops)
+        cop_with_corrections = cops.find { |cop| cop.corrections.any? }
+        corrector = Corrector.new(buffer, cop_with_corrections.corrections)
+        corrector.rewrite
+      end
+
+      def process_commissioner_errors(file, file_errors)
+        file_errors.each do |cop, errors|
+          errors.each do |e|
+            handle_error(e,
+                         "An error occurred while #{cop.name}".color(:red) +
+                         " cop was inspecting #{file}.".color(:red))
+          end
+        end
+      end
+
+      def handle_error(e, message)
+        @errors << message
+        warn message
+        if debug?
+          puts e.message, e.backtrace
+        else
+          warn 'To see the complete backtrace run rubocop -d.'
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/util.rb b/lib/rubocop/cop/util.rb
new file mode 100644
index 0000000..a922a7c
--- /dev/null
+++ b/lib/rubocop/cop/util.rb
@@ -0,0 +1,166 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    # This module contains a collection of useful utility methods.
+    module Util
+      include PathUtil
+      extend AST::Sexp
+
+      PROC_NEW_NODE = s(:send, s(:const, nil, :Proc), :new)
+      EQUALS_ASGN_NODES = [:lvasgn, :ivasgn, :cvasgn, :gvasgn, :casgn, :masgn]
+      SHORTHAND_ASGN_NODES = [:op_asgn, :or_asgn, :and_asgn]
+      ASGN_NODES = EQUALS_ASGN_NODES + SHORTHAND_ASGN_NODES
+
+      # http://phrogz.net/programmingruby/language.html#table_18.4
+      # Backtick is added last just to help editors parse this code.
+      OPERATOR_METHODS = %w(
+        | ^ & <=> == === =~ > >= < <= << >>
+        + - * / % ** ~ +@ -@ [] []= ! != !~
+      ).map(&:to_sym) + [:'`']
+
+      module_function
+
+      def operator?(symbol)
+        OPERATOR_METHODS.include?(symbol)
+      end
+
+      def strip_quotes(str)
+        if str[0] == '"' || str[0] == "'"
+          str[0] = ''
+          str[-1] = ''
+        else
+          # we're dealing with %q or %Q
+          str[0, 3] = ''
+          str[-1] = ''
+        end
+
+        str
+      end
+
+      def block_length(block_node)
+        block_node.loc.end.line - block_node.loc.begin.line
+      end
+
+      def comment_line?(line_source)
+        line_source =~ /^\s*#/
+      end
+
+      def line_range(arg)
+        source_range = case arg
+                       when Parser::Source::Range
+                         arg
+                       when Parser::AST::Node
+                         arg.loc.expression
+                       else
+                         fail ArgumentError, "Invalid argument #{arg}"
+                       end
+
+        source_range.begin.line..source_range.end.line
+      end
+
+      def const_name(node)
+        return nil if node.nil? || node.type != :const
+
+        const_names = []
+        const_node = node
+
+        loop do
+          namespace_node, name = *const_node
+          const_names << name
+          break unless namespace_node
+          break unless namespace_node.is_a?(Parser::AST::Node)
+          break if namespace_node.type == :cbase
+          const_node = namespace_node
+        end
+
+        const_names.reverse.join('::')
+      end
+
+      def command?(name, node)
+        return unless node.type == :send
+
+        receiver, method_name, _args = *node
+
+        # commands have no explicit receiver
+        !receiver && method_name == name
+      end
+
+      def lambda?(node)
+        fail 'Not a block node' unless node.type == :block
+
+        send_node, _block_args, _block_body = *node
+
+        command?(:lambda, send_node)
+      end
+
+      def proc?(node)
+        fail 'Not a block node' unless node.type == :block
+
+        send_node, _block_args, _block_body = *node
+
+        command?(:proc, send_node) || send_node == PROC_NEW_NODE
+      end
+
+      def lambda_or_proc?(node)
+        lambda?(node) || proc?(node)
+      end
+
+      def parentheses?(node)
+        node.loc.respond_to?(:end) && node.loc.end
+      end
+
+      def on_node(syms, sexp, excludes = [])
+        yield sexp if Array(syms).include?(sexp.type)
+
+        return if Array(excludes).include?(sexp.type)
+
+        sexp.children.each do |elem|
+          if elem.is_a?(Parser::AST::Node)
+            on_node(syms, elem, excludes) { |s| yield s }
+          end
+        end
+      end
+
+      def source_range(source_buffer, preceding_lines, begin_column,
+                       column_count)
+        newline_length = 1
+        begin_pos = preceding_lines.reduce(0) do |a, e|
+          a + e.length + newline_length
+        end + begin_column
+        Parser::Source::Range.new(source_buffer, begin_pos,
+                                  begin_pos + column_count)
+      end
+
+      def range_with_surrounding_space(range, side = :both)
+        src = @processed_source.buffer.source
+        go_left = side == :left || side == :both
+        go_right = side == :right || side == :both
+        begin_pos = range.begin_pos
+        begin_pos -= 1 while go_left && src[begin_pos - 1] =~ /[ \t]/
+        end_pos = range.end_pos
+        end_pos += 1 while go_right && src[end_pos] =~ /[ \t]/
+        end_pos += 1 if go_right && src[end_pos] == "\n"
+        Parser::Source::Range.new(@processed_source.buffer, begin_pos, end_pos)
+      end
+
+      # Returns for example a bare `if` node if the given node is an `if` whith
+      # calls chained to the end of it.
+      def first_part_of_call_chain(node)
+        while node
+          case node.type
+          when :send
+            receiver, _method_name, _args = *node
+            node = receiver
+          when :block
+            method, _args, _body = *node
+            node = method
+          else
+            break
+          end
+        end
+        node
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/variable_inspector.rb b/lib/rubocop/cop/variable_inspector.rb
new file mode 100644
index 0000000..eb9d689
--- /dev/null
+++ b/lib/rubocop/cop/variable_inspector.rb
@@ -0,0 +1,427 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    # This module provides a way to track local variables and scopes of Ruby.
+    # This is intended to be used as mix-in, and the user class may override
+    # some of the hook methods.
+    module VariableInspector
+      VARIABLE_ASSIGNMENT_TYPE = :lvasgn
+      REGEXP_NAMED_CAPTURE_TYPE = :match_with_lvasgn
+      VARIABLE_ASSIGNMENT_TYPES =
+        [VARIABLE_ASSIGNMENT_TYPE, REGEXP_NAMED_CAPTURE_TYPE].freeze
+
+      METHOD_ARGUMENT_DECLARATION_TYPES = [
+        :arg, :optarg, :restarg,
+        :kwarg, :kwoptarg, :kwrestarg
+      ].freeze
+      BLOCK_ARGUMENT_DECLARATION_TYPE = :blockarg
+      ARGUMENT_DECLARATION_TYPES = (
+        METHOD_ARGUMENT_DECLARATION_TYPES + [BLOCK_ARGUMENT_DECLARATION_TYPE]
+      ).freeze
+      BLOCK_LOCAL_VARIABLE_DECLARATION_TYPE = :shadowarg
+      DECLARATION_TYPES = (
+        ARGUMENT_DECLARATION_TYPES + [BLOCK_LOCAL_VARIABLE_DECLARATION_TYPE]
+      ).freeze
+
+      LOGICAL_OPERATOR_ASSIGNMENT_TYPES = [:or_asgn, :and_asgn].freeze
+      OPERATOR_ASSIGNMENT_TYPES =
+        (LOGICAL_OPERATOR_ASSIGNMENT_TYPES + [:op_asgn]).freeze
+
+      MULTIPLE_ASSIGNMENT_TYPE = :masgn
+
+      VARIABLE_REFERENCE_TYPE = :lvar
+
+      POST_CONDITION_LOOP_TYPES = [:while_post, :until_post].freeze
+      LOOP_TYPES = (POST_CONDITION_LOOP_TYPES + [:while, :until, :for]).freeze
+
+      RESCUE_TYPE = :rescue
+
+      ZERO_ARITY_SUPER_TYPE = :zsuper
+
+      TWISTED_SCOPE_TYPES = [:block, :class, :sclass, :defs].freeze
+      SCOPE_TYPES = (TWISTED_SCOPE_TYPES + [:top_level, :module, :def]).freeze
+
+      def variable_table
+        @variable_table ||= VariableTable.new(self)
+      end
+
+      # Starting point.
+      def inspect_variables(root_node)
+        return unless root_node
+
+        # Wrap the root node with :top_level scope node.
+        top_level_node = wrap_with_top_level_node(root_node)
+
+        inspect_variables_in_scope(top_level_node)
+      end
+
+      def wrap_with_top_level_node(node)
+        # This is a custom node type, not defined in Parser.
+        Parser::AST::Node.new(:top_level, [node])
+      end
+
+      module_function :wrap_with_top_level_node
+
+      # This is called for each scope recursively.
+      def inspect_variables_in_scope(scope_node)
+        variable_table.push_scope(scope_node)
+        process_children(scope_node)
+        variable_table.pop_scope
+      end
+
+      def process_children(origin_node)
+        origin_node.children.each do |child|
+          next unless child.is_a?(Parser::AST::Node)
+          next if scanned_node?(child)
+          process_node(child)
+        end
+      end
+
+      def process_node(node)
+        catch(:skip_children) do
+          dispatch_node(node)
+          process_children(node)
+        end
+      end
+
+      def skip_children!
+        throw :skip_children
+      end
+
+      # rubocop:disable MethodLength, CyclomaticComplexity
+      def dispatch_node(node)
+        case node.type
+        when *DECLARATION_TYPES
+          process_variable_declaration(node)
+        when VARIABLE_ASSIGNMENT_TYPE
+          process_variable_assignment(node)
+        when REGEXP_NAMED_CAPTURE_TYPE
+          process_regexp_named_captures(node)
+        when *OPERATOR_ASSIGNMENT_TYPES
+          process_variable_operator_assignment(node)
+        when MULTIPLE_ASSIGNMENT_TYPE
+          process_variable_multiple_assignment(node)
+        when VARIABLE_REFERENCE_TYPE
+          process_variable_referencing(node)
+        when *LOOP_TYPES
+          process_loop(node)
+        when RESCUE_TYPE
+          process_rescue(node)
+        when ZERO_ARITY_SUPER_TYPE
+          process_zero_arity_super(node)
+        when *SCOPE_TYPES
+          process_scope(node)
+        end
+      end
+      # rubocop:enable MethodLength, CyclomaticComplexity
+
+      def process_variable_declaration(node)
+        # restarg would have no name:
+        #
+        #   def initialize(*)
+        #   end
+        return if node.type == :restarg && node.children.empty?
+
+        variable_name = node.children.first
+        variable_table.declare_variable(variable_name, node)
+      end
+
+      def process_variable_assignment(node)
+        name = node.children.first
+
+        unless variable_table.variable_exist?(name)
+          variable_table.declare_variable(name, node)
+        end
+
+        # Need to scan rhs before assignment so that we can mark previous
+        # assignments as referenced if rhs has referencing to the variable
+        # itself like:
+        #
+        #   foo = 1
+        #   foo = foo + 1
+        process_children(node)
+
+        variable_table.assign_to_variable(name, node)
+
+        skip_children!
+      end
+
+      def process_regexp_named_captures(node)
+        regexp_node, rhs_node = *node
+
+        regexp_string = regexp_node.children[0].children[0]
+        regexp = Regexp.new(regexp_string)
+        variable_names = regexp.named_captures.keys
+
+        variable_names.each do |name|
+          unless variable_table.variable_exist?(name)
+            variable_table.declare_variable(name, node)
+          end
+        end
+
+        process_node(rhs_node)
+        process_node(regexp_node)
+
+        variable_names.each do |name|
+          variable_table.assign_to_variable(name, node)
+        end
+
+        skip_children!
+      end
+
+      def process_variable_operator_assignment(node)
+        if LOGICAL_OPERATOR_ASSIGNMENT_TYPES.include?(node.type)
+          asgn_node, rhs_node = *node
+        else
+          asgn_node, _operator, rhs_node = *node
+        end
+
+        return unless asgn_node.type == :lvasgn
+
+        name = asgn_node.children.first
+
+        unless variable_table.variable_exist?(name)
+          variable_table.declare_variable(name, asgn_node)
+        end
+
+        # The following statements:
+        #
+        #   foo = 1
+        #   foo += foo = 2
+        #   # => 3
+        #
+        # are equivalent to:
+        #
+        #   foo = 1
+        #   foo = foo + (foo = 2)
+        #   # => 3
+        #
+        # So, at operator assignment node, we need to reference the variable
+        # before processing rhs nodes.
+
+        variable_table.reference_variable(name, node)
+        process_node(rhs_node)
+        variable_table.assign_to_variable(name, asgn_node)
+
+        skip_children!
+      end
+
+      def process_variable_multiple_assignment(node)
+        lhs_node, rhs_node = *node
+        process_node(rhs_node)
+        process_node(lhs_node)
+        skip_children!
+      end
+
+      def process_variable_referencing(node)
+        name = node.children.first
+        variable_table.reference_variable(name, node)
+      end
+
+      def process_loop(node)
+        if POST_CONDITION_LOOP_TYPES.include?(node.type)
+          # See the comment at the end of file for this behavior.
+          condition_node, body_node = *node
+          process_node(body_node)
+          process_node(condition_node)
+        else
+          process_children(node)
+        end
+
+        mark_assignments_as_referenced_in_loop(node)
+
+        skip_children!
+      end
+
+      def process_rescue(node)
+        resbody_nodes = node.children.select do |child|
+          next false unless child.is_a?(Parser::AST::Node)
+          child.type == :resbody
+        end
+
+        contain_retry = resbody_nodes.any? do |resbody_node|
+          scan(resbody_node) do |node_in_resbody|
+            break true if node_in_resbody.type == :retry
+          end
+        end
+
+        # Treat begin..rescue..end with retry as a loop.
+        process_loop(node) if contain_retry
+      end
+
+      def process_zero_arity_super(node)
+        variable_table.accessible_variables.each do |variable|
+          next unless variable.method_argument?
+          variable.reference!(node)
+        end
+      end
+
+      def process_scope(node)
+        if TWISTED_SCOPE_TYPES.include?(node.type)
+          # See the comment at the end of file for this behavior.
+          twisted_nodes = [node.children[0]]
+          twisted_nodes << node.children[1] if node.type == :class
+          twisted_nodes.compact!
+
+          twisted_nodes.each do |twisted_node|
+            process_node(twisted_node)
+            scanned_nodes << twisted_node
+          end
+        end
+
+        inspect_variables_in_scope(node)
+        skip_children!
+      end
+
+      # Mark all assignments which are referenced in the same loop
+      # as referenced by ignoring AST order since they would be referenced
+      # in next iteration.
+      def mark_assignments_as_referenced_in_loop(node)
+        referenced_variable_names_in_loop, assignment_nodes_in_loop =
+          find_variables_in_loop(node)
+
+        referenced_variable_names_in_loop.each do |name|
+          variable = variable_table.find_variable(name)
+          # Non related references which are catched in the above scan
+          # would be skipped here.
+          next unless variable
+          variable.assignments.each do |assignment|
+            next if assignment_nodes_in_loop.none? do |assignment_node|
+                      assignment_node.equal?(assignment.node)
+                    end
+            assignment.reference!
+          end
+        end
+      end
+
+      def find_variables_in_loop(loop_node)
+        referenced_variable_names_in_loop = []
+        assignment_nodes_in_loop = []
+
+        # #scan does not consider scope,
+        # but we don't need to care about it here.
+        scan(loop_node) do |node|
+          case node.type
+          when :lvar
+            referenced_variable_names_in_loop << node.children.first
+          when *OPERATOR_ASSIGNMENT_TYPES
+            asgn_node = node.children.first
+            if asgn_node.type == :lvasgn
+              referenced_variable_names_in_loop << asgn_node.children.first
+            end
+          when :lvasgn
+            assignment_nodes_in_loop << node
+          end
+        end
+
+        [referenced_variable_names_in_loop, assignment_nodes_in_loop]
+      end
+
+      # Simple recursive scan
+      def scan(node, &block)
+        node.children.each do |child|
+          next unless child.is_a?(Parser::AST::Node)
+          yield child
+          scan(child, &block)
+        end
+        nil
+      end
+
+      # Use Node#equal? for accurate check.
+      def scanned_node?(node)
+        scanned_nodes.any? do |scanned_node|
+          scanned_node.equal?(node)
+        end
+      end
+
+      def scanned_nodes
+        @scanned_nodes ||= []
+      end
+
+      # Hooks
+
+      def before_entering_scope(scope)
+      end
+
+      def after_entering_scope(scope)
+      end
+
+      def before_leaving_scope(scope)
+      end
+
+      def after_leaving_scope(scope)
+      end
+
+      def before_declaring_variable(variable_variable)
+      end
+
+      def after_declaring_variable(variable_variable)
+      end
+
+      # Post condition loops
+      #
+      # Loop body nodes need to be scanned first.
+      #
+      # Ruby:
+      #   begin
+      #     foo = 1
+      #   end while foo > 10
+      #   puts foo
+      #
+      # AST:
+      #   (begin
+      #     (while-post
+      #       (send
+      #         (lvar :foo) :>
+      #         (int 10))
+      #       (kwbegin
+      #         (lvasgn :foo
+      #           (int 1))))
+      #     (send nil :puts
+      #       (lvar :foo)))
+
+      # Twisted scope types
+      #
+      # The variable foo belongs to the top level scope,
+      # but in AST, it's under the block node.
+      #
+      # Ruby:
+      #   some_method(foo = 1) do
+      #   end
+      #   puts foo
+      #
+      # AST:
+      #   (begin
+      #     (block
+      #       (send nil :some_method
+      #         (lvasgn :foo
+      #           (int 1)))
+      #       (args) nil)
+      #     (send nil :puts
+      #       (lvar :foo)))
+      #
+      # So the the method argument nodes need to be processed
+      # in current scope.
+      #
+      # Same thing.
+      #
+      # Ruby:
+      #   instance = Object.new
+      #   class << instance
+      #     foo = 1
+      #   end
+      #
+      # AST:
+      #   (begin
+      #     (lvasgn :instance
+      #       (send
+      #         (const nil :Object) :new))
+      #     (sclass
+      #       (lvar :instance)
+      #       (begin
+      #         (lvasgn :foo
+      #           (int 1))
+    end
+  end
+end
diff --git a/lib/rubocop/cop/variable_inspector/assignment.rb b/lib/rubocop/cop/variable_inspector/assignment.rb
new file mode 100644
index 0000000..8e73fca
--- /dev/null
+++ b/lib/rubocop/cop/variable_inspector/assignment.rb
@@ -0,0 +1,103 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module VariableInspector
+      # This class represents each assignment of a variable.
+      class Assignment
+        include Locatable
+
+        MULTIPLE_LEFT_HAND_SIDE_TYPE = :mlhs
+        REFERENCE_PENETRABLE_BRANCH_TYPES = %w(rescue_main ensure_main).freeze
+
+        attr_reader :node, :variable, :referenced
+        alias_method :referenced?, :referenced
+
+        def initialize(node, variable)
+          unless VARIABLE_ASSIGNMENT_TYPES.include?(node.type)
+            fail ArgumentError,
+                 "Node type must be any of #{VARIABLE_ASSIGNMENT_TYPES}, " \
+                 "passed #{node.type}"
+          end
+
+          @node = node
+          @variable = variable
+          @referenced = false
+        end
+
+        def name
+          @node.children.first
+        end
+
+        def scope
+          @variable.scope
+        end
+
+        def reference!
+          @referenced = true
+        end
+
+        def used?
+          @variable.captured_by_block? || @referenced
+        end
+
+        def reference_penetrable?
+          REFERENCE_PENETRABLE_BRANCH_TYPES.include?(branch_type)
+        end
+
+        def regexp_named_capture?
+          @node.type == REGEXP_NAMED_CAPTURE_TYPE
+        end
+
+        def operator_assignment?
+          return false unless meta_assignment_node
+          OPERATOR_ASSIGNMENT_TYPES.include?(meta_assignment_node.type)
+        end
+
+        def multiple_assignment?
+          return false unless meta_assignment_node
+          meta_assignment_node.type == MULTIPLE_ASSIGNMENT_TYPE
+        end
+
+        def operator
+          assignment_node = meta_assignment_node || @node
+          assignment_node.loc.operator.source
+        end
+
+        def meta_assignment_node
+          if instance_variable_defined?(:@meta_assignment_node)
+            return @meta_assignment_node
+          end
+
+          @meta_assignment_node = nil
+
+          return unless parent_node
+
+          if OPERATOR_ASSIGNMENT_TYPES.include?(parent_node.type) &&
+             parent_node.children.index(@node) == 0
+            return @meta_assignment_node = parent_node
+          end
+
+          return unless grantparent_node
+
+          if parent_node.type == MULTIPLE_LEFT_HAND_SIDE_TYPE &&
+             grantparent_node.type == MULTIPLE_ASSIGNMENT_TYPE
+            return @meta_assignment_node = grantparent_node
+          end
+
+          nil
+        end
+
+        private
+
+        def parent_node
+          ancestor_nodes_in_scope.last
+        end
+
+        def grantparent_node
+          ancestor_nodes_in_scope[-2]
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/variable_inspector/locatable.rb b/lib/rubocop/cop/variable_inspector/locatable.rb
new file mode 100644
index 0000000..ef26666
--- /dev/null
+++ b/lib/rubocop/cop/variable_inspector/locatable.rb
@@ -0,0 +1,162 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module VariableInspector
+      # This module provides a way to locate the conditional branch the node is
+      # in. This is intended to be used as mix-in.
+      module Locatable
+        BRANCH_TYPES = [:if, :case].freeze
+        CONDITION_INDEX_OF_BRANCH_NODE = 0
+
+        LOGICAL_OPERATOR_TYPES = [:and, :or].freeze
+        LEFT_SIDE_INDEX_OF_LOGICAL_OPERATOR_NODE = 0
+
+        ENSURE_TYPE = :ensure
+        ENSURE_INDEX_OF_ENSURE_NODE = 1
+
+        def node
+          fail '#node must be declared!'
+        end
+
+        def scope
+          fail '#scope must be declared!'
+        end
+
+        def inside_of_branch?
+          branch_point_node
+        end
+
+        def branch_id
+          return nil unless inside_of_branch?
+          @branch_id ||= [branch_point_node.object_id, branch_type].join('_')
+        end
+
+        def branch_type
+          return nil unless inside_of_branch?
+          @branch_type ||= [branch_point_node.type, branch_body_name].join('_')
+        end
+
+        # Inner if, case, rescue, or ensure node.
+        def branch_point_node
+          if instance_variable_defined?(:@branch_point_node)
+            return @branch_point_node
+          end
+
+          set_branch_point_and_body_nodes!
+          @branch_point_node
+        end
+
+        # A child node of #branch_point_node this assignment belongs.
+        def branch_body_node
+          if instance_variable_defined?(:@branch_body_node)
+            return @branch_body_node
+          end
+
+          set_branch_point_and_body_nodes!
+          @branch_body_node
+        end
+
+        def ancestor_nodes_in_scope
+          @ancestor_nodes_in_scope ||= scope.ancestors_of_node(@node)
+        end
+
+        private
+
+        def branch_body_name
+          case branch_point_node.type
+          when :if
+            if_body_name
+          when :case
+            case_body_name
+          when *LOGICAL_OPERATOR_TYPES
+            logical_operator_body_name
+          when RESCUE_TYPE
+            rescue_body_name
+          when ENSURE_TYPE
+            ensure_body_name
+          else
+            fail InvalidBranchBodyError
+          end
+        rescue InvalidBranchBodyError
+          raise InvalidBranchBodyError,
+                "Invalid body index #{body_index} of #{branch_point_node.type}"
+        end
+
+        def if_body_name
+          case body_index
+          when 1 then 'true'
+          when 2 then 'false'
+          else fail InvalidBranchBodyError
+          end
+        end
+
+        def case_body_name
+          if branch_body_node.type == :when
+            "when#{body_index - 1}"
+          else
+            'else'
+          end
+        end
+
+        def logical_operator_body_name
+          case body_index
+          when 1 then 'right'
+          else fail InvalidBranchBodyError
+          end
+        end
+
+        def rescue_body_name
+          if body_index == 0
+            'main'
+          elsif branch_body_node.type == :resbody
+            "rescue#{body_index - 1}"
+          else
+            'else'
+          end
+        end
+
+        def ensure_body_name
+          case body_index
+          when 0 then 'main'
+          else fail InvalidBranchBodyError
+          end
+        end
+
+        def body_index
+          branch_point_node.children.index(branch_body_node)
+        end
+
+        def set_branch_point_and_body_nodes!
+          ancestors_and_self_nodes = ancestor_nodes_in_scope + [@node]
+
+          ancestors_and_self_nodes.reverse.each_cons(2) do |child, parent|
+            next unless branch?(parent, child)
+            @branch_point_node = parent
+            @branch_body_node = child
+            break
+          end
+        end
+
+        def branch?(parent_node, child_node)
+          child_index = parent_node.children.index(child_node)
+
+          case parent_node.type
+          when *BRANCH_TYPES
+            child_index != CONDITION_INDEX_OF_BRANCH_NODE
+          when *LOGICAL_OPERATOR_TYPES
+            child_index != LEFT_SIDE_INDEX_OF_LOGICAL_OPERATOR_NODE
+          when RESCUE_TYPE
+            true
+          when ENSURE_TYPE
+            child_index != ENSURE_INDEX_OF_ENSURE_NODE
+          else
+            false
+          end
+        end
+
+        class InvalidBranchBodyError < StandardError; end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/variable_inspector/reference.rb b/lib/rubocop/cop/variable_inspector/reference.rb
new file mode 100644
index 0000000..0f5e6c9
--- /dev/null
+++ b/lib/rubocop/cop/variable_inspector/reference.rb
@@ -0,0 +1,31 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module VariableInspector
+      # This class represents each reference of a variable.
+      class Reference
+        include Locatable
+
+        VARIABLE_REFERENCE_TYPES = (
+          [VARIABLE_REFERENCE_TYPE] +
+          OPERATOR_ASSIGNMENT_TYPES +
+          [ZERO_ARITY_SUPER_TYPE]
+        ).freeze
+
+        attr_reader :node, :scope
+
+        def initialize(node, scope)
+          unless VARIABLE_REFERENCE_TYPES.include?(node.type)
+            fail ArgumentError,
+                 "Node type must be any of #{VARIABLE_REFERENCE_TYPES}, " \
+                 "passed #{node.type}"
+          end
+
+          @node = node
+          @scope = scope
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/variable_inspector/scope.rb b/lib/rubocop/cop/variable_inspector/scope.rb
new file mode 100644
index 0000000..6057bbb
--- /dev/null
+++ b/lib/rubocop/cop/variable_inspector/scope.rb
@@ -0,0 +1,71 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module VariableInspector
+      # A Scope represents a context of local variable visibility.
+      # This is a place where local variables belong to.
+      # A scope instance holds a scope node and variable entries.
+      class Scope
+        attr_reader :node, :variables
+
+        def initialize(node)
+          # Accept begin node for top level scope.
+          unless SCOPE_TYPES.include?(node.type) || node.type == :begin
+            fail ArgumentError,
+                 "Node type must be any of #{SCOPE_TYPES}, " \
+                 "passed #{node.type}"
+          end
+          @node = node
+          @variables = {}
+        end
+
+        def ==(other)
+          @node.equal?(other.node)
+        end
+
+        def body_node
+          child_index = case @node.type
+                        when :top_level           then 0
+                        when :module, :sclass     then 1
+                        when :def, :class, :block then 2
+                        when :defs                then 3
+                        end
+
+          @node.children[child_index]
+        end
+
+        def ancestors_of_node(target_node)
+          ASTScanner.scan(@node) do |scanning_node, ancestor_nodes|
+            return ancestor_nodes[1..-1] if scanning_node.equal?(target_node)
+          end
+
+          fail "Node #{target_node} is not found in scope #{@node}"
+        end
+
+        # This class provides a ways to scan AST with tracking ancestor nodes.
+        class ASTScanner
+          def self.scan(node, &block)
+            new.scan(node, &block)
+          end
+
+          def initialize
+            @ancestor_nodes = []
+          end
+
+          def scan(node, &block)
+            @ancestor_nodes.push(node)
+
+            node.children.each do |child|
+              next unless child.is_a?(Parser::AST::Node)
+              yield child, @ancestor_nodes
+              scan(child, &block)
+            end
+
+            @ancestor_nodes.pop
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/variable_inspector/variable.rb b/lib/rubocop/cop/variable_inspector/variable.rb
new file mode 100644
index 0000000..dd20518
--- /dev/null
+++ b/lib/rubocop/cop/variable_inspector/variable.rb
@@ -0,0 +1,87 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module VariableInspector
+      # A Variable represents existance of a local variable.
+      # This holds a variable declaration node,
+      # and some states of the variable.
+      class Variable
+        VARIABLE_DECLARATION_TYPES =
+          (VARIABLE_ASSIGNMENT_TYPES + DECLARATION_TYPES).freeze
+
+        attr_reader :name, :declaration_node, :scope,
+                    :assignments, :captured_by_block
+        alias_method :captured_by_block?, :captured_by_block
+
+        def initialize(name, declaration_node, scope)
+          unless VARIABLE_DECLARATION_TYPES.include?(declaration_node.type)
+            fail ArgumentError,
+                 "Node type must be any of #{VARIABLE_DECLARATION_TYPES}, " \
+                 "passed #{declaration_node.type}"
+          end
+
+          @name = name.to_sym
+          @declaration_node = declaration_node
+          @scope = scope
+
+          @assignments = []
+          @captured_by_block = false
+        end
+
+        def assign(node)
+          @assignments << Assignment.new(node, self)
+        end
+
+        def referenced?
+          @assignments.any?(&:referenced?)
+        end
+
+        def reference!(node)
+          reference = Reference.new(node, @scope)
+          consumed_branch_ids = Set.new
+
+          @assignments.reverse_each do |assignment|
+            next if consumed_branch_ids.include?(assignment.branch_id)
+
+            assignment.reference!
+
+            if assignment.inside_of_branch?
+              break if assignment.branch_id == reference.branch_id
+
+              unless assignment.reference_penetrable?
+                consumed_branch_ids << assignment.branch_id
+              end
+            else
+              break
+            end
+          end
+        end
+
+        def capture_with_block!
+          @captured_by_block = true
+        end
+
+        # This is a convenient way to check whether the variable is used
+        # in its entire variable lifetime.
+        # For more precise usage check, refer Assignment#used?.
+        #
+        # Once the variable is captured by a block, we have no idea
+        # when, where and how many times the block would be invoked
+        # and it means we cannot track the usage of the variable.
+        # So we consider it's used to suppress false positive offenses.
+        def used?
+          @captured_by_block || referenced?
+        end
+
+        def method_argument?
+          METHOD_ARGUMENT_DECLARATION_TYPES.include?(@declaration_node.type)
+        end
+
+        def block_local_variable?
+          @declaration_node.type == BLOCK_LOCAL_VARIABLE_DECLARATION_TYPE
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/cop/variable_inspector/variable_table.rb b/lib/rubocop/cop/variable_inspector/variable_table.rb
new file mode 100644
index 0000000..5355ea6
--- /dev/null
+++ b/lib/rubocop/cop/variable_inspector/variable_table.rb
@@ -0,0 +1,129 @@
+# encoding: utf-8
+
+module Rubocop
+  module Cop
+    module VariableInspector
+      # A VariableTable manages the lifetime of all scopes and local variables
+      # in a program.
+      # This holds scopes as stack structure, and provides a way to add local
+      # variables to current scope and find local variables by considering
+      # variable visibility of the current scope.
+      class VariableTable
+        def initialize(hook_receiver = nil)
+          @hook_receiver = hook_receiver
+        end
+
+        def invoke_hook(hook_name, *args)
+          @hook_receiver.send(hook_name, *args) if @hook_receiver
+        end
+
+        def scope_stack
+          @scope_stack ||= []
+        end
+
+        def push_scope(scope_node)
+          scope = Scope.new(scope_node)
+          invoke_hook(:before_entering_scope, scope)
+          scope_stack.push(scope)
+          invoke_hook(:after_entering_scope, scope)
+          scope
+        end
+
+        def pop_scope
+          scope = current_scope
+          invoke_hook(:before_leaving_scope, scope)
+          scope_stack.pop
+          invoke_hook(:after_leaving_scope, scope)
+          scope
+        end
+
+        def current_scope
+          scope_stack.last
+        end
+
+        def current_scope_level
+          scope_stack.count
+        end
+
+        def declare_variable(name, node)
+          variable = Variable.new(name, node, current_scope)
+          invoke_hook(:before_declaring_variable, variable)
+          current_scope.variables[variable.name] = variable
+          invoke_hook(:after_declaring_variable, variable)
+          variable
+        end
+
+        def assign_to_variable(name, node)
+          variable = find_variable(name)
+
+          unless variable
+            fail "Assigning to undeclared local variable \"#{name}\" " \
+                 "at #{node.loc.expression}, #{node.inspect}"
+          end
+
+          variable.assign(node)
+          mark_variable_as_captured_by_block_if_so(variable)
+        end
+
+        def reference_variable(name, node)
+          variable = find_variable(name)
+
+          # In this code:
+          #
+          #   foo = 1 unless foo
+          #
+          #   (if
+          #     (lvar :foo) nil
+          #     (lvasgn :foo
+          #       (int 1)))
+          #
+          # Parser knows whether the foo is a variable or method invocation.
+          # This means that if a :lvar node is shown in AST, the variable is
+          # assumed to be already declared, even if we haven't seen any :lvasgn
+          # or :arg node before the :lvar node.
+          #
+          # We don't invoke #declare_variable here otherwise
+          # Variable#declaration_node will be :lvar node, that is actually not.
+          # So just skip.
+          return unless variable
+
+          variable.reference!(node)
+          mark_variable_as_captured_by_block_if_so(variable)
+        end
+
+        def find_variable(name)
+          name = name.to_sym
+
+          scope_stack.reverse_each do |scope|
+            variable = scope.variables[name]
+            return variable if variable
+            # Only block scope allows referencing outer scope variables.
+            return nil unless scope.node.type == :block
+          end
+
+          nil
+        end
+
+        def variable_exist?(name)
+          find_variable(name)
+        end
+
+        def accessible_variables
+          scope_stack.reverse_each.reduce([]) do |variables, scope|
+            variables.concat(scope.variables.values)
+            break variables unless scope.node.type == :block
+            variables
+          end
+        end
+
+        private
+
+        def mark_variable_as_captured_by_block_if_so(variable)
+          return unless current_scope.node.type == :block
+          return if variable.scope == current_scope
+          variable.capture_with_block!
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/file_inspector.rb b/lib/rubocop/file_inspector.rb
new file mode 100644
index 0000000..3985fca
--- /dev/null
+++ b/lib/rubocop/file_inspector.rb
@@ -0,0 +1,149 @@
+# encoding: utf-8
+
+module Rubocop
+  # This class handles the processing of files, which includes dealing with
+  # formatters and letting cops inspect the files.
+  class FileInspector
+    def initialize(options)
+      @options = options
+      @errors = []
+    end
+
+    # Takes a block which it calls once per inspected file.  The block shall
+    # return true if the caller wants to break the loop early.
+    def process_files(target_files, config_store)
+      target_files.each(&:freeze).freeze
+      inspected_files = []
+      any_failed = false
+
+      formatter_set.started(target_files)
+
+      target_files.each do |file|
+        break if yield
+        offenses = process_file(file, config_store)
+
+        any_failed = true if offenses.any? do |o|
+          o.severity >= fail_level
+        end
+        inspected_files << file
+      end
+
+      formatter_set.finished(inspected_files.freeze)
+
+      formatter_set.close_output_files
+      any_failed
+    end
+
+    def display_error_summary
+      return if @errors.empty?
+      plural = @errors.count > 1 ? 's' : ''
+      warn "\n#{@errors.count} error#{plural} occurred:".color(:red)
+      @errors.each { |error| warn error }
+      warn 'Errors are usually caused by RuboCop bugs.'
+      warn 'Please, report your problems to RuboCop\'s issue tracker.'
+      warn 'Mention the following information in the issue report:'
+      warn Rubocop::Version.version(true)
+    end
+
+    private
+
+    def process_file(file, config_store)
+      puts "Scanning #{file}" if @options[:debug]
+      processed_source, offenses = process_source(file)
+
+      if offenses.any?
+        formatter_set.file_started(file, offenses)
+        formatter_set.file_finished(file, offenses.compact.sort.freeze)
+        return offenses
+      end
+
+      formatter_set.file_started(
+        file, cop_disabled_line_ranges: processed_source.disabled_line_ranges)
+
+      # When running with --auto-correct, we need to inspect the file (which
+      # includes writing a corrected version of it) until no more corrections
+      # are made. This is because automatic corrections can introduce new
+      # offenses. In the normal case the loop is only executed once.
+      loop do
+        new_offenses, updated_source_file =
+          inspect_file(processed_source, config_store)
+        offenses += new_offenses.reject { |n| offenses.include?(n) }
+        break unless updated_source_file
+
+        # We have to reprocess the source to pickup the changes. Since the
+        # change could (theoretically) introduce parsing errors, we break the
+        # loop if we find any.
+        processed_source, parse_offenses = process_source(file)
+        offenses += parse_offenses if parse_offenses.any?
+      end
+
+      formatter_set.file_finished(file, offenses.compact.sort.freeze)
+      offenses
+    end
+
+    def process_source(file)
+      begin
+        processed_source = SourceParser.parse_file(file)
+      rescue Encoding::UndefinedConversionError, ArgumentError => e
+        range = Struct.new(:line, :column, :source_line).new(1, 0, '')
+        return [
+          nil,
+          [Cop::Offense.new(:fatal, range, e.message.capitalize + '.',
+                            'Parser')]]
+      end
+
+      [processed_source, []]
+    end
+
+    def inspect_file(processed_source, config_store)
+      config = config_store.for(processed_source.file_path)
+      team = Cop::Team.new(mobilized_cop_classes(config), config, @options)
+      offenses = team.inspect_file(processed_source)
+      @errors.concat(team.errors)
+      [offenses, team.updated_source_file?]
+    end
+
+    def mobilized_cop_classes(config)
+      @mobilized_cop_classes ||= {}
+      @mobilized_cop_classes[config.object_id] ||= begin
+        cop_classes = Cop::Cop.all
+
+        if @options[:only]
+          cop_classes.select! { |c| c.cop_name == @options[:only] }
+        else
+          # filter out Rails cops unless requested
+          cop_classes.reject!(&:rails?) unless run_rails_cops?(config)
+
+          # filter out style cops when --lint is passed
+          cop_classes.select!(&:lint?) if @options[:lint]
+        end
+
+        cop_classes
+      end
+    end
+
+    def run_rails_cops?(config)
+      @options[:rails] || config['AllCops']['RunRailsCops']
+    end
+
+    def formatter_set
+      @formatter_set ||= begin
+        set = Formatter::FormatterSet.new
+        pairs = @options[:formatters] || [[Options::DEFAULT_FORMATTER]]
+        pairs.each do |formatter_key, output_path|
+          set.add_formatter(formatter_key, output_path)
+        end
+        set
+      rescue => error
+        warn error.message
+        $stderr.puts error.backtrace
+        exit(1)
+      end
+    end
+
+    def fail_level
+      @fail_level ||= Rubocop::Cop::Severity.new(
+        @options[:fail_level] || :refactor)
+    end
+  end
+end
diff --git a/lib/rubocop/formatter/base_formatter.rb b/lib/rubocop/formatter/base_formatter.rb
new file mode 100644
index 0000000..2a6f80d
--- /dev/null
+++ b/lib/rubocop/formatter/base_formatter.rb
@@ -0,0 +1,119 @@
+# encoding: utf-8
+
+# rubocop:disable LineLength
+
+module Rubocop
+  module Formatter
+    # Abstract base class for formatter, implements all public API methods.
+    #
+    # ## Creating Custom Formatter
+    #
+    # You can create a custom formatter by subclassing
+    # `Rubocop::Formatter::BaseFormatter` and overriding some methods,
+    # or by implementing all the methods by duck typing.
+    #
+    # ## Using Custom Formatter in Command Line
+    #
+    # You can tell RuboCop to use your custom formatter with a combination of
+    # `--format` and `--require` option.
+    # For example, when you have defined `MyCustomFormatter` in
+    # `./path/to/my_custom_formatter.rb`, you would type this command:
+    #
+    #     rubocop --require ./path/to/my_custom_formatter --format MyCustomFormatter
+    #
+    # Note: The path passed to `--require` is directly passed to
+    # `Kernel.require`.
+    # If your custom formatter file is not in `$LOAD_PATH`,
+    # you need to specify the path as relative path prefixed with `./`
+    # explicitly, or absolute path.
+    #
+    # ## Method Invocation Order
+    #
+    # For example, when RuboCop inspects 2 files,
+    # the invocation order should be like this:
+    #
+    # * `#initialize`
+    # * `#started`
+    # * `#file_started`
+    # * `#file_finished`
+    # * `#file_started`
+    # * `#file_finished`
+    # * `#finished`
+    #
+    class BaseFormatter
+      # rubocop:enable LineLength
+
+      # @api public
+      #
+      # @!attribute [r] output
+      #
+      # @return [IO]
+      #   the IO object passed to `#initialize`
+      #
+      # @see #initialize
+      attr_reader :output
+
+      # @api public
+      #
+      # @param output [IO]
+      #   `$stdout` or opened file
+      def initialize(output)
+        @output = output
+      end
+
+      # @api public
+      #
+      # Invoked once before any files are inspected.
+      #
+      # @param target_files [Array(String)]
+      #   all target file paths to be inspected
+      #
+      # @return [void]
+      def started(target_files)
+      end
+
+      # @api public
+      #
+      # Invoked at the beginning of inspecting each files.
+      #
+      # @param file [String]
+      #   the file path
+      #
+      # @param options [Hash]
+      #   file specific information, currently this is always empty.
+      #
+      # @return [void]
+      def file_started(file, options)
+      end
+
+      # @api public
+      #
+      # Invoked at the end of inspecting each files.
+      #
+      # @param file [String]
+      #   the file path
+      #
+      # @param offenses [Array(Rubocop::Cop::Offense)]
+      #   all detected offenses for the file
+      #
+      # @return [void]
+      #
+      # @see Rubocop::Cop::Offense
+      def file_finished(file, offenses)
+      end
+
+      # @api public
+      #
+      # Invoked after all files are inspected, or interrupted by user.
+      #
+      # @param inspected_files [Array(String)]
+      #   the inspected file paths.
+      #   This would be same as `target_files` passed to `#started`
+      #   unless RuboCop is interrupted by user.
+      #
+      # @return [void]
+      def finished(inspected_files)
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/formatter/clang_style_formatter.rb b/lib/rubocop/formatter/clang_style_formatter.rb
new file mode 100644
index 0000000..2ff1c07
--- /dev/null
+++ b/lib/rubocop/formatter/clang_style_formatter.rb
@@ -0,0 +1,35 @@
+# encoding: utf-8
+
+module Rubocop
+  module Formatter
+    # This formatter formats report data in clang style.
+    # The precise location of the problem is shown together with the
+    # relevant source code.
+    class ClangStyleFormatter < SimpleTextFormatter
+      def report_file(file, offenses)
+        offenses.each do |o|
+          output.printf("%s:%d:%d: %s: %s\n",
+                        cyan(smart_path(file)), o.line, o.real_column,
+                        colored_severity_code(o), message(o))
+
+          source_line = o.location.source_line
+
+          unless source_line.blank?
+            output.puts(source_line)
+            output.puts(highlight_line(o.location))
+          end
+        end
+      end
+
+      def highlight_line(location)
+        column_length = if location.begin.line == location.end.line
+                          location.column_range.count
+                        else
+                          location.source_line.length - location.column
+                        end
+
+        ' ' * location.column + '^' * column_length
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/formatter/colorizable.rb b/lib/rubocop/formatter/colorizable.rb
new file mode 100644
index 0000000..7c0abbc
--- /dev/null
+++ b/lib/rubocop/formatter/colorizable.rb
@@ -0,0 +1,37 @@
+# encoding: utf-8
+
+module Rubocop
+  module Formatter
+    # This mix-in module provides string coloring methods for terminals.
+    # It automatically disables coloring if coloring is disabled in the process
+    # globally or the formatter's output is not a terminal.
+    module Colorizable
+      def rainbow
+        @rainbow ||= begin
+          rainbow = Rainbow.new
+          rainbow.enabled = false unless output.tty?
+          rainbow
+        end
+      end
+
+      def colorize(string, *args)
+        rainbow.wrap(string).color(*args)
+      end
+
+      [
+        :black,
+        :red,
+        :green,
+        :yellow,
+        :blue,
+        :magenta,
+        :cyan,
+        :white
+      ].each do |color|
+        define_method(color) do |string|
+          colorize(string, color)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/formatter/disabled_config_formatter.rb b/lib/rubocop/formatter/disabled_config_formatter.rb
new file mode 100644
index 0000000..1eacb63
--- /dev/null
+++ b/lib/rubocop/formatter/disabled_config_formatter.rb
@@ -0,0 +1,65 @@
+# encoding: utf-8
+
+module Rubocop
+  module Formatter
+    # This formatter displays a YAML configuration file where all cops that
+    # detected any offenses are configured to not detect the offense.
+    class DisabledConfigFormatter < BaseFormatter
+      HEADING =
+        ['# This configuration was generated by `rubocop --auto-gen-config`',
+         "# on #{Time.now} using RuboCop version #{Version.version}.",
+         '# The point is for the user to remove these configuration records',
+         '# one by one as the offenses are removed from the code base.',
+         '# Note that changes in the inspected code, or installation of new',
+         '# versions of RuboCop, may require this file to be generated again.']
+        .join("\n")
+
+      @config_to_allow_offenses = {}
+
+      COPS = Cop::Cop.all.group_by { |c| c.cop_name }
+
+      class << self
+        attr_accessor :config_to_allow_offenses
+      end
+
+      def file_finished(file, offenses)
+        @cops_with_offenses ||= Hash.new(0)
+        offenses.each { |o| @cops_with_offenses[o.cop_name] += 1 }
+      end
+
+      def finished(inspected_files)
+        output.puts HEADING
+
+        # Syntax isn't a real cop and it can't be disabled.
+        @cops_with_offenses.delete('Syntax')
+
+        @cops_with_offenses.sort.each do |cop_name, offense_count|
+          output.puts
+          cfg = self.class.config_to_allow_offenses[cop_name]
+          cfg ||= { 'Enabled' => false }
+          output_cop_comments(output, cfg, cop_name, offense_count)
+          output.puts "#{cop_name}:"
+          cfg.each { |key, value| output.puts "  #{key}: #{value}" }
+        end
+        puts "Created #{output.path}."
+        puts "Run `rubocop --config #{output.path}`, or"
+        puts "add inherit_from: #{output.path} in a .rubocop.yml file."
+      end
+
+      def output_cop_comments(output, cfg, cop_name, offense_count)
+        output.puts "# Offense count: #{offense_count}"
+        if COPS[cop_name] && COPS[cop_name].first.new.support_autocorrect?
+          output.puts '# Cop supports --auto-correct.'
+        end
+
+        default_cfg = Rubocop::ConfigLoader.default_configuration[cop_name]
+        if default_cfg
+          params = default_cfg.keys - %w(Description Enabled) - cfg.keys
+          unless params.empty?
+            output.puts "# Configuration parameters: #{params.join(', ')}."
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/formatter/disabled_lines_formatter.rb b/lib/rubocop/formatter/disabled_lines_formatter.rb
new file mode 100644
index 0000000..c7779bb
--- /dev/null
+++ b/lib/rubocop/formatter/disabled_lines_formatter.rb
@@ -0,0 +1,56 @@
+# encoding: utf-8
+module Rubocop
+  module Formatter
+    # A basic formatter that displays the lines disabled
+    # inline comments.
+    class DisabledLinesFormatter < BaseFormatter
+      include PathUtil
+      include Colorizable
+
+      attr_reader :cop_disabled_line_ranges
+
+      def started(target_files)
+        @cop_disabled_line_ranges = {}
+      end
+
+      def file_started(file, options)
+        return unless options[:cop_disabled_line_ranges]
+
+        @cop_disabled_line_ranges[file] =
+          options[:cop_disabled_line_ranges]
+      end
+
+      def finished(inspected_files)
+        cops_disabled_in_comments_summary
+      end
+
+      private
+
+      def cops_disabled_in_comments_summary
+        summary = "\nCops disabled line ranges:\n\n"
+
+        @cop_disabled_line_ranges.each do |file, disabled_cops|
+          disabled_cops.each do |cop, line_ranges|
+            line_ranges.each do |line_range|
+              file = cyan(smart_path(file))
+              summary << "#{file}:#{line_range}: #{cop}\n"
+            end
+          end
+        end
+
+        output.puts summary
+      end
+
+      def smart_path(path)
+        # Ideally, we calculate this relative to the project root.
+        base_dir = Dir.pwd
+
+        if path.start_with? base_dir
+          relative_path(path, base_dir)
+        else
+          path
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/formatter/emacs_style_formatter.rb b/lib/rubocop/formatter/emacs_style_formatter.rb
new file mode 100644
index 0000000..69a48be
--- /dev/null
+++ b/lib/rubocop/formatter/emacs_style_formatter.rb
@@ -0,0 +1,21 @@
+# encoding: utf-8
+
+module Rubocop
+  module Formatter
+    # This formatter displays the report data in format that's
+    # easy to process in the Emacs text editor.
+    # The output is machine-parsable.
+    class EmacsStyleFormatter < BaseFormatter
+      def file_finished(file, offenses)
+        offenses.each do |o|
+          message = o.corrected? ? '[Corrected] ' : ''
+          message << o.message
+
+          output.printf("%s:%d:%d: %s: %s\n",
+                        file, o.line, o.real_column, o.severity.code,
+                        message)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/formatter/file_list_formatter.rb b/lib/rubocop/formatter/file_list_formatter.rb
new file mode 100644
index 0000000..5defceb
--- /dev/null
+++ b/lib/rubocop/formatter/file_list_formatter.rb
@@ -0,0 +1,19 @@
+# encoding: utf-8
+
+module Rubocop
+  module Formatter
+    # This formatter displays just a list of the files with offenses in them,
+    # separated by newlines. The output is machine-parsable.
+    #
+    # Here's the format:
+    #
+    # /some/file
+    # /some/other/file
+    class FileListFormatter < BaseFormatter
+      def file_finished(file, offenses)
+        return if offenses.empty?
+        output.printf("%s\n", file)
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/formatter/formatter_set.rb b/lib/rubocop/formatter/formatter_set.rb
new file mode 100644
index 0000000..a0ea76a
--- /dev/null
+++ b/lib/rubocop/formatter/formatter_set.rb
@@ -0,0 +1,75 @@
+# encoding: utf-8
+
+module Rubocop
+  module Formatter
+    # This is a collection of formatters. A FormatterSet can hold multiple
+    # formatter instances and provides transparent formatter API methods
+    # which invoke same method of each formatters.
+    class FormatterSet < Array
+      BUILTIN_FORMATTERS_FOR_KEYS = {
+        'progress' => ProgressFormatter,
+        'simple'   => SimpleTextFormatter,
+        'clang'    => ClangStyleFormatter,
+        'fuubar'   => FuubarStyleFormatter,
+        'emacs'    => EmacsStyleFormatter,
+        'json'     => JSONFormatter,
+        'files'    => FileListFormatter,
+        'offenses' => OffenseCountFormatter,
+        'disabled' => DisabledLinesFormatter
+      }
+
+      FORMATTER_APIS = [:started, :file_started, :file_finished, :finished]
+
+      FORMATTER_APIS.each do |method_name|
+        define_method(method_name) do |*args|
+          each { |f| f.send(method_name, *args) }
+        end
+      end
+
+      def add_formatter(formatter_type, output_path = nil)
+        formatter_class = case formatter_type
+                          when Class
+                            formatter_type
+                          when /\A[A-Z]/
+                            custom_formatter_class(formatter_type)
+                          else
+                            builtin_formatter_class(formatter_type)
+                          end
+
+        output = output_path ? File.open(output_path, 'w') : $stdout
+
+        self << formatter_class.new(output)
+      end
+
+      def close_output_files
+        each do |formatter|
+          formatter.output.close if formatter.output.is_a?(File)
+        end
+      end
+
+      private
+
+      def builtin_formatter_class(specified_key)
+        matching_keys = BUILTIN_FORMATTERS_FOR_KEYS.keys.select do |key|
+          key.start_with?(specified_key)
+        end
+
+        if matching_keys.empty?
+          fail %(No formatter for "#{specified_key}")
+        elsif matching_keys.size > 1
+          fail %(Cannot determine formatter for "#{specified_key}")
+        end
+
+        BUILTIN_FORMATTERS_FOR_KEYS[matching_keys.first]
+      end
+
+      def custom_formatter_class(specified_class_name)
+        constant_names = specified_class_name.split('::')
+        constant_names.shift if constant_names.first.empty?
+        constant_names.reduce(Object) do |namespace, constant_name|
+          namespace.const_get(constant_name, false)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/formatter/fuubar_style_formatter.rb b/lib/rubocop/formatter/fuubar_style_formatter.rb
new file mode 100644
index 0000000..d5e8a4b
--- /dev/null
+++ b/lib/rubocop/formatter/fuubar_style_formatter.rb
@@ -0,0 +1,74 @@
+# encoding: utf-8
+
+require 'ruby-progressbar'
+
+module Rubocop
+  module Formatter
+    # This formatter displays a progress bar and shows details of offenses as
+    # soon as they are detected.
+    # This is inspired by the Fuubar formatter for RSpec by Jeff Kreeftmeijer.
+    # https://github.com/jeffkreeftmeijer/fuubar
+    class FuubarStyleFormatter < ClangStyleFormatter
+      RESET_SEQUENCE = "\e[0m"
+
+      def started(target_files)
+        super
+
+        @severest_offense = nil
+
+        file_phrase = target_files.count == 1 ? 'file' : 'files'
+
+        # 185/407 files |====== 45 ======>                    |  ETA: 00:00:04
+        # %c / %C       |       %w       >         %i         |       %e
+        bar_format = " %c/%C #{file_phrase} |%w>%i| %e "
+
+        @progressbar = ProgressBar.create(
+          output: output,
+          total: target_files.count,
+          format: bar_format,
+          autostart: false
+        )
+        with_color { @progressbar.start }
+      end
+
+      def file_finished(file, offenses)
+        count_stats(offenses)
+
+        unless offenses.empty?
+          @progressbar.clear
+          report_file(file, offenses)
+        end
+
+        with_color { @progressbar.increment }
+      end
+
+      def count_stats(offenses)
+        super
+
+        offenses = offenses.reject(&:corrected?)
+        return if offenses.empty?
+
+        offenses << @severest_offense if @severest_offense
+        @severest_offense = offenses.max_by { |offense| offense.severity }
+      end
+
+      def with_color
+        if rainbow.enabled
+          output.write colorize('', progressbar_color).chomp(RESET_SEQUENCE)
+          yield
+          output.write RESET_SEQUENCE
+        else
+          yield
+        end
+      end
+
+      def progressbar_color
+        if @severest_offense
+          COLOR_FOR_SEVERITY[@severest_offense.severity.name]
+        else
+          :green
+        end
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/formatter/json_formatter.rb b/lib/rubocop/formatter/json_formatter.rb
new file mode 100644
index 0000000..e928c2e
--- /dev/null
+++ b/lib/rubocop/formatter/json_formatter.rb
@@ -0,0 +1,74 @@
+# encoding: utf-8
+
+require 'json'
+require 'pathname'
+
+module Rubocop
+  module Formatter
+    # This formatter formats the report data in JSON format.
+    class JSONFormatter < BaseFormatter
+      include PathUtil
+
+      attr_reader :output_hash
+
+      def initialize(output)
+        super
+        @output_hash = {
+          metadata: metadata_hash,
+          files:    [],
+          summary:  { offense_count: 0 }
+        }
+      end
+
+      def started(target_files)
+        output_hash[:summary][:target_file_count] = target_files.count
+      end
+
+      def file_finished(file, offenses)
+        output_hash[:files] << hash_for_file(file, offenses)
+        output_hash[:summary][:offense_count] += offenses.count
+      end
+
+      def finished(inspected_files)
+        output_hash[:summary][:inspected_file_count] = inspected_files.count
+        output.write output_hash.to_json
+      end
+
+      def metadata_hash
+        {
+          rubocop_version: Rubocop::Version::STRING,
+          ruby_engine:     RUBY_ENGINE,
+          ruby_version:    RUBY_VERSION,
+          ruby_patchlevel: RUBY_PATCHLEVEL.to_s,
+          ruby_platform:   RUBY_PLATFORM
+        }
+      end
+
+      def hash_for_file(file, offenses)
+        {
+          path:     relative_path(file),
+          offenses: offenses.map { |o| hash_for_offense(o) }
+        }
+      end
+
+      def hash_for_offense(offense)
+        {
+          severity: offense.severity.name,
+          message:  offense.message,
+          cop_name: offense.cop_name,
+          corrected: offense.corrected?,
+          location: hash_for_location(offense)
+        }
+      end
+
+      # TODO: Consider better solution for Offense#real_column.
+      def hash_for_location(offense)
+        {
+          line:   offense.line,
+          column: offense.real_column,
+          length: offense.location.length
+        }
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/formatter/offense_count_formatter.rb b/lib/rubocop/formatter/offense_count_formatter.rb
new file mode 100644
index 0000000..7bcb14f
--- /dev/null
+++ b/lib/rubocop/formatter/offense_count_formatter.rb
@@ -0,0 +1,54 @@
+# encoding: utf-8
+
+module Rubocop
+  module Formatter
+    # This formatter displays the list of offended cops with a count of how
+    # many offenses of their kind were found. Ordered by desc offense count
+    #
+    # Here's the format:
+    #
+    # 26  LineLength
+    # 3   OneLineConditional
+    # --
+    # 29  Total
+    class OffenseCountFormatter < BaseFormatter
+      attr_reader :offense_counts
+
+      def started(target_files)
+        super
+        @offense_counts = Hash.new(0)
+      end
+
+      def file_finished(file, offenses)
+        offenses.each { |o| @offense_counts[o.cop_name] += 1 }
+      end
+
+      def finished(inspected_files)
+        report_summary(inspected_files.count,
+                       ordered_offense_counts(@offense_counts))
+      end
+
+      def report_summary(file_count, offense_counts)
+        output.puts
+
+        offense_count = total_offense_count(offense_counts)
+        offense_counts.each do |cop_name, count|
+          output.puts "#{count.to_s.ljust(offense_count.to_s.length + 2)}" \
+                      "#{cop_name}\n"
+        end
+        output.puts '--'
+        output.puts "#{offense_count}  Total"
+
+        output.puts
+      end
+
+      def ordered_offense_counts(offense_counts)
+        Hash[offense_counts.sort_by { |k, v| [-v, k] }]
+      end
+
+      def total_offense_count(offense_counts = {})
+        offense_counts.values.inject(0, :+)
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/formatter/progress_formatter.rb b/lib/rubocop/formatter/progress_formatter.rb
new file mode 100644
index 0000000..168ca85
--- /dev/null
+++ b/lib/rubocop/formatter/progress_formatter.rb
@@ -0,0 +1,55 @@
+# encoding: utf-8
+
+module Rubocop
+  module Formatter
+    # This formatter display dots for files with no offenses and
+    # letters for files with problems in the them. In the end it
+    # appends the regular report data in the clang style format.
+    class ProgressFormatter < ClangStyleFormatter
+      def started(target_files)
+        super
+        @offenses_for_files = {}
+        file_phrase = target_files.count == 1 ? 'file' : 'files'
+        output.puts "Inspecting #{target_files.count} #{file_phrase}"
+      end
+
+      def file_finished(file, offenses)
+        unless offenses.empty?
+          count_stats(offenses)
+          @offenses_for_files[file] = offenses
+        end
+
+        report_file_as_mark(file, offenses)
+      end
+
+      def finished(inspected_files)
+        output.puts
+
+        unless @offenses_for_files.empty?
+          output.puts
+          output.puts 'Offenses:'
+          output.puts
+
+          @offenses_for_files.each do |file, offenses|
+            report_file(file, offenses)
+          end
+        end
+
+        report_summary(inspected_files.count,
+                       @total_offense_count,
+                       @total_correction_count)
+      end
+
+      def report_file_as_mark(file, offenses)
+        mark = if offenses.empty?
+                 green('.')
+               else
+                 highest_offense = offenses.max_by { |o| o.severity }
+                 colored_severity_code(highest_offense)
+               end
+
+        output.write mark
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/formatter/simple_text_formatter.rb b/lib/rubocop/formatter/simple_text_formatter.rb
new file mode 100644
index 0000000..25242a9
--- /dev/null
+++ b/lib/rubocop/formatter/simple_text_formatter.rb
@@ -0,0 +1,117 @@
+# encoding: utf-8
+
+require 'rubocop/formatter/colorizable'
+
+module Rubocop
+  module Formatter
+    # A basic formatter that displays only files with offenses.
+    # Offenses are displayed at compact form - just the
+    # location of the problem and the associated message.
+    class SimpleTextFormatter < BaseFormatter
+      include Colorizable
+      include PathUtil
+
+      COLOR_FOR_SEVERITY = {
+        refactor:   :yellow,
+        convention: :yellow,
+        warning:    :magenta,
+        error:      :red,
+        fatal:      :red
+      }.freeze
+
+      def started(target_files)
+        @total_offense_count = 0
+        @total_correction_count = 0
+      end
+
+      def file_finished(file, offenses)
+        return if offenses.empty?
+        count_stats(offenses)
+        report_file(file, offenses)
+      end
+
+      def finished(inspected_files)
+        report_summary(inspected_files.count,
+                       @total_offense_count,
+                       @total_correction_count)
+      end
+
+      def report_file(file, offenses)
+        output.puts yellow("== #{smart_path(file)} ==")
+
+        offenses.each do |o|
+          output.printf("%s:%3d:%3d: %s\n",
+                        colored_severity_code(o),
+                        o.line, o.real_column, message(o))
+        end
+      end
+
+      def report_summary(file_count, offense_count, correction_count)
+        summary = pluralize(file_count, 'file')
+        summary << ' inspected, '
+
+        offenses_text = pluralize(offense_count, 'offense', no_for_zero: true)
+        offenses_text << ' detected'
+        summary << colorize(offenses_text, offense_count.zero? ? :green : :red)
+
+        if correction_count > 0
+          summary << ', '
+          correction_text = pluralize(correction_count, 'offense')
+          correction_text << ' corrected'
+          color = correction_count == offense_count ? :green : :cyan
+          summary << colorize(correction_text, color)
+        end
+
+        output.puts
+        output.puts summary
+      end
+
+      private
+
+      def count_stats(offenses)
+        @total_offense_count += offenses.count
+        @total_correction_count += offenses.select(&:corrected?).count
+      end
+
+      def smart_path(path)
+        # Ideally, we calculate this relative to the project root.
+        base_dir = Dir.pwd
+
+        if path.start_with? base_dir
+          relative_path(path, base_dir)
+        else
+          path
+        end
+      end
+
+      def colored_severity_code(offense)
+        color = COLOR_FOR_SEVERITY[offense.severity.name]
+        colorize(offense.severity.code, color)
+      end
+
+      def annotate_message(msg)
+        msg.gsub(/`(.*?)`/, Rainbow('\1').yellow)
+      end
+
+      def message(offense)
+        message = offense.corrected? ? green('[Corrected] ') : ''
+        message << annotate_message(offense.message)
+      end
+
+      def pluralize(number, thing, options = {})
+        text = ''
+
+        if number == 0 && options[:no_for_zero]
+          text = 'no'
+        else
+          text << number.to_s
+        end
+
+        text << " #{thing}"
+        text << 's' unless number == 1
+
+        text
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/options.rb b/lib/rubocop/options.rb
new file mode 100644
index 0000000..f9f9c43
--- /dev/null
+++ b/lib/rubocop/options.rb
@@ -0,0 +1,189 @@
+# encoding: utf-8
+
+require 'optparse'
+
+module Rubocop
+  # This class handles command line options.
+  class Options
+    DEFAULT_FORMATTER = 'progress'
+    EXITING_OPTIONS = [:version, :verbose_version, :show_cops]
+
+    def initialize
+      @options = {}
+    end
+
+    def parse(args)
+      ignore_dropped_options(args)
+      convert_deprecated_options(args)
+
+      OptionParser.new do |opts|
+        opts.banner = 'Usage: rubocop [options] [file1, file2, ...]'
+
+        option(opts, '--only COP', 'Run just one cop.') do
+          validate_only_option
+        end
+
+        add_configuration_options(opts, args)
+        add_formatting_options(opts, args)
+
+        option(opts, '-r', '--require FILE', 'Require Ruby file.') do |f|
+          require f
+        end
+
+        add_severity_option(opts)
+        add_flags_with_optional_args(opts)
+        add_boolean_flags(opts)
+      end.parse!(args)
+
+      if (incompat = @options.keys & EXITING_OPTIONS).size > 1
+        fail ArgumentError, "Incompatible cli options: #{incompat.inspect}"
+      end
+
+      [@options, args]
+    end
+
+    private
+
+    def add_configuration_options(opts, args)
+      option(opts, '-c', '--config FILE', 'Specify configuration file.')
+
+      option(opts, '--auto-gen-config',
+             'Generate a configuration file acting as a', 'TODO list.') do
+        validate_auto_gen_config_option(args)
+        @options[:formatters] = [[DEFAULT_FORMATTER],
+                                 [Formatter::DisabledConfigFormatter,
+                                  ConfigLoader::AUTO_GENERATED_FILE]]
+      end
+
+      option(opts, '--force-exclusion',
+             'Force excluding files specified in the',
+             'configuration `Exclude` even if they are',
+             'explicitly passed as arguments.')
+    end
+
+    FORMAT_HELP = ['Choose an output formatter. This option',
+                   'can be specified multiple times to enable',
+                   'multiple formatters at the same time.',
+                   '  [p]rogress (default)',
+                   '  [s]imple',
+                   '  [c]lang',
+                   '  [d]isabled cops via inline comments',
+                   '  [fu]ubar',
+                   '  [e]macs',
+                   '  [j]son',
+                   '  [fi]les',
+                   '  [o]ffenses',
+                   '  custom formatter class name']
+
+    def add_formatting_options(opts, args)
+      option(opts, '-f', '--format FORMATTER', *FORMAT_HELP) do |key|
+        @options[:formatters] ||= []
+        @options[:formatters] << [key]
+      end
+
+      option(opts, '-o', '--out FILE',
+             'Write output to a file instead of STDOUT.',
+             'This option applies to the previously',
+             'specified --format, or the default format',
+             'if no format is specified.') do |path|
+        @options[:formatters] ||= [[DEFAULT_FORMATTER]]
+        @options[:formatters].last << path
+      end
+    end
+
+    def add_severity_option(opts)
+      opts.on('--fail-level SEVERITY',
+              Rubocop::Cop::Severity::NAMES,
+              Rubocop::Cop::Severity::CODE_TABLE,
+              'Minimum severity for exit with error code.') do |severity|
+                @options[:fail_level] = severity
+              end
+    end
+
+    def add_flags_with_optional_args(opts)
+      option(opts, '--show-cops [cop1,cop2,...]',
+             'Shows the given cops, or all cops by',
+             'default, and their configurations for the',
+             'current directory.') do |list|
+        @options[:show_cops] = list.nil? ? [] : list.split(',')
+      end
+    end
+
+    def add_boolean_flags(opts)
+      option(opts, '-d', '--debug', 'Display debug info.')
+      option(opts,
+             '-D', '--display-cop-names',
+             'Display cop names in offense messages.')
+      option(opts, '-R', '--rails', 'Run extra Rails cops.')
+      option(opts, '-l', '--lint', 'Run only lint cops.')
+      option(opts, '-a', '--auto-correct', 'Auto-correct offenses.')
+
+      @options[:color] = true
+      opts.on('-n', '--no-color', 'Disable color output.') do
+        @options[:color] = false
+      end
+
+      option(opts, '-v', '--version', 'Display version.')
+      option(opts, '-V', '--verbose-version', 'Display verbose version.')
+    end
+
+    # Sets a value in the @options hash, based on the given long option and its
+    # value, in addition to calling the block if a block is given.
+    def option(opts, *args)
+      opts.on(*args) do |arg|
+        @options[long_opt_symbol(args)] = arg
+        yield arg if block_given?
+      end
+    end
+
+    # Finds the option in `args` starting with -- and converts it to a symbol,
+    # e.g. [..., '--auto-correct', ...] to :auto_correct.
+    def long_opt_symbol(args)
+      long_opt = args.find { |arg| arg.start_with?('--') }
+      long_opt[2..-1].sub(/ .*/, '').gsub(/-/, '_').to_sym
+    end
+
+    def ignore_dropped_options(args)
+      # Currently we don't make -s/--silent option raise error
+      # since those are mostly used by external tools.
+      rejected = args.reject! { |a| %w(-s --silent).include?(a) }
+      if rejected
+        warn '-s/--silent options is dropped. ' \
+             '`emacs` and `files` formatters no longer display summary.'
+      end
+    end
+
+    def convert_deprecated_options(args)
+      args.map! do |arg|
+        case arg
+        when '-e', '--emacs'
+          deprecate("#{arg} option", '--format emacs', '1.0.0')
+          %w(--format emacs)
+        else
+          arg
+        end
+      end.flatten!
+    end
+
+    def deprecate(subject, alternative = nil, version = nil)
+      message =  "#{subject} is deprecated"
+      message << " and will be removed in RuboCop #{version}" if version
+      message << '.'
+      message << " Please use #{alternative} instead." if alternative
+      warn message
+    end
+
+    def validate_only_option
+      if Cop::Cop.all.none? { |c| c.cop_name == @options[:only] }
+        fail ArgumentError, "Unrecognized cop name: #{@options[:only]}."
+      end
+    end
+
+    def validate_auto_gen_config_option(args)
+      if args.any?
+        warn '--auto-gen-config can not be combined with any other arguments.'
+        exit(1)
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/path_util.rb b/lib/rubocop/path_util.rb
new file mode 100644
index 0000000..97ce6cb
--- /dev/null
+++ b/lib/rubocop/path_util.rb
@@ -0,0 +1,23 @@
+# encoding: utf-8
+
+module Rubocop
+  # Common methods and behaviors for dealing with paths.
+  module PathUtil
+    module_function
+
+    def relative_path(path, base_dir = Dir.pwd)
+      path_name = Pathname.new(File.expand_path(path))
+      path_name.relative_path_from(Pathname.new(base_dir)).to_s
+    end
+
+    def match_path?(pattern, path)
+      case pattern
+      when String
+        basename = File.basename(path)
+        path == pattern || basename == pattern || File.fnmatch(pattern, path)
+      when Regexp
+        path =~ pattern
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/processed_source.rb b/lib/rubocop/processed_source.rb
new file mode 100644
index 0000000..ebe40e9
--- /dev/null
+++ b/lib/rubocop/processed_source.rb
@@ -0,0 +1,61 @@
+# encoding: utf-8
+
+module Rubocop
+  # ProcessedSource contains objects which are generated by Parser
+  # and other information such as disabled lines for cops.
+  # It also provides a convenient way to access source lines.
+  class ProcessedSource
+    attr_reader :buffer, :ast, :comments, :tokens, :diagnostics,
+                :comment_config
+
+    def initialize(buffer, ast, comments, tokens, diagnostics)
+      @buffer = buffer
+      @ast = ast
+      @comments = comments
+      @tokens = tokens
+      @diagnostics = diagnostics
+      @comment_config = CommentConfig.new(self)
+    end
+
+    def disabled_line_ranges
+      comment_config.cop_disabled_line_ranges
+    end
+
+    def lines
+      if @lines
+        @lines
+      else
+        init_lines
+        @lines
+      end
+    end
+
+    def raw_lines
+      if @raw_lines
+        @raw_lines
+      else
+        init_lines
+        @raw_lines
+      end
+    end
+
+    def [](*args)
+      lines[*args]
+    end
+
+    def valid_syntax?
+      @diagnostics.none? { |d| [:error, :fatal].include?(d.level) }
+    end
+
+    def file_path
+      @buffer.name
+    end
+
+    private
+
+    def init_lines
+      @raw_lines = @buffer.source.lines
+      @lines = @raw_lines.map(&:chomp)
+    end
+  end
+end
diff --git a/lib/rubocop/rake_task.rb b/lib/rubocop/rake_task.rb
new file mode 100644
index 0000000..49cb3da
--- /dev/null
+++ b/lib/rubocop/rake_task.rb
@@ -0,0 +1,70 @@
+# encoding: utf-8
+
+require 'rake'
+require 'rake/tasklib'
+
+module Rubocop
+  # Provides a custom rake task.
+  #
+  # require 'rubocop/rake_task'
+  # Rubocop::RakeTask.new
+  class RakeTask < Rake::TaskLib
+    attr_accessor :name
+    attr_accessor :verbose
+    attr_accessor :fail_on_error
+    attr_accessor :patterns
+    attr_accessor :formatters
+    attr_accessor :requires
+    attr_accessor :options
+
+    def initialize(*args, &task_block)
+      setup_ivars(args)
+
+      desc 'Run RuboCop' unless ::Rake.application.last_comment
+
+      task(name, *args) do |_, task_args|
+        RakeFileUtils.send(:verbose, verbose) do
+          if task_block
+            task_block.call(*[self, task_args].slice(0, task_block.arity))
+          end
+          run_task(verbose)
+        end
+      end
+    end
+
+    def run_task(verbose)
+      # We lazy-load rubocop so that the task doesn't dramatically impact the
+      # load time of your Rakefile.
+      require 'rubocop'
+
+      cli = CLI.new
+      puts 'Running RuboCop...' if verbose
+      result = cli.run(full_options)
+      abort('RuboCop failed!') if fail_on_error unless result == 0
+    end
+
+    private
+
+    def full_options
+      [].tap do |result|
+        result.concat(formatters.map { |f| ['--format', f] }.flatten)
+        result.concat(requires.map { |r| ['--require', r] }.flatten)
+        result.concat(options)
+        result.concat(patterns)
+      end
+    end
+
+    def setup_ivars(args)
+      # More lazy-loading to keep load time down.
+      require 'rubocop/options'
+
+      @name = args.shift || :rubocop
+      @verbose = true
+      @fail_on_error = true
+      @patterns = []
+      @requires = []
+      @options = []
+      @formatters = [Rubocop::Options::DEFAULT_FORMATTER]
+    end
+  end
+end
diff --git a/lib/rubocop/source_parser.rb b/lib/rubocop/source_parser.rb
new file mode 100644
index 0000000..c27dc33
--- /dev/null
+++ b/lib/rubocop/source_parser.rb
@@ -0,0 +1,47 @@
+# encoding: utf-8
+
+module Rubocop
+  # SourceParser provides a way to parse Ruby source with Parser gem
+  # and also parses comment directives which disable arbitrary cops.
+  module SourceParser
+    module_function
+
+    def parse_file(path)
+      parse(File.read(path), path)
+    end
+
+    def parse(string, name = '(string)')
+      source_buffer = Parser::Source::Buffer.new(name, 1)
+      source_buffer.source = string
+
+      parser = create_parser
+      diagnostics = []
+      parser.diagnostics.consumer = lambda do |diagnostic|
+        diagnostics << diagnostic
+      end
+
+      begin
+        ast, comments, tokens = parser.tokenize(source_buffer)
+      rescue Parser::SyntaxError # rubocop:disable HandleExceptions
+        # All errors are in diagnostics. No need to handle exception.
+      end
+
+      tokens = tokens.map { |t| Token.from_parser_token(t) } if tokens
+
+      ProcessedSource.new(source_buffer, ast, comments, tokens, diagnostics)
+    end
+
+    def create_parser
+      parser = Parser::CurrentRuby.new
+
+      # On JRuby and Rubinius, there's a risk that we hang in tokenize() if we
+      # don't set the all errors as fatal flag. The problem is caused by a bug
+      # in Racc that is discussed in issue #93 of the whitequark/parser project
+      # on GitHub.
+      parser.diagnostics.all_errors_are_fatal = RUBY_ENGINE != 'ruby'
+      parser.diagnostics.ignore_warnings      = false
+
+      parser
+    end
+  end
+end
diff --git a/lib/rubocop/target_finder.rb b/lib/rubocop/target_finder.rb
new file mode 100644
index 0000000..46233cd
--- /dev/null
+++ b/lib/rubocop/target_finder.rb
@@ -0,0 +1,91 @@
+# encoding: utf-8
+
+module Rubocop
+  # This class finds target files to inspect by scanning the directory tree
+  # and picking ruby files.
+  class TargetFinder
+    def initialize(config_store, options = {})
+      @config_store = config_store
+      @options = { force_exclusion: false, debug: false }.merge(options)
+    end
+
+    def force_exclusion?
+      @options[:force_exclusion]
+    end
+
+    def debug?
+      @options[:debug]
+    end
+
+    # Generate a list of target files by expanding globbing patterns
+    # (if any). If args is empty, recursively find all Ruby source
+    # files under the current directory
+    # @return [Array] array of file paths
+    def find(args)
+      return target_files_in_dir if args.empty?
+
+      files = []
+
+      args.uniq.each do |arg|
+        files += if File.directory?(arg)
+                   target_files_in_dir(arg.chomp(File::SEPARATOR))
+                 else
+                   process_explicit_path(arg)
+                 end
+      end
+
+      files.map { |f| File.expand_path(f) }.uniq
+    end
+
+    # Finds all Ruby source files under the current or other supplied
+    # directory.  A Ruby source file is defined as a file with the `.rb`
+    # extension or a file with no extension that has a ruby shebang line
+    # as its first line.
+    # It is possible to specify includes and excludes using the config file,
+    # so you can include other Ruby files like Rakefiles and gemspecs.
+    # @param base_dir Root directory under which to search for
+    #   ruby source files
+    # @return [Array] Array of filenames
+    def target_files_in_dir(base_dir = Dir.pwd)
+      # Support Windows: Backslashes from command-line -> forward slashes
+      if File::ALT_SEPARATOR
+        base_dir.gsub!(File::ALT_SEPARATOR, File::SEPARATOR)
+      end
+      files = Dir["#{base_dir}/**/*"].select { |path| FileTest.file?(path) }
+      base_dir_config = @config_store.for(base_dir)
+
+      target_files = files.select do |file|
+        next false if base_dir_config.file_to_exclude?(file)
+        next true if File.extname(file) == '.rb'
+        next true if ruby_executable?(file)
+        @config_store.for(file).file_to_include?(file)
+      end
+
+      target_files
+    end
+
+    def ruby_executable?(file)
+      return false unless File.extname(file).empty?
+      first_line = File.open(file) { |f| f.readline }
+      first_line =~ /#!.*ruby/
+    rescue EOFError, ArgumentError => e
+      warn "Unprocessable file #{file}: #{e.class}, #{e.message}" if debug?
+      false
+    end
+
+    def process_explicit_path(path)
+      files = if path.include?('*')
+                Dir[path]
+              else
+                [path]
+              end
+
+      return files unless force_exclusion?
+
+      files.reject do |file|
+        config = @config_store.for(file)
+        config.file_to_exclude?(file)
+      end
+    end
+  end
+end
diff --git a/lib/rubocop/token.rb b/lib/rubocop/token.rb
new file mode 100644
index 0000000..2a1677c
--- /dev/null
+++ b/lib/rubocop/token.rb
@@ -0,0 +1,22 @@
+# encoding: utf-8
+
+module Rubocop
+  # A basic wrapper around Parser's tokens.
+  class Token
+    attr_reader :pos, :type, :text
+
+    def self.from_parser_token(parser_token)
+      type, details = *parser_token
+      text, range = *details
+      new(range, type, text)
+    end
+
+    def initialize(pos, type, text)
+      @pos, @type, @text = pos, type, text
+    end
+
+    def to_s
+      "[[#{@pos.line}, #{@pos.column}], #{@type}, #{@text.inspect}]"
+    end
+  end
+end
diff --git a/lib/rubocop/version.rb b/lib/rubocop/version.rb
new file mode 100644
index 0000000..075be93
--- /dev/null
+++ b/lib/rubocop/version.rb
@@ -0,0 +1,21 @@
+# encoding: utf-8
+
+module Rubocop
+  # This module holds the RuboCop version information.
+  module Version
+    STRING = '0.20.1'
+
+    MSG = '%s (using Parser %s, running on %s %s %s)'
+
+    module_function
+
+    def version(debug = false)
+      if debug
+        format(MSG, STRING, Parser::VERSION,
+               RUBY_ENGINE, RUBY_VERSION, RUBY_PLATFORM)
+      else
+        STRING
+      end
+    end
+  end
+end
diff --git a/relnotes/v0.19.0.md b/relnotes/v0.19.0.md
new file mode 100644
index 0000000..1b81f09
--- /dev/null
+++ b/relnotes/v0.19.0.md
@@ -0,0 +1,94 @@
+This is the biggest RuboCop release we've done in a while. The highlights include
+about a dozen new cops, more cop configuration options, improved auto-correct and so many bugfixes.
+
+You'll might note that we changed the use of `offence` with `offense`. This was done to keep the spelling
+in our code consistent. Hopefully this won't cause anyone problems, but we're obliged to mention it as
+the `Offence` class itself got renamed.
+
+Below is the list of all the gory details. Enjoy!
+
+## RuboCop 0.19.0
+
+### New features
+
+* New cop `FileName` makes sure that source files have snake_case names. ([@bbatsov][])
+* New cop `DeprecatedClassMethods` checks for deprecated class methods. ([@bbatsov][])
+* New cop `StringConversionInInterpolation` checks for redundant `Object#to_s` in string interpolation. ([@bbatsov][])
+* New cop `LiteralInInterpolation` checks for interpolated string literals. ([@bbatsov][])
+* New cop `SelfAssignment` checks for places where the self-assignment shorthand should have been used. ([@bbatsov][])
+* New cop `DoubleNegation` checks for uses of `!!`. ([@bbatsov][])
+* New cop `PercentLiteralDelimiters` enforces consistent usage of `%`-literal delimiters. ([@hannestyden][])
+* New Rails cop `ActionFilter` enforces the use of `_filter` or `_action` action filter methods. ([@bbatsov][])
+* New Rails cop `ScopeArgs` makes sure you invoke the `scope` method properly. ([@bbatsov][])
+* Add `with_fixed_indentation` style to `AlignParameters` cop. ([@hannestyden][])
+* Add `IgnoreLastArgumentHash` option to `AlignHash` cop. ([@hannestyden][])
+* [#743](https://github.com/bbatsov/rubocop/issues/743): `SingleLineMethods` cop does auto-correction. ([@jonas054][])
+* [#743](https://github.com/bbatsov/rubocop/issues/743): `Semicolon` cop does auto-correction. ([@jonas054][])
+* [#743](https://github.com/bbatsov/rubocop/issues/743): `EmptyLineBetweenDefs` cop does auto-correction. ([@jonas054][])
+* [#743](https://github.com/bbatsov/rubocop/issues/743): `IndentationWidth` cop does auto-correction. ([@jonas054][])
+* [#743](https://github.com/bbatsov/rubocop/issues/743): `IndentationConsistency` cop does auto-correction. ([@jonas054][])
+* [#809](https://github.com/bbatsov/rubocop/issues/809): New formatter `fuubar` displays a progress bar and shows details of offenses as soon as they are detected. ([@yujinakayama][])
+* [#797](https://github.com/bbatsov/rubocop/issues/797): New cop `IndentHash` checks the indentation of the first key in multi-line hash literals. ([@jonas054][])
+* [#797](https://github.com/bbatsov/rubocop/issues/797): New cop `IndentArray` checks the indentation of the first element in multi-line array literals. ([@jonas054][])
+* [#806](https://github.com/bbatsov/rubocop/issues/806): Now excludes files in `vendor/**` by default. ([@jeremyolliver][])
+* [#795](https://github.com/bbatsov/rubocop/issues/795): `IfUnlessModifier` and `WhileUntilModifier` supports `MaxLineLength`, which is independent of `LineLength` parameter `Max`. ([@agrimm][])
+* [#868](https://github.com/bbatsov/rubocop/issues/868): New cop `ClassAndModuleChildren` checks the style of children definitions at classes and modules: nested / compact. ([@geniou][])
+
+### Changes
+
+* [#793](https://github.com/bbatsov/rubocop/issues/793): Add printing total count when `rubocop --format offences`. ([@ma2gedev][])
+* Remove `Ignore` param from the Rails `Output` cop. The standard `Exclude/Include` should be used instead. ([@bbatsov][])
+* Renamed `FavorSprintf` to `FormatString` and made it configurable. ([@bbatsov][])
+* Renamed `Offence` to `Offense`. ([@bbatsov][])
+* Use `offense` in all messages instead of `offence`. ([@bbatsov][])
+* For indentation of `if`/`unless`/`while`/`until` bodies when the result is assigned to a variable, instead of supporting two styles simultaneously, `IndentationWidth` now supports one style of indentation at a time, specified by `EndAlignment`/`AlignWith`. ([@jonas054][])
+* Renamed `Style` param of `DotPosition` cop to `EnforcedStyle`. ([@bbatsov][])
+* Add `length` value to locations of offense in JSON formatter. ([@yujinakayama][])
+* `SpaceAroundBlockBraces` cop replaced by `SpaceBeforeBlockBraces` and `SpaceInsideBlockBraces`. ([@jonas054][])
+* `SpaceAroundEqualsInParameterDefault` cop is now configurable with the `EnforcedStyle` option. ([@jonas054][])
+
+### Bugs fixed
+
+* [#790](https://github.com/bbatsov/rubocop/issues/790): Fix auto-correction interference problem between `MethodDefParentheses` and other cops. ([@jonas054][])
+* [#794](https://github.com/bbatsov/rubocop/issues/794): Fix handling of modifier keywords with required parentheses in `ParenthesesAroundCondition`. ([@bbatsov][])
+* [#804](https://github.com/bbatsov/rubocop/issues/804): Fix a false positive with operator assignments in a loop (including `begin..rescue..end` with `retry`) in `UselessAssignment`. ([@yujinakayama][])
+* [#815](https://github.com/bbatsov/rubocop/issues/815): Fix a false positive for heredocs with blank lines in them in `EmptyLines`. ([@bbatsov][])
+* Auto-correction is now more robust and less likely to die because of `RangeError` or "clobbering". ([@jonas054][])
+* Offenses always reported in order of position in file, also during `--auto-correct` runs. ([@jonas054][])
+* Fix problem with `[Corrected]` tag sometimes missing in output from `--auto-correct` runs. ([@jonas054][])
+* Fix message from `EndAlignment` cop when `AlignWith` is `keyword`. ([@jonas054][])
+* Handle `case` conditions in `LiteralInCondition`. ([@bbatsov][])
+* [#822](https://github.com/bbatsov/rubocop/issues/822): Fix a false positive in `DotPosition` when enforced style is set to `trailing`. ([@bbatsov][])
+* Handle properly dynamic strings in `LineEndConcatenation`. ([@bbatsov][])
+* [#832](https://github.com/bbatsov/rubocop/issues/832): Fix auto-correction interference problem between `BracesAroundHashParameters` and `SpaceInsideHashLiteralBraces`. ([@jonas054][])
+* Fix bug in auto-correction of alignment so that only space can be removed. ([@jonas054][])
+* Fix bug in `IndentationWidth` auto-correction so it doesn't correct things that `IndentationConsistency` should correct. ([@jonas054][])
+* [#847](https://github.com/bbatsov/rubocop/issues/847): Fix bug in `RegexpLiteral` concerning `--auto-gen-config`. ([@jonas054][])
+* [#848](https://github.com/bbatsov/rubocop/issues/848): Fix bug in `--show-cops` that made it print the default configuration rather than the current configuration. ([@jonas054][])
+* [#862](https://github.com/bbatsov/rubocop/issues/862): Fix a bug where single line `rubocop:disable` comments with indentations were treated as multiline cop disabling comments. ([@yujinakayama][])
+* Fix a bug where `rubocop:disable` comments with a cop name including `all` (e.g. `MethodCallParentheses`) were disabling all cops. ([@yujinakayama][])
+* Fix a bug where string and regexp literals including `# rubocop:disable` were confused with real comments. ([@yujinakayama][])
+
+[@bbatsov]: https://github.com/bbatsov
+[@jonas054]: https://github.com/jonas054
+[@yujinakayama]: https://github.com/yujinakayama
+[@dblock]: https://github.com/dblock
+[@nevir]: https://github.com/nevir
+[@daviddavis]: https://github.com/daviddavis
+[@sds]: https://github.com/sds
+[@fancyremarker]: https://github.com/fancyremarker
+[@sinisterchipmunk]: https://github.com/sinisterchipmunk
+[@vonTronje]: https://github.com/vonTronje
+[@agrimm]: https://github.com/agrimm
+[@pmenglund]: https://github.com/pmenglund
+[@chulkilee]: https://github.com/chulkilee
+[@codez]: https://github.com/codez
+[@emou]: https://github.com/emou
+[@skanev]: http://github.com/skanev
+[@claco]: http://github.com/claco
+[@rifraf]: http://github.com/rifraf
+[@scottmatthewman]: https://github.com/scottmatthewman
+[@ma2gedev]: http://github.com/ma2gedev
+[@jeremyolliver]: https://github.com/jeremyolliver
+[@hannestyden]: https://github.com/hannestyden
+[@geniou]: https://github.com/geniou
diff --git a/relnotes/v0.19.1.md b/relnotes/v0.19.1.md
new file mode 100644
index 0000000..b5ca81d
--- /dev/null
+++ b/relnotes/v0.19.1.md
@@ -0,0 +1,16 @@
+RuboCop 0.19.1 is a bugfix-only release. Below is a list of the bugs we've fixed since 0.19.0:
+
+### Bugs fixed
+
+* [#884](https://github.com/bbatsov/rubocop/issues/884): Fix --auto-gen-config for `NumericLiterals` so MinDigits is correct. ([@tmorris-fiksu][])
+* [#879](https://github.com/bbatsov/rubocop/issues/879): Fix --auto-gen-config for `RegexpLiteral` so we don't generate illegal values for `MaxSlashes`. ([@jonas054][])
+* Fix the name of the `Include` param in the default config of the Rails cops. ([@bbatsov][])
+* [#878](https://github.com/bbatsov/rubocop/pull/878): Blacklist `Rakefile`, `Gemfile` and `Capfile` by default in the `FileName` cop. ([@bbatsov][])
+* [#875](https://github.com/bbatsov/rubocop/issues/875): Handle `separator` style hashes in `IndentHash`. ([@jonas054][])
+* Fix a bug where multiple cli options that result in exit can be specified at once (e.g. `-vV`, `-v --show-cops`). ([@jkogara][])
+* [#889](https://github.com/bbatsov/rubocop/issues/889): Fix a false positive for `LiteralInCondition` when the condition is non-primitive array. ([@bbatsov][])
+
+[@bbatsov]: https://github.com/bbatsov
+[@jonas054]: https://github.com/jonas054
+[@jkogara]: https://github.com/jkogara
+[@tmorris-fiksu]: https://github.com/tmorris-fiksu
diff --git a/relnotes/v0.20.0.md b/relnotes/v0.20.0.md
new file mode 100644
index 0000000..ab2d4c9
--- /dev/null
+++ b/relnotes/v0.20.0.md
@@ -0,0 +1,69 @@
+There aren't many exciting new features this time around - our focus in 0.20 has been fixing most of the problems we
+introduced in 0.19. Apart from that we've added a few new cops and implemented auto-correct for a bunch of the existing cops.
+You'll also notice that the messages produced by most formatters a bit more colorful (and hopefully more readable as well).
+
+You should also note that `AllCops/Includes` and `AllCops/Excludes` have been renamed, so you'll have to update your config files
+accordingly.
+
+Below is the list of all the gory details. Enjoy!
+
+### New features
+
+* New cop `GuardClause` checks for conditionals that can be replaced by guard clauses. ([@bbatsov][])
+* New cop `EmptyInterpolation` checks for empty interpolation in double-quoted strings. ([@bbatsov][])
+* [#899](https://github.com/bbatsov/rubocop/issues/899): Make `LineEndConcatenation` cop `<<` aware. ([@mockdeep][])
+* [#896](https://github.com/bbatsov/rubocop/issues/896): New option `--fail-level` changes minimum severity for exit with error code. ([@hiroponz][])
+* [#893](https://github.com/bbatsov/rubocop/issues/893): New option `--force-exclusion` forces excluding files specified in the configuration `Exclude` even if they are explicitly passed as arguments. ([@yujinakayama][])
+* `VariableInterpolation` cop does auto-correction. ([@bbatsov][])
+* `Not` cop does auto-correction. ([@bbatsov][])
+* `ClassMethods` cop does auto-correction. ([@bbatsov][])
+* `StringConversionInInterpolation` cop does auto-correction. ([@bbatsov][])
+* `NilComparison` cop does auto-correction. ([@bbatsov][])
+* `NonNilComparison` cop does auto-correction. ([@bbatsov][])
+* `NegatedIf` cop does auto-correction. ([@bbatsov][])
+* `NegatedWhile` cop does auto-correction. ([@bbatsov][])
+* New lint cop `SpaceBeforeFirstArg` checks for space between the method name and the first argument in method calls without parentheses. ([@jonas054][])
+* New style cop `SingleSpaceBeforeFirstArg` checks that no more than one space is used between the method name and the first argument in method calls without parentheses. ([@jonas054][])
+* New formatter `disabled_lines` displays cops and line ranges disabled by inline comments. ([@fshowalter][])
+* New cop `UselessAccessModifiers` checks for access modifiers that have no effect. ([@fshowalter][])
+
+### Changes
+
+* [#913](https://github.com/bbatsov/rubocop/issues/913): `FileName` accepts multiple extensions. ([@tamird][])
+* `AllCops/Excludes` and `AllCops/Includes` were renamed to `AllCops/Exclude` and `AllCops/Include` for consistency with standard cop params. ([@bbatsov][])
+* Extract `NonNilCheck` cop from `NilComparison`. ([@bbatsov][])
+* Renamed `FavorJoin` to `ArrayJoin`. ([@bbatsov][])
+* Renamed `FavorUnlessOverNegatedIf` to `NegatedIf`. ([@bbatsov][])
+* Renamed `FavorUntilOverNegatedWhile`to `NegatedWhile`. ([@bbatsov][])
+* Renamed `HashMethods` to `DeprecatedHashMethods`. ([@bbatsov][])
+* Renamed `ReadAttribute` to `ReadWriteAttribute` and extended it to check for uses of `write_attribute`. ([@bbatsov][])
+* Add experimental support for Ruby 2.2 (development version) by falling back to Ruby 2.1 parser. ([@yujinakayama][])
+
+### Bugs fixed
+
+* [#926](https://github.com/bbatsov/rubocop/issues/926): Fixed `BlockNesting` not auto-generating correctly. ([@tmorris-fiksu][])
+* [#904](https://github.com/bbatsov/rubocop/issues/904): Fixed a NPE in `LiteralInInterpolation`. ([@bbatsov][])
+* [#904](https://github.com/bbatsov/rubocop/issues/904): Fixed a NPE in `StringConversionInInterpolation`. ([@bbatsov][])
+* [#892](https://github.com/bbatsov/rubocop/issues/892): Make sure `Include` and `Exclude` paths in a `.rubocop.yml` are interpreted as relative to the directory of that file. ([@jonas054][])
+* [#906](https://github.com/bbatsov/rubocop/issues/906): Fixed a false positive in `LiteralInInterpolation`. ([@bbatsov][])
+* [#909](https://github.com/bbatsov/rubocop/issues/909): Handle properly multiple `rescue` clauses in `SignalException`. ([@bbatsov][])
+* [#876](https://github.com/bbatsov/rubocop/issues/876): Do a deep merge of hashes when overriding default configuration in a `.rubocop.yml` file. ([@jonas054][])
+* [#912](https://github.com/bbatsov/rubocop/issues/912): Fix a false positive in `LineEndConcatenation` for `%` string literals. ([@bbatsov][])
+* [#912](https://github.com/bbatsov/rubocop/issues/912): Handle top-level constant resolution in `DeprecatedClassMethods` (e.g. `::File.exists?`). ([@bbatsov][])
+* [#914](https://github.com/bbatsov/rubocop/issues/914): Fixed rdoc error during gem installation. ([@bbatsov][])
+* The `--only` option now enables the given cop in case it is disabled in configuration. ([@jonas054][])
+* Fix path resolution so that the default exclusion of `vendor` directories works. ([@jonas054][])
+* [#908](https://github.com/bbatsov/rubocop/issues/908): Fixed hanging while auto correct for `SpaceAfterComma` and `SpaceInsideBrackets`. ([@hiroponz][])
+* [#919](https://github.com/bbatsov/rubocop/issues/919): Don't avoid auto-correction in `HashSyntax` when there is missing space around operator. ([@jonas054][])
+* Fixed handling of floats in `NumericLiterals`. ([@bbatsov][])
+* [#927](https://github.com/bbatsov/rubocop/issues/927): Let `--auto-gen-config` overwrite an existing `rubocop-todo.yml` file instead of asking the user to remove it. ([@jonas054][])
+* [#936](https://github.com/bbatsov/rubocop/issues/936): Allow `_other` as well as `other` in `OpMethod`. ([@bbatsov][])
+
+[@bbatsov]: https://github.com/bbatsov
+[@jonas054]: https://github.com/jonas054
+[@yujinakayama]: https://github.com/yujinakayama
+[@tmorris-fiksu]: https://github.com/tmorris-fiksu
+[@mockdeep]: https://github.com/mockdeep
+[@hiroponz]: https://github.com/hiroponz
+[@tamird]: https://github.com/tamird
+[@fshowalter]: https://github.com/fshowalter
diff --git a/relnotes/v0.20.1.md b/relnotes/v0.20.1.md
new file mode 100644
index 0000000..c5d8115
--- /dev/null
+++ b/relnotes/v0.20.1.md
@@ -0,0 +1,24 @@
+RuboCop 0.20.1 is a bugfix-only release. Below is a list of the bugs we've fixed since 0.20.0:
+
+## 0.20.1 (05/04/2014)
+
+### Bugs fixed
+
+* [#940](https://github.com/bbatsov/rubocop/issues/940): Fixed `UselessAccessModifier` not handling `attr_*` correctly. ([@fshowalter][])
+* `NegatedIf` properly handles negated `unless` condition. ([@bbatsov][])
+* `NegatedWhile` properly handles negated `until` condition. ([@bbatsov][])
+* [#925](https://github.com/bbatsov/rubocop/issues/925): Do not disable the `Syntax` cop in output from `--auto-gen-config`. ([@jonas054][])
+* [#943](https://github.com/bbatsov/rubocop/issues/943): Fix auto-correction interference problem between `SpaceAfterComma` and other cops. ([@jonas054][])
+* [#954](https://github.com/bbatsov/rubocop/pull/954): Fix auto-correction bug in `NilComparison`. ([@bbatsov][])
+* [#953](https://github.com/bbatsov/rubocop/pull/953): Fix auto-correction bug in `NonNilCheck`. ([@bbatsov][])
+* [#952](https://github.com/bbatsov/rubocop/pull/952): Handle implicit receiver in `StringConversionInInterpolation`. ([@bbatsov][])
+* [#956](https://github.com/bbatsov/rubocop/pull/956): Apply `ClassMethods` check only on `class`/`module` bodies. ([@bbatsov][])
+* [#945](https://github.com/bbatsov/rubocop/issues/945): Fix SpaceBeforeFirstArg cop for multiline argument and exclude assignments. ([@cschramm][])
+* [#948](https://github.com/bbatsov/rubocop/issues/948): `Blocks` cop avoids auto-correction if it would introduce a semantic change. ([@jonas054][])
+* [#946](https://github.com/bbatsov/rubocop/issues/946): Allow non-nil checks that are the final expressions of predicate method definitions in `NonNilCheck`. ([@bbatsov][])
+* [#957](https://github.com/bbatsov/rubocop/issues/957): Allow space + comment inside parentheses, braces, and square brackets. ([@jonas054][])
+
+[@bbatsov]: https://github.com/bbatsov
+[@jonas054]: https://github.com/jonas054
+[@fshowalter]: https://github.com/fshowalter
+[@cschramm]: https://github.com/cschramm
diff --git a/rubocop-todo.yml b/rubocop-todo.yml
new file mode 100644
index 0000000..4728290
--- /dev/null
+++ b/rubocop-todo.yml
@@ -0,0 +1,20 @@
+# This configuration was generated by `rubocop --auto-gen-config`
+# on 2014-03-01 12:00:46 +1100 using RuboCop version 0.18.1.
+# The point is for the user to remove these configuration records
+# one by one as the offenses are removed from the code base.
+# Note that changes in the inspected code, or installation of new
+# versions of RuboCop, may require this file to be generated again.
+
+# Offense count: 6
+# Configuration parameters: CountComments.
+ClassLength:
+  Max: 146
+
+# Offense count: 16
+CyclomaticComplexity:
+  Max: 10
+
+# Offense count: 105
+# Configuration parameters: CountComments.
+MethodLength:
+  Max: 22
diff --git a/rubocop.gemspec b/rubocop.gemspec
new file mode 100644
index 0000000..cc5721d
--- /dev/null
+++ b/rubocop.gemspec
@@ -0,0 +1,39 @@
+# encoding: utf-8
+
+$LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
+require 'rubocop/version'
+require 'English'
+
+Gem::Specification.new do |s|
+  s.name = 'rubocop'
+  s.version = Rubocop::Version::STRING
+  s.platform = Gem::Platform::RUBY
+  s.required_ruby_version = '>= 1.9.2'
+  s.authors = ['Bozhidar Batsov']
+  s.description = <<-EOF
+    Automatic Ruby code style checking tool.
+    Aims to enforce the community-driven Ruby Style Guide.
+  EOF
+
+  s.email = 'bozhidar at batsov.com'
+  s.files = `git ls-files`.split($RS)
+  s.test_files = s.files.grep(/^spec\//)
+  s.executables = s.files.grep(/^bin\//) { |f| File.basename(f) }
+  s.extra_rdoc_files = ['LICENSE.txt', 'README.md']
+  s.homepage = 'http://github.com/bbatsov/rubocop'
+  s.licenses = ['MIT']
+  s.require_paths = ['lib']
+  s.rubygems_version = '1.8.23'
+  s.summary = 'Automatic Ruby code style checking tool.'
+
+  s.add_runtime_dependency('rainbow', '>= 1.99.1', '< 3.0')
+  s.add_runtime_dependency('parser', '~> 2.1.7')
+  s.add_runtime_dependency('powerpack', '~> 0.0.6')
+  s.add_runtime_dependency('json', '>= 1.7.7', '< 2')
+  s.add_runtime_dependency('ruby-progressbar', '~> 1.4')
+  s.add_development_dependency('rake', '~> 10.1')
+  s.add_development_dependency('rspec', '~> 2.14')
+  s.add_development_dependency('yard', '~> 0.8')
+  s.add_development_dependency('bundler', '~> 1.3')
+  s.add_development_dependency('simplecov', '~> 0.7')
+end
diff --git a/spec/.rubocop.yml b/spec/.rubocop.yml
new file mode 100644
index 0000000..98fc057
--- /dev/null
+++ b/spec/.rubocop.yml
@@ -0,0 +1,5 @@
+inherit_from: ../.rubocop.yml
+
+# The documentation check doesn't make sense for test code
+Documentation:
+  Enabled: false
diff --git a/spec/isolated_environment_spec.rb b/spec/isolated_environment_spec.rb
new file mode 100644
index 0000000..8cf69a9
--- /dev/null
+++ b/spec/isolated_environment_spec.rb
@@ -0,0 +1,24 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe 'isolated environment', :isolated_environment do
+  include FileHelper
+
+  let(:cli) { Rubocop::CLI.new }
+
+  before(:each) { $stdout = StringIO.new }
+  after(:each) { $stdout = STDOUT }
+
+  # Configuration files above the work directory shall not disturb the
+  # tests. This is especially important on Windows where the temporary
+  # directory is under the user's home directory. On any platform we don't want
+  # a .rubocop.yml file in the temporary directory to affect the outcome of
+  # rspec.
+  it 'is not affected by a config file above the work directory' do
+    create_file('../.rubocop.yml', ['inherit_from: missing_file.yml'])
+    create_file('ex.rb', ['# encoding: utf-8'])
+    # A return value of 0 means that the erroneous config file was not read.
+    expect(cli.run([])).to eq(0)
+  end
+end
diff --git a/spec/project_spec.rb b/spec/project_spec.rb
new file mode 100644
index 0000000..41bb356
--- /dev/null
+++ b/spec/project_spec.rb
@@ -0,0 +1,118 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe 'RuboCop Project' do
+  describe 'default configuration file' do
+    let(:cop_names) { Rubocop::Cop::Cop.all.map(&:cop_name) }
+
+    subject(:default_config) do
+      Rubocop::ConfigLoader.load_file('config/default.yml')
+    end
+
+    it 'has configuration for all cops' do
+      expect(default_config.keys.sort).to eq((['AllCops'] + cop_names).sort)
+    end
+
+    it 'has a nicely formatted description for all cops' do
+      cop_names.each do |name|
+        description = default_config[name]['Description']
+        expect(description).not_to be_nil
+        expect(description).not_to include("\n")
+      end
+    end
+  end
+
+  describe 'changelog' do
+    subject(:changelog) do
+      path = File.join(File.dirname(__FILE__), '..', 'CHANGELOG.md')
+      File.read(path)
+    end
+
+    it 'has link definitions for all implicit links' do
+      implicit_link_names = changelog.scan(/\[([^\]]+)\]\[\]/).flatten.uniq
+      implicit_link_names.each do |name|
+        expect(changelog).to include("[#{name}]: http")
+      end
+    end
+
+    describe 'entry' do
+      subject(:entries) { lines.grep(/^\*/).map(&:chomp) }
+      let(:lines) { changelog.each_line }
+
+      it 'has a whitespace between the * and the body' do
+        entries.each do |entry|
+          expect(entry).to match(/^\* \S/)
+        end
+      end
+
+      context 'after version 0.14.0' do
+        let(:lines) do
+          changelog.each_line.take_while do |line|
+            !line.start_with?('## 0.14.0')
+          end
+        end
+
+        it 'has a link to the contributors at the end' do
+          entries.each do |entry|
+            expect(entry).to match(/\(\[@\S+\]\[\](?:, \[@\S+\]\[\])*\)$/)
+          end
+        end
+      end
+
+      describe 'link to related issue' do
+        let(:issues) do
+          entries.map do |entry|
+            entry.match(/\[(?<number>[#\d]+)\]\((?<url>[^\)]+)\)/)
+          end.compact
+        end
+
+        it 'has an issue number prefixed with #' do
+          issues.each do |issue|
+            expect(issue[:number]).to match(/^#\d+$/)
+          end
+        end
+
+        it 'has a valid URL' do
+          issues.each do |issue|
+            number = issue[:number].gsub(/\D/, '')
+            pattern = %r{^https://github\.com/bbatsov/rubocop/(?:issues|pull)/#{number}$} # rubocop:disable LineLength
+            expect(issue[:url]).to match(pattern)
+          end
+        end
+
+        it 'has a colon and a whitespace at the end' do
+          entries_including_issue_link = entries.select do |entry|
+            entry.match(/^\*\s*\[/)
+          end
+
+          entries_including_issue_link.each do |entry|
+            expect(entry).to include('): ')
+          end
+        end
+      end
+
+      describe 'body' do
+        let(:bodies) do
+          entries.map do |entry|
+            entry
+              .sub(/^\*\s*(?:\[.+?\):\s*)?/, '')
+              .sub(/\s*\([^\)]+\)$/, '')
+          end
+        end
+
+        it 'does not start with a lower case' do
+          bodies.each do |body|
+            expect(body).not_to match(/^[a-z]/)
+          end
+        end
+
+        it 'ends with a punctuation' do
+          bodies.each do |body|
+            expect(body).to match(/[\.\!]$/)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/cli_spec.rb b/spec/rubocop/cli_spec.rb
new file mode 100644
index 0000000..17cfa53
--- /dev/null
+++ b/spec/rubocop/cli_spec.rb
@@ -0,0 +1,1830 @@
+# encoding: utf-8
+
+require 'fileutils'
+require 'tmpdir'
+require 'spec_helper'
+require 'timeout'
+
+describe Rubocop::CLI, :isolated_environment do
+  include FileHelper
+
+  subject(:cli) { described_class.new }
+
+  before(:each) do
+    $stdout = StringIO.new
+    $stderr = StringIO.new
+    Rubocop::ConfigLoader.debug = false
+  end
+
+  after(:each) do
+    $stdout = STDOUT
+    $stderr = STDERR
+  end
+
+  def abs(path)
+    File.expand_path(path)
+  end
+
+  describe 'option' do
+    describe '--version' do
+      it 'exits cleanly' do
+        expect { cli.run ['-v'] }.to exit_with_code(0)
+        expect { cli.run ['--version'] }.to exit_with_code(0)
+        expect($stdout.string).to eq((Rubocop::Version::STRING + "\n") * 2)
+      end
+    end
+
+    describe '--auto-correct' do
+      it 'can correct two problems with blocks' do
+        # {} should be do..end and space is missing.
+        create_file('example.rb', ['# encoding: utf-8',
+                                   '(1..10).each{ |i|',
+                                   '  puts i',
+                                   '}'])
+        expect(cli.run(['--auto-correct'])).to eq(1)
+        expect(IO.read('example.rb'))
+          .to eq(['# encoding: utf-8',
+                  '(1..10).each do |i|',
+                  '  puts i',
+                  'end'].join("\n") + "\n")
+      end
+
+      it 'can handle spaces when removing braces' do
+        create_file('example.rb',
+                    ['# encoding: utf-8',
+                     "assert_post_status_code 400, 's', {:type => 'bad'}"])
+        expect(cli.run(%w(--auto-correct --format emacs))).to eq(1)
+        expect(IO.read('example.rb'))
+          .to eq(['# encoding: utf-8',
+                  "assert_post_status_code 400, 's', type: 'bad'",
+                  ''].join("\n"))
+        e = abs('example.rb')
+        expect($stdout.string)
+          .to eq(["#{e}:2:35: C: [Corrected] Redundant curly braces around " \
+                  "a hash parameter.",
+                  "#{e}:2:35: C: [Corrected] Use the new Ruby 1.9 hash " \
+                  "syntax.",
+                  # TODO: Don't report that a problem is corrected when it
+                  # actually went away due to another correction.
+                  "#{e}:2:35: C: [Corrected] Space inside { missing.",
+                  # TODO: Don't report duplicates (HashSyntax in this case).
+                  "#{e}:2:36: C: [Corrected] Use the new Ruby 1.9 hash " \
+                  "syntax.",
+                  "#{e}:2:50: C: [Corrected] Space inside } missing.",
+                  ''].join("\n"))
+      end
+
+      # A case where two cops, EmptyLinesAroundBody and EmptyLines, try to
+      # remove the same line in autocorrect.
+      it 'can correct two empty lines at end of class body' do
+        create_file('example.rb', ['class Test',
+                                   '  def f',
+                                   '  end',
+                                   '',
+                                   '',
+                                   'end'])
+        expect(cli.run(['--auto-correct'])).to eq(1)
+        expect($stderr.string).to eq('')
+        expect(IO.read('example.rb')).to eq(['class Test',
+                                             '  def f',
+                                             '  end',
+                                             'end'].join("\n") + "\n")
+      end
+
+      # A case where WordArray's correction can be clobbered by
+      # AccessModifierIndentation's correction.
+      it 'can correct indentation and another thing' do
+        create_file('example.rb', ['# encoding: utf-8',
+                                   'class Dsl',
+                                   'private',
+                                   '  A = ["git", "path"]',
+                                   'end'])
+        expect(cli.run(%w(--auto-correct --format emacs))).to eq(1)
+        expect(IO.read('example.rb')).to eq(['# encoding: utf-8',
+                                             'class Dsl',
+                                             '  private',
+                                             '  A = %w(git path)',
+                                             'end'].join("\n") + "\n")
+        e = abs('example.rb')
+        expect($stdout.string)
+          .to eq(["#{e}:2:1: C: Missing top-level class documentation " \
+                  'comment.',
+                  "#{e}:3:1: C: [Corrected] Indent access modifiers like " \
+                  '`private`.',
+                  "#{e}:3:1: C: Keep a blank line before and after `private`.",
+                  "#{e}:3:1: W: Useless `private` access modifier.",
+                  # An offense that moves around during auto-correction will
+                  # appear to be duplicated:
+                  "#{e}:3:3: C: Keep a blank line before and after `private`.",
+                  "#{e}:3:3: W: Useless `private` access modifier.",
+                  "#{e}:4:7: C: [Corrected] Use `%w` or `%W` " \
+                  'for array of words.',
+                  "#{e}:4:8: C: [Corrected] Prefer single-quoted strings " \
+                  "when you don't need string interpolation or special " \
+                  'symbols.',
+                  # Another instance of the same offense reported twice:
+                  "#{e}:4:15: C: [Corrected] Prefer single-quoted strings " \
+                  "when you don't need string interpolation or special " \
+                  'symbols.',
+                  ''].join("\n"))
+      end
+
+      # A case where the same cop could try to correct an offense twice in one
+      # place.
+      it 'can correct empty line inside special form of nested modules' do
+        create_file('example.rb', ['module A module B',
+                                   '',
+                                   'end end'])
+        expect(cli.run(['--auto-correct'])).to eq(1)
+        expect(IO.read('example.rb')).to eq(['module A module B',
+                                             'end end'].join("\n") + "\n")
+      end
+
+      it 'can correct single line methods' do
+        create_file('example.rb', ['# encoding: utf-8',
+                                   'def func1; do_something end # comment',
+                                   'def func2() do_1; do_2; end'])
+        expect(cli.run(%w(--auto-correct --format offenses))).to eq(1)
+        expect(IO.read('example.rb')).to eq(['# encoding: utf-8',
+                                             '# comment',
+                                             'def func1',
+                                             '  do_something',
+                                             'end',
+                                             '',
+                                             'def func2',
+                                             '  do_1',
+                                             '  do_2',
+                                             'end',
+                                             ''].join("\n"))
+        expect($stdout.string).to eq(['',
+                                      '6   TrailingWhitespace',
+                                      '4   Semicolon',
+                                      '2   SingleLineMethods',
+                                      '1   DefWithParentheses',
+                                      '1   EmptyLineBetweenDefs',
+                                      '--',
+                                      '14  Total',
+                                      '',
+                                      ''].join("\n"))
+      end
+
+      # In this example, the auto-correction (changing "raise" to "fail")
+      # creates a new problem (alignment of parameters), which is also
+      # corrected automatically.
+      it 'can correct a problems and the problem it creates' do
+        create_file('example.rb',
+                    ['# encoding: utf-8',
+                     'raise NotImplementedError,',
+                     "      'Method should be overridden in child classes'"])
+        expect(cli.run(['--auto-correct'])).to eq(1)
+        expect(IO.read('example.rb'))
+          .to eq(['# encoding: utf-8',
+                  'fail NotImplementedError,',
+                  "     'Method should be overridden in child classes'"]
+                   .join("\n") + "\n")
+        expect($stdout.string)
+          .to eq(['Inspecting 1 file',
+                  'C',
+                  '',
+                  'Offenses:',
+                  '',
+                  'example.rb:2:1: C: [Corrected] Use fail instead of ' \
+                  'raise to signal exceptions.',
+                  'raise NotImplementedError,',
+                  '^^^^^',
+                  'example.rb:3:7: C: [Corrected] Align the parameters of a ' \
+                  'method call if they span more than one line.',
+                  "      'Method should be overridden in child classes'",
+                  '      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^',
+                  '',
+                  '1 file inspected, 2 offenses detected, 2 offenses ' \
+                  'corrected',
+                  ''].join("\n"))
+      end
+
+      # Thanks to repeated auto-correction, we can get rid of the trailing
+      # spaces, and then the extra empty line.
+      it 'can correct two problems in the same place' do
+        create_file('example.rb',
+                    ['# encoding: utf-8',
+                     '# Example class.',
+                     'class Klass',
+                     '  ',
+                     '  def f',
+                     '  end',
+                     'end'])
+        expect(cli.run(['--auto-correct'])).to eq(1)
+        expect(IO.read('example.rb'))
+          .to eq(['# encoding: utf-8',
+                  '# Example class.',
+                  'class Klass',
+                  '  def f',
+                  '  end',
+                  'end'].join("\n") + "\n")
+        expect($stderr.string).to eq('')
+        expect($stdout.string)
+          .to eq(['Inspecting 1 file',
+                  'C',
+                  '',
+                  'Offenses:',
+                  '',
+                  'example.rb:4:1: C: [Corrected] Extra empty line detected ' \
+                  'at body beginning.',
+                  'example.rb:4:1: C: [Corrected] Trailing whitespace ' \
+                  'detected.',
+                  '',
+                  '1 file inspected, 2 offenses detected, 2 offenses ' \
+                  'corrected',
+                  ''].join("\n"))
+      end
+
+      it 'can correct MethodDefParentheses and other offense' do
+        create_file('example.rb',
+                    ['# encoding: utf-8',
+                     'def primes limit',
+                     '  1.upto(limit).find_all { |i| is_prime[i] }',
+                     'end'])
+        expect(cli.run(%w(-D --auto-correct))).to eq(1)
+        expect($stderr.string).to eq('')
+        expect(IO.read('example.rb'))
+          .to eq(['# encoding: utf-8',
+                  'def primes(limit)',
+                  '  1.upto(limit).select { |i| is_prime[i] }',
+                  'end'].join("\n") + "\n")
+        expect($stdout.string)
+          .to eq(['Inspecting 1 file',
+                  'C',
+                  '',
+                  'Offenses:',
+                  '',
+                  'example.rb:2:12: C: [Corrected] MethodDefParentheses: ' \
+                  'Use def with parentheses when there are parameters.',
+                  'def primes limit',
+                  '           ^^^^^',
+                  'example.rb:3:17: C: [Corrected] CollectionMethods: ' \
+                  'Prefer select over find_all.',
+                  '  1.upto(limit).find_all { |i| is_prime[i] }',
+                  '                ^^^^^^^^',
+                  '',
+                  '1 file inspected, 2 offenses detected, 2 offenses ' \
+                  'corrected',
+                  ''].join("\n"))
+      end
+
+      it 'can correct WordArray and SpaceAfterComma offenses' do
+        create_file('example.rb',
+                    ['# encoding: utf-8',
+                     "f(type: ['offline','offline_payment'],",
+                     "  bar_colors: ['958c12','953579','ff5800','0085cc'])"])
+        expect(cli.run(%w(-D --auto-correct --format o))).to eq(1)
+        expect($stdout.string)
+          .to eq(['',
+                  '4  SpaceAfterComma',
+                  '2  WordArray',
+                  '--',
+                  '6  Total',
+                  '',
+                  ''].join("\n"))
+        expect(IO.read('example.rb'))
+          .to eq(['# encoding: utf-8',
+                  'f(type: %w(offline offline_payment),',
+                  '  bar_colors: %w(958c12 953579 ff5800 0085cc))',
+                  ''].join("\n"))
+      end
+
+      it 'can correct SpaceAfterComma and HashSyntax offenses' do
+        create_file('example.rb',
+                    ['# encoding: utf-8',
+                     "I18n.t('description',:property_name => property.name)"])
+        expect(cli.run(%w(-D --auto-correct --format emacs))).to eq(1)
+        expect($stdout.string)
+          .to eq(["#{abs('example.rb')}:2:21: C: [Corrected] " \
+                  "SpaceAfterComma: Space missing after comma.",
+                  "#{abs('example.rb')}:2:22: C: [Corrected] " \
+                  "HashSyntax: Use the new Ruby 1.9 hash syntax.",
+                  ''].join("\n"))
+        expect(IO.read('example.rb'))
+          .to eq(['# encoding: utf-8',
+                  "I18n.t('description', property_name: property.name)",
+                  ''].join("\n"))
+      end
+
+      it 'can correct HashSyntax and SpaceAroundOperators offenses' do
+        create_file('example.rb',
+                    ['# encoding: utf-8',
+                     '{ :b=>1 }'])
+        expect(cli.run(%w(-D --auto-correct --format emacs))).to eq(1)
+        expect(IO.read('example.rb')).to eq(['# encoding: utf-8',
+                                             '{ b: 1 }',
+                                             ''].join("\n"))
+        expect($stdout.string)
+          .to eq(["#{abs('example.rb')}:2:3: C: [Corrected] HashSyntax: Use " \
+                  "the new Ruby 1.9 hash syntax.",
+                  "#{abs('example.rb')}:2:5: C: [Corrected] " \
+                  "SpaceAroundOperators: Surrounding space missing for " \
+                  "operator '=>'.",
+                  ''].join("\n"))
+      end
+
+      it 'can correct HashSyntax when --only is used' do
+        create_file('example.rb',
+                    ['# encoding: utf-8',
+                     '{ :b=>1 }'])
+        expect(cli.run(%w(--auto-correct -f emacs --only HashSyntax))).to eq(1)
+        expect($stderr.string).to eq('')
+        expect(IO.read('example.rb')).to eq(['# encoding: utf-8',
+                                             '{ b: 1 }',
+                                             ''].join("\n"))
+        expect($stdout.string)
+          .to eq(["#{abs('example.rb')}:2:3: C: [Corrected] Use the new " \
+                  "Ruby 1.9 hash syntax.",
+                  ''].join("\n"))
+      end
+
+      it 'can correct TrailingBlankLines and TrailingWhitespace offenses' do
+        create_file('example.rb',
+                    ['# encoding: utf-8',
+                     '',
+                     '  ',
+                     '',
+                     ''])
+        expect(cli.run(%w(--auto-correct --format emacs))).to eq(1)
+        expect($stderr.string).to eq('')
+        expect(IO.read('example.rb')).to eq("# encoding: utf-8\n")
+        expect($stdout.string)
+          .to eq(["#{abs('example.rb')}:2:1: C: [Corrected] 3 trailing " \
+                  "blank lines detected.",
+                  "#{abs('example.rb')}:3:1: C: [Corrected] Trailing " \
+                  "whitespace detected.",
+                  ''].join("\n"))
+      end
+
+      it 'can correct MethodCallParentheses and EmptyLiteral offenses' do
+        create_file('example.rb',
+                    ['# encoding: utf-8',
+                     'Hash.new()'])
+        expect(cli.run(%w(--auto-correct --format emacs))).to eq(1)
+        expect($stderr.string).to eq('')
+        expect(IO.read('example.rb')).to eq(['# encoding: utf-8',
+                                             '{}',
+                                             ''].join("\n"))
+        expect($stdout.string)
+          .to eq(["#{abs('example.rb')}:2:1: C: [Corrected] Use hash " \
+                  "literal {} instead of Hash.new.",
+                  "#{abs('example.rb')}:2:9: C: [Corrected] Do not use " \
+                  "parentheses for method calls with no arguments.",
+                  ''].join("\n"))
+      end
+
+      it 'can correct IndentHash offenses with separator style' do
+        create_file('example.rb',
+                    ['# encoding: utf-8',
+                     'CONVERSION_CORRESPONDENCE = {',
+                     '              match_for_should: :match,',
+                     '          match_for_should_not: :match_when_negated,',
+                     '    failure_message_for_should: :failure_message,',
+                     'failure_message_for_should_not: :failure_message_when',
+                     '}'])
+        create_file('.rubocop.yml',
+                    ['AlignHash:',
+                     '  EnforcedColonStyle: separator'])
+        expect(cli.run(%w(--auto-correct))).to eq(1)
+        expect(IO.read('example.rb'))
+          .to eq(['# encoding: utf-8',
+                  'CONVERSION_CORRESPONDENCE = {',
+                  '                match_for_should: :match,',
+                  '            match_for_should_not: :match_when_negated,',
+                  '      failure_message_for_should: :failure_message,',
+                  '  failure_message_for_should_not: :failure_message_when',
+                  '}',
+                  ''].join("\n"))
+      end
+
+      it 'should not hang SpaceAfterPunctuation and SpaceInsideParens' do
+        create_file('example.rb',
+                    ['# encoding: utf-8',
+                     'some_method(a, )'])
+        Timeout.timeout(10) do
+          expect(cli.run(%w(--auto-correct))).to eq(1)
+        end
+        expect($stderr.string).to eq('')
+        expect(IO.read('example.rb')).to eq(['# encoding: utf-8',
+                                             'some_method(a,)',
+                                             ''].join("\n"))
+      end
+
+      it 'should not hang SpaceAfterPunctuation and SpaceInsideBrackets' do
+        create_file('example.rb',
+                    ['# encoding: utf-8',
+                     'puts [1, ]'])
+        Timeout.timeout(10) do
+          expect(cli.run(%w(--auto-correct))).to eq(1)
+        end
+        expect($stderr.string).to eq('')
+        expect(IO.read('example.rb')).to eq(['# encoding: utf-8',
+                                             'puts [1,]',
+                                             ''].join("\n"))
+      end
+    end
+
+    describe '--auto-gen-config' do
+      it 'overwrites an existing todo file' do
+        create_file('example1.rb', ['# encoding: utf-8',
+                                    'x= 0 ',
+                                    '#' * 85,
+                                    'y ',
+                                    'puts x'])
+        create_file('rubocop-todo.yml', ['LineLength:',
+                                         '  Enabled: false'])
+        create_file('.rubocop.yml', ['inherit_from: rubocop-todo.yml'])
+        expect(cli.run(['--auto-gen-config'])).to eq(1)
+        expect(IO.readlines('rubocop-todo.yml')[7..-1].map(&:chomp))
+          .to eq(['# Offense count: 1',
+                  'LineLength:',
+                  '  Max: 85',
+                  '',
+                  '# Offense count: 1',
+                  '# Cop supports --auto-correct.',
+                  'SpaceAroundOperators:',
+                  '  Enabled: false',
+                  '',
+                  '# Offense count: 2',
+                  '# Cop supports --auto-correct.',
+                  'TrailingWhitespace:',
+                  '  Enabled: false'])
+
+        # Create new CLI instance to avoid using cached configuration.
+        new_cli = described_class.new
+
+        expect(new_cli.run(['example1.rb'])).to eq(0)
+      end
+
+      it 'exits with error if file arguments are given' do
+        create_file('example1.rb', ['# encoding: utf-8',
+                                    'x= 0 ',
+                                    '#' * 85,
+                                    'y ',
+                                    'puts x'])
+        expect { cli.run(['--auto-gen-config', 'example1.rb']) }
+          .to exit_with_code(1)
+        expect($stderr.string)
+          .to eq('--auto-gen-config can not be combined with any other ' \
+                 "arguments.\n")
+        expect($stdout.string).to eq('')
+      end
+
+      it 'can generate a todo list' do
+        create_file('example1.rb', ['# encoding: utf-8',
+                                    '$x= 0 ',
+                                    '#' * 90,
+                                    '#' * 85,
+                                    'y ',
+                                    'puts x'])
+        create_file('example2.rb', ['# encoding: utf-8',
+                                    "\tx = 0",
+                                    'puts x'])
+        expect(cli.run(['--auto-gen-config'])).to eq(1)
+        expect($stderr.string).to eq('')
+        expect($stdout.string)
+          .to include(['Created rubocop-todo.yml.',
+                       'Run `rubocop --config rubocop-todo.yml`, or',
+                       'add inherit_from: rubocop-todo.yml in a ' \
+                       '.rubocop.yml file.',
+                       ''].join("\n"))
+        expected =
+          ['# This configuration was generated by `rubocop --auto-gen-config`',
+           /# on .* using RuboCop version .*/,
+           '# The point is for the user to remove these configuration records',
+           '# one by one as the offenses are removed from the code base.',
+           '# Note that changes in the inspected code, or installation of new',
+           '# versions of RuboCop, may require this file to be generated ' \
+           'again.',
+           '',
+           '# Offense count: 1',
+           '# Configuration parameters: AllowedVariables.',
+           'GlobalVars:',
+           '  Enabled: false',
+           '',
+           '# Offense count: 1',
+           '# Cop supports --auto-correct.',
+           'IndentationConsistency:',
+           '  Enabled: false',
+           '',
+           '# Offense count: 2',
+           'LineLength:',
+           '  Max: 90',
+           '',
+           '# Offense count: 1',
+           '# Cop supports --auto-correct.',
+           'SpaceAroundOperators:',
+           '  Enabled: false',
+           '',
+           '# Offense count: 1',
+           'Tab:',
+           '  Enabled: false',
+           '',
+           '# Offense count: 2',
+           '# Cop supports --auto-correct.',
+           'TrailingWhitespace:',
+           '  Enabled: false']
+        actual = IO.read('rubocop-todo.yml').split($RS)
+        expected.each_with_index do |line, ix|
+          if line.is_a?(String)
+            expect(actual[ix]).to eq(line)
+          else
+            expect(actual[ix]).to match(line)
+          end
+        end
+      end
+
+      it 'does not generate configuration for the Syntax cop' do
+        create_file('example1.rb', ['# encoding: utf-8',
+                                    'x = < ', # Syntax error
+                                    'puts x'])
+        create_file('example2.rb', ['# encoding: utf-8',
+                                    "\tx = 0",
+                                    'puts x'])
+        expect(cli.run(['--auto-gen-config'])).to eq(1)
+        expect($stderr.string).to eq('')
+        expected =
+          ['# This configuration was generated by `rubocop --auto-gen-config`',
+           /# on .* using RuboCop version .*/,
+           '# The point is for the user to remove these configuration records',
+           '# one by one as the offenses are removed from the code base.',
+           '# Note that changes in the inspected code, or installation of new',
+           '# versions of RuboCop, may require this file to be generated ' \
+           'again.',
+           '',
+           '# Offense count: 1',
+           '# Cop supports --auto-correct.',
+           'IndentationConsistency:',
+           '  Enabled: false',
+           '',
+           '# Offense count: 1',
+           'Tab:',
+           '  Enabled: false']
+        actual = IO.read('rubocop-todo.yml').split($RS)
+        expect(actual.length).to eq(expected.length)
+        expected.each_with_index do |line, ix|
+          if line.is_a?(String)
+            expect(actual[ix]).to eq(line)
+          else
+            expect(actual[ix]).to match(line)
+          end
+        end
+      end
+
+      it 'generates a todo list that removes the reports' do
+        create_file('example.rb', ['# encoding: utf-8',
+                                   'y.gsub!(%r{abc/xyz}, "#{x}")'])
+        expect(cli.run(%w(--format emacs))).to eq(1)
+        expect($stdout.string)
+          .to eq(["#{abs('example.rb')}:2:9: C: Use %r only for regular " \
+                  "expressions matching more than 1 '/' character.",
+                  ''].join("\n"))
+        expect(cli.run(['--auto-gen-config'])).to eq(1)
+        expected =
+          ['# This configuration was generated by `rubocop --auto-gen-config`',
+           /# on .* using RuboCop version .*/,
+           '# The point is for the user to remove these configuration records',
+           '# one by one as the offenses are removed from the code base.',
+           '# Note that changes in the inspected code, or installation of new',
+           '# versions of RuboCop, may require this file to be generated ' \
+           'again.',
+           '',
+           '# Offense count: 1',
+           'RegexpLiteral:',
+           '  MaxSlashes: 0']
+        actual = IO.read('rubocop-todo.yml').split($RS)
+        expected.each_with_index do |line, ix|
+          if line.is_a?(String)
+            expect(actual[ix]).to eq(line)
+          else
+            expect(actual[ix]).to match(line)
+          end
+        end
+        $stdout = StringIO.new
+        result = cli.run(%w(--config rubocop-todo.yml --format emacs))
+        expect($stdout.string).to eq('')
+        expect(result).to eq(0)
+      end
+    end
+
+    describe '--only' do
+      it 'runs just one cop' do
+        create_file('example.rb', ['if x== 0 ',
+                                   "\ty",
+                                   'end'])
+        # IfUnlessModifier depends on the configuration of LineLength.
+
+        expect(cli.run(['--format', 'simple',
+                        '--only', 'IfUnlessModifier',
+                        'example.rb'])).to eq(1)
+        expect($stdout.string)
+          .to eq(['== example.rb ==',
+                  'C:  1:  1: Favor modifier if usage when ' \
+                  'having a single-line body. Another good alternative is ' \
+                  'the usage of control flow &&/||.',
+                  '',
+                  '1 file inspected, 1 offense detected',
+                  ''].join("\n"))
+      end
+
+      it 'enables the given cop' do
+        create_file('example.rb', ['x = 0 ',
+                                   # Disabling comments still apply.
+                                   '# rubocop:disable TrailingWhitespace',
+                                   'y = 1  '])
+
+        create_file('.rubocop.yml', ['TrailingWhitespace:',
+                                     '  Enabled: false'])
+
+        expect(cli.run(['--format', 'simple',
+                        '--only', 'TrailingWhitespace',
+                        'example.rb'])).to eq(1)
+        expect($stderr.string).to eq('')
+        expect($stdout.string)
+          .to eq(['== example.rb ==',
+                  'C:  1:  6: Trailing whitespace detected.',
+                  '',
+                  '1 file inspected, 1 offense detected',
+                  ''].join("\n"))
+      end
+    end
+
+    describe '--lint' do
+      it 'runs only lint cops' do
+        create_file('example.rb', ['if 0 ',
+                                   "\ty",
+                                   'end'])
+        # IfUnlessModifier depends on the configuration of LineLength.
+
+        expect(cli.run(['--format', 'simple', '--lint',
+                        'example.rb'])).to eq(1)
+        expect($stdout.string)
+          .to eq(['== example.rb ==',
+                  'W:  1:  4: Literal 0 appeared in a condition.',
+                  '',
+                  '1 file inspected, 1 offense detected',
+                  ''].join("\n"))
+      end
+    end
+
+    describe '-d/--debug' do
+      it 'shows config files' do
+        create_file('example1.rb', "\tputs 0")
+        expect(cli.run(['--debug', 'example1.rb'])).to eq(1)
+        home = File.dirname(File.dirname(File.dirname(__FILE__)))
+        expect($stdout.string.lines.grep(/configuration/).map(&:chomp))
+          .to eq(["For #{abs('')}:" \
+                  " configuration from #{home}/config/default.yml",
+                  "Inheriting configuration from #{home}/config/enabled.yml",
+                  "Inheriting configuration from #{home}/config/disabled.yml"
+                 ])
+      end
+
+      it 'shows cop names' do
+        create_file('example1.rb', "\tputs 0")
+        expect(cli.run(['--format',
+                        'emacs',
+                        '--debug',
+                        'example1.rb'])).to eq(1)
+        expect($stdout.string.lines.to_a[-1])
+          .to eq(["#{abs('example1.rb')}:1:1: C: Tab: Tab detected.",
+                  ''].join("\n"))
+      end
+    end
+
+    describe '-D/--display-cop-names' do
+      it 'shows cop names' do
+        create_file('example1.rb', "\tputs 0")
+        expect(cli.run(['--format',
+                        'emacs',
+                        '--debug',
+                        'example1.rb'])).to eq(1)
+        expect($stdout.string.lines.to_a[-1])
+          .to eq(["#{abs('example1.rb')}:1:1: C: Tab: Tab detected.",
+                  ''].join("\n"))
+      end
+    end
+
+    describe '--show-cops' do
+      shared_examples(:prints_config) do
+        it 'prints the current configuration' do
+          out = stdout.lines.to_a
+          printed_config = YAML.load(out.join)
+          cop_names = (cop_list[0] || '').split(',')
+          cop_names.each do |cop_name|
+            global_conf[cop_name].each do |key, value|
+              printed_value = printed_config[cop_name][key]
+              expect(printed_value).to eq(value)
+            end
+          end
+        end
+      end
+
+      let(:cops) { Rubocop::Cop::Cop.all }
+
+      let(:global_conf) do
+        config_path =
+          Rubocop::ConfigLoader.configuration_file_for(Dir.pwd.to_s)
+        Rubocop::ConfigLoader.configuration_from_file(config_path)
+      end
+
+      let(:stdout) { $stdout.string }
+
+      before do
+        create_file('.rubocop.yml', ['LineLength:',
+                                     '  Max: 110'])
+        expect { cli.run ['--show-cops'] + cop_list }.to exit_with_code(0)
+      end
+
+      context 'with no args' do
+        let(:cop_list) { [] }
+
+        # Extracts the first line out of the description
+        def short_description_of_cop(cop)
+          desc = full_description_of_cop(cop)
+          desc ? desc.lines.first.strip : ''
+        end
+
+        # Gets the full description of the cop or nil if no description is set.
+        def full_description_of_cop(cop)
+          cop_config = global_conf.for_cop(cop)
+          cop_config['Description']
+        end
+
+        it 'prints all available cops and their description' do
+          cops.each do |cop|
+            expect(stdout).to include cop.cop_name
+            # Because of line breaks, we will only find the beginning.
+            expect(stdout).to include short_description_of_cop(cop)[0..60]
+          end
+        end
+
+        it 'prints all types' do
+          cops
+            .types
+            .map(&:to_s)
+            .map(&:capitalize)
+            .each { |type| expect(stdout).to include(type) }
+        end
+
+        it 'prints all cops in their right type listing' do
+          lines = stdout.lines
+          lines.slice_before(/Type /).each do |slice|
+            types = cops.types.map(&:to_s).map(&:capitalize)
+            current = types.delete(slice.shift[/Type '(?<c>[^'']+)'/, 'c'])
+            # all cops in their type listing
+            cops.with_type(current).each do |cop|
+              expect(slice.any? { |l| l.include? cop.cop_name }).to be_true
+            end
+
+            # no cop in wrong type listing
+            types.each do |type|
+              cops.with_type(type).each do |cop|
+                expect(slice.any? { |l| l.include? cop.cop_name }).to be_false
+              end
+            end
+          end
+        end
+
+        include_examples :prints_config
+      end
+
+      context 'with one cop given' do
+        let(:cop_list) { ['Tab'] }
+
+        it 'prints that cop and nothing else' do
+          expect(stdout).to eq(['Tab:',
+                                '  Description: No hard tabs.',
+                                '  Enabled: true',
+                                '',
+                                ''].join("\n"))
+        end
+
+        include_examples :prints_config
+      end
+
+      context 'with two cops given' do
+        let(:cop_list) { ['Tab,LineLength'] }
+        include_examples :prints_config
+      end
+
+      context 'with one of the cops misspelled' do
+        let(:cop_list) { ['Tab,X123'] }
+
+        it 'skips the unknown cop' do
+          expect(stdout).to eq(['Tab:',
+                                '  Description: No hard tabs.',
+                                '  Enabled: true',
+                                '',
+                                ''].join("\n"))
+        end
+      end
+    end
+
+    describe '-f/--format' do
+      let(:target_file) { 'example.rb' }
+
+      before do
+        create_file(target_file, ['# encoding: utf-8',
+                                  '#' * 90])
+      end
+
+      describe 'builtin formatters' do
+        context 'when simple format is specified' do
+          it 'outputs with simple format' do
+            cli.run(['--format', 'simple', 'example.rb'])
+            expect($stdout.string)
+              .to include(["== #{target_file} ==",
+                           'C:  2: 80: Line is too long. [90/79]'].join("\n"))
+          end
+        end
+
+        context 'when clang format is specified' do
+          it 'outputs with clang format' do
+            create_file('example1.rb', ['# encoding: utf-8',
+                                        'x= 0 ',
+                                        '#' * 85,
+                                        'y ',
+                                        'puts x'])
+            create_file('example2.rb', ['# encoding: utf-8',
+                                        "\tx",
+                                        'def a',
+                                        '   puts',
+                                        'end'])
+            create_file('example3.rb', ['# encoding: utf-8',
+                                        'def badName',
+                                        '  if something',
+                                        '    test',
+                                        '    end',
+                                        'end'])
+            expect(cli.run(['--format', 'clang', 'example1.rb',
+                            'example2.rb', 'example3.rb']))
+              .to eq(1)
+            expect($stdout.string)
+              .to eq(['example1.rb:2:2: C: Surrounding space missing for ' \
+                      "operator '='.",
+                      'x= 0 ',
+                      ' ^',
+                      'example1.rb:2:5: C: Trailing whitespace detected.',
+                      'x= 0 ',
+                      '    ^',
+                      'example1.rb:3:80: C: Line is too long. [85/79]',
+                      '###################################################' \
+                      '##################################',
+                      '                                                   ' \
+                      '                            ^^^^^^',
+                      'example1.rb:4:2: C: Trailing whitespace detected.',
+                      'y ',
+                      ' ^',
+                      'example2.rb:2:1: C: Tab detected.',
+                      "\tx",
+                      '^',
+                      'example2.rb:3:1: C: Inconsistent indentation ' \
+                      'detected.',
+                      'def a',
+                      '^^^^^',
+                      'example2.rb:4:1: C: Use 2 (not 3) spaces for ' \
+                      'indentation.',
+                      '   puts',
+                      '^^^',
+                      'example3.rb:2:5: C: Use snake_case for methods.',
+                      'def badName',
+                      '    ^^^^^^^',
+                      'example3.rb:3:3: C: Favor modifier if usage ' \
+                      'when having a single-line body. Another good ' \
+                      'alternative is the usage of control flow &&/||.',
+                      '  if something',
+                      '  ^^',
+                      'example3.rb:5:5: W: end at 5, 4 is not aligned ' \
+                      'with if at 3, 2',
+                      '    end',
+                      '    ^^^',
+                      '',
+                      '3 files inspected, 10 offenses detected',
+                      ''].join("\n"))
+          end
+        end
+
+        context 'when emacs format is specified' do
+          it 'outputs with emacs format' do
+            create_file('example1.rb', ['# encoding: utf-8',
+                                        'x= 0 ',
+                                        'y ',
+                                        'puts x'])
+            create_file('example2.rb', ['# encoding: utf-8',
+                                        "\tx = 0",
+                                        'puts x'])
+            expect(cli.run(['--format', 'emacs', 'example1.rb',
+                            'example2.rb'])).to eq(1)
+            expected_output =
+              ["#{abs('example1.rb')}:2:2: C: Surrounding space missing" \
+               " for operator '='.",
+               "#{abs('example1.rb')}:2:5: C: Trailing whitespace detected.",
+               "#{abs('example1.rb')}:3:2: C: Trailing whitespace detected.",
+               "#{abs('example2.rb')}:2:1: C: Tab detected.",
+               "#{abs('example2.rb')}:3:1: C: Inconsistent indentation " \
+               'detected.',
+               ''].join("\n")
+            expect($stdout.string).to eq(expected_output)
+          end
+        end
+
+        context 'when unknown format name is specified' do
+          it 'aborts with error message' do
+            expect { cli.run(['--format', 'unknown', 'example.rb']) }
+              .to exit_with_code(1)
+            expect($stderr.string)
+              .to include('No formatter for "unknown"')
+          end
+        end
+      end
+
+      describe 'custom formatter' do
+        let(:target_file) { abs('example.rb') }
+
+        context 'when a class name is specified' do
+          it 'uses the class as a formatter' do
+            module MyTool
+              class RubocopFormatter < Rubocop::Formatter::BaseFormatter
+                def started(all_files)
+                  output.puts "started: #{all_files.join(',')}"
+                end
+
+                def file_started(file, options)
+                  output.puts "file_started: #{file}"
+                end
+
+                def file_finished(file, offenses)
+                  output.puts "file_finished: #{file}"
+                end
+
+                def finished(processed_files)
+                  output.puts "finished: #{processed_files.join(',')}"
+                end
+              end
+            end
+
+            cli.run(['--format', 'MyTool::RubocopFormatter', 'example.rb'])
+            expect($stdout.string).to eq(["started: #{target_file}",
+                                          "file_started: #{target_file}",
+                                          "file_finished: #{target_file}",
+                                          "finished: #{target_file}",
+                                          ''].join("\n"))
+          end
+        end
+
+        context 'when unknown class name is specified' do
+          it 'aborts with error message' do
+            args = '--format UnknownFormatter example.rb'
+            expect { cli.run(args.split) }.to exit_with_code(1)
+            expect($stderr.string).to include('UnknownFormatter')
+          end
+        end
+      end
+
+      it 'can be used multiple times' do
+        cli.run(['--format', 'simple', '--format', 'emacs', 'example.rb'])
+        expect($stdout.string)
+          .to include(["== #{target_file} ==",
+                       'C:  2: 80: Line is too long. [90/79]',
+                       "#{abs(target_file)}:2:80: C: Line is too long. " \
+                       '[90/79]'].join("\n"))
+      end
+    end
+
+    describe '-o/--out option' do
+      let(:target_file) { 'example.rb' }
+
+      before do
+        create_file(target_file, ['# encoding: utf-8',
+                                  '#' * 90])
+      end
+
+      it 'redirects output to the specified file' do
+        cli.run(['--out', 'output.txt', target_file])
+        expect(File.read('output.txt')).to include('Line is too long.')
+      end
+
+      it 'is applied to the previously specified formatter' do
+        cli.run(['--format', 'simple',
+                 '--format', 'emacs', '--out', 'emacs_output.txt',
+                 target_file])
+
+        expect($stdout.string).to eq(["== #{target_file} ==",
+                                      'C:  2: 80: Line is too long. [90/79]',
+                                      '',
+                                      '1 file inspected, 1 offense detected',
+                                      ''].join("\n"))
+
+        expect(File.read('emacs_output.txt'))
+          .to eq("#{abs(target_file)}:2:80: C: Line is too long. [90/79]\n")
+      end
+    end
+
+    describe '--fail-level option' do
+      let(:target_file) { 'example.rb' }
+
+      before do
+        create_file(target_file, ['# encoding: utf-8',
+                                  '#' * 90])
+      end
+
+      it 'should be failed when option is less than the severity level' do
+        expect(cli.run(['--fail-level', 'convention', target_file])).to eq(1)
+      end
+
+      it 'should be success when option is greater than the severity level' do
+        expect(cli.run(['--fail-level', 'warning', target_file])).to eq(0)
+      end
+    end
+
+    describe '--force-exclusion' do
+      let(:target_file) { 'example.rb' }
+
+      before do
+        create_file(target_file, ['# encoding: utf-8',
+                                  '#' * 90])
+
+        create_file('.rubocop.yml', ['AllCops:',
+                                     '  Exclude:',
+                                     "    - #{target_file}"])
+
+      end
+
+      it 'excludes files specified in the configuration Exclude ' \
+         'even if they are explicitly passed as arguments' do
+        expect(cli.run(['--force-exclusion', target_file])).to eq(0)
+      end
+    end
+  end
+
+  describe '#wants_to_quit?' do
+    it 'is initially false' do
+      expect(cli.wants_to_quit?).to be_false
+    end
+
+    context 'when true' do
+      it 'returns 1' do
+        create_file('example.rb', '# encoding: utf-8')
+        cli.wants_to_quit = true
+        expect(cli.run(['example.rb'])).to eq(1)
+      end
+    end
+  end
+
+  describe '#trap_interrupt' do
+    before do
+      @interrupt_handlers = []
+      allow(Signal).to receive(:trap).with('INT') do |&block|
+        @interrupt_handlers << block
+      end
+    end
+
+    def interrupt
+      @interrupt_handlers.each(&:call)
+    end
+
+    it 'adds a handler for SIGINT' do
+      expect(@interrupt_handlers).to be_empty
+      cli.trap_interrupt
+      expect(@interrupt_handlers.size).to eq(1)
+    end
+
+    context 'with SIGINT once' do
+      it 'sets #wants_to_quit? to true' do
+        cli.trap_interrupt
+        expect(cli.wants_to_quit?).to be_false
+        interrupt
+        expect(cli.wants_to_quit?).to be_true
+      end
+
+      it 'does not exit immediately' do
+        expect_any_instance_of(Object).not_to receive(:exit)
+        expect_any_instance_of(Object).not_to receive(:exit!)
+        cli.trap_interrupt
+        interrupt
+      end
+    end
+
+    context 'with SIGINT twice' do
+      it 'exits immediately' do
+        expect_any_instance_of(Object).to receive(:exit!).with(1)
+        cli.trap_interrupt
+        interrupt
+        interrupt
+      end
+    end
+  end
+
+  it 'checks a given correct file and returns 0' do
+    create_file('example.rb', ['# encoding: utf-8',
+                               'x = 0',
+                               'puts x'])
+    expect(cli.run(['--format', 'simple', 'example.rb'])).to eq(0)
+    expect($stdout.string)
+      .to eq("\n1 file inspected, no offenses detected\n")
+  end
+
+  it 'checks a given file with faults and returns 1' do
+    create_file('example.rb', ['# encoding: utf-8',
+                               'x = 0 ',
+                               'puts x'])
+    expect(cli.run(['--format', 'simple', 'example.rb'])).to eq(1)
+    expect($stdout.string)
+      .to eq ['== example.rb ==',
+              'C:  2:  6: Trailing whitespace detected.',
+              '',
+              '1 file inspected, 1 offense detected',
+              ''].join("\n")
+  end
+
+  it 'registers an offense for a syntax error' do
+    create_file('example.rb', ['# encoding: utf-8',
+                               'class Test',
+                               'en'])
+    expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(1)
+    expect($stdout.string)
+      .to eq(["#{abs('example.rb')}:4:1: E: unexpected " \
+              'token $end',
+              ''].join("\n"))
+  end
+
+  it 'registers an offense for Parser warnings' do
+    create_file('example.rb', ['# encoding: utf-8',
+                               'puts *test',
+                               'if a then b else c end'])
+    expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(1)
+    expect($stdout.string)
+      .to eq(["#{abs('example.rb')}:2:6: W: " \
+              'Ambiguous splat operator. Parenthesize the method arguments ' \
+              "if it's surely a splat operator, or add a whitespace to the " \
+              'right of the * if it should be a multiplication.',
+              "#{abs('example.rb')}:3:1: C: " \
+              'Favor the ternary operator (?:) over if/then/else/end ' \
+              'constructs.',
+              ''].join("\n"))
+  end
+
+  it 'can process a file with an invalid UTF-8 byte sequence' do
+    create_file('example.rb', ['# encoding: utf-8',
+                               "# #{'f9'.hex.chr}#{'29'.hex.chr}"])
+    expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(1)
+    expect($stdout.string)
+      .to eq(["#{abs('example.rb')}:1:1: F: Invalid byte sequence in utf-8.",
+              ''].join("\n"))
+  end
+
+  describe 'rubocop:disable comment' do
+    it 'can disable all cops in a code section' do
+      create_file('example.rb',
+                  ['# encoding: utf-8',
+                   '# rubocop:disable all',
+                   '#' * 90,
+                   'x(123456)',
+                   'y("123")',
+                   'def func',
+                   '  # rubocop: enable LineLength, StringLiterals',
+                   '  ' + '#' * 93,
+                   '  x(123456)',
+                   '  y("123")',
+                   'end'])
+      expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(1)
+      # all cops were disabled, then 2 were enabled again, so we
+      # should get 2 offenses reported.
+      expect($stdout.string)
+        .to eq(["#{abs('example.rb')}:8:80: C: Line is too long. [95/79]",
+                "#{abs('example.rb')}:10:5: C: Prefer single-quoted " \
+                "strings when you don't need string interpolation or " \
+                'special symbols.',
+                ''].join("\n"))
+    end
+
+    it 'can disable selected cops in a code section' do
+      create_file('example.rb',
+                  ['# encoding: utf-8',
+                   '# rubocop:disable LineLength,NumericLiterals,' \
+                   'StringLiterals',
+                   '#' * 90,
+                   'x(123456)',
+                   'y("123")',
+                   'def func',
+                   '  # rubocop: enable LineLength, StringLiterals',
+                   '  ' + '#' * 93,
+                   '  x(123456)',
+                   '  y("123")',
+                   'end'])
+      expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(1)
+      # 3 cops were disabled, then 2 were enabled again, so we
+      # should get 2 offenses reported.
+      expect($stdout.string)
+        .to eq(["#{abs('example.rb')}:8:80: C: Line is too long. [95/79]",
+                "#{abs('example.rb')}:10:5: C: Prefer single-quoted " \
+                "strings when you don't need string interpolation or " \
+                'special symbols.',
+                ''].join("\n"))
+    end
+
+    it 'can disable all cops on a single line' do
+      create_file('example.rb', ['# encoding: utf-8',
+                                 'y("123", 123456) # rubocop:disable all'
+                                ])
+      expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(0)
+      expect($stdout.string).to be_empty
+    end
+
+    it 'can disable selected cops on a single line' do
+      create_file('example.rb',
+                  ['# encoding: utf-8',
+                   'a' * 90 + ' # rubocop:disable LineLength',
+                   '#' * 95,
+                   'y("123") # rubocop:disable LineLength,StringLiterals'
+                  ])
+      expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(1)
+      expect($stdout.string)
+        .to eq(
+               ["#{abs('example.rb')}:3:80: C: Line is too long. [95/79]",
+                ''].join("\n"))
+    end
+  end
+
+  it 'finds a file with no .rb extension but has a shebang line' do
+    create_file('example', ['#!/usr/bin/env ruby',
+                            '# encoding: utf-8',
+                            'x = 0',
+                            'puts x'
+                           ])
+    expect(cli.run(%w(--format simple))).to eq(0)
+    expect($stdout.string)
+      .to eq(['', '1 file inspected, no offenses detected', ''].join("\n"))
+  end
+
+  describe 'rails cops' do
+    describe 'enabling/disabling' do
+      it 'by default does not run rails cops' do
+        create_file('app/models/example1.rb', ['# encoding: utf-8',
+                                               'read_attribute(:test)'])
+        expect(cli.run(['--format', 'simple', 'app/models/example1.rb']))
+          .to eq(0)
+      end
+
+      it 'with -R given runs rails cops' do
+        create_file('app/models/example1.rb', ['# encoding: utf-8',
+                                               'read_attribute(:test)'])
+        expect(cli.run(['--format', 'simple', '-R', 'app/models/example1.rb']))
+          .to eq(1)
+        expect($stdout.string).to include('Prefer self[:attr]')
+      end
+
+      it 'with configation option true in one dir runs rails cops there' do
+        source = ['# encoding: utf-8',
+                  'read_attribute(:test)']
+        create_file('dir1/app/models/example1.rb', source)
+        create_file('dir1/.rubocop.yml', ['AllCops:',
+                                          '  RunRailsCops: true',
+                                          '',
+                                          'ReadAttribute:',
+                                          '  Include:',
+                                          '    - app/models/*.rb'])
+        create_file('dir2/app/models/example2.rb', source)
+        create_file('dir2/.rubocop.yml', ['AllCops:',
+                                          '  RunRailsCops: false',
+                                          '',
+                                          'ReadAttribute:',
+                                          '  Include:',
+                                          '    - app/models/*.rb'])
+        expect(cli.run(%w(--format simple dir1 dir2))).to eq(1)
+        expect($stdout.string)
+          .to eq(['== dir1/app/models/example1.rb ==',
+                  'C:  2:  1: Prefer self[:attr] over read_attribute' \
+                  '(:attr).',
+                  '',
+                  '2 files inspected, 1 offense detected',
+                  ''].join("\n"))
+      end
+
+      it 'with configation option false but -R given runs rails cops' do
+        create_file('app/models/example1.rb', ['# encoding: utf-8',
+                                               'read_attribute(:test)'])
+        create_file('.rubocop.yml', ['AllCops:',
+                                     '  RunRailsCops: false'])
+        expect(cli.run(['--format', 'simple', '-R', 'app/models/example1.rb']))
+          .to eq(1)
+        expect($stdout.string).to include('Prefer self[:attr]')
+      end
+    end
+
+    describe 'including/excluding' do
+      it 'includes some directories by default' do
+        source = ['# encoding: utf-8',
+                  'read_attribute(:test)',
+                  "default_scope order: 'position'"]
+        # Several rails cops include app/models by default.
+        create_file('dir1/app/models/example1.rb', source)
+        create_file('dir1/app/models/example2.rb', source)
+        # No rails cops include app/views by default.
+        create_file('dir1/app/views/example3.rb', source)
+        # The .rubocop.yml file inherits from default.yml where the Include
+        # config parameter is set for the rails cops. The paths are interpreted
+        # as relative to dir1 because .rubocop.yml is placed there.
+        create_file('dir1/.rubocop.yml', ['AllCops:',
+                                          '  RunRailsCops: true',
+                                          '',
+                                          'ReadWriteAttribute:',
+                                          '  Exclude:',
+                                          '    - example2.rb',
+                                          '',
+                                          'DefaultScope:',
+                                          '  Exclude:',
+                                          '    - "**/example2.rb"'])
+        # No .rubocop.yml file in dir2 means that the paths from default.yml
+        # are interpreted as relative to the current directory, so they don't
+        # match.
+        create_file('dir2/app/models/example4.rb', source)
+
+        expect(cli.run(%w(--format simple dir1 dir2))).to eq(1)
+        expect($stdout.string)
+          .to eq(['== dir1/app/models/example1.rb ==',
+                  'C:  2:  1: Prefer self[:attr] over read_attribute' \
+                  '(:attr).',
+                  'C:  3: 15: default_scope expects a block as its sole' \
+                  ' argument.',
+                  '',
+                  '4 files inspected, 2 offenses detected',
+                  ''].join("\n"))
+      end
+    end
+  end
+
+  describe 'cops can exclude files based on config' do
+    it 'ignores excluded files' do
+      create_file('example.rb', ['# encoding: utf-8',
+                                 'x = 0'])
+      create_file('regexp.rb', ['# encoding: utf-8',
+                                'x = 0'])
+      create_file('exclude_glob.rb', ['#!/usr/bin/env ruby',
+                                      '# encoding: utf-8',
+                                      'x = 0'])
+      create_file('dir/thing.rb', ['# encoding: utf-8',
+                                   'x = 0'])
+      create_file('.rubocop.yml', ['UselessAssignment:',
+                                   '  Exclude:',
+                                   '    - example.rb',
+                                   '    - !ruby/regexp /regexp.rb\z/',
+                                   '    - "exclude_*"',
+                                   '    - "dir/*"'])
+      expect(cli.run(%w(--format simple))).to eq(0)
+      expect($stdout.string)
+        .to eq(['', '4 files inspected, no offenses detected',
+                ''].join("\n"))
+    end
+
+  end
+
+  describe 'configuration from file' do
+    it 'finds included files' do
+      create_file('example', ['# encoding: utf-8',
+                              'x = 0',
+                              'puts x'
+                             ])
+      create_file('regexp', ['# encoding: utf-8',
+                             'x = 0',
+                             'puts x'
+                            ])
+      create_file('.rubocop.yml', ['AllCops:',
+                                   '  Include:',
+                                   '    - example',
+                                   '    - !ruby/regexp /regexp$/'
+                                  ])
+      expect(cli.run(%w(--format simple))).to eq(0)
+      expect($stdout.string)
+        .to eq(['', '2 files inspected, no offenses detected',
+                ''].join("\n"))
+    end
+
+    it 'ignores excluded files' do
+      create_file('example.rb', ['# encoding: utf-8',
+                                 'x = 0',
+                                 'puts x'
+                                ])
+      create_file('regexp.rb', ['# encoding: utf-8',
+                                'x = 0',
+                                'puts x'
+                               ])
+      create_file('exclude_glob.rb', ['#!/usr/bin/env ruby',
+                                      '# encoding: utf-8',
+                                      'x = 0',
+                                      'puts x'
+                                     ])
+      create_file('.rubocop.yml', ['AllCops:',
+                                   '  Exclude:',
+                                   '    - example.rb',
+                                   '    - !ruby/regexp /regexp.rb$/',
+                                   '    - "exclude_*"'
+                                  ])
+      expect(cli.run(%w(--format simple))).to eq(0)
+      expect($stdout.string)
+        .to eq(['', '0 files inspected, no offenses detected',
+                ''].join("\n"))
+    end
+
+    # With rubinius 2.0.0.rc1 + rspec 2.13.1,
+    # File.stub(:open).and_call_original causes SystemStackError.
+    it 'does not read files in excluded list', broken: :rbx do
+      %w(rb.rb non-rb.ext without-ext).each do |filename|
+        create_file("example/ignored/#{filename}", ['# encoding: utf-8',
+                                                    '#' * 90
+                                                   ])
+      end
+
+      create_file('example/.rubocop.yml', ['AllCops:',
+                                           '  Exclude:',
+                                           '    - ignored/**'])
+      expect(File).not_to receive(:open).with(%r{/ignored/})
+      allow(File).to receive(:open).and_call_original
+      expect(cli.run(%w(--format simple example))).to eq(0)
+      expect($stdout.string)
+        .to eq(['', '0 files inspected, no offenses detected',
+                ''].join("\n"))
+    end
+
+    it 'can be configured with option to disable a certain error' do
+      create_file('example1.rb', 'puts 0 ')
+      create_file('rubocop.yml', ['Encoding:',
+                                  '  Enabled: false',
+                                  '',
+                                  'CaseIndentation:',
+                                  '  Enabled: false'])
+      expect(cli.run(['--format', 'simple',
+                      '-c', 'rubocop.yml', 'example1.rb'])).to eq(1)
+      expect($stdout.string)
+        .to eq(['== example1.rb ==',
+                'C:  1:  7: Trailing whitespace detected.',
+                '',
+                '1 file inspected, 1 offense detected',
+                ''].join("\n"))
+    end
+
+    it 'can disable parser-derived offenses with warning severity' do
+      # `-' interpreted as argument prefix
+      create_file('example.rb', 'puts -1')
+      create_file('.rubocop.yml', ['Encoding:',
+                                   '  Enabled: false',
+                                   '',
+                                   'AmbiguousOperator:',
+                                   '  Enabled: false'
+                                  ])
+      expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(0)
+    end
+
+    it 'cannot disable Syntax offenses with fatal/error severity' do
+      create_file('example.rb', 'class Test')
+      create_file('.rubocop.yml', ['Encoding:',
+                                   '  Enabled: false',
+                                   '',
+                                   'Syntax:',
+                                   '  Enabled: false'
+                                  ])
+      expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(1)
+      expect($stdout.string).to include('unexpected token $end')
+    end
+
+    it 'can be configured to merge a parameter that is a hash' do
+      create_file('example1.rb',
+                  ['# encoding: utf-8',
+                   'puts %w(a b c)',
+                   'puts %q|hi|'])
+      # We want to change the preferred delimiters for word arrays. The other
+      # settings from default.yml are unchanged.
+      create_file('rubocop.yml',
+                  ['PercentLiteralDelimiters:',
+                   '  PreferredDelimiters:',
+                   "    '%w': '[]'",
+                   "    '%W': '[]'"])
+      cli.run(['--format', 'simple', '-c', 'rubocop.yml', 'example1.rb'])
+      expect($stdout.string)
+        .to eq(['== example1.rb ==',
+                'C:  2:  6: %w-literals should be delimited by [ and ]',
+                'C:  3:  6: %q-literals should be delimited by ( and )',
+                '',
+                '1 file inspected, 2 offenses detected',
+                ''].join("\n"))
+    end
+
+    it 'can be configured to override a parameter that is a hash in a ' \
+       'special case' do
+      create_file('example1.rb',
+                  ['# encoding: utf-8',
+                   'arr.select { |e| e > 0 }.collect { |e| -e }',
+                   'a2.find_all { |e| e > 0 }'])
+      # We prefer find_all over select. This setting overrides the default
+      # select over find_all. Other preferred methods appearing in the default
+      # config (e.g., map over collect) are kept.
+      create_file('rubocop.yml',
+                  ['CollectionMethods:',
+                   '  PreferredMethods:',
+                   '    select: find_all'])
+      cli.run(['--format', 'simple', '-c', 'rubocop.yml', 'example1.rb'])
+      expect($stdout.string)
+        .to eq(['== example1.rb ==',
+                'C:  2:  5: Prefer find_all over select.',
+                'C:  2: 26: Prefer map over collect.',
+                '',
+                '1 file inspected, 2 offenses detected',
+                ''].join("\n"))
+    end
+
+    it 'works when a cop that others depend on is disabled' do
+      create_file('example1.rb', ['if a',
+                                  '  b',
+                                  'end'])
+      create_file('rubocop.yml', ['Encoding:',
+                                  '  Enabled: false',
+                                  '',
+                                  'LineLength:',
+                                  '  Enabled: false'
+                                 ])
+      result = cli.run(['--format', 'simple',
+                        '-c', 'rubocop.yml', 'example1.rb'])
+      expect($stdout.string)
+        .to eq(['== example1.rb ==',
+                'C:  1:  1: Favor modifier if usage when having ' \
+                'a single-line body. Another good alternative is the ' \
+                'usage of control flow &&/||.',
+                '',
+                '1 file inspected, 1 offense detected',
+                ''].join("\n"))
+      expect(result).to eq(1)
+    end
+
+    it 'can be configured with project config to disable a certain error' do
+      create_file('example_src/example1.rb', 'puts 0 ')
+      create_file('example_src/.rubocop.yml', ['Encoding:',
+                                               '  Enabled: false',
+                                               '',
+                                               'CaseIndentation:',
+                                               '  Enabled: false'
+                                              ])
+      expect(cli.run(['--format', 'simple',
+                      'example_src/example1.rb'])).to eq(1)
+      expect($stdout.string)
+        .to eq(['== example_src/example1.rb ==',
+                'C:  1:  7: Trailing whitespace detected.',
+                '',
+                '1 file inspected, 1 offense detected',
+                ''].join("\n"))
+    end
+
+    it 'can use an alternative max line length from a config file' do
+      create_file('example_src/example1.rb', ['# encoding: utf-8',
+                                              '#' * 90
+                                             ])
+      create_file('example_src/.rubocop.yml', ['LineLength:',
+                                               '  Enabled: true',
+                                               '  Max: 100'
+                                              ])
+      expect(cli.run(['--format', 'simple',
+                      'example_src/example1.rb'])).to eq(0)
+      expect($stdout.string)
+        .to eq(['', '1 file inspected, no offenses detected', ''].join("\n"))
+    end
+
+    it 'can have different config files in different directories' do
+      %w(src lib).each do |dir|
+        create_file("example/#{dir}/example1.rb", ['# encoding: utf-8',
+                                                   '#' * 90
+                                                  ])
+      end
+      create_file('example/src/.rubocop.yml', ['LineLength:',
+                                               '  Enabled: true',
+                                               '  Max: 100'
+                                              ])
+      expect(cli.run(%w(--format simple example))).to eq(1)
+      expect($stdout.string).to eq(
+                                   ['== example/lib/example1.rb ==',
+                                    'C:  2: 80: Line is too long. [90/79]',
+                                    '',
+                                    '2 files inspected, 1 offense detected',
+                                    ''].join("\n"))
+    end
+
+    it 'prefers a config file in ancestor directory to another in home' do
+      create_file('example_src/example1.rb', ['# encoding: utf-8',
+                                              '#' * 90
+                                             ])
+      create_file('example_src/.rubocop.yml', ['LineLength:',
+                                               '  Enabled: true',
+                                               '  Max: 100'
+                                              ])
+      create_file("#{Dir.home}/.rubocop.yml", ['LineLength:',
+                                               '  Enabled: true',
+                                               '  Max: 80'
+                                              ])
+      expect(cli.run(['--format', 'simple',
+                      'example_src/example1.rb'])).to eq(0)
+      expect($stdout.string)
+        .to eq(['', '1 file inspected, no offenses detected', ''].join("\n"))
+    end
+
+    it 'can exclude directories relative to .rubocop.yml' do
+      %w(src etc/test etc/spec tmp/test tmp/spec).each do |dir|
+        create_file("example/#{dir}/example1.rb", ['# encoding: utf-8',
+                                                   '#' * 90
+                                                  ])
+      end
+
+      create_file('example/.rubocop.yml', ['AllCops:',
+                                           '  Exclude:',
+                                           '    - src/**',
+                                           '    - etc/**',
+                                           '    - tmp/spec/**'])
+
+      expect(cli.run(%w(--format simple example))).to eq(1)
+      expect($stdout.string).to eq(
+                                   ['== example/tmp/test/example1.rb ==',
+                                    'C:  2: 80: Line is too long. [90/79]',
+                                    '',
+                                    '1 file inspected, 1 offense detected',
+                                    ''].join("\n"))
+    end
+
+    it 'can exclude a typical vendor directory' do
+      create_file('vendor/bundle/ruby/1.9.1/gems/parser-2.0.0/.rubocop.yml',
+                  ['AllCops:',
+                   '  Exclude:',
+                   '    - lib/parser/lexer.rb'])
+
+      create_file('vendor/bundle/ruby/1.9.1/gems/parser-2.0.0/lib/ex.rb',
+                  ['# encoding: utf-8',
+                   '#' * 90])
+
+      create_file('.rubocop.yml',
+                  ['AllCops:',
+                   '  Exclude:',
+                   '    - vendor/**'])
+
+      cli.run(%w(--format simple))
+      expect($stdout.string)
+        .to eq(['', '0 files inspected, no offenses detected',
+                ''].join("\n"))
+    end
+
+    it 'excludes the vendor directory by default' do
+      create_file('vendor/ex.rb',
+                  ['# encoding: utf-8',
+                   '#' * 90])
+
+      cli.run(%w(--format simple))
+      expect($stdout.string)
+        .to eq(['', '0 files inspected, no offenses detected',
+                ''].join("\n"))
+    end
+
+    # Being immune to bad configuration files in excluded directories has
+    # become important due to a bug in rubygems
+    # (https://github.com/rubygems/rubygems/issues/680) that makes
+    # installations of, for example, rubocop lack their .rubocop.yml in the
+    # root directory.
+    it 'can exclude a vendor directory with an erroneous config file' do
+      create_file('vendor/bundle/ruby/1.9.1/gems/parser-2.0.0/.rubocop.yml',
+                  ['inherit_from: non_existent.yml'])
+
+      create_file('vendor/bundle/ruby/1.9.1/gems/parser-2.0.0/lib/ex.rb',
+                  ['# encoding: utf-8',
+                   '#' * 90])
+
+      create_file('.rubocop.yml',
+                  ['AllCops:',
+                   '  Exclude:',
+                   '    - vendor/**'])
+
+      cli.run(%w(--format simple))
+      expect($stderr.string).to eq('')
+      expect($stdout.string)
+        .to eq(['', '0 files inspected, no offenses detected',
+                ''].join("\n"))
+    end
+
+    # Relative exclude paths in .rubocop.yml files are relative to that file,
+    # but in configuration files with other names they will be relative to
+    # whatever file inherits from them.
+    it 'can exclude a vendor directory indirectly' do
+      create_file('vendor/bundle/ruby/1.9.1/gems/parser-2.0.0/.rubocop.yml',
+                  ['AllCops:',
+                   '  Exclude:',
+                   '    - lib/parser/lexer.rb'])
+
+      create_file('vendor/bundle/ruby/1.9.1/gems/parser-2.0.0/lib/ex.rb',
+                  ['# encoding: utf-8',
+                   '#' * 90])
+
+      create_file('.rubocop.yml',
+                  ['inherit_from: config/default.yml'])
+
+      create_file('config/default.yml',
+                  ['AllCops:',
+                   '  Exclude:',
+                   '    - vendor/**'])
+
+      cli.run(%w(--format simple))
+      expect($stdout.string)
+        .to eq(['', '0 files inspected, no offenses detected',
+                ''].join("\n"))
+    end
+
+    it 'prints a warning for an unrecognized cop name in .rubocop.yml' do
+      create_file('example/example1.rb', ['# encoding: utf-8',
+                                          '#' * 90])
+
+      create_file('example/.rubocop.yml', ['LyneLenth:',
+                                           '  Enabled: true',
+                                           '  Max: 100'])
+
+      expect(cli.run(%w(--format simple example))).to eq(1)
+      expect($stderr.string)
+        .to eq(
+               ['Warning: unrecognized cop LyneLenth found in ' +
+                abs('example/.rubocop.yml'),
+                ''].join("\n"))
+    end
+
+    it 'prints a warning for an unrecognized configuration parameter' do
+      create_file('example/example1.rb', ['# encoding: utf-8',
+                                          '#' * 90])
+
+      create_file('example/.rubocop.yml', ['LineLength:',
+                                           '  Enabled: true',
+                                           '  Min: 10'])
+
+      expect(cli.run(%w(--format simple example))).to eq(1)
+      expect($stderr.string)
+        .to eq(
+               ['Warning: unrecognized parameter LineLength:Min found in ' +
+                abs('example/.rubocop.yml'),
+                ''].join("\n"))
+    end
+
+    it 'works when a configuration file passed by -c specifies Exclude ' \
+       'with regexp' do
+      create_file('example/example1.rb', ['# encoding: utf-8',
+                                          '#' * 90])
+
+      create_file('rubocop.yml', ['AllCops:',
+                                  '  Exclude:',
+                                  '    - !ruby/regexp /example1\.rb$/'])
+
+      cli.run(%w(--format simple -c rubocop.yml))
+      expect($stdout.string)
+        .to eq(['', '0 files inspected, no offenses detected',
+                ''].join("\n"))
+    end
+
+    it 'works when a configuration file passed by -c specifies Exclude ' \
+       'with strings' do
+      create_file('example/example1.rb', ['# encoding: utf-8',
+                                          '#' * 90])
+
+      create_file('rubocop.yml', ['AllCops:',
+                                  '  Exclude:',
+                                  '    - example/**'])
+
+      cli.run(%w(--format simple -c rubocop.yml))
+      expect($stdout.string)
+        .to eq(['', '0 files inspected, no offenses detected',
+                ''].join("\n"))
+    end
+
+    it 'works when a configuration file specifies a Severity' do
+      create_file('example/example1.rb', ['# encoding: utf-8',
+                                          '#' * 90])
+
+      create_file('rubocop.yml', ['LineLength:',
+                                  '  Severity: error'])
+
+      cli.run(%w(--format simple -c rubocop.yml))
+      expect($stdout.string)
+        .to eq(['== example/example1.rb ==',
+                'E:  2: 80: Line is too long. [90/79]',
+                '',
+                '1 file inspected, 1 offense detected',
+                ''].join("\n"))
+      expect($stderr.string).to eq('')
+    end
+
+    it 'fails when a configuration file specifies an invalid Severity' do
+      create_file('example/example1.rb', ['# encoding: utf-8',
+                                          '#' * 90])
+
+      create_file('rubocop.yml', ['LineLength:',
+                                  '  Severity: superbad'])
+
+      cli.run(%w(--format simple -c rubocop.yml))
+      expect($stderr.string)
+        .to eq("Warning: Invalid severity 'superbad'. " \
+               'Valid severities are refactor, convention, ' \
+               "warning, error, fatal.\n")
+    end
+  end
+end
diff --git a/spec/rubocop/comment_config_spec.rb b/spec/rubocop/comment_config_spec.rb
new file mode 100644
index 0000000..5b2ce0a
--- /dev/null
+++ b/spec/rubocop/comment_config_spec.rb
@@ -0,0 +1,103 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::CommentConfig do
+  subject(:comment_config) { Rubocop::CommentConfig.new(parse_source(source)) }
+
+  describe '#cop_enabled_at_line?' do
+    let(:source) do
+      [
+        '# encoding: utf-8',
+        '',
+        '# rubocop:disable MethodLength',
+        'def some_method',
+        "  puts 'foo'",
+        'end',
+        '# rubocop:enable MethodLength',
+        '',
+        '# rubocop:disable all',
+        'some_method',
+        '# rubocop:enable all',
+        '',
+        "code = 'This is evil.'",
+        'eval(code) # rubocop:disable Eval',
+        "puts 'This is not evil.'",
+        '',
+        'def some_method',
+        "  puts 'Disabling indented single line' # rubocop:disable LineLength",
+        'end',
+        '',
+        'string = <<END',
+        'This is a string not a real comment # rubocop:disable Loop',
+        'END',
+        '',
+        'foo # rubocop:disable MethodCallParentheses',
+        '',
+        '# rubocop:enable Void',
+        '',
+        '# rubocop:disable For',
+        'foo'
+      ]
+    end
+
+    def disabled_lines_of_cop(cop)
+      (1..source.size).each_with_object([]) do |line_number, disabled_lines|
+        enabled = comment_config.cop_enabled_at_line?(cop, line_number)
+        disabled_lines << line_number unless enabled
+      end
+    end
+
+    it 'supports disabling multiple lines with a pair of directive' do
+      method_length_disabled_lines = disabled_lines_of_cop('MethodLength')
+      expected_part = (3..6).to_a
+      expect(method_length_disabled_lines & expected_part)
+        .to eq(expected_part)
+    end
+
+    it 'supports disabling all lines after a directive' do
+      for_disabled_lines = disabled_lines_of_cop('For')
+      expected_part = (29..source.size).to_a
+      expect(for_disabled_lines & expected_part)
+        .to eq(expected_part)
+    end
+
+    it 'just ignores unpaired enabling directives' do
+      void_disabled_lines = disabled_lines_of_cop('Void')
+      expected_part = (27..source.size).to_a
+      expect(void_disabled_lines & expected_part).to be_empty
+    end
+
+    it 'supports disabling single line with a direcive at end of line' do
+      eval_disabled_lines = disabled_lines_of_cop('Eval')
+      expect(eval_disabled_lines).to include(14)
+      expect(eval_disabled_lines).not_to include(15)
+    end
+
+    it 'handles indented single line' do
+      line_length_disabled_lines = disabled_lines_of_cop('LineLength')
+      expect(line_length_disabled_lines).to include(18)
+      expect(line_length_disabled_lines).not_to include(19)
+    end
+
+    it 'does not confuse a comment directive embedded in a string literal ' \
+       'with a real comment' do
+      loop_disabled_lines = disabled_lines_of_cop('Loop')
+      expect(loop_disabled_lines).not_to include(22)
+    end
+
+    it 'supports disabling all cops with keyword all' do
+      expected_part = (9..10).to_a
+
+      Rubocop::Cop::Cop.all.each do |cop|
+        disabled_lines = disabled_lines_of_cop(cop)
+        expect(disabled_lines & expected_part).to eq(expected_part)
+      end
+    end
+
+    it 'does not confuse a cop name including "all" with all cops' do
+      alias_disabled_lines = disabled_lines_of_cop('Alias')
+      expect(alias_disabled_lines).not_to include(25)
+    end
+  end
+end
diff --git a/spec/rubocop/config_loader_spec.rb b/spec/rubocop/config_loader_spec.rb
new file mode 100644
index 0000000..1997f8b
--- /dev/null
+++ b/spec/rubocop/config_loader_spec.rb
@@ -0,0 +1,328 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::ConfigLoader do
+  include FileHelper
+
+  let(:default_config) { Rubocop::ConfigLoader.default_configuration }
+
+  describe '.configuration_file_for', :isolated_environment do
+    subject(:configuration_file_for) do
+      described_class.configuration_file_for(dir_path)
+    end
+
+    context 'when no config file exists in ancestor directories' do
+      let(:dir_path) { 'dir' }
+      before { create_file('dir/example.rb', '') }
+
+      context 'but a config file exists in home directory' do
+        before { create_file('~/.rubocop.yml', '') }
+
+        it 'returns the path to the file in home directory' do
+          expect(configuration_file_for).to end_with('home/.rubocop.yml')
+        end
+      end
+
+      context 'and no config file exists in home directory' do
+        it 'falls back to the provided default file' do
+          expect(configuration_file_for).to end_with('config/default.yml')
+        end
+      end
+    end
+
+    context 'when a config file exists in the parent directory' do
+      let(:dir_path) { 'dir' }
+
+      before do
+        create_file('dir/example.rb', '')
+        create_file('.rubocop.yml', '')
+      end
+
+      it 'returns the path to that configuration file' do
+        expect(configuration_file_for).to end_with('work/.rubocop.yml')
+      end
+    end
+
+    context 'when multiple config files exist in ancestor directories' do
+      let(:dir_path) { 'dir' }
+
+      before do
+        create_file('dir/example.rb', '')
+        create_file('dir/.rubocop.yml', '')
+        create_file('.rubocop.yml', '')
+      end
+
+      it 'prefers closer config file' do
+        expect(configuration_file_for).to end_with('dir/.rubocop.yml')
+      end
+    end
+  end
+
+  describe '.configuration_from_file', :isolated_environment do
+    subject(:configuration_from_file) do
+      described_class.configuration_from_file(file_path)
+    end
+
+    context 'with any config file' do
+      let(:file_path) { '.rubocop.yml' }
+
+      before do
+        create_file(file_path, ['Encoding:',
+                                '  Enabled: false'])
+      end
+      it 'returns a configuration inheriting from default.yml' do
+        config = default_config['Encoding'].dup
+        config['Enabled'] = false
+        expect(configuration_from_file)
+          .to eql(default_config.merge('Encoding' => config))
+      end
+    end
+
+    context 'when multiple config files exist in ancestor directories' do
+      let(:file_path) { 'dir/.rubocop.yml' }
+
+      before do
+        create_file('.rubocop.yml',
+                    ['AllCops:',
+                     '  Exclude:',
+                     '    - vendor/**'
+                    ])
+
+        create_file(file_path,
+                    ['AllCops:',
+                     '  Exclude: []'
+                    ])
+      end
+
+      it 'gets AllCops/Exclude from the highest directory level' do
+        excludes = configuration_from_file['AllCops']['Exclude']
+        expect(excludes).to eq([File.expand_path('vendor/**')])
+      end
+    end
+
+    context 'when a file inherits from a parent file' do
+      let(:file_path) { 'dir/.rubocop.yml' }
+
+      before do
+        create_file('.rubocop.yml',
+                    ['AllCops:',
+                     '  Exclude:',
+                     '    - vendor/**',
+                     '    - !ruby/regexp /[A-Z]/'
+                    ])
+
+        create_file(file_path, ['inherit_from: ../.rubocop.yml'])
+      end
+
+      it 'gets an absolute AllCops/Exclude' do
+        excludes = configuration_from_file['AllCops']['Exclude']
+        expect(excludes).to eq([File.expand_path('vendor/**'), /[A-Z]/])
+      end
+    end
+
+    context 'when a file inherits from an empty parent file' do
+      let(:file_path) { 'dir/.rubocop.yml' }
+
+      before do
+        create_file('.rubocop.yml', [''])
+
+        create_file(file_path, ['inherit_from: ../.rubocop.yml'])
+      end
+
+      it 'does not fail to load' do
+        expect { configuration_from_file }.not_to raise_error
+      end
+    end
+
+    context 'when a file inherits from a sibling file' do
+      let(:file_path) { 'dir/.rubocop.yml' }
+
+      before do
+        create_file('src/.rubocop.yml',
+                    ['AllCops:',
+                     '  Exclude:',
+                     '    - vendor/**'
+                    ])
+
+        create_file(file_path, ['inherit_from: ../src/.rubocop.yml'])
+      end
+
+      it 'gets an absolute AllCops/Exclude' do
+        excludes = configuration_from_file['AllCops']['Exclude']
+        expect(excludes).to eq([File.expand_path('src/vendor/**')])
+      end
+    end
+
+    context 'when a file inherits from a parent and grandparent file' do
+      let(:file_path) { 'dir/subdir/.rubocop.yml' }
+
+      before do
+        create_file('dir/subdir/example.rb', '')
+
+        create_file('.rubocop.yml',
+                    ['LineLength:',
+                     '  Enabled: false',
+                     '  Max: 77'])
+
+        create_file('dir/.rubocop.yml',
+                    ['inherit_from: ../.rubocop.yml',
+                     '',
+                     'MethodLength:',
+                     '  Enabled: true',
+                     '  CountComments: false',
+                     '  Max: 10'
+                    ])
+
+        create_file(file_path,
+                    ['inherit_from: ../.rubocop.yml',
+                     '',
+                     'LineLength:',
+                     '  Enabled: true',
+                     '',
+                     'MethodLength:',
+                     '  Max: 5'
+                    ])
+      end
+
+      it 'returns the ancestor configuration plus local overrides' do
+        config = default_config
+                   .merge('LineLength' => {
+                            'Description' =>
+                               default_config['LineLength']['Description'],
+                            'Enabled' => true,
+                            'Max' => 77
+                          },
+                          'MethodLength' => {
+                            'Description' =>
+                               default_config['MethodLength']['Description'],
+                            'Enabled' => true,
+                            'CountComments' => false,
+                            'Max' => 5
+                          })
+        expect(configuration_from_file).to eq(config)
+      end
+    end
+
+    context 'when a file inherits from two configurations' do
+      let(:file_path) { '.rubocop.yml' }
+
+      before do
+        create_file('example.rb', '')
+
+        create_file('normal.yml',
+                    ['MethodLength:',
+                     '  Enabled: false',
+                     '  CountComments: true',
+                     '  Max: 79'])
+
+        create_file('special.yml',
+                    ['MethodLength:',
+                     '  Enabled: false',
+                     '  Max: 200'])
+
+        create_file(file_path,
+                    ['inherit_from:',
+                     '  - normal.yml',
+                     '  - special.yml',
+                     '',
+                     'MethodLength:',
+                     '  Enabled: true'
+                    ])
+      end
+
+      it 'returns values from the last one when possible' do
+        expected = { 'Enabled' => true,        # overridden in .rubocop.yml
+                     'CountComments' => true,  # only defined in normal.yml
+                     'Max' => 200 }            # special.yml takes precedence
+        expect(configuration_from_file['MethodLength'].to_set)
+          .to be_superset(expected.to_set)
+      end
+    end
+  end
+
+  describe '.load_file', :isolated_environment do
+    subject(:load_file) do
+      described_class.load_file(configuration_path)
+    end
+
+    let(:configuration_path) { '.rubocop.yml' }
+
+    it 'returns a configuration loaded from the passed path' do
+      create_file(configuration_path, [
+        'Encoding:',
+        '  Enabled: true'
+      ])
+      configuration = load_file
+      expect(configuration['Encoding']).to eq(
+        'Enabled' => true
+      )
+    end
+  end
+
+  describe '.merge' do
+    subject(:merge) { described_class.merge(base, derived) }
+
+    let(:base) do
+      {
+        'AllCops' => {
+          'Include' => ['**/*.gemspec', '**/Rakefile'],
+          'Exclude' => []
+        }
+      }
+    end
+    let(:derived) do
+      { 'AllCops' => { 'Exclude' => ['example.rb', 'exclude_*'] } }
+    end
+
+    it 'returns a recursive merge of its two arguments' do
+      expect(merge).to eq('AllCops' => {
+                            'Include' => ['**/*.gemspec', '**/Rakefile'],
+                            'Exclude' => ['example.rb', 'exclude_*']
+                          })
+    end
+  end
+
+  describe 'configuration for SymbolArray', :isolated_environment do
+    let(:config) do
+      config_path = described_class.configuration_file_for('.')
+      described_class.configuration_from_file(config_path)
+    end
+
+    context 'when no config file exists for the target file' do
+      it 'is disabled' do
+        expect(config.cop_enabled?('SymbolArray')).to be_false
+      end
+    end
+
+    context 'when a config file which does not mention SymbolArray exists' do
+      it 'is disabled' do
+        create_file('.rubocop.yml', [
+          'LineLength:',
+          '  Max: 79'
+        ])
+        expect(config.cop_enabled?('SymbolArray')).to be_false
+      end
+    end
+
+    context 'when a config file which explicitly enables SymbolArray exists' do
+      it 'is enabled' do
+        create_file('.rubocop.yml', [
+          'SymbolArray:',
+          '  Enabled: true'
+        ])
+        expect(config.cop_enabled?('SymbolArray')).to be_true
+      end
+    end
+  end
+
+  describe 'configuration for AssignmentInCondition' do
+    describe 'AllowSafeAssignment' do
+      it 'is enabled by default' do
+        default_config = described_class.default_configuration
+        symbol_name_config = default_config.for_cop('AssignmentInCondition')
+        expect(symbol_name_config['AllowSafeAssignment']).to be_true
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/config_spec.rb b/spec/rubocop/config_spec.rb
new file mode 100644
index 0000000..cef8044
--- /dev/null
+++ b/spec/rubocop/config_spec.rb
@@ -0,0 +1,179 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Config do
+  include FileHelper
+
+  subject(:configuration) { described_class.new(hash, loaded_path) }
+  let(:hash) { {} }
+  let(:loaded_path) { 'example/.rubocop.yml' }
+
+  describe '#validate', :isolated_environment do
+    # TODO: Because Config.load_file now outputs the validation warning,
+    #       it is inserting text into the rspec test output here.
+    #       The next 2 lines should be removed eventually.
+    before(:each) { $stderr = StringIO.new }
+    after(:each) { $stderr = STDERR }
+
+    subject(:configuration) do
+      Rubocop::ConfigLoader.load_file(configuration_path)
+    end
+
+    let(:configuration_path) { '.rubocop.yml' }
+
+    context 'when the configuration includes any unrecognized cop name' do
+      before do
+        create_file(configuration_path, [
+          'LyneLenth:',
+          '  Enabled: true',
+          '  Max: 100'
+        ])
+      end
+
+      it 'raises validation error' do
+        expect { configuration.validate }
+          .to raise_error(described_class::ValidationError,
+                          /^unrecognized cop LyneLenth/)
+      end
+    end
+
+    context 'when the configuration includes any unrecognized parameter' do
+      before do
+        create_file(configuration_path, [
+          'LineLength:',
+          '  Enabled: true',
+          '  Min: 10'
+        ])
+      end
+
+      it 'raises validation error' do
+        expect { configuration.validate }
+          .to raise_error(described_class::ValidationError,
+                          /^unrecognized parameter LineLength:Min/)
+      end
+    end
+
+    context 'when the configuration includes any common parameter' do
+      # Common parameters are parameters that are not in the default
+      # configuration, but are nonetheless allowed for any cop.
+      before do
+        create_file(configuration_path, [
+          'LineLength:',
+          '  Exclude:',
+          '    - lib/file.rb',
+          '  Include:',
+          '    - lib/file.xyz',
+          '  Severity: warning'
+        ])
+      end
+
+      it 'does not raise validation error' do
+        expect { configuration.validate }.to_not raise_error
+      end
+    end
+  end
+
+  describe '#file_to_include?' do
+    let(:hash) do
+      {
+        'AllCops' => {
+          'Include' => ['Gemfile', 'config/unicorn.rb.example']
+        }
+      }
+    end
+
+    let(:loaded_path) { '/home/foo/project/.rubocop.yml' }
+
+    context 'when the passed path matches any of patterns to include' do
+      it 'returns true' do
+        file_path = '/home/foo/project/Gemfile'
+        expect(configuration.file_to_include?(file_path)).to be_true
+      end
+    end
+
+    context 'when the passed path does not match any of patterns to include' do
+      it 'returns false' do
+        file_path = '/home/foo/project/Gemfile.lock'
+        expect(configuration.file_to_include?(file_path)).to be_false
+      end
+    end
+  end
+
+  describe '#file_to_exclude?' do
+    let(:hash) do
+      {
+        'AllCops' => {
+          'Exclude' => ['/home/foo/project/log/*']
+        }
+      }
+    end
+
+    let(:loaded_path) { '/home/foo/project/.rubocop.yml' }
+
+    context 'when the passed path matches any of patterns to exclude' do
+      it 'returns true' do
+        file_path = '/home/foo/project/log/foo.rb'
+        expect(configuration.file_to_exclude?(file_path)).to be_true
+      end
+    end
+
+    context 'when the passed path does not match any of patterns to exclude' do
+      it 'returns false' do
+        file_path = '/home/foo/project/log_file.rb'
+        expect(configuration.file_to_exclude?(file_path)).to be_false
+      end
+    end
+  end
+
+  describe '#patterns_to_include' do
+    subject(:patterns_to_include) do
+      configuration = described_class.new(hash, loaded_path)
+      configuration.patterns_to_include
+    end
+
+    let(:hash) { {} }
+    let(:loaded_path) { 'example/.rubocop.yml' }
+
+    context 'when config file has AllCops => Include key' do
+      let(:hash) do
+        {
+          'AllCops' => {
+            'Include' => ['Gemfile', 'config/unicorn.rb.example']
+          }
+        }
+      end
+
+      it 'returns the Include value' do
+        expect(patterns_to_include).to eq([
+          'Gemfile',
+          'config/unicorn.rb.example'
+        ])
+      end
+    end
+  end
+
+  describe '#patterns_to_exclude' do
+    subject(:patterns_to_exclude) do
+      configuration = described_class.new(hash, loaded_path)
+      configuration.patterns_to_exclude
+    end
+
+    let(:hash) { {} }
+    let(:loaded_path) { 'example/.rubocop.yml' }
+
+    context 'when config file has AllCops => Exclude key' do
+      let(:hash) do
+        {
+          'AllCops' => {
+            'Exclude' => ['log/*']
+          }
+        }
+      end
+
+      it 'returns the Exclude value' do
+        expect(patterns_to_exclude).to eq(['log/*'])
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/config_store_spec.rb b/spec/rubocop/config_store_spec.rb
new file mode 100644
index 0000000..61ee4fc
--- /dev/null
+++ b/spec/rubocop/config_store_spec.rb
@@ -0,0 +1,53 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::ConfigStore do
+  subject(:config_store) { described_class.new }
+
+  before do
+    allow(Rubocop::ConfigLoader).to receive(:configuration_file_for) do |arg|
+      # File tree:
+      # file1
+      # dir/.rubocop.yml
+      # dir/file2
+      # dir/subdir/file3
+      (arg =~ /dir/ ? 'dir' : '.') + '/.rubocop.yml'
+    end
+    allow(Rubocop::ConfigLoader)
+      .to receive(:configuration_from_file) { |arg| arg }
+    allow(Rubocop::ConfigLoader)
+      .to receive(:load_file) { |arg| "#{arg} loaded" }
+    allow(Rubocop::ConfigLoader)
+      .to receive(:merge_with_default) { |config, file| "merged #{config}" }
+  end
+
+  describe '.for' do
+    it 'always uses config specified in command line' do
+      config_store.options_config = :options_config
+      expect(config_store.for('file1')).to eq('merged options_config loaded')
+    end
+
+    context 'when no config specified in command line' do
+      it 'gets config path and config from cache if available' do
+        expect(Rubocop::ConfigLoader).to receive(:configuration_file_for).once
+          .with('dir')
+        expect(Rubocop::ConfigLoader).to receive(:configuration_file_for).once
+          .with('dir/subdir')
+        # The stub returns the same config path for dir and dir/subdir.
+        expect(Rubocop::ConfigLoader).to receive(:configuration_from_file).once
+          .with('dir/.rubocop.yml')
+
+        config_store.for('dir/file2')
+        config_store.for('dir/file2')
+        config_store.for('dir/subdir/file3')
+      end
+
+      it 'searches for config path if not available in cache' do
+        expect(Rubocop::ConfigLoader).to receive(:configuration_file_for).once
+        expect(Rubocop::ConfigLoader).to receive(:configuration_from_file).once
+        config_store.for('file1')
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/cop/commissioner_spec.rb b/spec/rubocop/cop/commissioner_spec.rb
new file mode 100644
index 0000000..3a105e2
--- /dev/null
+++ b/spec/rubocop/cop/commissioner_spec.rb
@@ -0,0 +1,83 @@
+# encoding: utf-8
+# rubocop:disable LineLength
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Commissioner do
+  describe '#investigate' do
+    let(:cop) { double(Rubocop::Cop, offenses: []).as_null_object }
+
+    it 'returns all offenses found by the cops' do
+      allow(cop).to receive(:offenses).and_return([1])
+
+      commissioner = described_class.new([cop])
+      source = []
+      processed_source = parse_source(source)
+
+      expect(commissioner.investigate(processed_source)).to eq [1]
+    end
+
+    context 'when a cop has no interest in the file' do
+      it 'returns all offenses except the ones of the cop' do
+        cops = []
+        cops << double('cop A', offenses: %w(foo), relevant_file?: true)
+        cops << double('cop B', offenses: %w(bar), relevant_file?: false)
+        cops << double('cop C', offenses: %w(baz), relevant_file?: true)
+        cops.each(&:as_null_object)
+
+        commissioner = described_class.new(cops)
+        source = []
+        processed_source = parse_source(source)
+
+        expect(commissioner.investigate(processed_source)).to eq %w(foo baz)
+      end
+    end
+
+    it 'traverses the AST and invoke cops specific callbacks' do
+      expect(cop).to receive(:on_def)
+
+      commissioner = described_class.new([cop])
+      source = ['def method', '1', 'end']
+      processed_source = parse_source(source)
+
+      commissioner.investigate(processed_source)
+    end
+
+    it 'passes the input params to all cops that implement their own #investigate method' do
+      source = []
+      processed_source = parse_source(source)
+      expect(cop).to receive(:investigate).with(processed_source)
+
+      commissioner = described_class.new([cop])
+
+      commissioner.investigate(processed_source)
+    end
+
+    it 'stores all errors raised by the cops' do
+      allow(cop).to receive(:on_def) { fail RuntimeError }
+
+      commissioner = described_class.new([cop])
+      source = ['def method', '1', 'end']
+      processed_source = parse_source(source)
+
+      commissioner.investigate(processed_source)
+
+      expect(commissioner.errors[cop].size).to eq(1)
+      expect(commissioner.errors[cop][0]).to be_instance_of(RuntimeError)
+    end
+
+    context 'when passed :raise_error option' do
+      it 're-raises the exception received while processing' do
+        allow(cop).to receive(:on_def) { fail RuntimeError }
+
+        commissioner = described_class.new([cop], raise_error: true)
+        source = ['def method', '1', 'end']
+        processed_source = parse_source(source)
+
+        expect do
+          commissioner.investigate(processed_source)
+        end.to raise_error(RuntimeError)
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/cop/cop_spec.rb b/spec/rubocop/cop/cop_spec.rb
new file mode 100644
index 0000000..c4b21cd
--- /dev/null
+++ b/spec/rubocop/cop/cop_spec.rb
@@ -0,0 +1,114 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Cop do
+  subject(:cop) { described_class.new }
+  let(:location) do
+    source_buffer = Parser::Source::Buffer.new('test', 1)
+    source_buffer.source = "a\n"
+    Parser::Source::Range.new(source_buffer, 0, 1)
+  end
+
+  it 'initially has 0 offenses' do
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'keeps track of offenses' do
+    cop.add_offense(nil, location, 'message')
+
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'will report registered offenses' do
+    cop.add_offense(nil, location, 'message')
+
+    expect(cop.offenses).not_to be_empty
+  end
+
+  it 'will set default severity' do
+    cop.add_offense(nil, location, 'message')
+
+    expect(cop.offenses.first.severity).to eq(:convention)
+  end
+
+  it 'will set custom severity if present' do
+    cop.config[cop.name] = { 'Severity' => 'warning' }
+    cop.add_offense(nil, location, 'message')
+
+    expect(cop.offenses.first.severity).to eq(:warning)
+  end
+
+  it 'will warn if custom severity is invalid' do
+    cop.config[cop.name] = { 'Severity' => 'superbad' }
+    expect(cop).to receive(:warn)
+    cop.add_offense(nil, location, 'message')
+  end
+
+  it 'registers offense with its name' do
+    cop = Rubocop::Cop::Style::For.new
+    cop.add_offense(nil, location, 'message')
+    expect(cop.offenses.first.cop_name).to eq('For')
+  end
+
+  context 'with no submodule' do
+    subject(:cop) { described_class }
+    it('has right name') { expect(cop.cop_name).to eq('Cop') }
+    it('has right type') { expect(cop.cop_type).to eq(:cop) }
+  end
+
+  context 'with style cops' do
+    subject(:cop) { Rubocop::Cop::Style::For }
+    it('has right name') { expect(cop.cop_name).to eq('For') }
+    it('has right type') { expect(cop.cop_type).to eq(:style) }
+  end
+
+  context 'with lint cops' do
+    subject(:cop) { Rubocop::Cop::Lint::Loop }
+    it('has right name') { expect(cop.cop_name).to eq('Loop') }
+    it('has right type') { expect(cop.cop_type).to eq(:lint) }
+  end
+
+  context 'with rails cops' do
+    subject(:cop) { Rubocop::Cop::Rails::Validation }
+    it('has right name') { expect(cop.cop_name).to eq('Validation') }
+    it('has right type') { expect(cop.cop_type).to eq(:rails) }
+  end
+
+  describe 'CopStore' do
+    context '#types' do
+      subject { described_class.all.types }
+      it('has types') { expect(subject.length).not_to eq(0) }
+      it { should include :lint }
+      it do
+        pending 'Rails cops are usually removed after CLI start, ' \
+                'so CLI spec impacts this one'
+        should include :rails
+      end
+      it { should include :style }
+      it 'contains every value only once' do
+        expect(subject.length).to eq(subject.uniq.length)
+      end
+    end
+    context '#with_type' do
+      let(:types) { described_class.all.types }
+      it 'has at least one cop per type' do
+        types.each do |c|
+          expect(described_class.all.with_type(c).length).to be > 0
+        end
+      end
+
+      it 'has each cop in exactly one type' do
+        sum = 0
+        types.each do |c|
+          sum += described_class.all.with_type(c).length
+        end
+        expect(sum).to be described_class.all.length
+      end
+
+      it 'returns 0 for an invalid type' do
+        expect(described_class.all.with_type('x').length).to be 0
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/cop/corrector_spec.rb b/spec/rubocop/cop/corrector_spec.rb
new file mode 100644
index 0000000..aca5bc7
--- /dev/null
+++ b/spec/rubocop/cop/corrector_spec.rb
@@ -0,0 +1,59 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Corrector do
+  describe '#rewrite' do
+    it 'allows removal of a range' do
+      source = 'true and false'
+      processed_source = parse_source(source)
+
+      correction = lambda do |corrector|
+        node = processed_source.ast
+        corrector.remove(node.loc.operator)
+      end
+
+      corrector = described_class.new(processed_source.buffer, [correction])
+      expect(corrector.rewrite).to eq 'true  false'
+    end
+
+    it 'allows insertion before a source range' do
+      source = 'true and false'
+      processed_source = parse_source(source)
+
+      correction = lambda do |corrector|
+        node = processed_source.ast
+        corrector.insert_before(node.loc.operator, ';nil ')
+      end
+
+      corrector = described_class.new(processed_source.buffer, [correction])
+      expect(corrector.rewrite).to eq 'true ;nil and false'
+    end
+
+    it 'allows insertion after a source range' do
+      source = 'true and false'
+      processed_source = parse_source(source)
+
+      correction = lambda do |corrector|
+        node = processed_source.ast
+        corrector.insert_after(node.loc.operator, ' nil;')
+      end
+
+      corrector = described_class.new(processed_source.buffer, [correction])
+      expect(corrector.rewrite).to eq 'true and nil; false'
+    end
+
+    it 'allows replacement of a range' do
+      source = 'true and false'
+      processed_source = parse_source(source)
+
+      correction = lambda do |corrector|
+        node = processed_source.ast
+        corrector.replace(node.loc.operator, 'or')
+      end
+
+      corrector = described_class.new(processed_source.buffer, [correction])
+      expect(corrector.rewrite).to eq 'true or false'
+    end
+  end
+end
diff --git a/spec/rubocop/cop/lint/ambiguous_operator_spec.rb b/spec/rubocop/cop/lint/ambiguous_operator_spec.rb
new file mode 100644
index 0000000..54ad05a
--- /dev/null
+++ b/spec/rubocop/cop/lint/ambiguous_operator_spec.rb
@@ -0,0 +1,113 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::AmbiguousOperator do
+  subject(:cop) { described_class.new }
+
+  before do
+    inspect_source(cop, source)
+  end
+
+  context 'with a splat operator in the first argument' do
+    context 'without parentheses' do
+      context 'without whitespaces on the right of the operator' do
+        let(:source) do
+          [
+            'array = [1, 2, 3]',
+            'puts *array'
+          ]
+        end
+
+        it 'registers an offense' do
+          expect(cop.offenses.size).to eq(1)
+          expect(cop.offenses.first.message).to eq(
+            'Ambiguous splat operator. ' \
+            "Parenthesize the method arguments if it's surely a splat " \
+            'operator, ' \
+            'or add a whitespace to the right of the * if it should be a ' \
+            'multiplication.'
+          )
+          expect(cop.highlights).to eq(['*'])
+        end
+      end
+
+      context 'with a whitespace on the right of the operator' do
+        let(:source) do
+          [
+            'array = [1, 2, 3]',
+            'puts * array'
+          ]
+        end
+
+        it 'accepts' do
+          expect(cop.offenses).to be_empty
+        end
+      end
+    end
+
+    context 'with parentheses' do
+      let(:source) do
+        [
+          'array = [1, 2, 3]',
+          'puts(*array)'
+        ]
+      end
+
+      it 'accepts' do
+        expect(cop.offenses).to be_empty
+      end
+    end
+  end
+
+  context 'with a block ampersand in the first argument' do
+    context 'without parentheses' do
+      context 'without whitespaces on the right of the operator' do
+        let(:source) do
+          [
+            'process = proc { do_something }',
+            '2.times &process'
+          ]
+        end
+
+        it 'registers an offense' do
+          expect(cop.offenses.size).to eq(1)
+          expect(cop.offenses.first.message).to eq(
+            'Ambiguous block operator. ' \
+            "Parenthesize the method arguments if it's surely a block " \
+            'operator, ' \
+            'or add a whitespace to the right of the & if it should be a ' \
+            'binary AND.'
+          )
+          expect(cop.highlights).to eq(['&'])
+        end
+      end
+
+      context 'with a whitespace on the right of the operator' do
+        let(:source) do
+          [
+            'process = proc { do_something }',
+            '2.times & process'
+          ]
+        end
+
+        it 'accepts' do
+          expect(cop.offenses).to be_empty
+        end
+      end
+    end
+
+    context 'with parentheses' do
+      let(:source) do
+        [
+          'process = proc { do_something }',
+          '2.times(&process)'
+        ]
+      end
+
+      it 'accepts' do
+        expect(cop.offenses).to be_empty
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/cop/lint/ambiguous_regexp_literal_spec.rb b/spec/rubocop/cop/lint/ambiguous_regexp_literal_spec.rb
new file mode 100644
index 0000000..bad9858
--- /dev/null
+++ b/spec/rubocop/cop/lint/ambiguous_regexp_literal_spec.rb
@@ -0,0 +1,35 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::AmbiguousRegexpLiteral do
+  subject(:cop) { described_class.new }
+
+  before do
+    inspect_source(cop, source)
+  end
+
+  context 'with a regexp literal in the first argument' do
+    context 'without parentheses' do
+      let(:source) { 'p /pattern/' }
+
+      it 'registers an offense' do
+        expect(cop.offenses.size).to eq(1)
+        expect(cop.offenses.first.message).to eq(
+          'Ambiguous regexp literal. Parenthesize the method arguments ' \
+          "if it's surely a regexp literal, or add a whitespace to the " \
+          'right of the / if it should be a division.'
+        )
+        expect(cop.highlights).to eq(['/'])
+      end
+    end
+
+    context 'with parentheses' do
+      let(:source) { 'p(/pattern/)' }
+
+      it 'accepts' do
+        expect(cop.offenses).to be_empty
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/cop/lint/assignment_in_condition_spec.rb b/spec/rubocop/cop/lint/assignment_in_condition_spec.rb
new file mode 100644
index 0000000..bcf46de
--- /dev/null
+++ b/spec/rubocop/cop/lint/assignment_in_condition_spec.rb
@@ -0,0 +1,107 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::AssignmentInCondition, :config do
+  subject(:cop) { described_class.new(config) }
+  let(:cop_config) { { 'AllowSafeAssignment' => true } }
+
+  it 'registers an offense for lvar assignment in condition' do
+    inspect_source(cop,
+                   ['if test = 10',
+                    'end'
+                   ])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for lvar assignment in while condition' do
+    inspect_source(cop,
+                   ['while test = 10',
+                    'end'
+                   ])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for lvar assignment in until condition' do
+    inspect_source(cop,
+                   ['until test = 10',
+                    'end'
+                   ])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for ivar assignment in condition' do
+    inspect_source(cop,
+                   ['if @test = 10',
+                    'end'
+                   ])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for clvar assignment in condition' do
+    inspect_source(cop,
+                   ['if @@test = 10',
+                    'end'
+                   ])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for gvar assignment in condition' do
+    inspect_source(cop,
+                   ['if $test = 10',
+                    'end'
+                   ])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for constant assignment in condition' do
+    inspect_source(cop,
+                   ['if TEST = 10',
+                    'end'
+                   ])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts == in condition' do
+    inspect_source(cop,
+                   ['if test == 10',
+                    'end'
+                   ])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts = in a block that is called in a condition' do
+    inspect_source(cop,
+                   ['return 1 if any_errors? { o = inspect(file) }'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts ||= in condition' do
+    inspect_source(cop,
+                   ['raise StandardError unless foo ||= bar'])
+    expect(cop.offenses).to be_empty
+  end
+
+  context 'safe assignment is allowed' do
+    it 'accepts = in condition surrounded with braces' do
+      inspect_source(cop,
+                     ['if (test = 10)',
+                      'end'
+                     ])
+      expect(cop.offenses).to be_empty
+    end
+
+  end
+
+  context 'safe assignment is not allowed' do
+    let(:cop_config) { { 'AllowSafeAssignment' => false } }
+
+    it 'does not accepts = in condition surrounded with braces' do
+      inspect_source(cop,
+                     ['if (test = 10)',
+                      'end'
+                     ])
+      expect(cop.offenses.size).to eq(1)
+    end
+  end
+end
diff --git a/spec/rubocop/cop/lint/block_alignment_spec.rb b/spec/rubocop/cop/lint/block_alignment_spec.rb
new file mode 100644
index 0000000..48f7015
--- /dev/null
+++ b/spec/rubocop/cop/lint/block_alignment_spec.rb
@@ -0,0 +1,411 @@
+# encoding: utf-8
+# rubocop:disable LineLength
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::BlockAlignment do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for mismatched block end' do
+    inspect_source(cop,
+                   ['test do |ala|',
+                    '  end'
+                   ])
+    expect(cop.messages)
+      .to eq(['end at 2, 2 is not aligned with test do |ala| at 1, 0'])
+  end
+
+  context 'when the block is a logical operand' do
+    it 'accepts a correctly aligned block end' do
+      inspect_source(cop,
+                     ['(value.is_a? Array) && value.all? do |subvalue|',
+                      '  type_check_value(subvalue, array_type)',
+                      'end',
+                      'a || b do',
+                      'end'
+                     ])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  it 'accepts end aligned with a variable' do
+    inspect_source(cop,
+                   ['variable = test do |ala|',
+                    'end'
+                   ])
+    expect(cop.offenses).to be_empty
+  end
+
+  context 'when there is an assignment chain' do
+    it 'registers an offense for an end aligned with the 2nd variable' do
+      inspect_source(cop,
+                     ['a = b = c = test do |ala|',
+                      '    end'
+                     ])
+      expect(cop.messages)
+        .to eq(['end at 2, 4 is not aligned with a = b = c = test do |ala| at 1, 0'])
+    end
+
+    it 'accepts end aligned with the first variable' do
+      inspect_source(cop,
+                     ['a = b = c = test do |ala|',
+                      'end'
+                     ])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'and the block is an operand' do
+    it 'accepts end aligned with a variable' do
+      inspect_source(cop,
+                     ['b = 1 + preceding_line.reduce(0) do |a, e|',
+                      '  a + e.length + newline_length',
+                      'end + 1'
+                     ])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  it 'registers an offense for mismatched block end with a variable' do
+    inspect_source(cop,
+                   ['variable = test do |ala|',
+                    '  end'
+                   ])
+    expect(cop.messages)
+      .to eq(['end at 2, 2 is not aligned with variable = test do |ala| at 1, 0'])
+  end
+
+  context 'when the block is defined on the next line' do
+    it 'accepts end aligned with the block expression' do
+      inspect_source(cop,
+                     ['variable =',
+                      '  a_long_method_that_dont_fit_on_the_line do |v|',
+                      '    v.foo',
+                      '  end'
+                     ])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offenses for mismatched end alignment' do
+      inspect_source(cop,
+                     ['variable =',
+                      '  a_long_method_that_dont_fit_on_the_line do |v|',
+                      '    v.foo',
+                      'end'
+                     ])
+      expect(cop.messages)
+        .to eq(['end at 4, 0 is not aligned with a_long_method_that_dont_fit_on_the_line ' \
+                'do |v| at 2, 2'])
+    end
+  end
+
+  context 'when the method part is a call chain that spans several lines' do
+    # Example from issue 346 of bbatsov/rubocop on github:
+    it 'accepts pretty alignment style' do
+      src = ['def foo(bar)',
+             '  bar.get_stuffs',
+             '      .reject do |stuff| ',
+             '        stuff.with_a_very_long_expression_that_doesnt_fit_the_line',
+             '      end.select do |stuff|',
+             '        stuff.another_very_long_expression_that_doesnt_fit_the_line',
+             '      end',
+             '      .select do |stuff|',
+             '        stuff.another_very_long_expression_that_doesnt_fit_the_line',
+             '      end',
+             'end']
+      inspect_source(cop, src)
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers offenses for misaligned ends' do
+      src = ['def foo(bar)',
+             '  bar.get_stuffs',
+             '      .reject do |stuff|',
+             '        stuff.with_a_very_long_expression_that_doesnt_fit_the_line',
+             '        end.select do |stuff|',
+             '        stuff.another_very_long_expression_that_doesnt_fit_the_line',
+             '    end',
+             '      .select do |stuff|',
+             '        stuff.another_very_long_expression_that_doesnt_fit_the_line',
+             '        end',
+             'end']
+      inspect_source(cop, src)
+      expect(cop.messages)
+        .to eq(['end at 5, 8 is not aligned with bar.get_stuffs at 2, 2 or' \
+                ' .reject do |stuff| at 3, 6',
+                'end at 7, 4 is not aligned with bar.get_stuffs at 2, 2 or' \
+                ' end.select do |stuff| at 5, 8',
+                'end at 10, 8 is not aligned with bar.get_stuffs at 2, 2 or' \
+                ' .select do |stuff| at 8, 6'])
+    end
+
+    # Example from issue 393 of bbatsov/rubocop on github:
+    it 'accepts end indented as the start of the block' do
+      src = ['my_object.chaining_this_very_long_method(with_a_parameter)',
+             '    .and_one_with_a_block do',
+             '  do_something',
+             'end',
+             '', # Other variant:
+             'my_object.chaining_this_very_long_method(',
+             '    with_a_parameter).and_one_with_a_block do',
+             '  do_something',
+             'end']
+      inspect_source(cop, src)
+      expect(cop.offenses).to be_empty
+    end
+
+    # Example from issue 447 of bbatsov/rubocop on github:
+    it 'accepts two kinds of end alignment' do
+      src = [
+        # Aligned with start of line where do is:
+        'params = default_options.merge(options)',
+        '          .delete_if { |k, v| v.nil? }',
+        '          .each_with_object({}) do |(k, v), new_hash|',
+        '            new_hash[k.to_s] = v.to_s',
+        '          end',
+        # Aligned with start of the whole expression:
+        'params = default_options.merge(options)',
+        '          .delete_if { |k, v| v.nil? }',
+        '          .each_with_object({}) do |(k, v), new_hash|',
+        '            new_hash[k.to_s] = v.to_s',
+        'end'
+      ]
+      inspect_source(cop, src)
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'when variables of a mass assignment spans several lines' do
+    it 'accepts end aligned with the variables' do
+      src = ['e,',
+             'f = [5, 6].map do |i|',
+             '  i - 5',
+             'end']
+      inspect_source(cop, src)
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for end aligned with the block' do
+      src = ['e,',
+             'f = [5, 6].map do |i|',
+             '  i - 5',
+             '    end']
+      inspect_source(cop, src)
+      expect(cop.messages)
+        .to eq(['end at 4, 4 is not aligned with e, at 1, 0 or f = [5, 6].map do |i| at 2, 0'])
+    end
+  end
+
+  it 'accepts end aligned with an instance variable' do
+    inspect_source(cop,
+                   ['@variable = test do |ala|',
+                    'end'
+                   ])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'registers an offense for mismatched block end with an instance variable' do
+    inspect_source(cop,
+                   ['@variable = test do |ala|',
+                    '  end'
+                   ])
+    expect(cop.messages)
+      .to eq(['end at 2, 2 is not aligned with @variable = test do |ala| at 1, 0'])
+  end
+
+  it 'accepts end aligned with a class variable' do
+    inspect_source(cop,
+                   ['@@variable = test do |ala|',
+                    'end'
+                   ])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'registers an offense for mismatched block end with a class variable' do
+    inspect_source(cop,
+                   ['@@variable = test do |ala|',
+                    '  end'
+                   ])
+    expect(cop.messages)
+      .to eq(['end at 2, 2 is not aligned with @@variable = test do |ala| at 1, 0'])
+  end
+
+  it 'accepts end aligned with a global variable' do
+    inspect_source(cop,
+                   ['$variable = test do |ala|',
+                    'end'
+                   ])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'registers an offense for mismatched block end with a global variable' do
+    inspect_source(cop,
+                   ['$variable = test do |ala|',
+                    '  end'
+                   ])
+    expect(cop.messages)
+      .to eq(['end at 2, 2 is not aligned with $variable = test do |ala| at 1, 0'])
+  end
+
+  it 'accepts end aligned with a constant' do
+    inspect_source(cop,
+                   ['CONSTANT = test do |ala|',
+                    'end'
+                   ])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'registers an offense for mismatched block end with a constant' do
+    inspect_source(cop,
+                   ['Module::CONSTANT = test do |ala|',
+                    '  end'
+                   ])
+    expect(cop.messages)
+      .to eq(['end at 2, 2 is not aligned with Module::CONSTANT = test do |ala| at 1, 0'])
+  end
+
+  it 'accepts end aligned with a method call' do
+    inspect_source(cop,
+                   ['parser.childs << lambda do |token|',
+                    '  token << 1',
+                    'end'
+                   ])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'registers an offense for mismatched block end with a method call' do
+    inspect_source(cop,
+                   ['parser.childs << lambda do |token|',
+                    '  token << 1',
+                    '  end'
+                   ])
+    expect(cop.messages)
+      .to eq(['end at 3, 2 is not aligned with parser.childs << lambda do |token| at 1, 0'])
+  end
+
+  it 'accepts end aligned with a method call with arguments' do
+    inspect_source(cop,
+                   ['@h[:f] = f.each_pair.map do |f, v|',
+                    '  v = 1',
+                    'end'
+                   ])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'registers an offense for mismatched end with a method call with arguments' do
+    inspect_source(cop,
+                   ['@h[:f] = f.each_pair.map do |f, v|',
+                    '  v = 1',
+                    '  end'
+                   ])
+    expect(cop.messages)
+      .to eq(['end at 3, 2 is not aligned with @h[:f] = f.each_pair.map do |f, v| at 1, 0'])
+  end
+
+  it 'does not raise an error for nested block in a method call' do
+    inspect_source(cop,
+                   ['expect(arr.all? { |o| o.valid? })'
+                   ])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts end aligned with the block when the block is a method argument' do
+    inspect_source(cop,
+                   ['expect(arr.all? do |o|',
+                    '         o.valid?',
+                    '       end)'
+                   ])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'registers an offense for mismatched end not aligned with the block that is an argument' do
+    inspect_source(cop,
+                   ['expect(arr.all? do |o|',
+                    '  o.valid?',
+                    '  end)'
+                   ])
+    expect(cop.messages)
+      .to eq(['end at 3, 2 is not aligned with arr.all? do |o| at 1, 7 or ' \
+              'expect(arr.all? do |o| at 1, 0'])
+  end
+
+  it 'accepts end aligned with an op-asgn (+=, -=)' do
+    inspect_source(cop,
+                   ['rb += files.select do |file|',
+                    '  file << something',
+                    'end'
+                   ])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'registers an offense for mismatched block end with an op-asgn (+=, -=)' do
+    inspect_source(cop,
+                   ['rb += files.select do |file|',
+                    '  file << something',
+                    '  end'
+                   ])
+    expect(cop.messages)
+      .to eq(['end at 3, 2 is not aligned with rb at 1, 0'])
+  end
+
+  it 'accepts end aligned with an and-asgn (&&=)' do
+    inspect_source(cop,
+                   ['variable &&= test do |ala|',
+                    'end'
+                   ])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'registers an offense for mismatched block end with an and-asgn (&&=)' do
+    inspect_source(cop,
+                   ['variable &&= test do |ala|',
+                    '  end'
+                   ])
+    expect(cop.messages)
+      .to eq(['end at 2, 2 is not aligned with variable &&= test do |ala| at 1, 0'])
+  end
+
+  it 'accepts end aligned with an or-asgn (||=)' do
+    inspect_source(cop,
+                   ['variable ||= test do |ala|',
+                    'end'
+                   ])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'registers an offense for mismatched block end with an or-asgn (||=)' do
+    inspect_source(cop,
+                   ['variable ||= test do |ala|',
+                    '  end'
+                   ])
+    expect(cop.messages)
+      .to eq(['end at 2, 2 is not aligned with variable ||= test do |ala| at 1, 0'])
+  end
+
+  it 'accepts end aligned with a mass assignment' do
+    inspect_source(cop,
+                   ['var1, var2 = lambda do |test|',
+                    '  [1, 2]',
+                    'end'
+                   ])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts end aligned with a call chain left hand side' do
+    inspect_source(cop,
+                   ['parser.diagnostics.consumer = lambda do |diagnostic|',
+                    '  diagnostics << diagnostic',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'registers an offense for mismatched block end with a mass assignment' do
+    inspect_source(cop,
+                   ['var1, var2 = lambda do |test|',
+                    '  [1, 2]',
+                    '  end'
+                   ])
+    expect(cop.messages)
+      .to eq(['end at 3, 2 is not aligned with var1, var2 at 1, 0'])
+  end
+end
diff --git a/spec/rubocop/cop/lint/condition_position_spec.rb b/spec/rubocop/cop/lint/condition_position_spec.rb
new file mode 100644
index 0000000..fa26861
--- /dev/null
+++ b/spec/rubocop/cop/lint/condition_position_spec.rb
@@ -0,0 +1,49 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::ConditionPosition do
+  subject(:cop) { described_class.new }
+
+  %w(if unless while until).each do |keyword|
+    it 'registers an offense for condition on the next line' do
+      inspect_source(cop,
+                     ["#{keyword}",
+                      'x == 10',
+                      'end'
+                    ])
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it 'accepts condition on the same line' do
+      inspect_source(cop,
+                     ["#{keyword} x == 10",
+                      ' bala',
+                      'end'
+                    ])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  it 'registers an offense for elsif condition on the next line' do
+    inspect_source(cop,
+                   ['if something',
+                    '  test',
+                    'elsif',
+                    '  something',
+                    '  test',
+                    'end'
+                  ])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'handles ternary ops' do
+    inspect_source(cop, ['x ? a : b'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'handles modifier forms' do
+    inspect_source(cop, ['x if something'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/lint/debugger_spec.rb b/spec/rubocop/cop/lint/debugger_spec.rb
new file mode 100644
index 0000000..22d058e
--- /dev/null
+++ b/spec/rubocop/cop/lint/debugger_spec.rb
@@ -0,0 +1,39 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::Debugger do
+  subject(:cop) { described_class.new  }
+
+  it 'reports an offense for a debugger call' do
+    src = ['debugger']
+    inspect_source(cop, src)
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'reports an offense for pry bindings' do
+    src = ['binding.pry',
+           'binding.remote_pry']
+    inspect_source(cop, src)
+    expect(cop.offenses.size).to eq(2)
+  end
+
+  it 'does not report an offense for non-pry binding' do
+    src = ['binding.pirate']
+    inspect_source(cop, src)
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not report an offense for debugger in comments' do
+    src = ['# debugger']
+    inspect_source(cop, src)
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not report an offense for a debugger or pry method' do
+    src = ['code.debugger',
+           'door.pry']
+    inspect_source(cop, src)
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/lint/deprecated_class_methods_spec.rb b/spec/rubocop/cop/lint/deprecated_class_methods_spec.rb
new file mode 100644
index 0000000..ffac3c4
--- /dev/null
+++ b/spec/rubocop/cop/lint/deprecated_class_methods_spec.rb
@@ -0,0 +1,38 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::DeprecatedClassMethods do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for File.exists?' do
+    inspect_source(cop, 'File.exists?(o)')
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages)
+      .to eq(['`File.exists?` is deprecated in favor of `File.exist?`.'])
+  end
+
+  it 'registers an offense for ::File.exists?' do
+    inspect_source(cop, '::File.exists?(o)')
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages)
+      .to eq(['`File.exists?` is deprecated in favor of `File.exist?`.'])
+  end
+
+  it 'registers an offense for Dir.exists?' do
+    inspect_source(cop, 'Dir.exists?(o)')
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages)
+      .to eq(['`Dir.exists?` is deprecated in favor of `Dir.exist?`.'])
+  end
+
+  it 'auto-corrects File.exists? with File.exist?' do
+    new_source = autocorrect_source(cop, 'File.exists?(something)')
+    expect(new_source).to eq('File.exist?(something)')
+  end
+
+  it 'auto-corrects Dir.exists? with Dir.exist?' do
+    new_source = autocorrect_source(cop, 'Dir.exists?(something)')
+    expect(new_source).to eq('Dir.exist?(something)')
+  end
+end
diff --git a/spec/rubocop/cop/lint/else_layout_spec.rb b/spec/rubocop/cop/lint/else_layout_spec.rb
new file mode 100644
index 0000000..8ea4aa2
--- /dev/null
+++ b/spec/rubocop/cop/lint/else_layout_spec.rb
@@ -0,0 +1,65 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::ElseLayout do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for expr on same line as else' do
+    inspect_source(cop,
+                   ['if something',
+                    '  test',
+                    'else ala',
+                    '  something',
+                    '  test',
+                    'end'
+                  ])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts proper else' do
+    inspect_source(cop,
+                   ['if something',
+                    '  test',
+                    'else',
+                    '  something',
+                    '  test',
+                    'end'
+                  ])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts single-expr else regardless of layout' do
+    inspect_source(cop,
+                   ['if something',
+                    '  test',
+                    'else bala',
+                    'end'
+                  ])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'can handle elsifs' do
+    inspect_source(cop,
+                   ['if something',
+                    '  test',
+                    'elsif something',
+                    '  bala',
+                    'else ala',
+                    '  something',
+                    '  test',
+                    'end'
+                  ])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'handles ternary ops' do
+    inspect_source(cop, 'x ? a : b')
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'handles modifier forms' do
+    inspect_source(cop, 'x if something')
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/lint/empty_ensure_spec.rb b/spec/rubocop/cop/lint/empty_ensure_spec.rb
new file mode 100644
index 0000000..08863e9
--- /dev/null
+++ b/spec/rubocop/cop/lint/empty_ensure_spec.rb
@@ -0,0 +1,27 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::EmptyEnsure do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for empty ensure' do
+    inspect_source(cop,
+                   ['begin',
+                    '  something',
+                    'ensure',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'does not register an offense for non-empty ensure' do
+    inspect_source(cop,
+                   ['begin',
+                    '  something',
+                    '  return',
+                    'ensure',
+                    '  file.close',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/lint/empty_interpolation_spec.rb b/spec/rubocop/cop/lint/empty_interpolation_spec.rb
new file mode 100644
index 0000000..630ae74
--- /dev/null
+++ b/spec/rubocop/cop/lint/empty_interpolation_spec.rb
@@ -0,0 +1,18 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::EmptyInterpolation do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for #{} in interpolation' do
+    inspect_source(cop, ['"this is the #{}"'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.highlights).to eq(['#{}'])
+  end
+
+  it 'accepts non-empty interpolation' do
+    inspect_source(cop, '"this is #{top} silly"')
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/lint/end_alignment_spec.rb b/spec/rubocop/cop/lint/end_alignment_spec.rb
new file mode 100644
index 0000000..ff200fb
--- /dev/null
+++ b/spec/rubocop/cop/lint/end_alignment_spec.rb
@@ -0,0 +1,135 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::EndAlignment, :config do
+  subject(:cop) { described_class.new(config) }
+  let(:cop_config) { { 'AlignWith' => 'keyword' } }
+  let(:opposite) do
+    cop_config['AlignWith'] == 'keyword' ? 'variable' : 'keyword'
+  end
+
+  shared_examples 'misaligned' do |prefix, alignment_base, arg, end_kw, name|
+    name ||= alignment_base
+    it "registers an offense for mismatched #{name} ... end" do
+      inspect_source(cop, ["#{prefix}#{alignment_base} #{arg}",
+                           end_kw])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages.first)
+        .to match(/end at 2, \d+ is not aligned with #{alignment_base} at 1,/)
+      expect(cop.highlights.first).to eq('end')
+      expect(cop.config_to_allow_offenses).to eq('AlignWith' => opposite)
+    end
+  end
+
+  shared_examples 'aligned' do |alignment_base, arg, end_kw, name|
+    name ||= alignment_base
+    it "accepts matching #{name} ... end" do
+      inspect_source(cop, ["#{alignment_base} #{arg}",
+                           end_kw])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  include_examples 'misaligned', '', 'class',  'Test',      '  end'
+  include_examples 'misaligned', '', 'module', 'Test',      '  end'
+  include_examples 'misaligned', '', 'def',    'test',      '  end'
+  include_examples 'misaligned', '', 'def',    'Test.test', '  end', 'defs'
+  include_examples 'misaligned', '', 'if',     'test',      '  end'
+  include_examples 'misaligned', '', 'unless', 'test',      '  end'
+  include_examples 'misaligned', '', 'while',  'test',      '  end'
+  include_examples 'misaligned', '', 'until',  'test',      '  end'
+
+  include_examples 'aligned', 'class',  'Test',      'end'
+  include_examples 'aligned', 'module', 'Test',      'end'
+  include_examples 'aligned', 'def',    'test',      'end'
+  include_examples 'aligned', 'def',    'Test.test', 'end', 'defs'
+  include_examples 'aligned', 'if',     'test',      'end'
+  include_examples 'aligned', 'unless', 'test',      'end'
+  include_examples 'aligned', 'while',  'test',      'end'
+  include_examples 'aligned', 'until',  'test',      'end'
+
+  context 'in ruby 2.1 or later' do
+    include_examples 'aligned', 'public def',          'test', 'end'
+    include_examples 'aligned', 'protected def',       'test', 'end'
+    include_examples 'aligned', 'private def',         'test', 'end'
+    include_examples 'aligned', 'module_function def', 'test', 'end'
+
+    include_examples('misaligned', '',
+                     'public def', 'test',
+                     '       end')
+    include_examples('misaligned', '',
+                     'protected def', 'test',
+                     '          end')
+    include_examples('misaligned', '',
+                     'private def', 'test',
+                     '        end')
+    include_examples('misaligned', '',
+                     'module_function def', 'test',
+                     '                end')
+  end
+
+  it 'can handle ternary if' do
+    inspect_source(cop, 'a = cond ? x : y')
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'can handle modifier if' do
+    inspect_source(cop, 'a = x if cond')
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'registers an offense for correct + opposite' do
+    inspect_source(cop, ['x = if a',
+                         '      a1',
+                         '    end',
+                         'y = if b',
+                         '  b1',
+                         'end'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages.first)
+      .to eq('end at 6, 0 is not aligned with if at 4, 4')
+    expect(cop.highlights.first).to eq('end')
+    expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+  end
+
+  context 'regarding assignment' do
+    context 'when AlignWith is keyword' do
+      include_examples 'misaligned', 'var = ', 'if',     'test', 'end'
+      include_examples 'misaligned', 'var = ', 'unless', 'test', 'end'
+      include_examples 'misaligned', 'var = ', 'while',  'test', 'end'
+      include_examples 'misaligned', 'var = ', 'until',  'test', 'end'
+
+      include_examples 'aligned', 'var = if',     'test', '      end'
+      include_examples 'aligned', 'var = unless', 'test', '      end'
+      include_examples 'aligned', 'var = while',  'test', '      end'
+      include_examples 'aligned', 'var = until',  'test', '      end'
+    end
+
+    context 'when AlignWith is variable' do
+      let(:cop_config) { { 'AlignWith' => 'variable' } }
+
+      include_examples 'aligned', 'var = if',     'test', 'end'
+      include_examples 'aligned', 'var = unless', 'test', 'end'
+      include_examples 'aligned', 'var = while',  'test', 'end'
+      include_examples 'aligned', 'var = until',  'test', 'end'
+      include_examples 'aligned', 'var = until',  'test', 'end.abc.join("")'
+      include_examples 'aligned', 'var = until',  'test', 'end.abc.tap {}'
+
+      include_examples 'misaligned', '', 'var = if',     'test', '      end'
+      include_examples 'misaligned', '', 'var = unless', 'test', '      end'
+      include_examples 'misaligned', '', 'var = while',  'test', '      end'
+      include_examples 'misaligned', '', 'var = until',  'test', '      end'
+      include_examples 'misaligned', '', 'var = until',  'test', '      end.j'
+
+      include_examples 'aligned', '@var = if',  'test', 'end'
+      include_examples 'aligned', '@@var = if', 'test', 'end'
+      include_examples 'aligned', '$var = if',  'test', 'end'
+      include_examples 'aligned', 'CNST = if',  'test', 'end'
+      include_examples 'aligned', 'a, b = if',  'test', 'end'
+      include_examples 'aligned', 'var ||= if', 'test', 'end'
+      include_examples 'aligned', 'var &&= if', 'test', 'end'
+      include_examples 'aligned', 'var += if',  'test', 'end'
+    end
+  end
+end
diff --git a/spec/rubocop/cop/lint/end_in_method_spec.rb b/spec/rubocop/cop/lint/end_in_method_spec.rb
new file mode 100644
index 0000000..aad28e0
--- /dev/null
+++ b/spec/rubocop/cop/lint/end_in_method_spec.rb
@@ -0,0 +1,29 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::EndInMethod do
+  subject(:cop) { described_class.new }
+
+  it 'reports an offense for def with an END inside' do
+    src = ['def test',
+           '  END { something }',
+           'end']
+    inspect_source(cop, src)
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'reports an offense for defs with an END inside' do
+    src = ['def self.test',
+           '  END { something }',
+           'end']
+    inspect_source(cop, src)
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts END outside of def(s)' do
+    src = ['END { something }']
+    inspect_source(cop, src)
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/lint/ensure_return_spec.rb b/spec/rubocop/cop/lint/ensure_return_spec.rb
new file mode 100644
index 0000000..471c547
--- /dev/null
+++ b/spec/rubocop/cop/lint/ensure_return_spec.rb
@@ -0,0 +1,39 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::EnsureReturn do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for return in ensure' do
+    inspect_source(cop,
+                   ['begin',
+                    '  something',
+                    'ensure',
+                    '  file.close',
+                    '  return',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'does not register an offense for return outside ensure' do
+    inspect_source(cop,
+                   ['begin',
+                    '  something',
+                    '  return',
+                    'ensure',
+                    '  file.close',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not check when ensure block has no body' do
+    expect do
+      inspect_source(cop,
+                     ['begin',
+                      '  something',
+                      'ensure',
+                      'end'])
+    end.to_not raise_exception
+  end
+end
diff --git a/spec/rubocop/cop/lint/eval_spec.rb b/spec/rubocop/cop/lint/eval_spec.rb
new file mode 100644
index 0000000..aba9114
--- /dev/null
+++ b/spec/rubocop/cop/lint/eval_spec.rb
@@ -0,0 +1,33 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::Eval do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for eval as function' do
+    inspect_source(cop,
+                   ['eval(something)'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.highlights) .to eq(['eval'])
+  end
+
+  it 'registers an offense for eval as command' do
+    inspect_source(cop,
+                   ['eval something'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.highlights) .to eq(['eval'])
+  end
+
+  it 'does not register an offense for eval as variable' do
+    inspect_source(cop,
+                   ['eval = something'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense for eval as method' do
+    inspect_source(cop,
+                   ['something.eval'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/lint/handle_exceptions_spec.rb b/spec/rubocop/cop/lint/handle_exceptions_spec.rb
new file mode 100644
index 0000000..adf3f51
--- /dev/null
+++ b/spec/rubocop/cop/lint/handle_exceptions_spec.rb
@@ -0,0 +1,30 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::HandleExceptions do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for empty rescue block' do
+    inspect_source(cop,
+                   ['begin',
+                    '  something',
+                    'rescue',
+                    '  #do nothing',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages)
+      .to eq(['Do not suppress exceptions.'])
+  end
+
+  it 'does not register an offense for rescue with body' do
+    inspect_source(cop,
+                   ['begin',
+                    '  something',
+                    '  return',
+                    'rescue',
+                    '  file.close',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/lint/invalid_character_literal_spec.rb b/spec/rubocop/cop/lint/invalid_character_literal_spec.rb
new file mode 100644
index 0000000..2624fb1
--- /dev/null
+++ b/spec/rubocop/cop/lint/invalid_character_literal_spec.rb
@@ -0,0 +1,33 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::InvalidCharacterLiteral do
+  subject(:cop) { described_class.new }
+
+  # Is there a way to emit this warning without syntax error?
+  #
+  #   $ ruby -w
+  #   p(? )
+  #   -:1: warning: invalid character syntax; use ?\s
+  #   -:1: syntax error, unexpected '?', expecting ')'
+  #   p(? )
+  #      ^
+  #
+  # https://github.com/ruby/ruby/blob/v2_1_0/parse.y#L7276
+  # https://github.com/whitequark/parser/blob/v2.1.2/lib/parser/lexer.rl#L1660
+  context 'with a non-escaped whitespace character literal ' do
+    let(:source) { 'p(? )' }
+
+    it 'registers an offense' do
+      pending 'Is there a way to emit this warning without syntax errors?'
+
+      inspect_source(cop, source)
+
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Invalid character literal; use ?\s')
+      expect(cop.highlights).to eq([' '])
+    end
+  end
+end
diff --git a/spec/rubocop/cop/lint/literal_in_condition_spec.rb b/spec/rubocop/cop/lint/literal_in_condition_spec.rb
new file mode 100644
index 0000000..03d8784
--- /dev/null
+++ b/spec/rubocop/cop/lint/literal_in_condition_spec.rb
@@ -0,0 +1,154 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::LiteralInCondition do
+  subject(:cop) { described_class.new }
+
+  %w(1 2.0 [1] {}).each do |lit|
+    it "registers an offense for literal #{lit} in if" do
+      inspect_source(cop,
+                     ["if #{lit}",
+                      '  top',
+                      'end'
+                     ])
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it "registers an offense for literal #{lit} in while" do
+      inspect_source(cop,
+                     ["while #{lit}",
+                      '  top',
+                      'end'
+                     ])
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it "registers an offense for literal #{lit} in until" do
+      inspect_source(cop,
+                     ["until #{lit}",
+                      '  top',
+                      'end'
+                     ])
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it "registers an offense for literal #{lit} in case" do
+      inspect_source(cop,
+                     ["case #{lit}",
+                      'when x then top',
+                      'end'
+                     ])
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it "registers an offense for literal #{lit} in a when " \
+       'of a case without anything after case keyword' do
+      inspect_source(cop,
+                     ['case',
+                      "when #{lit} then top",
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it "accepts literal #{lit} in a when of a case with " \
+       'something after case keyword' do
+      inspect_source(cop,
+                     ['case x',
+                      "when #{lit} then top",
+                      'end'
+                     ])
+      expect(cop.offenses).to be_empty
+    end
+
+    it "registers an offense for literal #{lit} in &&" do
+      inspect_source(cop,
+                     ["if x && #{lit}",
+                      '  top',
+                      'end'
+                     ])
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it "registers an offense for literal #{lit} in complex cond" do
+      inspect_source(cop,
+                     ["if x && !(a && #{lit}) && y && z",
+                      '  top',
+                      'end'
+                     ])
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it "registers an offense for literal #{lit} in !" do
+      inspect_source(cop,
+                     ["if !#{lit}",
+                      '  top',
+                      'end'
+                     ])
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it "registers an offense for literal #{lit} in complex !" do
+      inspect_source(cop,
+                     ["if !(x && (y && #{lit}))",
+                      '  top',
+                      'end'
+                     ])
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it "accepts literal #{lit} if it's not an and/or operand" do
+      inspect_source(cop,
+                     ["if test(#{lit})",
+                      '  top',
+                      'end'
+                     ])
+      expect(cop.offenses).to be_empty
+    end
+
+    it "accepts literal #{lit} in non-toplevel and/or" do
+      inspect_source(cop,
+                     ["if (a || #{lit}).something",
+                      '  top',
+                      'end'
+                     ])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  it 'accepts array literal in case, if it has non-literal elements' do
+    inspect_source(cop,
+                   ['case [1, 2, x]',
+                    'when [1, 2, 5] then top',
+                    'end'
+                   ])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts array literal in case, if it has non-literal elements' do
+    inspect_source(cop,
+                   ['case [1, 2, [x, 1]]',
+                    'when [1, 2, 5] then top',
+                    'end'
+                   ])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'registers an offense for case with a primitive array condition' do
+    inspect_source(cop,
+                   ['case [1, 2, [3, 4]]',
+                    'when [1, 2, 5] then top',
+                    'end'
+                   ])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts dstr literal in case' do
+    inspect_source(cop,
+                   ['case "#{x}"',
+                    'when [1, 2, 5] then top',
+                    'end'
+                   ])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/lint/literal_in_interpolation_spec.rb b/spec/rubocop/cop/lint/literal_in_interpolation_spec.rb
new file mode 100644
index 0000000..0da5b16
--- /dev/null
+++ b/spec/rubocop/cop/lint/literal_in_interpolation_spec.rb
@@ -0,0 +1,31 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::LiteralInInterpolation do
+  subject(:cop) { described_class.new }
+
+  %w(1 2.0 [1] {}).each do |lit|
+    it "registers an offense for #{lit} in interpolation" do
+      inspect_source(cop,
+                     ["\"this is the \#{#{lit}}\""])
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it "registers an offense only for final #{lit} in interpolation" do
+      inspect_source(cop,
+                     ["\"this is the \#{#{lit};#{lit}}\""])
+      expect(cop.offenses.size).to eq(1)
+    end
+  end
+
+  it 'accepts empty interpolation' do
+    inspect_source(cop, '"this is #{} silly"')
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts strings like __FILE__' do
+    inspect_source(cop, '"this is #{__FILE__} silly"')
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/lint/loop_spec.rb b/spec/rubocop/cop/lint/loop_spec.rb
new file mode 100644
index 0000000..35bb7c6
--- /dev/null
+++ b/spec/rubocop/cop/lint/loop_spec.rb
@@ -0,0 +1,27 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::Loop do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for begin/end/while' do
+    inspect_source(cop, ['begin something; top; end while test'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for begin/end/until' do
+    inspect_source(cop, ['begin something; top; end until test'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts normal while' do
+    inspect_source(cop, ['while test; one; two; end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts normal until' do
+    inspect_source(cop, ['until test; one; two; end'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/lint/parentheses_as_grouped_expression_spec.rb b/spec/rubocop/cop/lint/parentheses_as_grouped_expression_spec.rb
new file mode 100644
index 0000000..da07e4b
--- /dev/null
+++ b/spec/rubocop/cop/lint/parentheses_as_grouped_expression_spec.rb
@@ -0,0 +1,57 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::ParenthesesAsGroupedExpression do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for method call with space before the ' \
+     'parenthesis' do
+    inspect_source(cop, ['a.func (x)'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for predicate method call with space ' \
+     'before the parenthesis' do
+    inspect_source(cop, ['is? (x)'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for math expression' do
+    inspect_source(cop, ['puts (2 + 3) * 4'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts a method call without arguments' do
+    inspect_source(cop, ['func'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a method call with arguments but no parentheses' do
+    inspect_source(cop, ['puts x'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a chain of method calls' do
+    inspect_source(cop, ['a.b',
+                         'a.b 1',
+                         'a.b(1)'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts method with parens as arg to method without' do
+    inspect_source(cop, ['a b(c)'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts an operator call with argument in parentheses' do
+    inspect_source(cop, ['a % (b + c)',
+                         'a.b = (c == d)'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a space inside opening paren followed by left paren' do
+    inspect_source(cop, ['a( (b) )'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/lint/require_parentheses_spec.rb b/spec/rubocop/cop/lint/require_parentheses_spec.rb
new file mode 100644
index 0000000..b156a1f
--- /dev/null
+++ b/spec/rubocop/cop/lint/require_parentheses_spec.rb
@@ -0,0 +1,82 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::RequireParentheses do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for missing parentheses around expression with ' \
+     '&& operator' do
+    inspect_source(cop, ["if day.is? 'monday' && month == :jan",
+                         '  foo',
+                         'end'])
+    expect(cop.highlights).to eq(["day.is? 'monday' && month == :jan"])
+    expect(cop.messages)
+      .to eq(['Use parentheses in the method call to avoid confusion about ' \
+              'precedence.'])
+  end
+
+  it 'registers an offense for missing parentheses around expression with ' \
+     '|| operator' do
+    inspect_source(cop, "day_is? 'tuesday' || true")
+    expect(cop.highlights).to eq(["day_is? 'tuesday' || true"])
+  end
+
+  it 'registers an offense for missing parentheses around expression in ' \
+     'ternary' do
+    inspect_source(cop, "wd.include? 'tuesday' && true == true ? a : b")
+    expect(cop.highlights).to eq(["wd.include? 'tuesday' && true == true"])
+  end
+
+  it 'accepts missing parentheses around expression with + operator' do
+    inspect_source(cop, ["if day_is? 'tuesday' + rest",
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts method calls without parentheses followed by keyword and/or' do
+    inspect_source(cop, ["if day.is? 'tuesday' and month == :jan",
+                         'end',
+                         "if day.is? 'tuesday' or month == :jan",
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts method calls that are all operations' do
+    inspect_source(cop, ['if current_level == max + 1',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts condition that is not a call' do
+    inspect_source(cop, ['if @debug',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts parentheses around expression with boolean operator' do
+    inspect_source(cop, ["if day.is?('tuesday' && true == true)",
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts method call with parentheses in ternary' do
+    inspect_source(cop, "wd.include?('tuesday' && true == true) ? a : b")
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts missing parentheses when method is not a predicate' do
+    inspect_source(cop, "weekdays.foo 'tuesday' && true == true")
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts calls to methods that are setters' do
+    inspect_source(cop, 's.version = @version || ">= 1.8.5"')
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts calls to methods that are operators' do
+    inspect_source(cop, 'a[b || c]')
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/lint/rescue_exception_spec.rb b/spec/rubocop/cop/lint/rescue_exception_spec.rb
new file mode 100644
index 0000000..2f62410
--- /dev/null
+++ b/spec/rubocop/cop/lint/rescue_exception_spec.rb
@@ -0,0 +1,123 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::RescueException do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for rescue from Exception' do
+    inspect_source(cop,
+                   ['begin',
+                    '  something',
+                    'rescue Exception',
+                    '  #do nothing',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for rescue with ::Exception' do
+    inspect_source(cop,
+                   ['begin',
+                    '  something',
+                    'rescue ::Exception',
+                    '  #do nothing',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for rescue with StandardError, Exception' do
+    inspect_source(cop,
+                   ['begin',
+                    '  something',
+                    'rescue StandardError, Exception',
+                    '  #do nothing',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for rescue with Exception => e' do
+    inspect_source(cop,
+                   ['begin',
+                    '  something',
+                    'rescue Exception => e',
+                    '  #do nothing',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'does not register an offense for rescue with no class' do
+    inspect_source(cop,
+                   ['begin',
+                    '  something',
+                    '  return',
+                    'rescue',
+                    '  file.close',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense for rescue with no class and => e' do
+    inspect_source(cop,
+                   ['begin',
+                    '  something',
+                    '  return',
+                    'rescue => e',
+                    '  file.close',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense for rescue with other class' do
+    inspect_source(cop,
+                   ['begin',
+                    '  something',
+                    '  return',
+                    'rescue ArgumentError => e',
+                    '  file.close',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense for rescue with other classes' do
+    inspect_source(cop,
+                   ['begin',
+                    '  something',
+                    '  return',
+                    'rescue EOFError, ArgumentError => e',
+                    '  file.close',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense for rescue with a module prefix' do
+    inspect_source(cop,
+                   ['begin',
+                    '  something',
+                    '  return',
+                    'rescue Test::Exception => e',
+                    '  file.close',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not crash when the splat operator is used in a rescue' do
+    inspect_source(cop,
+                   ['ERRORS = [Exception]',
+                    'begin',
+                    '  a = 3 / 0',
+                    'rescue *ERRORS',
+                    '  puts e',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not crash when the namespace of a rescued class is in a local ' \
+     'variable' do
+    inspect_source(cop,
+                   ['adapter = current_adapter',
+                    'begin',
+                    'rescue adapter::ParseError',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/lint/shadowing_outer_local_variable_spec.rb b/spec/rubocop/cop/lint/shadowing_outer_local_variable_spec.rb
new file mode 100644
index 0000000..3948343
--- /dev/null
+++ b/spec/rubocop/cop/lint/shadowing_outer_local_variable_spec.rb
@@ -0,0 +1,237 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::ShadowingOuterLocalVariable do
+  subject(:cop) { described_class.new }
+
+  context 'when a block argument has same name ' \
+          'as an outer scope variable' do
+    let(:source) do
+      [
+        'def some_method',
+        '  foo = 1',
+        '  puts foo',
+        '  1.times do |foo|',
+        '  end',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to include('Shadowing outer local variable - `foo`')
+      expect(cop.offenses.first.line).to eq(4)
+    end
+
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a splat block argument has same name ' \
+          'as an outer scope variable' do
+    let(:source) do
+      [
+        'def some_method',
+        '  foo = 1',
+        '  puts foo',
+        '  1.times do |*foo|',
+        '  end',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to include('Shadowing outer local variable - `foo`')
+      expect(cop.offenses.first.line).to eq(4)
+    end
+
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a block block argument has same name ' \
+          'as an outer scope variable' do
+    let(:source) do
+      [
+        'def some_method',
+        '  foo = 1',
+        '  puts foo',
+        '  proc_taking_block = proc do |&foo|',
+        '  end',
+        '  proc_taking_block.call do',
+        '  end',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to include('Shadowing outer local variable - `foo`')
+      expect(cop.offenses.first.line).to eq(4)
+    end
+
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a block local variable has same name ' \
+          'as an outer scope variable' do
+    let(:source) do
+      [
+        'def some_method',
+        '  foo = 1',
+        '  puts foo',
+        '  1.times do |i; foo|',
+        '    puts foo',
+        '  end',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to include('Shadowing outer local variable - `foo`')
+      expect(cop.offenses.first.line).to eq(4)
+    end
+
+    include_examples 'mimics MRI 2.1', 'shadowing'
+  end
+
+  context 'when a block argument has different name ' \
+          'with outer scope variables' do
+    let(:source) do
+      [
+        'def some_method',
+        '  foo = 1',
+        '  puts foo',
+        '  1.times do |bar|',
+        '  end',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when an outer scope variable is reassigned in a block' do
+    let(:source) do
+      [
+        'def some_method',
+        '  foo = 1',
+        '  puts foo',
+        '  1.times do',
+        '    foo = 2',
+        '  end',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when an outer scope variable is referenced in a block' do
+    let(:source) do
+      [
+        'def some_method',
+        '  foo = 1',
+        '  puts foo',
+        '  1.times do',
+        '    puts foo',
+        '  end',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when multiple block arguments have same name "_"' do
+    let(:source) do
+      [
+        'def some_method',
+        '  1.times do |_, foo, _|',
+        '  end',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when multiple block arguments have ' \
+          'a same name starts with "_"' do
+    let(:source) do
+      [
+        'def some_method',
+        '  1.times do |_foo, bar, _foo|',
+        '  end',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts' unless RUBY_VERSION < '2.0'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a block argument has same name "_" ' \
+          'as outer scope variable "_"' do
+    let(:source) do
+      [
+        'def some_method',
+        '  _ = 1',
+        '  puts _',
+        '  1.times do |_|',
+        '  end',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a block argument has a same name starts with "_" ' \
+          'as an outer scope variable' do
+    let(:source) do
+      [
+        'def some_method',
+        '  _foo = 1',
+        '  puts _foo',
+        '  1.times do |_foo|',
+        '  end',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a method argument has same name ' \
+          'as an outer scope variable' do
+    let(:source) do
+      [
+        'class SomeClass',
+        '  foo = 1',
+        '  puts foo',
+        '  def some_method(foo)',
+        '  end',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+end
diff --git a/spec/rubocop/cop/lint/space_before_first_arg_spec.rb b/spec/rubocop/cop/lint/space_before_first_arg_spec.rb
new file mode 100644
index 0000000..64ed798
--- /dev/null
+++ b/spec/rubocop/cop/lint/space_before_first_arg_spec.rb
@@ -0,0 +1,58 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::SpaceBeforeFirstArg do
+  subject(:cop) { described_class.new }
+
+  context 'for method calls without parentheses' do
+    it 'registers an offense for method call with no space before the ' \
+       'first arg' do
+      inspect_source(cop, ['something?x',
+                           'a.something!y, z'])
+      expect(cop.messages)
+        .to eq(['Put space between the method name and the first ' \
+                'argument.'] * 2)
+      expect(cop.highlights).to eq(%w(x y))
+    end
+
+    it 'accepts a method call with space before the first arg' do
+      inspect_source(cop, ['something? x',
+                           'a.something! y, z'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts square brackets operator' do
+      inspect_source(cop, ['something[:x]'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts a method call with space before a multiline arg' do
+      inspect_source(cop, "something [\n  'foo',\n  'bar'\n]")
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts an assignment without space before first arg' do
+      inspect_source(cop, ['a.something=c', 'a.something,b=c,d'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'for method calls with parentheses' do
+    it 'accepts a method call without space' do
+      inspect_source(cop, ['something?(x)',
+                           'a.something(y, z)'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts a method call with space after the left parenthesis' do
+      inspect_source(cop, ['something?(  x  )'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts setter call' do
+      inspect_source(cop, ['self.class.controller_path=(path)'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+end
diff --git a/spec/rubocop/cop/lint/string_conversion_in_interpolation_spec.rb b/spec/rubocop/cop/lint/string_conversion_in_interpolation_spec.rb
new file mode 100644
index 0000000..c13b9c5
--- /dev/null
+++ b/spec/rubocop/cop/lint/string_conversion_in_interpolation_spec.rb
@@ -0,0 +1,51 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::StringConversionInInterpolation do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for #to_s in interpolation' do
+    inspect_source(cop, '"this is the #{result.to_s}"')
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages)
+      .to eq(['Redundant use of `Object#to_s` in interpolation.'])
+  end
+
+  it 'detects #to_s in an interpolation with several expressions' do
+    inspect_source(cop, '"this is the #{top; result.to_s}"')
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts #to_s with arguments in an interpolation' do
+    inspect_source(cop, '"this is a #{result.to_s(8)}"')
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts interpolation without #to_s' do
+    inspect_source(cop, '"this is the #{result}"')
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not explode on implicit receiver' do
+    inspect_source(cop, '"#{to_s}"')
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages)
+      .to eq(['Use `self` instead of `Object#to_s` in interpolation.'])
+  end
+
+  it 'does not explode on empty interpolation' do
+    inspect_source(cop, '"this is #{} silly"')
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'autocorrects by removing the redundant to_s' do
+    corrected = autocorrect_source(cop, ['"some #{something.to_s}"'])
+    expect(corrected).to eq '"some #{something}"'
+  end
+
+  it 'autocorrects implicit receiver by replacing to_s with self' do
+    corrected = autocorrect_source(cop, ['"some #{to_s}"'])
+    expect(corrected).to eq '"some #{self}"'
+  end
+end
diff --git a/spec/rubocop/cop/lint/syntax_spec.rb b/spec/rubocop/cop/lint/syntax_spec.rb
new file mode 100644
index 0000000..8671411
--- /dev/null
+++ b/spec/rubocop/cop/lint/syntax_spec.rb
@@ -0,0 +1,34 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::Syntax do
+  describe '.offense_from_diagnostic' do
+    subject(:offense) { described_class.offense_from_diagnostic(diagnostic) }
+    let(:diagnostic) { Parser::Diagnostic.new(level, reason, args, location) }
+    let(:level) { :warning }
+    let(:reason) { :odd_hash }
+    let(:args) { [] }
+    let(:location) { double('location').as_null_object }
+
+    it 'returns an offense' do
+      expect(offense).to be_a(Rubocop::Cop::Offense)
+    end
+
+    it "sets diagnostic's level to offense's severity" do
+      expect(offense.severity).to eq(level)
+    end
+
+    it "sets diagnostic's message to offense's message" do
+      expect(offense.message).to eq('odd number of entries for a hash')
+    end
+
+    it "sets diagnostic's location to offense's location" do
+      expect(offense.location).to eq(location)
+    end
+
+    it 'sets Syntax as a cop name' do
+      expect(offense.cop_name).to eq('Syntax')
+    end
+  end
+end
diff --git a/spec/rubocop/cop/lint/unreachable_code_spec.rb b/spec/rubocop/cop/lint/unreachable_code_spec.rb
new file mode 100644
index 0000000..4ffefde
--- /dev/null
+++ b/spec/rubocop/cop/lint/unreachable_code_spec.rb
@@ -0,0 +1,63 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::UnreachableCode do
+  subject(:cop) { described_class.new }
+
+  described_class::NODE_TYPES.each do |t|
+    it "registers an offense for #{t} before other statements" do
+      inspect_source(cop,
+                     ['foo = 5',
+                      "#{t}",
+                      'bar'
+                     ])
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it "accepts code with conditional #{t}" do
+      inspect_source(cop,
+                     ['foo = 5',
+                      "#{t} if test",
+                      'bar'
+                     ])
+      expect(cop.offenses).to be_empty
+    end
+
+    it "accepts #{t} as the final expression" do
+      inspect_source(cop,
+                     ['foo = 5',
+                      "#{t} if test"
+                     ])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  described_class::FLOW_COMMANDS.each do |t|
+    it "registers an offense for #{t} before other statements" do
+      inspect_source(cop,
+                     ['foo = 5',
+                      "#{t} something",
+                      'bar'
+                     ])
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it "accepts code with conditional #{t}" do
+      inspect_source(cop,
+                     ['foo = 5',
+                      "#{t} something if test",
+                      'bar'
+                     ])
+      expect(cop.offenses).to be_empty
+    end
+
+    it "accepts #{t} as the final expression" do
+      inspect_source(cop,
+                     ['foo = 5',
+                      "#{t} something if test"
+                     ])
+      expect(cop.offenses).to be_empty
+    end
+  end
+end
diff --git a/spec/rubocop/cop/lint/useless_access_modifier_spec.rb b/spec/rubocop/cop/lint/useless_access_modifier_spec.rb
new file mode 100644
index 0000000..642dd19
--- /dev/null
+++ b/spec/rubocop/cop/lint/useless_access_modifier_spec.rb
@@ -0,0 +1,192 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::UselessAccessModifier do
+  subject(:cop) { described_class.new }
+
+  context 'when an access modifier has no effect' do
+    let(:source) do
+      [
+        'class SomeClass',
+        '  def some_method',
+        '    puts 10',
+        '  end',
+        '  private',
+        '  def self.some_method',
+        '    puts 10',
+        '  end',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless `private` access modifier.')
+      expect(cop.offenses.first.line).to eq(5)
+      expect(cop.highlights).to eq(['private'])
+    end
+  end
+
+  context 'when an access modifier has no methods' do
+    let(:source) do
+      [
+        'class SomeClass',
+        '  protected',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless `protected` access modifier.')
+      expect(cop.offenses.first.line).to eq(2)
+      expect(cop.highlights).to eq(['protected'])
+    end
+  end
+
+  context 'when an access modifier is followed by attr_*' do
+    let(:source) do
+      [
+        'class SomeClass',
+        '  protected',
+        '  attr_accessor :some_property',
+        'end'
+      ]
+    end
+
+    it 'does not register an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(0)
+    end
+  end
+
+  context 'when an access modifier is followed by a ' \
+    'class method defined on constant' do
+    let(:source) do
+      [
+        'class SomeClass',
+        '  protected',
+        '  def SomeClass.some_method',
+        '  end',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless `protected` access modifier.')
+      expect(cop.offenses.first.line).to eq(2)
+      expect(cop.highlights).to eq(['protected'])
+    end
+  end
+
+  context 'when consecutive access modifiers' do
+    let(:source) do
+      [
+        'class SomeClass',
+        ' private',
+        ' private',
+        '  def some_method',
+        '    puts 10',
+        '  end',
+        '  def some_other_method',
+        '    puts 10',
+        '  end',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless `private` access modifier.')
+      expect(cop.offenses.first.line).to eq(2)
+      expect(cop.highlights).to eq(['private'])
+    end
+  end
+
+  context 'when passing method as symbol' do
+    let(:source) do
+      [
+        'class SomeClass',
+        '  def some_method',
+        '    puts 10',
+        '  end',
+        '  private :some_method',
+        'end'
+      ]
+    end
+
+    it 'does not register an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(0)
+    end
+  end
+
+  context 'when class is empty save modifier' do
+    let(:source) do
+      [
+        'class SomeClass',
+        '  private',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless `private` access modifier.')
+      expect(cop.offenses.first.line).to eq(2)
+      expect(cop.highlights).to eq(['private'])
+    end
+  end
+
+  context 'when multiple class definitions in file but only one has offense' do
+    let(:source) do
+      [
+        'class SomeClass',
+        '  private',
+        'end',
+        'class SomeOtherClass',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless `private` access modifier.')
+      expect(cop.offenses.first.line).to eq(2)
+      expect(cop.highlights).to eq(['private'])
+    end
+  end
+
+  if RUBY_ENGINE == 'ruby' && RUBY_VERSION.start_with?('2.1')
+    context 'ruby 2.1 style modifiers' do
+      let(:source) do
+        [
+          'class SomeClass',
+          '  private def some_method',
+          '    puts 10',
+          '  end',
+          'end'
+        ]
+      end
+
+      it 'does not register an offense' do
+        inspect_source(cop, source)
+        expect(cop.offenses.size).to eq(0)
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/cop/lint/useless_assignment_spec.rb b/spec/rubocop/cop/lint/useless_assignment_spec.rb
new file mode 100644
index 0000000..81e2fa5
--- /dev/null
+++ b/spec/rubocop/cop/lint/useless_assignment_spec.rb
@@ -0,0 +1,1608 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::UselessAssignment do
+  subject(:cop) { described_class.new }
+
+  context 'when a variable is assigned and unreferenced in a method' do
+    let(:source) do
+      [
+        'class SomeClass',
+        '  foo = 1',
+        '  puts foo',
+        '  def some_method',
+        '    foo = 2',
+        '    bar = 3',
+        '    puts bar',
+        '  end',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(5)
+      expect(cop.highlights).to eq(['foo'])
+    end
+
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is assigned and unreferenced ' \
+          'in a singleton method defined with self keyword' do
+    let(:source) do
+      [
+        'class SomeClass',
+        '  foo = 1',
+        '  puts foo',
+        '  def self.some_method',
+        '    foo = 2',
+        '    bar = 3',
+        '    puts bar',
+        '  end',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(5)
+      expect(cop.highlights).to eq(['foo'])
+    end
+
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is assigned and unreferenced ' \
+          'in a singleton method defined with variable name' do
+    let(:source) do
+      [
+        '1.times do',
+        '  foo = 1',
+        '  puts foo',
+        '  instance = Object.new',
+        '  def instance.some_method',
+        '    foo = 2',
+        '    bar = 3',
+        '    puts bar',
+        '  end',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(6)
+      expect(cop.highlights).to eq(['foo'])
+    end
+
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is assigned and unreferenced in a class' do
+    let(:source) do
+      [
+        '1.times do',
+        '  foo = 1',
+        '  puts foo',
+        '  class SomeClass',
+        '    foo = 2',
+        '    bar = 3',
+        '    puts bar',
+        '  end',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(5)
+      expect(cop.highlights).to eq(['foo'])
+    end
+
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is assigned and unreferenced in a class ' \
+          'subclassing another class stored in local variable' do
+    let(:source) do
+      [
+        '1.times do',
+        '  foo = 1',
+        '  puts foo',
+        '  array_class = Array',
+        '  class SomeClass < array_class',
+        '    foo = 2',
+        '    bar = 3',
+        '    puts bar',
+        '  end',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(6)
+      expect(cop.highlights).to eq(['foo'])
+    end
+
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is assigned and unreferenced ' \
+          'in a singleton class' do
+    let(:source) do
+      [
+        '1.times do',
+        '  foo = 1',
+        '  puts foo',
+        '  instance = Object.new',
+        '  class << instance',
+        '    foo = 2',
+        '    bar = 3',
+        '    puts bar',
+        '  end',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(6)
+      expect(cop.highlights).to eq(['foo'])
+    end
+
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is assigned and unreferenced in a module' do
+    let(:source) do
+      [
+        '1.times do',
+        '  foo = 1',
+        '  puts foo',
+        '  module SomeModule',
+        '    foo = 2',
+        '    bar = 3',
+        '    puts bar',
+        '  end',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(5)
+      expect(cop.highlights).to eq(['foo'])
+    end
+
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is assigned and unreferenced in top level' do
+    let(:source) do
+      [
+        'foo = 1',
+        'bar = 2',
+        'puts bar'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(1)
+      expect(cop.highlights).to eq(['foo'])
+    end
+
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is assigned with operator assignment ' \
+          'in top level' do
+    let(:source) do
+      [
+        'foo ||= 1'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo. Use just operator ||.')
+      expect(cop.offenses.first.line).to eq(1)
+      expect(cop.highlights).to eq(['foo'])
+    end
+  end
+
+  context 'when a variable is assigned multiple times ' \
+          'but unreferenced' do
+    let(:source) do
+      [
+        'def some_method',
+        '  foo = 1',
+        '  bar = 2',
+        '  foo = 3',
+        '  puts bar',
+        'end'
+      ]
+    end
+
+    it 'registers offenses for each asignment' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(2)
+
+      expect(cop.offenses[0].message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses[0].line).to eq(2)
+
+      expect(cop.offenses[1].message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses[1].line).to eq(4)
+
+      expect(cop.highlights).to eq(%w(foo foo))
+    end
+  end
+
+  context 'when a referenced variable is reassigned ' \
+          'but not re-referenced' do
+    let(:source) do
+      [
+        'def some_method',
+        '  foo = 1',
+        '  puts foo',
+        '  foo = 3',
+        'end'
+      ]
+    end
+
+    it 'registers an offense for the non-re-referenced assignment' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(4)
+      expect(cop.highlights).to eq(['foo'])
+    end
+  end
+
+  context 'when an unreferenced variable is reassigned ' \
+          'and re-referenced' do
+    let(:source) do
+      [
+        'def some_method',
+        '  foo = 1',
+        '  foo = 3',
+        '  puts foo',
+        'end'
+      ]
+    end
+
+    it 'registers an offense for the unreferenced assignment' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(2)
+      expect(cop.highlights).to eq(['foo'])
+    end
+  end
+
+  context 'when an unreferenced variable is reassigned in a block' do
+    let(:source) do
+      [
+        'def const_name(node)',
+        '  const_names = []',
+        '  const_node = node',
+        '',
+        '  loop do',
+        '    namespace_node, name = *const_node',
+        '    const_names << name',
+        '    break unless namespace_node',
+        '    break if namespace_node.type == :cbase',
+        '    const_node = namespace_node',
+        '  end',
+        '',
+        "  const_names.reverse.join('::')",
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a referenced variable is reassigned in a block' do
+    let(:source) do
+      [
+        'def some_method',
+        '  foo = 1',
+        '  puts foo',
+        '  1.times do',
+        '    foo = 2',
+        '  end',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a block local variable is declared but not assigned' do
+    let(:source) do
+      [
+        '1.times do |i; foo|',
+        'end'
+      ]
+    end
+
+    it 'registers an offense for the declaration' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(1)
+      expect(cop.highlights).to eq(['foo'])
+    end
+
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a block local variable is assigned and unreferenced' do
+    let(:source) do
+      [
+        '1.times do |i; foo|',
+        '  foo = 2',
+        'end'
+      ]
+    end
+
+    it 'registers offenses for the assignment' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(2)
+      expect(cop.highlights).to eq(['foo'])
+    end
+  end
+
+  context 'when a variable is assigned in loop body and unreferenced' do
+    let(:source) do
+      [
+        'def some_method',
+        '  while true',
+        '    foo = 1',
+        '  end',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(3)
+      expect(cop.highlights).to eq(['foo'])
+    end
+
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is reassigned at the end of loop body ' \
+          'and would be referenced in next iteration' do
+    let(:source) do
+      [
+        'def some_method',
+        '  total = 0',
+        '  foo = 0',
+        '',
+        '  while total < 100',
+        '    total += foo',
+        '    foo += 1',
+        '  end',
+        '',
+        '  total',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is reassigned at the end of loop body ' \
+          'and would be referenced in loop condition' do
+    let(:source) do
+      [
+        'def some_method',
+        '  total = 0',
+        '  foo = 0',
+        '',
+        '  while foo < 100',
+        '    total += 1',
+        '    foo += 1',
+        '  end',
+        '',
+        '  total',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a setter is invoked with operator assignment in loop body' do
+    let(:source) do
+      [
+        'def some_method',
+        '  obj = {}',
+        '',
+        '  while obj[:count] < 100',
+        '    obj[:count] += 1',
+        '  end',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context "when a variable is reassigned in loop body but won't " \
+          'be referenced either next iteration or loop condition' do
+    let(:source) do
+      [
+        'def some_method',
+        '  total = 0',
+        '  foo = 0',
+        '',
+        '  while total < 100',
+        '    total += 1',
+        '    foo += 1',
+        '  end',
+        '',
+        '  total',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      pending 'Requires an advanced logic that checks whether the return ' \
+              'value of an operator assignment is used or not.'
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(7)
+      expect(cop.highlights).to eq(['foo'])
+    end
+  end
+
+  context 'when a referenced variable is reassigned ' \
+          'but not re-referenced in a method defined in loop' do
+    let(:source) do
+      [
+        'while true',
+        '  def some_method',
+        '    foo = 1',
+        '    puts foo',
+        '    foo = 3',
+        '  end',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(5)
+      expect(cop.highlights).to eq(['foo'])
+    end
+  end
+
+  context 'when a variable that has same name as outer scope variable ' \
+          'is not referenced in a method defined in loop' do
+    let(:source) do
+      [
+        'foo = 1',
+        '',
+        'while foo < 100',
+        '  foo += 1',
+        '  def some_method',
+        '    foo = 1',
+        '  end',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(6)
+      expect(cop.highlights).to eq(['foo'])
+    end
+  end
+
+  context 'when a variable is assigned in single branch if ' \
+          'and unreferenced' do
+    let(:source) do
+      [
+        'def some_method(flag)',
+        '  if flag',
+        '    foo = 1',
+        '  end',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(3)
+      expect(cop.highlights).to eq(['foo'])
+    end
+
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a unreferenced variable is reassigned in same branch ' \
+          'and referenced after the branching' do
+    let(:source) do
+      [
+        'def some_method(flag)',
+        '  if flag',
+        '    foo = 1',
+        '    foo = 2',
+        '  end',
+        '',
+        '  foo',
+        'end'
+      ]
+    end
+
+    it 'registers an offense for the unreferenced assignment' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(3)
+      expect(cop.highlights).to eq(['foo'])
+    end
+  end
+
+  context 'when a variable is reassigned in single branch if ' \
+          'and referenced after the branching' do
+    let(:source) do
+      [
+        'def some_method(flag)',
+        '  foo = 1',
+        '',
+        '  if flag',
+        '    foo = 2',
+        '  end',
+        '',
+        '  foo',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is assigned in each branch of if ' \
+          'and referenced after the branching' do
+    let(:source) do
+      [
+        'def some_method(flag)',
+        '  if flag',
+        '    foo = 2',
+        '  else',
+        '    foo = 3',
+        '  end',
+        '',
+        '  foo',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is reassigned in single branch if ' \
+          'and referenced in the branch' do
+    let(:source) do
+      [
+        'def some_method(flag)',
+        '  foo = 1',
+        '',
+        '  if flag',
+        '    foo = 2',
+        '    puts foo',
+        '  end',
+        'end'
+      ]
+    end
+
+    it 'registers an offense for the unreferenced assignment' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(2)
+      expect(cop.highlights).to eq(['foo'])
+    end
+  end
+
+  context 'when a variable is assigned in each branch of if ' \
+          'and referenced in the else branch' do
+    let(:source) do
+      [
+        'def some_method(flag)',
+        '  if flag',
+        '    foo = 2',
+        '  else',
+        '    foo = 3',
+        '    puts foo',
+        '  end',
+        'end'
+      ]
+    end
+
+    it 'registers an offense for the assignment in the if branch' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(3)
+      expect(cop.highlights).to eq(['foo'])
+    end
+  end
+
+  context 'when a variable is assigned in branch of modifier if ' \
+          'that references the variable in its conditional clause' \
+          'and referenced after the branching' do
+    let(:source) do
+      [
+        'def some_method(flag)',
+        '  foo = 1 unless foo',
+        '  puts foo',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is assigned in branch of modifier if ' \
+          'that references the variable in its conditional clause' \
+          'and unreferenced' do
+    let(:source) do
+      [
+        'def some_method(flag)',
+        '  foo = 1 unless foo',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(2)
+      expect(cop.highlights).to eq(['foo'])
+    end
+  end
+
+  context 'when a variable is assigned on each side of && ' \
+          'and referenced after the &&' do
+    let(:source) do
+      [
+        'def some_method',
+        '  (foo = do_something_returns_object_or_nil) && (foo = 1)',
+        '  foo',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a unreferenced variable is reassigned ' \
+          'on the left side of && and referenced after the &&' do
+    let(:source) do
+      [
+        'def some_method',
+        '  foo = 1',
+        '  (foo = do_something_returns_object_or_nil) && do_something',
+        '  foo',
+        'end'
+      ]
+    end
+
+    it 'registers an offense for the unreferenced assignment' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(2)
+      expect(cop.highlights).to eq(['foo'])
+    end
+  end
+
+  context 'when a unreferenced variable is reassigned ' \
+          'on the right side of && and referenced after the &&' do
+    let(:source) do
+      [
+        'def some_method',
+        '  foo = 1',
+        '  do_something_returns_object_or_nil && foo = 2',
+        '  foo',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is reassigned ' \
+          'while referencing itself in rhs and referenced' do
+    let(:source) do
+      [
+        'def some_method',
+        '  foo = [1, 2]',
+        '  foo = foo.map { |i| i + 1 }',
+        '  puts foo',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is reassigned ' \
+          'with binary operator assignment and referenced' do
+    let(:source) do
+      [
+        'def some_method',
+        '  foo = 1',
+        '  foo += 1',
+        '  foo',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is reassigned ' \
+          'with logical operator assignment and referenced' do
+    let(:source) do
+      [
+        'def some_method',
+        '  foo = do_something_returns_object_or_nil',
+        '  foo ||= 1',
+        '  foo',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is reassigned with binary operator ' \
+           'assignment while assigning to itself in rhs ' \
+           'then referenced' do
+    let(:source) do
+      [
+        'def some_method',
+        '  foo = 1',
+        '  foo += foo = 2',
+        '  foo',
+        'end'
+      ]
+    end
+
+    it 'registers an offense for the assignment in rhs' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(3)
+      expect(cop.highlights).to eq(['foo'])
+    end
+  end
+
+  context 'when a variable is assigned first with ||= and referenced' do
+    let(:source) do
+      [
+        'def some_method',
+        '  foo ||= 1',
+        '  foo',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is assigned with ||= ' \
+          'at the last expression of the scope' do
+    let(:source) do
+      [
+        'def some_method',
+        '  foo = do_something_returns_object_or_nil',
+        '  foo ||= 1',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message).to eq(
+        'Useless assignment to variable - foo. Use just operator ||.'
+      )
+      expect(cop.offenses.first.line).to eq(3)
+      expect(cop.highlights).to eq(['foo'])
+    end
+  end
+
+  context 'when a variable is assigned with ||= ' \
+          'before the last expression of the scope' do
+    let(:source) do
+      [
+        'def some_method',
+        '  foo = do_something_returns_object_or_nil',
+        '  foo ||= 1',
+        '  some_return_value',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(3)
+      expect(cop.highlights).to eq(['foo'])
+    end
+  end
+
+  context 'when a variable is assigned with multiple assignment ' \
+          'and unreferenced' do
+    let(:source) do
+      [
+        'def some_method',
+        '  foo, bar = do_something',
+        '  puts foo',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message).to eq(
+        'Useless assignment to variable - bar. ' \
+        'Use _ or _bar as a variable name ' \
+        "to indicate that it won't be used."
+      )
+      expect(cop.offenses.first.line).to eq(2)
+      expect(cop.highlights).to eq(['bar'])
+    end
+
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is reassigned with multiple assignment ' \
+          'while referencing itself in rhs and referenced' do
+    let(:source) do
+      [
+        'def some_method',
+        '  foo = 1',
+        '  foo, bar = do_something(foo)',
+        '  puts foo, bar',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is assigned in loop body ' \
+          'and referenced in post while condition' do
+    let(:source) do
+      [
+        'begin',
+        '  a = (a || 0) + 1',
+        '  puts a',
+        'end while a <= 2'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is assigned in loop body ' \
+          'and referenced in post until condition' do
+    let(:source) do
+      [
+        'begin',
+        '  a = (a || 0) + 1',
+        '  puts a',
+        'end until a > 2'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is assigned ' \
+          'in main body of begin with rescue but unreferenced' do
+    let(:source) do
+      [
+        'begin',
+        '  do_something',
+        '  foo = true',
+        'rescue',
+        '  do_anything',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(3)
+      expect(cop.highlights).to eq(['foo'])
+    end
+
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is assigned in main body of begin, rescue ' \
+          'and else then referenced after the begin' do
+    let(:source) do
+      [
+        'begin',
+        '  do_something',
+        '  foo = :in_begin',
+        'rescue FirstError',
+        '  foo = :in_first_rescue',
+        'rescue SecondError',
+        '  foo = :in_second_rescue',
+        'else',
+        '  foo = :in_else',
+        'end',
+        '',
+        'puts foo'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is reassigned multiple times ' \
+          'in main body of begin then referenced after the begin' do
+    let(:source) do
+      [
+        'begin',
+        '  status = :initial',
+        '  connect_sometimes_fails!',
+        '  status = :connected',
+        '  fetch_sometimes_fails!',
+        '  status = :fetched',
+        'rescue',
+        '  do_something',
+        'end',
+        '',
+        'puts status'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is reassigned multiple times ' \
+          'in main body of begin then referenced in rescue' do
+    let(:source) do
+      [
+        'begin',
+        '  status = :initial',
+        '  connect_sometimes_fails!',
+        '  status = :connected',
+        '  fetch_sometimes_fails!',
+        '  status = :fetched',
+        'rescue',
+        '  puts status',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is reassigned multiple times ' \
+          'in main body of begin then referenced in ensure' do
+    let(:source) do
+      [
+        'begin',
+        '  status = :initial',
+        '  connect_sometimes_fails!',
+        '  status = :connected',
+        '  fetch_sometimes_fails!',
+        '  status = :fetched',
+        'ensure',
+        '  puts status',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is reassigned multiple times in rescue ' \
+          'and referenced after the begin' do
+    let(:source) do
+      [
+        'foo = false',
+        '',
+        'begin',
+        '  do_something',
+        'rescue',
+        '  foo = true',
+        '  foo = true',
+        'end',
+        '',
+        'puts foo'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(6)
+      expect(cop.highlights).to eq(['foo'])
+    end
+  end
+
+  context 'when a variable is reassigned multiple times ' \
+          'in rescue with ensure then referenced after the begin' do
+    let(:source) do
+      [
+        'foo = false',
+        '',
+        'begin',
+        '  do_something',
+        'rescue',
+        '  foo = true',
+        '  foo = true',
+        'ensure',
+        '  do_anything',
+        'end',
+        '',
+        'puts foo'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(6)
+      expect(cop.highlights).to eq(['foo'])
+    end
+  end
+
+  context 'when a variable is reassigned multiple times ' \
+          'in ensure with rescue then referenced after the begin' do
+    let(:source) do
+      [
+        'begin',
+        '  do_something',
+        'rescue',
+        '  do_anything',
+        'ensure',
+        '  foo = true',
+        '  foo = true',
+        'end',
+        '',
+        'puts foo'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(6)
+      expect(cop.highlights).to eq(['foo'])
+    end
+  end
+
+  context 'when a variable is assigned at the end of rescue ' \
+          'and would be referenced with retry' do
+    let(:source) do
+      [
+        'retried = false',
+        '',
+        'begin',
+        '  do_something',
+        'rescue',
+        '  fail if retried',
+        '  retried = true',
+        '  retry',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is assigned with operator assignment ' \
+          'in rescue and would be referenced with retry' do
+    let(:source) do
+      [
+        'retry_count = 0',
+        '',
+        'begin',
+        '  do_something',
+        'rescue',
+        '  fail if (retry_count += 1) > 3',
+        '  retry',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is assigned ' \
+          'in main body of begin, rescue and else ' \
+          'and reassigned in ensure then referenced after the begin' do
+    let(:source) do
+      [
+        'begin',
+        '  do_something',
+        '  foo = :in_begin',
+        'rescue FirstError',
+        '  foo = :in_first_rescue',
+        'rescue SecondError',
+        '  foo = :in_second_rescue',
+        'else',
+        '  foo = :in_else',
+        'ensure',
+        '  foo = :in_ensure',
+        'end',
+        '',
+        'puts foo'
+      ]
+    end
+
+    it 'registers offenses for each assignment before ensure' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(4)
+
+      expect(cop.offenses[0].line).to eq(3)
+      expect(cop.offenses[1].line).to eq(5)
+      expect(cop.offenses[2].line).to eq(7)
+      expect(cop.offenses[3].line).to eq(9)
+    end
+  end
+
+  context 'when a method argument is reassigned ' \
+          'and zero arity super is called' do
+    let(:source) do
+      [
+        'def some_method(foo)',
+        '  foo = 1',
+        '  super',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a local variable is unreferenced ' \
+          'and zero arity super is called' do
+    let(:source) do
+      [
+        'def some_method(bar)',
+        '  foo = 1',
+        '  super',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(2)
+      expect(cop.highlights).to eq(['foo'])
+    end
+
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a method argument is reassigned ' \
+          'but not passed to super' do
+    let(:source) do
+      [
+        'def some_method(foo, bar)',
+        '  foo = 1',
+        '  super(bar)',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(2)
+      expect(cop.highlights).to eq(['foo'])
+    end
+  end
+
+  context 'when a named capture is unreferenced in top level' do
+    let(:source) do
+      [
+        "/(?<foo>\w+)/ =~ 'FOO'"
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(1)
+    end
+
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a named capture is unreferenced ' \
+          'in other than top level' do
+    let(:source) do
+      [
+        'def some_method',
+        "  /(?<foo>\w+)/ =~ 'FOO'",
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(2)
+      expect(cop.highlights).to eq(["/(?<foo>\w+)/"])
+    end
+
+    # MRI 2.0 accepts this case, but I have no idea why it does so
+    # and there's no convincing reason to conform to this behavior,
+    # so RuboCop does not mimic MRI in this case.
+  end
+
+  context 'when a named capture is referenced' do
+    let(:source) do
+      [
+        'def some_method',
+        "  /(?<foo>\w+)(?<bar>\s+)/ =~ 'FOO'",
+        '  puts foo',
+        '  puts bar',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is referenced ' \
+          'in rhs of named capture expression' do
+    let(:source) do
+      [
+        'def some_method',
+        "  foo = 'some string'",
+        "  /(?<foo>\w+)/ =~ foo",
+        '  puts foo',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+  end
+
+  context 'when a variable is assigned in begin ' \
+          'and referenced outside' do
+    let(:source) do
+      [
+        'def some_method',
+        '  begin',
+        '    foo = 1',
+        '  end',
+        '  puts foo',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is shadowed by a block argument ' \
+          'and unreferenced' do
+    let(:source) do
+      [
+        'def some_method',
+        '  foo = 1',
+        '  1.times do |foo|',
+        '    puts foo',
+        '  end',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(2)
+      expect(cop.highlights).to eq(['foo'])
+    end
+
+    include_examples 'mimics MRI 2.1', 'unused variable'
+  end
+
+  context 'when a variable is not used and the name starts with _' do
+    let(:source) do
+      [
+        'def some_method',
+        '  _foo = 1',
+        '  bar = 2',
+        '  puts bar',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a method argument is not used' do
+    let(:source) do
+      [
+        'def some_method(arg)',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when an optional method argument is not used' do
+    let(:source) do
+      [
+        'def some_method(arg = nil)',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a block method argument is not used' do
+    let(:source) do
+      [
+        'def some_method(&block)',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a splat method argument is not used' do
+    let(:source) do
+      [
+        'def some_method(*args)',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a optional keyword method argument is not used' do
+    let(:source) do
+      [
+        'def some_method(name: value)',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts' unless RUBY_VERSION < '2.0'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a keyword splat method argument is used' do
+    let(:source) do
+      [
+        'def some_method(name: value, **rest_keywords)',
+        '  p rest_keywords',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts' unless RUBY_VERSION < '2.0'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a keyword splat method argument is not used' do
+    let(:source) do
+      [
+        'def some_method(name: value, **rest_keywords)',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts' unless RUBY_VERSION < '2.0'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a block argument is not used' do
+    let(:source) do
+      [
+        '1.times do |i|',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when there is only one AST node and it is unused variable' do
+    let(:source) do
+      [
+        'foo = 1'
+      ]
+    end
+
+    it 'registers an offense' do
+      inspect_source(cop, source)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Useless assignment to variable - foo')
+      expect(cop.offenses.first.line).to eq(1)
+      expect(cop.highlights).to eq(['foo'])
+    end
+
+    include_examples 'mimics MRI 2.1'
+  end
+
+  context 'when a variable is assigned ' \
+          'while being passed to a method taking block' do
+
+    context 'and the variable is used' do
+      let(:source) do
+        [
+          'some_method(foo = 1) do',
+          'end',
+          'puts foo'
+        ]
+      end
+
+      include_examples 'accepts'
+      include_examples 'mimics MRI 2.1'
+    end
+
+    context 'and the variable is not used' do
+      let(:source) do
+        [
+          'some_method(foo = 1) do',
+          'end'
+        ]
+      end
+
+      it 'registers an offense' do
+        inspect_source(cop, source)
+        expect(cop.offenses.size).to eq(1)
+        expect(cop.offenses.first.message)
+          .to eq('Useless assignment to variable - foo')
+        expect(cop.offenses.first.line).to eq(1)
+        expect(cop.highlights).to eq(['foo'])
+      end
+
+      include_examples 'mimics MRI 2.1'
+    end
+  end
+
+  context 'when a variabled is assigned ' \
+          'and passed to a method followed by method taking block'  do
+    let(:source) do
+      [
+        "pattern = '*.rb'",
+        'Dir.glob(pattern).map do |path|',
+        'end'
+      ]
+    end
+
+    include_examples 'accepts'
+    include_examples 'mimics MRI 2.1'
+  end
+end
diff --git a/spec/rubocop/cop/lint/useless_comparison_spec.rb b/spec/rubocop/cop/lint/useless_comparison_spec.rb
new file mode 100644
index 0000000..d7b5299
--- /dev/null
+++ b/spec/rubocop/cop/lint/useless_comparison_spec.rb
@@ -0,0 +1,30 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::UselessComparison do
+  subject(:cop) { described_class.new }
+
+  described_class::OPS.each do |op|
+    it "registers an offense for a simple comparison with #{op}" do
+      inspect_source(cop,
+                     ["5 #{op} 5",
+                      "a #{op} a"
+                     ])
+      expect(cop.offenses.size).to eq(2)
+    end
+
+    it "registers an offense for a complex comparison with #{op}" do
+      inspect_source(cop,
+                     ["5 + 10 * 30 #{op} 5 + 10 * 30",
+                      "a.top(x) #{op} a.top(x)"
+                     ])
+      expect(cop.offenses.size).to eq(2)
+    end
+  end
+
+  it 'works with lambda.()' do
+    inspect_source(cop, ['a.(x) > a.(x)'])
+    expect(cop.offenses.size).to eq(1)
+  end
+end
diff --git a/spec/rubocop/cop/lint/useless_else_without_rescue_spec.rb b/spec/rubocop/cop/lint/useless_else_without_rescue_spec.rb
new file mode 100644
index 0000000..f70a8bf
--- /dev/null
+++ b/spec/rubocop/cop/lint/useless_else_without_rescue_spec.rb
@@ -0,0 +1,48 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::UselessElseWithoutRescue do
+  subject(:cop) { described_class.new }
+
+  before do
+    inspect_source(cop, source)
+  end
+
+  context 'with `else` without `rescue`' do
+    let(:source) do
+      [
+        'begin',
+        '  do_something',
+        'else',
+        '  handle_unknown_errors',
+        'end'
+      ]
+    end
+
+    it 'registers an offense' do
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.message)
+        .to eq('Else without rescue is useless')
+      expect(cop.highlights).to eq(['else'])
+    end
+  end
+
+  context 'with `else` with `rescue`' do
+    let(:source) do
+      [
+        'begin',
+        '  do_something',
+        'rescue ArgumentError',
+        '  handle_argument_error',
+        'else',
+        '  handle_unknown_errors',
+        'end'
+      ]
+    end
+
+    it 'accepts' do
+      expect(cop.offenses).to be_empty
+    end
+  end
+end
diff --git a/spec/rubocop/cop/lint/useless_setter_call_spec.rb b/spec/rubocop/cop/lint/useless_setter_call_spec.rb
new file mode 100644
index 0000000..6a68d9c
--- /dev/null
+++ b/spec/rubocop/cop/lint/useless_setter_call_spec.rb
@@ -0,0 +1,149 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::UselessSetterCall do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for def ending with lvar attr assignment' do
+    inspect_source(cop,
+                   ['def test',
+                    '  top = Top.new',
+                    '  top.attr = 5',
+                    'end'
+                   ])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for defs ending with lvar attr assignment' do
+    inspect_source(cop,
+                   ['def Top.test',
+                    '  top = Top.new',
+                    '  top.attr = 5',
+                    'end'
+                   ])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts def ending with ivar assignment' do
+    inspect_source(cop,
+                   ['def test',
+                    '  something',
+                    '  @top = 5',
+                    'end'
+                   ])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts def ending ivar attr assignment' do
+    inspect_source(cop,
+                   ['def test',
+                    '  something',
+                    '  @top.attr = 5',
+                    'end'
+                   ])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts def ending with argument attr assignment' do
+    inspect_source(cop,
+                   ['def test(some_arg)',
+                    '  unrelated_local_variable = Top.new',
+                    '  some_arg.attr = 5',
+                    'end'
+                   ])
+    expect(cop.offenses).to be_empty
+  end
+
+  context 'when a lvar has an object passed as argument ' \
+          'at the end of the method' do
+    it 'accepts the lvar attr assignment' do
+      inspect_source(cop,
+                     ['def test(some_arg)',
+                      '  @some_ivar = some_arg',
+                      '  @some_ivar.do_something',
+                      '  some_lvar = @some_ivar',
+                      '  some_lvar.do_something',
+                      '  some_lvar.attr = 5',
+                      'end'
+                     ])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'when a lvar has an object passed as argument ' \
+          'by multiple-assignment at the end of the method' do
+    it 'accepts the lvar attr assignment' do
+      inspect_source(cop,
+                     ['def test(some_arg)',
+                      '  _first, some_lvar, _third  = 1, some_arg, 3',
+                      '  some_lvar.attr = 5',
+                      'end'
+                     ])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'when a lvar does not have any object passed as argument ' \
+          'with multiple-assignment at the end of the method' do
+    it 'registers an offense' do
+      inspect_source(cop,
+                     ['def test(some_arg)',
+                      '  _first, some_lvar, _third  = do_something',
+                      '  some_lvar.attr = 5',
+                      'end'
+                     ])
+      expect(cop.offenses.size).to eq(1)
+    end
+  end
+
+  context 'when a lvar possibly has an object passed as argument ' \
+          'by logical-operator-assignment at the end of the method' do
+    it 'accepts the lvar attr assignment' do
+      inspect_source(cop,
+                     ['def test(some_arg)',
+                      '  some_lvar = nil',
+                      '  some_lvar ||= some_arg',
+                      '  some_lvar.attr = 5',
+                      'end'
+                     ])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'when a lvar does not have any object passed as argument ' \
+          'by binary-operator-assignment at the end of the method' do
+    it 'registers an offense' do
+      inspect_source(cop,
+                     ['def test(some_arg)',
+                      '  some_lvar = some_arg',
+                      '  some_lvar += some_arg',
+                      '  some_lvar.attr = 5',
+                      'end'
+                     ])
+      expect(cop.offenses.size).to eq(1)
+    end
+  end
+
+  context 'when a lvar declared as an argument ' \
+          'is no longer the passed object at the end of the method' do
+    it 'registers an offense for the lvar attr assignment' do
+      inspect_source(cop,
+                     ['def test(some_arg)',
+                      '  some_arg = Top.new',
+                      '  some_arg.attr = 5',
+                      'end'
+                     ])
+      expect(cop.offenses.size).to eq(1)
+    end
+  end
+
+  it 'is not confused by operators ending with =' do
+    inspect_source(cop,
+                   ['def test',
+                    '  top.attr == 5',
+                    'end'
+                   ])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/lint/void_spec.rb b/spec/rubocop/cop/lint/void_spec.rb
new file mode 100644
index 0000000..d58bf12
--- /dev/null
+++ b/spec/rubocop/cop/lint/void_spec.rb
@@ -0,0 +1,57 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Lint::Void do
+  subject(:cop) { described_class.new }
+
+  described_class::OPS.each do |op|
+    it "registers an offense for void op #{op} if not on last line" do
+      inspect_source(cop,
+                     ["a #{op} b",
+                      "a #{op} b",
+                      "a #{op} b"
+                     ])
+      expect(cop.offenses.size).to eq(2)
+    end
+  end
+
+  described_class::OPS.each do |op|
+    it "accepts void op #{op} if on last line" do
+      inspect_source(cop,
+                     ['something',
+                      "a #{op} b"
+                     ])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  described_class::OPS.each do |op|
+    it "accepts void op #{op} by itself without a begin block" do
+      inspect_source(cop, ["a #{op} b"])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  %w(var @var @@var VAR).each do |var|
+    it "registers an offense for void var #{var} if not on last line" do
+      inspect_source(cop,
+                     ["#{var} = 5",
+                      "#{var}",
+                      'top'
+                     ])
+      expect(cop.offenses.size).to eq(1)
+    end
+  end
+
+  %w(1 2.0 /test/ [1] {}).each do |lit|
+    it "registers an offense for void lit #{lit} if not on last line" do
+      inspect_source(cop,
+                     ["#{lit}",
+                      'top'
+                     ])
+      expect(cop.offenses.size).to eq(1)
+    end
+  end
+
+end
diff --git a/spec/rubocop/cop/offense_spec.rb b/spec/rubocop/cop/offense_spec.rb
new file mode 100644
index 0000000..28d7028
--- /dev/null
+++ b/spec/rubocop/cop/offense_spec.rb
@@ -0,0 +1,133 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Offense do
+  let(:location) do
+    source_buffer = Parser::Source::Buffer.new('test', 1)
+    source_buffer.source = "a\n"
+    Parser::Source::Range.new(source_buffer, 0, 1)
+  end
+  subject(:offense) do
+    described_class.new(:convention, location, 'message', 'CopName', true)
+  end
+
+  it 'has a few required attributes' do
+    expect(offense.severity).to eq(:convention)
+    expect(offense.line).to eq(1)
+    expect(offense.message).to eq('message')
+    expect(offense.cop_name).to eq('CopName')
+    expect(offense.corrected?).to be_true
+  end
+
+  it 'overrides #to_s' do
+    expect(offense.to_s).to eq('C:  1:  1: message')
+  end
+
+  it 'does not blow up if a message contains %' do
+    offense = described_class.new(:convention, location, 'message % test',
+                                  'CopName')
+
+    expect(offense.to_s).to eq('C:  1:  1: message % test')
+  end
+
+  it 'redefines == to compare offenses based on their contents' do
+    o1 = described_class.new(:convention, location, 'message', 'CopName')
+    o2 = described_class.new(:convention, location, 'message', 'CopName')
+
+    expect(o1 == o2).to be_true
+  end
+
+  it 'is frozen' do
+    expect(offense).to be_frozen
+  end
+
+  [:severity, :location, :line, :column, :message, :cop_name].each do |a|
+    describe "##{a}" do
+      it 'is frozen' do
+        expect(offense.send(a)).to be_frozen
+      end
+    end
+  end
+
+  context 'when unknown severity is passed' do
+    it 'raises error' do
+      expect do
+        described_class.new(:foobar, location, 'message', 'CopName')
+      end.to raise_error(ArgumentError)
+    end
+  end
+
+  describe '#severity_level' do
+    subject(:severity_level) do
+      described_class.new(severity, location, 'message', 'CopName')
+        .severity.level
+    end
+
+    context 'when severity is :refactor' do
+      let(:severity) { :refactor }
+      it 'is 1' do
+        expect(severity_level).to eq(1)
+      end
+    end
+
+    context 'when severity is :fatal' do
+      let(:severity) { :fatal }
+      it 'is 5' do
+        expect(severity_level).to eq(5)
+      end
+    end
+  end
+
+  describe '#<=>' do
+    def offense(hash = {})
+      attrs = {
+        sev:  :convention,
+        line: 5,
+        col:  5,
+        mes:  'message',
+        cop:  'CopName'
+      }.merge(hash)
+
+      described_class.new(
+        attrs[:sev],
+        location(attrs[:line], attrs[:col],
+                 %w(aaaaaa bbbbbb cccccc dddddd eeeeee ffffff)),
+        attrs[:mes],
+        attrs[:cop]
+      )
+    end
+
+    def location(line, column, source)
+      source_buffer = Parser::Source::Buffer.new('test', 1)
+      source_buffer.source = source.join("\n")
+      begin_pos = source[0...(line - 1)].reduce(0) do |a, e|
+        a + e.length + "\n".length
+      end + column
+      Parser::Source::Range.new(source_buffer, begin_pos, begin_pos + 1)
+    end
+
+    # We want a nice table layout, so we allow space inside empty hashes.
+    # rubocop:disable SpaceInsideHashLiteralBraces
+    [
+      [{                           }, {                           }, 0],
+
+      [{ line: 6                   }, { line: 5                   }, 1],
+
+      [{ line: 5, col: 6           }, { line: 5, col: 5           }, 1],
+      [{ line: 6, col: 4           }, { line: 5, col: 5           }, 1],
+
+      [{                  cop: 'B' }, {                  cop: 'A' }, 1],
+      [{ line: 6,         cop: 'A' }, { line: 5,         cop: 'B' }, 1],
+      [{          col: 6, cop: 'A' }, {          col: 5, cop: 'B' }, 1]
+    ].each do |one, other, expectation|
+      context "when receiver has #{one} and other has #{other}" do
+        it "returns #{expectation}" do
+          an_offense = offense(one)
+          other_offense = offense(other)
+          expect(an_offense <=> other_offense).to eq(expectation)
+        end
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/cop/rails/action_filter_spec.rb b/spec/rubocop/cop/rails/action_filter_spec.rb
new file mode 100644
index 0000000..bfc6ccf
--- /dev/null
+++ b/spec/rubocop/cop/rails/action_filter_spec.rb
@@ -0,0 +1,69 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Rails::ActionFilter, :config do
+  subject(:cop) { described_class.new(config) }
+
+  context 'when style is action' do
+    let(:cop_config) { { 'EnforcedStyle' => 'action' } }
+
+    described_class::FILTER_METHODS.each do |method|
+      it "registers an offense for #{method}" do
+        inspect_source_file(cop,
+                            ["#{method} :name"])
+        expect(cop.offenses.size).to eq(1)
+      end
+
+      it "registers an offense for #{method} with block" do
+        inspect_source_file(cop,
+                            ["#{method} { |controller| something }"])
+        expect(cop.offenses.size).to eq(1)
+      end
+    end
+
+    described_class::ACTION_METHODS.each do |method|
+      it "accepts #{method}" do
+        inspect_source_file(cop,
+                            ["#{method} :something"])
+        expect(cop.offenses).to be_empty
+      end
+    end
+
+    it 'auto-corrects to preferred method' do
+      new_source = autocorrect_source_file(cop, 'before_filter :test')
+      expect(new_source).to eq('before_action :test')
+    end
+  end
+
+  context 'when style is filter' do
+    let(:cop_config) { { 'EnforcedStyle' => 'filter' } }
+
+    described_class::ACTION_METHODS.each do |method|
+      it "registers an offense for #{method}" do
+        inspect_source_file(cop,
+                            ["#{method} :name"])
+        expect(cop.offenses.size).to eq(1)
+      end
+
+      it "registers an offense for #{method} with block" do
+        inspect_source_file(cop,
+                            ["#{method} { |controller| something }"])
+        expect(cop.offenses.size).to eq(1)
+      end
+    end
+
+    described_class::FILTER_METHODS.each do |method|
+      it "accepts #{method}" do
+        inspect_source_file(cop,
+                            ["#{method} :something"])
+        expect(cop.offenses).to be_empty
+      end
+    end
+
+    it 'auto-corrects to preferred method' do
+      new_source = autocorrect_source_file(cop, 'before_action :test')
+      expect(new_source).to eq('before_filter :test')
+    end
+  end
+end
diff --git a/spec/rubocop/cop/rails/default_scope_spec.rb b/spec/rubocop/cop/rails/default_scope_spec.rb
new file mode 100644
index 0000000..59b9849
--- /dev/null
+++ b/spec/rubocop/cop/rails/default_scope_spec.rb
@@ -0,0 +1,37 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Rails::DefaultScope do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for default scope with a lambda arg' do
+    inspect_source(cop,
+                   ['default_scope -> { something }'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for default scope with a proc arg' do
+    inspect_source(cop,
+                   ['default_scope proc { something }'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for default scope with a proc(Proc.new) arg' do
+    inspect_source(cop,
+                   ['default_scope Proc.new { something }'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for non blocks' do
+    inspect_source(cop,
+                   ['default_scope order: "position"'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts a block arg' do
+    inspect_source(cop,
+                   ['default_scope { something }'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/rails/has_and_belongs_to_many_spec.rb b/spec/rubocop/cop/rails/has_and_belongs_to_many_spec.rb
new file mode 100644
index 0000000..c5ff430
--- /dev/null
+++ b/spec/rubocop/cop/rails/has_and_belongs_to_many_spec.rb
@@ -0,0 +1,13 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Rails::HasAndBelongsToMany do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for has_and_belongs_to_many' do
+    inspect_source(cop,
+                   ['has_and_belongs_to_many :groups'])
+    expect(cop.offenses.size).to eq(1)
+  end
+end
diff --git a/spec/rubocop/cop/rails/output_spec.rb b/spec/rubocop/cop/rails/output_spec.rb
new file mode 100644
index 0000000..e433613
--- /dev/null
+++ b/spec/rubocop/cop/rails/output_spec.rb
@@ -0,0 +1,31 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Rails::Output do
+  subject(:cop) { described_class.new }
+
+  it 'should record an offense for puts statements' do
+    source = ['p "edmond dantes"',
+              'puts "sinbad"',
+              'print "abbe busoni"',
+              'pp "monte cristo"']
+    inspect_source(cop, source)
+    expect(cop.offenses.size).to eq(4)
+  end
+
+  it 'should not record an offense for methods' do
+    source = ['obj.print',
+              'something.p',
+              'nothing.pp']
+    inspect_source(cop, source)
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'should not record an offense for comments' do
+    source = ['# print "test"',
+              '# p']
+    inspect_source(cop, source)
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/rails/read_write_attribute_spec.rb b/spec/rubocop/cop/rails/read_write_attribute_spec.rb
new file mode 100644
index 0000000..533f32c
--- /dev/null
+++ b/spec/rubocop/cop/rails/read_write_attribute_spec.rb
@@ -0,0 +1,19 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Rails::ReadWriteAttribute do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for read_attribute' do
+    inspect_source(cop, 'res = read_attribute(:test)')
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.highlights).to eq(['read_attribute'])
+  end
+
+  it 'registers an offense for write_attribute' do
+    inspect_source(cop, 'write_attribute(:test, val)')
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.highlights).to eq(['write_attribute'])
+  end
+end
diff --git a/spec/rubocop/cop/rails/scope_args_spec.rb b/spec/rubocop/cop/rails/scope_args_spec.rb
new file mode 100644
index 0000000..cb7d372
--- /dev/null
+++ b/spec/rubocop/cop/rails/scope_args_spec.rb
@@ -0,0 +1,25 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Rails::ScopeArgs do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense a scope with a method arg' do
+    inspect_source(cop,
+                   ['scope :active, where(active: true)'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts a lambda arg' do
+    inspect_source(cop,
+                   ['scope :active, -> { where(active: true) }'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a proc arg' do
+    inspect_source(cop,
+                   ['scope :active, proc { where(active: true) }'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/rails/validation_spec.rb b/spec/rubocop/cop/rails/validation_spec.rb
new file mode 100644
index 0000000..50f55ff
--- /dev/null
+++ b/spec/rubocop/cop/rails/validation_spec.rb
@@ -0,0 +1,21 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Rails::Validation do
+  subject(:cop) { described_class.new }
+
+  described_class::BLACKLIST.each do |validation|
+    it "registers an offense for #{validation}" do
+      inspect_source(cop,
+                     ["#{validation} :name"])
+      expect(cop.offenses.size).to eq(1)
+    end
+  end
+
+  it 'accepts sexy validations' do
+    inspect_source(cop,
+                   ['validates :name'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/severity_spec.rb b/spec/rubocop/cop/severity_spec.rb
new file mode 100644
index 0000000..19baa32
--- /dev/null
+++ b/spec/rubocop/cop/severity_spec.rb
@@ -0,0 +1,113 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Severity do
+  let(:refactor) { described_class.new(:refactor) }
+  let(:convention) { described_class.new(:convention) }
+  let(:warning) { described_class.new(:warning) }
+  let(:error) { described_class.new(:error) }
+  let(:fatal) { described_class.new(:fatal) }
+
+  it 'has a few required attributes' do
+    expect(convention.name).to eq(:convention)
+  end
+
+  it 'overrides #to_s' do
+    expect(convention.to_s).to eq('convention')
+  end
+
+  it 'redefines == to compare severities' do
+    expect(convention).to eq(:convention)
+    expect(convention).to eq(described_class.new(:convention))
+    expect(convention).not_to eq(:warning)
+  end
+
+  it 'is frozen' do
+    expect(convention).to be_frozen
+  end
+
+  describe '#code' do
+    describe 'refactor' do
+      it { expect(refactor.code).to eq('R') }
+    end
+
+    describe 'convention' do
+      it { expect(convention.code).to eq('C') }
+    end
+
+    describe 'warning' do
+      it { expect(warning.code).to eq('W') }
+    end
+
+    describe 'error' do
+      it { expect(error.code).to eq('E') }
+    end
+
+    describe 'fatal' do
+      it { expect(fatal.code).to eq('F') }
+    end
+  end
+
+  describe '#level' do
+    describe 'refactor' do
+      it { expect(refactor.level).to eq(1) }
+    end
+
+    describe 'convention' do
+      it { expect(convention.level).to eq(2) }
+    end
+
+    describe 'warning' do
+      it { expect(warning.level).to eq(3) }
+    end
+
+    describe 'error' do
+      it { expect(error.level).to eq(4) }
+    end
+
+    describe 'fatal' do
+      it { expect(fatal.level).to eq(5) }
+    end
+  end
+
+  describe 'constructs from code' do
+    describe 'R' do
+      it { expect(Rubocop::Cop::Severity.new('R')).to eq(refactor) }
+    end
+
+    describe 'C' do
+      it { expect(Rubocop::Cop::Severity.new('C')).to eq(convention) }
+    end
+
+    describe 'W' do
+      it { expect(Rubocop::Cop::Severity.new('W')).to eq(warning) }
+    end
+
+    describe 'E' do
+      it { expect(Rubocop::Cop::Severity.new('E')).to eq(error) }
+    end
+
+    describe 'F' do
+      it { expect(Rubocop::Cop::Severity.new('F')).to eq(fatal) }
+    end
+  end
+
+  describe 'Comparable' do
+    describe 'refactor' do
+      it { expect(refactor).to be < convention }
+    end
+
+    describe 'convention' do
+      it { expect(convention).to be < warning }
+    end
+
+    describe 'warning' do
+      it { expect(warning).to be < error }
+    end
+
+    describe 'error' do
+      it { expect(error).to be < fatal }
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/access_modifier_indentation_spec.rb b/spec/rubocop/cop/style/access_modifier_indentation_spec.rb
new file mode 100644
index 0000000..f32e39f
--- /dev/null
+++ b/spec/rubocop/cop/style/access_modifier_indentation_spec.rb
@@ -0,0 +1,361 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::AccessModifierIndentation, :config do
+  subject(:cop) { described_class.new(config) }
+
+  context 'when EnforcedStyle is set to indent' do
+    let(:cop_config) { { 'EnforcedStyle' => 'indent' } }
+
+    it 'registers an offense for misaligned private' do
+      inspect_source(cop,
+                     ['class Test',
+                      '',
+                      'private',
+                      '',
+                      '  def test; end',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Indent access modifiers like `private`.'])
+      expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'outdent')
+    end
+
+    it 'registers an offense for misaligned private in module' do
+      inspect_source(cop,
+                     ['module Test',
+                      '',
+                      ' private',
+                      '',
+                      '  def test; end',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages).to eq(['Indent access modifiers like `private`.'])
+      # Not aligned according to `indent` or `outdent` style:
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'registers an offense for correct + opposite alignment' do
+      inspect_source(cop,
+                     ['module Test',
+                      '',
+                      '  public',
+                      '',
+                      'private',
+                      '',
+                      '  def test; end',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages).to eq(['Indent access modifiers like `private`.'])
+      # No EnforcedStyle can allow both aligments:
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'registers an offense for opposite + correct alignment' do
+      inspect_source(cop,
+                     ['module Test',
+                      '',
+                      'public',
+                      '',
+                      '  private',
+                      '',
+                      '  def test; end',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages).to eq(['Indent access modifiers like `public`.'])
+      # No EnforcedStyle can allow both aligments:
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'registers an offense for misaligned private in singleton class' do
+      inspect_source(cop,
+                     ['class << self',
+                      '',
+                      'private',
+                      '',
+                      '  def test; end',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Indent access modifiers like `private`.'])
+    end
+
+    it 'registers an offense for misaligned private in class ' \
+       'defined with Class.new' do
+      inspect_source(cop,
+                     ['Test = Class.new do',
+                      '',
+                      'private',
+                      '',
+                      '  def test; end',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Indent access modifiers like `private`.'])
+    end
+
+    it 'registers an offense for misaligned private in module ' \
+       'defined with Module.new' do
+      inspect_source(cop,
+                     ['Test = Module.new do',
+                      '',
+                      'private',
+                      '',
+                      '  def test; end',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Indent access modifiers like `private`.'])
+    end
+
+    it 'registers an offense for misaligned protected' do
+      inspect_source(cop,
+                     ['class Test',
+                      '',
+                      'protected',
+                      '',
+                      '  def test; end',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Indent access modifiers like `protected`.'])
+    end
+
+    it 'accepts properly indented private' do
+      inspect_source(cop,
+                     ['class Test',
+                      '',
+                      '  private',
+                      '',
+                      '  def test; end',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts properly indented protected' do
+      inspect_source(cop,
+                     ['class Test',
+                      '',
+                      '  protected',
+                      '',
+                      '  def test; end',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts an empty class' do
+      inspect_source(cop,
+                     ['class Test',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'handles properly nested classes' do
+      inspect_source(cop,
+                     ['class Test',
+                      '',
+                      '  class Nested',
+                      '',
+                      '  private',
+                      '',
+                      '    def a; end',
+                      '  end',
+                      '',
+                      '  protected',
+                      '',
+                      '  def test; end',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Indent access modifiers like `private`.'])
+    end
+
+    it 'auto-corrects incorrectly indented access modifiers' do
+      corrected = autocorrect_source(cop, ['class Test',
+                                           '',
+                                           'public',
+                                           ' private',
+                                           '   protected',
+                                           '',
+                                           '  def test; end',
+                                           'end'])
+      expect(corrected).to eq(['class Test',
+                               '',
+                               '  public',
+                               '  private',
+                               '  protected',
+                               '',
+                               '  def test; end',
+                               'end'].join("\n"))
+    end
+  end
+
+  context 'when EnforcedStyle is set to outdent' do
+    let(:cop_config) { { 'EnforcedStyle' => 'outdent' } }
+    let(:indent_msg) { 'Outdent access modifiers like `private`.' }
+
+    it 'registers offense for private indented to method depth in a class' do
+      inspect_source(cop,
+                     ['class Test',
+                      '',
+                      '  private',
+                      '',
+                      '  def test; end',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages).to eq([indent_msg])
+      expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'indent')
+    end
+
+    it 'registers offense for private indented to method depth in a module' do
+      inspect_source(cop,
+                     ['module Test',
+                      '',
+                      '  private',
+                      '',
+                      '  def test; end',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages).to eq([indent_msg])
+    end
+
+    it 'registers offense for private indented to method depth in singleton' \
+       'class' do
+      inspect_source(cop,
+                     ['class << self',
+                      '',
+                      '  private',
+                      '',
+                      '  def test; end',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages).to eq([indent_msg])
+    end
+
+    it 'registers offense for private indented to method depth in class ' \
+       'defined with Class.new' do
+      inspect_source(cop,
+                     ['Test = Class.new do',
+                      '',
+                      '  private',
+                      '',
+                      '  def test; end',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages).to eq([indent_msg])
+    end
+
+    it 'registers offense for private indented to method depth in module ' \
+       'defined with Module.new' do
+      inspect_source(cop,
+                     ['Test = Module.new do',
+                      '',
+                      '  private',
+                      '',
+                      '  def test; end',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages).to eq([indent_msg])
+    end
+
+    it 'accepts private indented to the containing class indent level' do
+      inspect_source(cop,
+                     ['class Test',
+                      '',
+                      'private',
+                      '',
+                      '  def test; end',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts protected indented to the containing class indent level' do
+      inspect_source(cop,
+                     ['class Test',
+                      '',
+                      'protected',
+                      '',
+                      '  def test; end',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'handles properly nested classes' do
+      inspect_source(cop,
+                     ['class Test',
+                      '',
+                      '  class Nested',
+                      '',
+                      '    private',
+                      '',
+                      '    def a; end',
+                      '  end',
+                      '',
+                      'protected',
+                      '',
+                      '  def test; end',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages).to eq([indent_msg])
+    end
+
+    it 'auto-corrects incorrectly indented access modifiers' do
+      corrected = autocorrect_source(cop, ['module M',
+                                           '  class Test',
+                                           '',
+                                           'public',
+                                           ' private',
+                                           '     protected',
+                                           '',
+                                           '    def test; end',
+                                           '  end',
+                                           'end'])
+      expect(corrected).to eq(['module M',
+                               '  class Test',
+                               '',
+                               '  public',
+                               '  private',
+                               '  protected',
+                               '',
+                               '    def test; end',
+                               '  end',
+                               'end'].join("\n"))
+    end
+
+    it 'auto-corrects private in complicated case' do
+      corrected = autocorrect_source(cop, ['class Hello',
+                                           '  def foo',
+                                           "    'hi'",
+                                           '  end',
+                                           '',
+                                           '  def bar',
+                                           '    Module.new do',
+                                           '',
+                                           '     private',
+                                           '',
+                                           '      def hi',
+                                           "        'bye'",
+                                           '      end',
+                                           '    end',
+                                           '  end',
+                                           'end'])
+      expect(corrected).to eq(['class Hello',
+                               '  def foo',
+                               "    'hi'",
+                               '  end',
+                               '',
+                               '  def bar',
+                               '    Module.new do',
+                               '',
+                               '    private',
+                               '',
+                               '      def hi',
+                               "        'bye'",
+                               '      end',
+                               '    end',
+                               '  end',
+                               'end'].join("\n"))
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/accessor_method_name_spec.rb b/spec/rubocop/cop/style/accessor_method_name_spec.rb
new file mode 100644
index 0000000..e3c02e0
--- /dev/null
+++ b/spec/rubocop/cop/style/accessor_method_name_spec.rb
@@ -0,0 +1,81 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::AccessorMethodName do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for method get_... with no args' do
+    inspect_source(cop, ['def get_attr',
+                         '  # ...',
+                         'end'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.highlights).to eq(['get_attr'])
+  end
+
+  it 'registers an offense for singleton method get_... with no args' do
+    inspect_source(cop, ['def self.get_attr',
+                         '  # ...',
+                         'end'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.highlights).to eq(['get_attr'])
+  end
+
+  it 'accepts method get_something with args' do
+    inspect_source(cop, ['def get_something(arg)',
+                         '  # ...',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts singleton method get_something with args' do
+    inspect_source(cop, ['def self.get_something(arg)',
+                         '  # ...',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'registers an offense for method set_something with one arg' do
+    inspect_source(cop, ['def set_attr(arg)',
+                         '  # ...',
+                         'end'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.highlights).to eq(['set_attr'])
+  end
+
+  it 'registers an offense for singleton method set_... with one args' do
+    inspect_source(cop, ['def self.set_attr(arg)',
+                         '  # ...',
+                         'end'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.highlights).to eq(['set_attr'])
+  end
+
+  it 'accepts method set_something with no args' do
+    inspect_source(cop, ['def set_something',
+                         '  # ...',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts singleton method set_something with no args' do
+    inspect_source(cop, ['def self.set_something',
+                         '  # ...',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts method set_something with two args' do
+    inspect_source(cop, ['def set_something(arg1, arg2)',
+                         '  # ...',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts singleton method set_something with two args' do
+    inspect_source(cop, ['def self.get_something(arg1, arg2)',
+                         '  # ...',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/alias_spec.rb b/spec/rubocop/cop/style/alias_spec.rb
new file mode 100644
index 0000000..ca92d13
--- /dev/null
+++ b/spec/rubocop/cop/style/alias_spec.rb
@@ -0,0 +1,59 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::Alias do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for alias with symbol args' do
+    inspect_source(cop,
+                   ['alias :ala :bala'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages)
+      .to eq(['Use `alias_method` instead of `alias`.'])
+  end
+
+  it 'autocorrects alias with symbol args' do
+    corrected = autocorrect_source(cop, ['alias :ala :bala'])
+    expect(corrected).to eq 'alias_method :ala, :bala'
+  end
+
+  it 'registers an offense for alias with bareword args' do
+    inspect_source(cop,
+                   ['alias ala bala'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages)
+      .to eq(['Use `alias_method` instead of `alias`.'])
+  end
+
+  it 'autocorrects alias with bareword args' do
+    corrected = autocorrect_source(cop, ['alias ala bala'])
+    expect(corrected).to eq 'alias_method :ala, :bala'
+  end
+
+  it 'does not register an offense for alias_method' do
+    inspect_source(cop,
+                   ['alias_method :ala, :bala'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense for :alias' do
+    inspect_source(cop,
+                   ['[:alias, :ala, :bala]'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense for alias with gvars' do
+    inspect_source(cop,
+                   ['alias $ala $bala'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts alias in an instance_exec block' do
+    inspect_source(cop,
+                   ['cli.instance_exec do',
+                    '  alias :old_trap_interrupt :trap_interrupt',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/align_array_spec.rb b/spec/rubocop/cop/style/align_array_spec.rb
new file mode 100644
index 0000000..6d713c1
--- /dev/null
+++ b/spec/rubocop/cop/style/align_array_spec.rb
@@ -0,0 +1,91 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::AlignArray do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for misaligned array elements' do
+    inspect_source(cop, ['array = [',
+                         '  a,',
+                         '   b,',
+                         '  c,',
+                         '   d',
+                         ']'])
+    expect(cop.messages).to eq(['Align the elements of an array ' \
+                                'literal if they span more than ' \
+                                'one line.'] * 2)
+    expect(cop.highlights).to eq(%w(b d))
+  end
+
+  it 'accepts aligned array keys' do
+    inspect_source(cop, ['array = [',
+                         '  a,',
+                         '  b,',
+                         '  c,',
+                         '  d',
+                         ']'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts single line array' do
+    inspect_source(cop, 'array = [ a, b ]')
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts several elements per line' do
+    inspect_source(cop, ['array = [ a, b,',
+                         '          c, d ]'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'auto-corrects alignment' do
+    new_source = autocorrect_source(cop, ['array = [',
+                                          '  a,',
+                                          '   b,',
+                                          '  c,',
+                                          ' d',
+                                          ']'])
+    expect(new_source).to eq(['array = [',
+                              '  a,',
+                              '  b,',
+                              '  c,',
+                              '  d',
+                              ']'].join("\n"))
+  end
+
+  it 'auto-corrects array within array with too much indentation' do
+    original_source = ['[:l1,',
+                       '  [:l2,',
+                       '',
+                       '    [:l3,',
+                       '     [:l4]]]]']
+    new_source = autocorrect_source(cop, original_source)
+    expect(new_source).to eq(['[:l1,',
+                              ' [:l2,',
+                              '',
+                              '  [:l3,',
+                              '   [:l4]]]]'].join("\n"))
+  end
+
+  it 'auto-corrects array within array with too little indentation' do
+    original_source = ['[:l1,',
+                       '[:l2,',
+                       '',
+                       '  [:l3,',
+                       '   [:l4]]]]']
+    new_source = autocorrect_source(cop, original_source)
+    expect(new_source).to eq(['[:l1,',
+                              ' [:l2,',
+                              '',
+                              '  [:l3,',
+                              '   [:l4]]]]'].join("\n"))
+  end
+
+  it 'auto-corrects only elements that begin a line' do
+    original_source = ['array = [:bar, {',
+                       '         whiz: 2, bang: 3 }, option: 3]']
+    new_source = autocorrect_source(cop, original_source)
+    expect(new_source).to eq(original_source.join("\n"))
+  end
+end
diff --git a/spec/rubocop/cop/style/align_hash_spec.rb b/spec/rubocop/cop/style/align_hash_spec.rb
new file mode 100644
index 0000000..e7c0966
--- /dev/null
+++ b/spec/rubocop/cop/style/align_hash_spec.rb
@@ -0,0 +1,391 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::AlignHash, :config do
+  subject(:cop) { described_class.new(config) }
+
+  shared_examples 'not on separate lines' do
+    it 'accepts single line hash' do
+      inspect_source(cop, 'func(a: 0, bb: 1)')
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts several pairs per line' do
+      inspect_source(cop, ['func(a: 1, bb: 2,',
+                           '     ccc: 3, dddd: 4)'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'always inspect last argument hash' do
+    let(:cop_config) do
+      {
+        'EnforcedLastArgumentHashStyle' => 'always_inspect'
+      }
+    end
+
+    it 'registers offence for misaligned keys in implicit hash' do
+      inspect_source(cop, ['func(a: 0,',
+                           '  b: 1)'])
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it 'registers offence for misaligned keys in explicit hash' do
+      inspect_source(cop, ['func({a: 0,',
+                           '  b: 1})'])
+      expect(cop.offenses.size).to eq(1)
+    end
+  end
+
+  context 'always ignore last argument hash' do
+    let(:cop_config) do
+      {
+        'EnforcedLastArgumentHashStyle' => 'always_ignore'
+      }
+    end
+
+    it 'accepts misaligned keys in implicit hash' do
+      inspect_source(cop, ['func(a: 0,',
+                           '  b: 1)'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts misaligned keys in explicit hash' do
+      inspect_source(cop, ['func({a: 0,',
+                           '  b: 1})'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'ignore implicit last argument hash' do
+    let(:cop_config) do
+      {
+        'EnforcedLastArgumentHashStyle' => 'ignore_implicit'
+      }
+    end
+
+    it 'accepts misaligned keys in implicit hash' do
+      inspect_source(cop, ['func(a: 0,',
+                           '  b: 1)'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers offence for misaligned keys in explicit hash' do
+      inspect_source(cop, ['func({a: 0,',
+                           '  b: 1})'])
+      expect(cop.offenses.size).to eq(1)
+    end
+  end
+
+  context 'ignore explicit last argument hash' do
+    let(:cop_config) do
+      {
+        'EnforcedLastArgumentHashStyle' => 'ignore_explicit'
+      }
+    end
+
+    it 'registers offence for misaligned keys in implicit hash' do
+      inspect_source(cop, ['func(a: 0,',
+                           '  b: 1)'])
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it 'accepts misaligned keys in explicit hash' do
+      inspect_source(cop, ['func({a: 0,',
+                           '  b: 1})'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  let(:cop_config) do
+    {
+      'EnforcedHashRocketStyle' => 'key',
+      'EnforcedColonStyle' => 'key'
+    }
+  end
+
+  context 'with default configuration' do
+    it 'registers an offense for misaligned hash keys' do
+      inspect_source(cop, ['hash1 = {',
+                           '  a: 0,',
+                           '   bb: 1',
+                           '}',
+                           'hash2 = {',
+                           "  'ccc' => 2,",
+                           " 'dddd'  =>  2",
+                           '}'])
+      expect(cop.messages).to eq(['Align the elements of a hash ' \
+                                  'literal if they span more than ' \
+                                  'one line.'] * 2)
+      expect(cop.highlights).to eq(['bb: 1',
+                                    "'dddd'  =>  2"])
+    end
+
+    it 'accepts aligned hash keys' do
+      inspect_source(cop, ['hash1 = {',
+                           '  a: 0,',
+                           '  bb: 1,',
+                           '}',
+                           'hash2 = {',
+                           "  'ccc' => 2,",
+                           "  'dddd'  =>  2",
+                           '}'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for separator alignment' do
+      inspect_source(cop, ['hash = {',
+                           "    'a' => 0,",
+                           "  'bbb' => 1",
+                           '}'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.highlights).to eq(["'bbb' => 1"])
+    end
+
+    context 'with implicit hash as last argument' do
+      it 'registers an offense for misaligned hash keys' do
+        inspect_source(cop, ['func(a: 0,',
+                             '  b: 1)'])
+        expect(cop.offenses.size).to eq(1)
+      end
+
+      it 'registers an offense for right alignment of keys' do
+        inspect_source(cop, ['func(a: 0,',
+                             '   bbb: 1)'])
+        expect(cop.offenses.size).to eq(1)
+      end
+
+      it 'accepts aligned hash keys' do
+        inspect_source(cop, ['func(a: 0,',
+                             '     b: 1)'])
+        expect(cop.offenses).to be_empty
+      end
+
+      it 'accepts an empty hash' do
+        inspect_source(cop, 'h = {}')
+        expect(cop.offenses).to be_empty
+      end
+    end
+
+    it 'auto-corrects alignment' do
+      new_source = autocorrect_source(cop, ['hash1 = { a: 0,',
+                                            '     bb: 1,',
+                                            '           ccc: 2 }',
+                                            'hash2 = { :a   => 0,',
+                                            '     :bb  => 1,',
+                                            '          :ccc  =>2 }'
+                                           ])
+      expect(new_source).to eq(['hash1 = { a: 0,',
+                                '          bb: 1,',
+                                '          ccc: 2 }',
+                                'hash2 = { :a   => 0,',
+                                '          :bb  => 1,',
+                                # Separator and value are not corrected
+                                # in 'key' mode.
+                                '          :ccc  =>2 }'].join("\n"))
+    end
+  end
+
+  include_examples 'not on separate lines'
+
+  context 'with table alignment configuration' do
+    let(:cop_config) do
+      {
+        'EnforcedHashRocketStyle' => 'table',
+        'EnforcedColonStyle' => 'table'
+      }
+    end
+
+    include_examples 'not on separate lines'
+
+    it 'accepts aligned hash keys' do
+      inspect_source(cop, ['hash1 = {',
+                           "  'a'   => 0,",
+                           "  'bbb' => 1",
+                           '}',
+                           'hash2 = {',
+                           '  a:   0,',
+                           '  bbb: 1',
+                           '}'
+                          ])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts an empty hash' do
+      inspect_source(cop, 'h = {}')
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts a multiline array of single line hashes' do
+      inspect_source(cop, ['def self.scenarios_order',
+                           '    [',
+                           '      { before:   %w( l k ) },',
+                           '      { ending:   %w( m l ) },',
+                           '      { starting: %w( m n ) },',
+                           '      { after:    %w( n o ) }',
+                           '    ]',
+                           '  end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for misaligned hash values' do
+      inspect_source(cop, ['hash1 = {',
+                           "  'a'   =>  0,",
+                           "  'bbb' => 1",
+                           '}',
+                           'hash2 = {',
+                           '  a:   0,',
+                           '  bbb:1',
+                           '}'
+                          ])
+      expect(cop.highlights).to eq(["'a'   =>  0",
+                                    'bbb:1'])
+    end
+
+    it 'registers an offense for misaligned hash rockets' do
+      inspect_source(cop, ['hash = {',
+                           "  'a'   => 0,",
+                           "  'bbb'  => 1",
+                           '}'])
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it 'auto-corrects alignment' do
+      new_source = autocorrect_source(cop, ['hash1 = { a: 0,',
+                                            '     bb:   1,',
+                                            '           ccc: 2 }',
+                                            "hash2 = { 'a' => 0,",
+                                            "     'bb' =>   1,",
+                                            "           'ccc'  =>2 }"])
+      expect(new_source).to eq(['hash1 = { a:   0,',
+                                '          bb:  1,',
+                                '          ccc: 2 }',
+                                "hash2 = { 'a'   => 0,",
+                                "          'bb'  => 1,",
+                                "          'ccc' => 2 }"].join("\n"))
+    end
+  end
+
+  context 'with table+separator alignment configuration' do
+    let(:cop_config) do
+      {
+        'EnforcedHashRocketStyle' => 'table',
+        'EnforcedColonStyle' => 'separator'
+      }
+    end
+
+    it 'accepts a single method argument entry with colon' do
+      inspect_source(cop, ['merge(parent: nil)'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'with invalid configuration' do
+    let(:cop_config) do
+      {
+        'EnforcedHashRocketStyle' => 'junk',
+        'EnforcedColonStyle' => 'junk'
+      }
+    end
+    it 'fails' do
+      src = ['hash = {',
+             '  a: 0,',
+             '  bb: 1',
+             '}']
+      expect { inspect_source(cop, src) }.to raise_error(RuntimeError)
+    end
+  end
+
+  context 'with separator alignment configuration' do
+    let(:cop_config) do
+      {
+        'EnforcedHashRocketStyle' => 'separator',
+        'EnforcedColonStyle' => 'separator'
+      }
+    end
+
+    it 'accepts aligned hash keys' do
+      inspect_source(cop, ['hash1 = {',
+                           '    a: 0,',
+                           '  bbb: 1',
+                           '}',
+                           'hash2 = {',
+                           "    'a' => 0,",
+                           "  'bbb' => 1",
+                           '}'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts an empty hash' do
+      inspect_source(cop, 'h = {}')
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for misaligned hash values' do
+      inspect_source(cop, ['hash = {',
+                           "    'a' =>  0,",
+                           "  'bbb' => 1",
+                           '}'])
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it 'registers an offense for misaligned hash rockets' do
+      inspect_source(cop, ['hash = {',
+                           "    'a'  => 0,",
+                           "  'bbb' =>  1",
+                           '}'])
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    include_examples 'not on separate lines'
+
+    it 'auto-corrects alignment' do
+      new_source = autocorrect_source(cop, ['hash1 = { a: 0,',
+                                            '     bb:    1,',
+                                            '           ccc: 2 }',
+                                            'hash2 = { a => 0,',
+                                            '     bb =>    1,',
+                                            '           ccc  =>2 }'])
+      expect(new_source).to eq(['hash1 = { a: 0,',
+                                '         bb: 1,',
+                                '        ccc: 2 }',
+                                'hash2 = { a => 0,',
+                                '         bb => 1,',
+                                '        ccc => 2 }'].join("\n"))
+    end
+  end
+
+  context 'with different settings for => and :' do
+    let(:cop_config) do
+      {
+        'EnforcedHashRocketStyle' => 'key',
+        'EnforcedColonStyle' => 'separator'
+      }
+    end
+
+    it 'registers offenses for misaligned entries' do
+      inspect_source(cop, ['hash1 = {',
+                           '  a:   0,',
+                           '  bbb: 1',
+                           '}',
+                           'hash2 = {',
+                           "    'a' => 0,",
+                           "  'bbb' => 1",
+                           '}'])
+      expect(cop.highlights).to eq(['bbb: 1', "'bbb' => 1"])
+    end
+
+    it 'accepts aligned entries' do
+      inspect_source(cop, ['hash1 = {',
+                           '    a: 0,',
+                           '  bbb: 1',
+                           '}',
+                           'hash2 = {',
+                           "  'a' => 0,",
+                           "  'bbb' => 1",
+                           '}'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/align_parameters_spec.rb b/spec/rubocop/cop/style/align_parameters_spec.rb
new file mode 100644
index 0000000..f8859a9
--- /dev/null
+++ b/spec/rubocop/cop/style/align_parameters_spec.rb
@@ -0,0 +1,295 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::AlignParameters, :config do
+  subject(:cop) { described_class.new(config) }
+
+  context 'aligned with first parameter' do
+    let(:cop_config) do
+      {
+        'EnforcedStyle' => 'with_first_parameter'
+      }
+    end
+
+    it 'registers an offense for parameters with single indent' do
+      inspect_source(cop, ['function(a,',
+                           '  if b then c else d end)'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.highlights).to eq(['if b then c else d end'])
+    end
+
+    it 'registers an offense for parameters with double indent' do
+      inspect_source(cop, ['function(a,',
+                           '    if b then c else d end)'])
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it 'accepts multiline []= method call' do
+      inspect_source(cop, ['Test.config["something"] =',
+                           ' true'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts correctly aligned parameters' do
+      inspect_source(cop, ['function(a,',
+                           '         0, 1,',
+                           '         (x + y),',
+                           '         if b then c else d end)'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts calls that only span one line' do
+      inspect_source(cop, ['find(path, s, @special[sexp[0]])'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it "doesn't get confused by a symbol argument" do
+      inspect_source(cop, ['add_offense(index,',
+                           '            MSG % kind)'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it "doesn't get confused by splat operator" do
+      inspect_source(cop, ['func1(*a,',
+                           '      *b,',
+                           '      c)',
+                           'func2(a,',
+                           '     *b,',
+                           '      c)',
+                           'func3(*a)'
+                          ])
+      expect(cop.offenses.map(&:to_s))
+        .to eq(['C:  5:  6: Align the parameters of a method call if ' \
+                'they span more than one line.'])
+      expect(cop.highlights).to eq(['*b'])
+    end
+
+    it "doesn't get confused by extra comma at the end" do
+      inspect_source(cop, ['func1(a,',
+                           '     b,)'])
+      expect(cop.offenses.map(&:to_s))
+        .to eq(['C:  2:  6: Align the parameters of a method call if ' \
+                'they span more than one line.'])
+      expect(cop.highlights).to eq(['b'])
+    end
+
+    it 'can handle a correctly aligned string literal as first argument' do
+      inspect_source(cop, ['add_offense(x,',
+                           '            a)'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'can handle a string literal as other argument' do
+      inspect_source(cop, ['add_offense(',
+                           '            "", a)'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it "doesn't get confused by a line break inside a parameter" do
+      inspect_source(cop, ['read(path, { headers:    true,',
+                           '             converters: :numeric })'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it "doesn't get confused by symbols with embedded expressions" do
+      inspect_source(cop, ['send(:"#{name}_comments_path")'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it "doesn't get confused by regexen with embedded expressions" do
+      inspect_source(cop, ['a(/#{name}/)'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts braceless hashes' do
+      inspect_source(cop, ['run(collection, :entry_name => label,',
+                           '                :paginator  => paginator)'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts the first parameter being on a new row' do
+      inspect_source(cop, ['  match(',
+                           '    a,',
+                           '    b',
+                           '  )'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'can handle heredoc strings' do
+      inspect_source(cop, ['class_eval(<<-EOS, __FILE__, __LINE__ + 1)',
+                           '            def run_#{name}_callbacks(*args)',
+                           '              a = 1',
+                           '              return value',
+                           '            end',
+                           '            EOS'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'can handle a method call within a method call' do
+      inspect_source(cop, ['a(a1,',
+                           '  b(b1,',
+                           '    b2),',
+                           '  a2)'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'can handle a call embedded in a string' do
+      inspect_source(cop, ['model("#{index(name)}", child)'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'can handle do-end' do
+      inspect_source(cop, ['      run(lambda do |e|',
+                           "        w = e['warden']",
+                           '      end)'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'can handle a call with a block inside another call' do
+      src = ['new(table_name,',
+             '    exec_query("info(\'#{row[\'name\']}\')").map { |col|',
+             "      col['name']",
+             '    })']
+      inspect_source(cop, src)
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'can handle a ternary condition with a block reference' do
+      inspect_source(cop, ['cond ? a : func(&b)'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'can handle parentheses used with no parameters' do
+      inspect_source(cop, ['func()'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'can handle a multiline hash as second parameter' do
+      inspect_source(cop, ['tag(:input, {',
+                           '  :value => value',
+                           '})'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'can handle method calls without parentheses' do
+      inspect_source(cop, ['a(b c, d)'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'can handle other method calls without parentheses' do
+      src = ['chars(Unicode.apply_mapping @wrapped_string, :uppercase)']
+      inspect_source(cop, src)
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'auto-corrects alignment' do
+      new_source = autocorrect_source(cop, ['func(a,',
+                                            '       b,',
+                                            'c)'])
+      expect(new_source).to eq(['func(a,',
+                                '     b,',
+                                '     c)'].join("\n"))
+    end
+
+    it 'auto-corrects each line of a multi-line parameter to the right' do
+      new_source =
+        autocorrect_source(cop,
+                           ['create :transaction, :closed,',
+                            '      account:          account,',
+                            '      open_price:       1.29,',
+                            '      close_price:      1.30'])
+      expect(new_source)
+        .to eq(['create :transaction, :closed,',
+                '       account:          account,',
+                '       open_price:       1.29,',
+                '       close_price:      1.30'].join("\n"))
+    end
+
+    it 'auto-corrects each line of a multi-line parameter to the left' do
+      new_source =
+        autocorrect_source(cop,
+                           ['create :transaction, :closed,',
+                            '         account:          account,',
+                            '         open_price:       1.29,',
+                            '         close_price:      1.30'])
+      expect(new_source)
+        .to eq(['create :transaction, :closed,',
+                '       account:          account,',
+                '       open_price:       1.29,',
+                '       close_price:      1.30'].join("\n"))
+    end
+
+    it 'auto-corrects only parameters that begin a line' do
+      original_source = ['foo(:bar, {',
+                         '    whiz: 2, bang: 3 }, option: 3)']
+      new_source = autocorrect_source(cop, original_source)
+      expect(new_source).to eq(original_source.join("\n"))
+    end
+  end
+
+  context 'aligned with fixed indentation' do
+    let(:cop_config) do
+      {
+        'EnforcedStyle' => 'with_fixed_indentation'
+      }
+    end
+
+    let(:correct_source) do
+      [
+        'create :transaction, :closed,',
+        '  account:     account,',
+        '  open_price:  1.29,',
+        '  close_price: 1.30'
+      ]
+    end
+
+    it 'does not autocorrect correct source' do
+      expect(autocorrect_source(cop, correct_source))
+        .to eq(correct_source.join("\n"))
+    end
+
+    it 'autocorrects by outdenting when indented too far' do
+      original_source = [
+        'create :transaction, :closed,',
+        '       account:     account,',
+        '       open_price:  1.29,',
+        '       close_price: 1.30'
+      ]
+
+      expect(autocorrect_source(cop, original_source))
+        .to eq(correct_source.join("\n"))
+    end
+
+    it 'autocorrects by indenting when not indented' do
+      original_source = [
+        'create :transaction, :closed,',
+        'account:     account,',
+        'open_price:  1.29,',
+        'close_price: 1.30'
+      ]
+
+      expect(autocorrect_source(cop, original_source))
+        .to eq(correct_source.join("\n"))
+    end
+
+    it 'autocorrects when first line is indented' do
+      original_source = [
+        '  create :transaction, :closed,',
+        '  account:     account,',
+        '  open_price:  1.29,',
+        '  close_price: 1.30'
+      ]
+
+      correct_source = [
+        '  create :transaction, :closed,',
+        '    account:     account,',
+        '    open_price:  1.29,',
+        '    close_price: 1.30'
+      ]
+
+      expect(autocorrect_source(cop, original_source))
+        .to eq(correct_source.join("\n"))
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/and_or_spec.rb b/spec/rubocop/cop/style/and_or_spec.rb
new file mode 100644
index 0000000..c16b158
--- /dev/null
+++ b/spec/rubocop/cop/style/and_or_spec.rb
@@ -0,0 +1,57 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::AndOr do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for OR' do
+    inspect_source(cop,
+                   ['test if a or b'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages).to eq(['Use `||` instead of `or`.'])
+  end
+
+  it 'registers an offense for AND' do
+    inspect_source(cop,
+                   ['test if a and b'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages).to eq(['Use `&&` instead of `and`.'])
+  end
+
+  it 'accepts ||' do
+    inspect_source(cop,
+                   ['test if a || b'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts &&' do
+    inspect_source(cop,
+                   ['test if a && b'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'auto-corrects "and" with &&' do
+    new_source = autocorrect_source(cop, 'true and false')
+    expect(new_source).to eq('true && false')
+  end
+
+  it 'auto-corrects "or" with ||' do
+    new_source = autocorrect_source(cop, ['x = 12345',
+                                          'true or false'])
+    expect(new_source).to eq(['x = 12345',
+                              'true || false'].join("\n"))
+  end
+
+  it 'leaves *or* as is if auto-correction changes the meaning' do
+    src = "teststring.include? 'a' or teststring.include? 'b'"
+    new_source = autocorrect_source(cop, src)
+    expect(new_source).to eq(src)
+  end
+
+  it 'leaves *and* as is if auto-correction changes the meaning' do
+    src = 'x = a + b and return x'
+    new_source = autocorrect_source(cop, src)
+    expect(new_source).to eq(src)
+  end
+end
diff --git a/spec/rubocop/cop/style/array_join_spec.rb b/spec/rubocop/cop/style/array_join_spec.rb
new file mode 100644
index 0000000..95e4671
--- /dev/null
+++ b/spec/rubocop/cop/style/array_join_spec.rb
@@ -0,0 +1,29 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::ArrayJoin do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for an array followed by string' do
+    inspect_source(cop,
+                   ['%w(one two three) * ", "'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'does not register an offense for numbers' do
+    inspect_source(cop,
+                   ['%w(one two three) * 4'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense for ambiguous cases' do
+    inspect_source(cop,
+                   ['test * ", "'])
+    expect(cop.offenses).to be_empty
+
+    inspect_source(cop,
+                   ['%w(one two three) * test'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/ascii_comments_spec.rb b/spec/rubocop/cop/style/ascii_comments_spec.rb
new file mode 100644
index 0000000..83b7134
--- /dev/null
+++ b/spec/rubocop/cop/style/ascii_comments_spec.rb
@@ -0,0 +1,22 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::AsciiComments do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for a comment with non-ascii chars' do
+    inspect_source(cop,
+                   ['# encoding: utf-8',
+                    '# 这是什么?'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages)
+      .to eq(['Use only ascii symbols in comments.'])
+  end
+
+  it 'accepts comments with only ascii chars' do
+    inspect_source(cop,
+                   ['# AZaz1@$%~,;*_`|'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/ascii_identifiers_spec.rb b/spec/rubocop/cop/style/ascii_identifiers_spec.rb
new file mode 100644
index 0000000..9e51d34
--- /dev/null
+++ b/spec/rubocop/cop/style/ascii_identifiers_spec.rb
@@ -0,0 +1,36 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::AsciiIdentifiers do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for a variable name with non-ascii chars' do
+    inspect_source(cop,
+                   ['# encoding: utf-8',
+                    'älg = 1'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages)
+      .to eq(['Use only ascii symbols in identifiers.'])
+  end
+
+  it 'accepts identifiers with only ascii chars' do
+    inspect_source(cop,
+                   ['x.empty?'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not get confused by a byte order mark' do
+    bom = "\xef\xbb\xbf"
+    inspect_source(cop,
+                   [bom + '# encoding: utf-8',
+                    "puts 'foo'"])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not get confused by an empty file' do
+    inspect_source(cop,
+                   [''])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/attr_spec.rb b/spec/rubocop/cop/style/attr_spec.rb
new file mode 100644
index 0000000..584122e
--- /dev/null
+++ b/spec/rubocop/cop/style/attr_spec.rb
@@ -0,0 +1,19 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::Attr do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense attr' do
+    inspect_source(cop, ['class SomeClass',
+                         '  attr :name',
+                         'end'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'auto-corrects attr to attr_reader' do
+    new_source = autocorrect_source(cop, 'attr')
+    expect(new_source).to eq('attr_reader')
+  end
+end
diff --git a/spec/rubocop/cop/style/begin_block_spec.rb b/spec/rubocop/cop/style/begin_block_spec.rb
new file mode 100644
index 0000000..13dbba0
--- /dev/null
+++ b/spec/rubocop/cop/style/begin_block_spec.rb
@@ -0,0 +1,13 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::BeginBlock do
+  subject(:cop) { described_class.new }
+
+  it 'reports an offense for a BEGIN block' do
+    src = ['BEGIN { test }']
+    inspect_source(cop, src)
+    expect(cop.offenses.size).to eq(1)
+  end
+end
diff --git a/spec/rubocop/cop/style/block_comments_spec.rb b/spec/rubocop/cop/style/block_comments_spec.rb
new file mode 100644
index 0000000..3dac5b4
--- /dev/null
+++ b/spec/rubocop/cop/style/block_comments_spec.rb
@@ -0,0 +1,21 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::BlockComments do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for block comments' do
+    inspect_source(cop,
+                   ['=begin',
+                    'comment',
+                    '=end'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts regular comments' do
+    inspect_source(cop,
+                   ['# comment'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/block_nesting_spec.rb b/spec/rubocop/cop/style/block_nesting_spec.rb
new file mode 100644
index 0000000..900fbed
--- /dev/null
+++ b/spec/rubocop/cop/style/block_nesting_spec.rb
@@ -0,0 +1,156 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::BlockNesting, :config do
+  subject(:cop) { described_class.new(config) }
+  let(:cop_config) { { 'Max' => 2 } }
+
+  it 'accepts `Max` levels of nesting' do
+    source = ['if a',
+              '  if b',
+              '    puts b',
+              '  end',
+              'end']
+    expect_nesting_offenses(source, [])
+  end
+
+  it 'registers an offense for `Max + 1` levels of `if` nesting' do
+    source = ['if a',
+              '  if b',
+              '    if c',
+              '      puts c',
+              '    end',
+              '  end',
+              'end']
+    expect_nesting_offenses(source, [3])
+  end
+
+  it 'registers one offense for `Max + 2` levels of `if` nesting' do
+    source = ['if a',
+              '  if b',
+              '    if c',
+              '      if d',
+              '        puts d',
+              '      end',
+              '    end',
+              '  end',
+              'end']
+    expect_nesting_offenses(source, [3], 4)
+  end
+
+  it 'registers 2 offenses' do
+    source = ['if a',
+              '  if b',
+              '    if c',
+              '      puts c',
+              '    end',
+              '  end',
+              '  if d',
+              '    if e',
+              '      puts e',
+              '    end',
+              '  end',
+              'end']
+    expect_nesting_offenses(source, [3, 8])
+  end
+
+  it 'registers an offense for nested `case`' do
+    source = ['if a',
+              '  if b',
+              '    case c',
+              '      when C',
+              '        puts C',
+              '    end',
+              '  end',
+              'end']
+    expect_nesting_offenses(source, [3])
+  end
+
+  it 'registers an offense for nested `while`' do
+    source = ['if a',
+              '  if b',
+              '    while c',
+              '      puts c',
+              '    end',
+              '  end',
+              'end']
+    expect_nesting_offenses(source, [3])
+  end
+
+  it 'registers an offense for nested modifier `while`' do
+    source = ['if a',
+              '  if b',
+              '    begin',
+              '      puts c',
+              '    end while c',
+              '  end',
+              'end']
+    expect_nesting_offenses(source, [3])
+  end
+
+  it 'registers an offense for nested `until`' do
+    source = ['if a',
+              '  if b',
+              '    until c',
+              '      puts c',
+              '    end',
+              '  end',
+              'end']
+    expect_nesting_offenses(source, [3])
+  end
+
+  it 'registers an offense for nested modifier `until`' do
+    source = ['if a',
+              '  if b',
+              '    begin',
+              '      puts c',
+              '    end until c',
+              '  end',
+              'end']
+    expect_nesting_offenses(source, [3])
+  end
+
+  it 'registers an offense for nested `for`' do
+    source = ['if a',
+              '  if b',
+              '    for c in [1,2] do',
+              '      puts c',
+              '    end',
+              '  end',
+              'end']
+    expect_nesting_offenses(source, [3])
+  end
+
+  it 'registers an offense for nested `rescue`' do
+    source = ['if a',
+              '  if b',
+              '    begin',
+              '      puts c',
+              '    rescue',
+              '      puts x',
+              '    end',
+              '  end',
+              'end']
+    expect_nesting_offenses(source, [5])
+  end
+
+  it 'accepts if/elsif' do
+    source = ['if a',
+              'elsif b',
+              'elsif c',
+              'elsif d',
+              'end']
+    expect_nesting_offenses(source, [])
+  end
+
+  def expect_nesting_offenses(source, lines, max_to_allow = 3)
+    inspect_source(cop, source)
+    expect(cop.offenses.map(&:line)).to eq(lines)
+    expect(cop.messages).to eq(
+      ['Avoid more than 2 levels of block nesting.'] * lines.length)
+    if cop.offenses.size > 0
+      expect(cop.config_to_allow_offenses['Max']).to eq(max_to_allow)
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/blocks_spec.rb b/spec/rubocop/cop/style/blocks_spec.rb
new file mode 100644
index 0000000..cd6f055
--- /dev/null
+++ b/spec/rubocop/cop/style/blocks_spec.rb
@@ -0,0 +1,105 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::Blocks do
+  subject(:cop) { described_class.new }
+
+  it 'accepts a multiline block with do-end' do
+    inspect_source(cop, ['each do |x|',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'registers an offense for a single line block with do-end' do
+    inspect_source(cop, ['each do |x| end'])
+    expect(cop.messages)
+      .to eq(['Prefer {...} over do...end for single-line blocks.'])
+  end
+
+  it 'accepts a single line block with braces' do
+    inspect_source(cop, ['each { |x| }'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'auto-corrects do and end for single line blocks to { and }' do
+    new_source = autocorrect_source(cop, 'block do |x| end')
+    expect(new_source).to eq('block { |x| }')
+  end
+
+  it 'does not auto-correct do-end if {} would change the meaning' do
+    src = "s.subspec 'Subspec' do |sp| end"
+    new_source = autocorrect_source(cop, src)
+    expect(new_source).to eq(src)
+  end
+
+  context 'when there are braces around a multi-line block' do
+    it 'registers an offense in the simple case' do
+      inspect_source(cop, ['each { |x|',
+                           '}'])
+      expect(cop.messages)
+        .to eq(['Avoid using {...} for multi-line blocks.'])
+    end
+
+    it 'accepts braces if do-end would change the meaning' do
+      src = ['scope :foo, lambda { |f|',
+             '  where(condition: "value")',
+             '}',
+             '',
+             'expect { something }.to raise_error(ErrorClass) { |error|',
+             '  # ...',
+             '}',
+             '',
+             'expect { x }.to change {',
+             '  Counter.count',
+             '}.from(0).to(1)']
+      inspect_source(cop, src)
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for braces if do-end would not change ' \
+       'the meaning' do
+      src = ['scope :foo, (lambda { |f|',
+             '  where(condition: "value")',
+             '})',
+             '',
+             'expect { something }.to(raise_error(ErrorClass) { |error|',
+             '  # ...',
+             '})']
+      inspect_source(cop, src)
+      expect(cop.offenses.size).to eq(2)
+    end
+
+    it 'can handle special method names such as []= and done?' do
+      src = ['h2[k2] = Hash.new { |h3,k3|',
+             '  h3[k3] = 0',
+             '}',
+             '',
+             'x = done? list.reject { |e|',
+             '  e.nil?',
+             '}']
+      inspect_source(cop, src)
+      expect(cop.messages)
+        .to eq(['Avoid using {...} for multi-line blocks.'])
+    end
+
+    it 'auto-corrects { and } to do and end' do
+      source = <<-END.strip_indent
+        each{ |x|
+          some_method
+          other_method
+        }
+      END
+
+      expected_source = <<-END.strip_indent
+        each do |x|
+          some_method
+          other_method
+        end
+      END
+
+      new_source = autocorrect_source(cop, source)
+      expect(new_source).to eq(expected_source)
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/braces_around_hash_parameters_spec.rb b/spec/rubocop/cop/style/braces_around_hash_parameters_spec.rb
new file mode 100644
index 0000000..fb1e182
--- /dev/null
+++ b/spec/rubocop/cop/style/braces_around_hash_parameters_spec.rb
@@ -0,0 +1,284 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::BracesAroundHashParameters, :config do
+  subject(:cop) { described_class.new(config) }
+
+  context 'no_braces' do
+    let(:cop_config) do
+      { 'EnforcedStyle' => 'no_braces' }
+    end
+
+    describe 'accepts' do
+      it 'one non-hash parameter' do
+        inspect_source(cop, ['where(2)'])
+        expect(cop.messages).to be_empty
+        expect(cop.highlights).to be_empty
+      end
+
+      it 'one empty hash parameter' do
+        inspect_source(cop, ['where({})'])
+        expect(cop.messages).to be_empty
+        expect(cop.highlights).to be_empty
+      end
+
+      it 'one hash parameter with separators' do
+        inspect_source(cop, ["where(  {     \n }\t   )  "])
+        expect(cop.messages).to be_empty
+        expect(cop.highlights).to be_empty
+      end
+
+      it 'multiple non-hash parameters' do
+        inspect_source(cop, ['where(1, "2")'])
+        expect(cop.messages).to be_empty
+        expect(cop.highlights).to be_empty
+      end
+
+      it 'one hash parameter without braces' do
+        inspect_source(cop, ['where(x: "y")'])
+        expect(cop.messages).to be_empty
+        expect(cop.highlights).to be_empty
+      end
+
+      it 'one hash parameter without braces and multiple keys' do
+        inspect_source(cop, ['where(x: "y", foo: "bar")'])
+        expect(cop.messages).to be_empty
+        expect(cop.highlights).to be_empty
+      end
+
+      it 'one hash parameter without braces and one hash value' do
+        inspect_source(cop, ['where(x: { "y" => "z" })'])
+        expect(cop.messages).to be_empty
+        expect(cop.highlights).to be_empty
+      end
+
+      it 'multiple hash parameters with braces' do
+        inspect_source(cop, ['where({ x: 1 }, { y: 2 })'])
+        expect(cop.messages).to be_empty
+        expect(cop.highlights).to be_empty
+      end
+
+      it 'property assignment with braces' do
+        inspect_source(cop, ['x.z = { y: "z" }'])
+        expect(cop.messages).to be_empty
+        expect(cop.highlights).to be_empty
+      end
+
+      it 'operator with a hash parameter with braces' do
+        inspect_source(cop, ['x.z - { y: "z" }'])
+        expect(cop.messages).to be_empty
+        expect(cop.highlights).to be_empty
+      end
+
+    end
+
+    describe 'registers an offense for' do
+      it 'one non-hash parameter followed by a hash parameter with braces' do
+        inspect_source(cop, ['where(1, { y: 2 })'])
+        expect(cop.messages).to eq([
+          'Redundant curly braces around a hash parameter.'
+        ])
+        expect(cop.highlights).to eq(['{ y: 2 }'])
+        expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'braces')
+      end
+
+      it 'correct + opposite style' do
+        inspect_source(cop, ['where(1, y: 2)',
+                             'where(1, { y: 2 })'])
+        expect(cop.messages).to eq([
+          'Redundant curly braces around a hash parameter.'
+        ])
+        expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+      end
+
+      it 'opposite + correct style' do
+        inspect_source(cop, ['where(1, { y: 2 })',
+                             'where(1, y: 2)'])
+        expect(cop.messages).to eq([
+          'Redundant curly braces around a hash parameter.'
+        ])
+        expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+      end
+
+      it 'one object method hash parameter with braces' do
+        inspect_source(cop, ['x.func({ y: "z" })'])
+        expect(cop.messages).to eq([
+          'Redundant curly braces around a hash parameter.'
+        ])
+        expect(cop.highlights).to eq(['{ y: "z" }'])
+      end
+
+      it 'one hash parameter with braces' do
+        inspect_source(cop, ['where({ x: 1 })'])
+        expect(cop.messages).to eq([
+          'Redundant curly braces around a hash parameter.'
+        ])
+        expect(cop.highlights).to eq(['{ x: 1 }'])
+      end
+
+      it 'one hash parameter with braces and separators' do
+        inspect_source(cop, ["where(  \n { x: 1 }   )"])
+        expect(cop.messages).to eq([
+          'Redundant curly braces around a hash parameter.'
+        ])
+        expect(cop.highlights).to eq(['{ x: 1 }'])
+      end
+
+      it 'one hash parameter with braces and multiple keys' do
+        inspect_source(cop, ['where({ x: 1, foo: "bar" })'])
+        expect(cop.messages).to eq([
+          'Redundant curly braces around a hash parameter.'
+        ])
+        expect(cop.highlights).to eq(['{ x: 1, foo: "bar" }'])
+      end
+    end
+
+    describe 'auto-corrects' do
+      it 'one non-hash parameter followed by a hash parameter with braces' do
+        corrected = autocorrect_source(cop, ['where(1, { y: 2 })'])
+        expect(corrected).to eq 'where(1,  y: 2 )'
+      end
+
+      it 'one object method hash parameter with braces' do
+        corrected = autocorrect_source(cop, ['x.func({ y: "z" })'])
+        expect(corrected).to eq 'x.func( y: "z" )'
+      end
+
+      it 'one hash parameter with braces' do
+        corrected = autocorrect_source(cop, ['where({ x: 1 })'])
+        expect(corrected).to eq 'where( x: 1 )'
+      end
+
+      it 'one hash parameter with braces and separators' do
+        corrected = autocorrect_source(cop, ["where(  \n { x: 1 }   )"])
+        expect(corrected).to eq "where(  \n  x: 1    )"
+      end
+
+      it 'one hash parameter with braces and multiple keys' do
+        corrected = autocorrect_source(cop, ['where({ x: 1, foo: "bar" })'])
+        expect(corrected).to eq 'where( x: 1, foo: "bar" )'
+      end
+
+      it 'one hash parameter with braces and a trailing comma' do
+        corrected = autocorrect_source(cop, ['where({ x: 1, y: 2, })'])
+        expect(corrected).to eq 'where( x: 1, y: 2 )'
+      end
+    end
+  end
+
+  context 'braces' do
+    let(:cop_config) do
+      { 'EnforcedStyle' => 'braces' }
+    end
+
+    describe 'accepts' do
+      it 'an empty hash parameter' do
+        inspect_source(cop, ['where({})'])
+        expect(cop.messages).to be_empty
+        expect(cop.highlights).to be_empty
+      end
+
+      it 'one non-hash parameter' do
+        inspect_source(cop, ['where(2)'])
+        expect(cop.messages).to be_empty
+        expect(cop.highlights).to be_empty
+      end
+
+      it 'multiple non-hash parameters' do
+        inspect_source(cop, ['where(1, "2")'])
+        expect(cop.messages).to be_empty
+        expect(cop.highlights).to be_empty
+      end
+
+      it 'one hash parameter with braces' do
+        inspect_source(cop, ['where({ x: 1 })'])
+        expect(cop.messages).to be_empty
+        expect(cop.highlights).to be_empty
+      end
+
+      it 'multiple hash parameters with braces' do
+        inspect_source(cop, ['where({ x: 1 }, { y: 2 })'])
+        expect(cop.messages).to be_empty
+        expect(cop.highlights).to be_empty
+      end
+
+      it 'one hash parameter with braces and spaces around it' do
+        inspect_source(cop, [
+          'where(     {  x: 1  }   )'
+        ])
+        expect(cop.messages).to be_empty
+        expect(cop.highlights).to be_empty
+      end
+
+      it 'one hash parameter with braces and separators around it' do
+        inspect_source(cop, ["where( \t    {  x: 1 \n  }   )"])
+        expect(cop.messages).to be_empty
+        expect(cop.highlights).to be_empty
+      end
+    end
+
+    describe 'registers an offense for' do
+      it 'one hash parameter without braces' do
+        inspect_source(cop, ['where(x: "y")'])
+        expect(cop.messages).to eq([
+          'Missing curly braces around a hash parameter.'
+        ])
+        expect(cop.highlights).to eq(['x: "y"'])
+        expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' =>
+                                                   'no_braces')
+      end
+
+      it 'opposite + correct style' do
+        inspect_source(cop, ['where(y: 2)',
+                             'where({ y: 2 })'])
+        expect(cop.messages).to eq([
+          'Missing curly braces around a hash parameter.'
+        ])
+        expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+      end
+
+      it 'correct + opposite style' do
+        inspect_source(cop, ['where({ y: 2 })',
+                             'where(y: 2)'])
+        expect(cop.messages).to eq([
+          'Missing curly braces around a hash parameter.'
+        ])
+        expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+      end
+
+      it 'one hash parameter with multiple keys and without braces' do
+        inspect_source(cop, ['where(x: "y", foo: "bar")'])
+        expect(cop.messages).to eq([
+          'Missing curly braces around a hash parameter.'
+        ])
+        expect(cop.highlights).to eq(['x: "y", foo: "bar"'])
+      end
+
+      it 'one hash parameter without braces with one hash value' do
+        inspect_source(cop, ['where(x: { "y" => "z" })'])
+        expect(cop.messages).to eq([
+          'Missing curly braces around a hash parameter.'
+        ])
+        expect(cop.highlights).to eq(['x: { "y" => "z" }'])
+      end
+    end
+
+    describe 'auto-corrects' do
+      it 'one hash parameter without braces' do
+        corrected = autocorrect_source(cop, ['where(x: "y")'])
+        expect(corrected).to eq 'where({x: "y"})'
+      end
+
+      it 'one hash parameter with multiple keys and without braces' do
+        corrected = autocorrect_source(cop, ['where(x: "y", foo: "bar")'])
+        expect(corrected).to eq 'where({x: "y", foo: "bar"})'
+      end
+
+      it 'one hash parameter without braces with one hash value' do
+        corrected = autocorrect_source(cop, ['where(x: { "y" => "z" })'])
+        expect(corrected).to eq 'where({x: { "y" => "z" }})'
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/case_equality_spec.rb b/spec/rubocop/cop/style/case_equality_spec.rb
new file mode 100644
index 0000000..05ae395
--- /dev/null
+++ b/spec/rubocop/cop/style/case_equality_spec.rb
@@ -0,0 +1,13 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::CaseEquality do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for ===' do
+    inspect_source(cop, ['Array === var'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.highlights).to eq(['==='])
+  end
+end
diff --git a/spec/rubocop/cop/style/case_indentation_spec.rb b/spec/rubocop/cop/style/case_indentation_spec.rb
new file mode 100644
index 0000000..cac6921
--- /dev/null
+++ b/spec/rubocop/cop/style/case_indentation_spec.rb
@@ -0,0 +1,292 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::CaseIndentation do
+  subject(:cop) { described_class.new(config) }
+  let(:config) do
+    merged = Rubocop::ConfigLoader
+      .default_configuration['CaseIndentation'].merge(cop_config)
+    Rubocop::Config.new('CaseIndentation' => merged)
+  end
+
+  context 'with IndentWhenRelativeTo: case' do
+    context 'with IndentOneStep: false' do
+      let(:cop_config) do
+        { 'IndentWhenRelativeTo' => 'case', 'IndentOneStep' => false }
+      end
+
+      context 'regarding assignment where the right hand side is a case' do
+        it 'accepts a correcty indented assignment' do
+          source = ['output = case variable',
+                    "         when 'value1'",
+                    "           'output1'",
+                    '         else',
+                    "           'output2'",
+                    '         end']
+          inspect_source(cop, source)
+          expect(cop.offenses).to be_empty
+        end
+
+        it 'registers on offense for an assignment indented as end' do
+          source = ['output = case variable',
+                    "when 'value1'",
+                    "  'output1'",
+                    'else',
+                    "  'output2'",
+                    'end']
+          inspect_source(cop, source)
+          expect(cop.messages).to eq(['Indent `when` as deep as `case`.'])
+          expect(cop.config_to_allow_offenses).to eq('IndentWhenRelativeTo' =>
+                                                     'end')
+        end
+
+        it 'registers on offense for an assignment indented some other way' do
+          source = ['output = case variable',
+                    "  when 'value1'",
+                    "    'output1'",
+                    '  else',
+                    "    'output2'",
+                    'end']
+          inspect_source(cop, source)
+          expect(cop.messages).to eq(['Indent `when` as deep as `case`.'])
+          expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+        end
+
+        it 'registers on offense for correct + opposite' do
+          source = ['output = case variable',
+                    "         when 'value1'",
+                    "           'output1'",
+                    '         else',
+                    "           'output2'",
+                    '         end',
+                    'output = case variable',
+                    "when 'value1'",
+                    "  'output1'",
+                    'else',
+                    "  'output2'",
+                    'end']
+          inspect_source(cop, source)
+          expect(cop.messages).to eq(['Indent `when` as deep as `case`.'])
+          expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+        end
+      end
+
+      it "registers an offense for a when clause that's deeper than case" do
+        source = ['case a',
+                  '    when 0 then return',
+                  '    else',
+                  '        case b',
+                  '         when 1 then return',
+                  '        end',
+                  'end']
+        inspect_source(cop, source)
+        expect(cop.messages).to eq(['Indent `when` as deep as `case`.'] * 2)
+      end
+
+      it "accepts a when clause that's equally indented with case" do
+        source = ['y = case a',
+                  '    when 0 then break',
+                  '    when 0 then return',
+                  '    else',
+                  '      z = case b',
+                  '          when 1 then return',
+                  '          when 1 then break',
+                  '          end',
+                  '    end',
+                  'case c',
+                  'when 2 then encoding',
+                  'end',
+                  '']
+        inspect_source(cop, source)
+        expect(cop.offenses).to be_empty
+      end
+
+      it "doesn't get confused by strings with case in them" do
+        source = ['a = "case"',
+                  'case x',
+                  'when 0',
+                  'end',
+                  '']
+        inspect_source(cop, source)
+        expect(cop.messages).to be_empty
+      end
+
+      it "doesn't get confused by symbols named case or when" do
+        source = ['KEYWORDS = { :case => true, :when => true }',
+                  'case type',
+                  'when 0',
+                  '  ParameterNode',
+                  'when 1',
+                  '  MethodCallNode',
+                  'end',
+                  '']
+        inspect_source(cop, source)
+        expect(cop.messages).to be_empty
+      end
+
+      it 'accepts correctly indented whens in complex combinations' do
+        source = ['each {',
+                  '  case state',
+                  '  when 0',
+                  '    case name',
+                  '    when :a',
+                  '    end',
+                  '  when 1',
+                  '    loop {',
+                  '      case name',
+                  '      when :b',
+                  '      end',
+                  '    }',
+                  '  end',
+                  '}',
+                  'case s',
+                  'when Array',
+                  'end',
+                  '']
+        inspect_source(cop, source)
+        expect(cop.messages).to be_empty
+      end
+    end
+
+    context 'with IndentOneStep: true' do
+      let(:cop_config) do
+        { 'IndentWhenRelativeTo' => 'case', 'IndentOneStep' => true }
+      end
+
+      context 'regarding assignment where the right hand side is a case' do
+        it 'accepts a correcty indented assignment' do
+          source = ['output = case variable',
+                    "           when 'value1'",
+                    "             'output1'",
+                    '           else',
+                    "             'output2'",
+                    '         end']
+          inspect_source(cop, source)
+          expect(cop.offenses).to be_empty
+        end
+
+        it 'registers on offense for an assignment indented some other way' do
+          source = ['output = case variable',
+                    "         when 'value1'",
+                    "           'output1'",
+                    '         else',
+                    "           'output2'",
+                    '         end']
+          inspect_source(cop, source)
+          expect(cop.messages)
+            .to eq(['Indent `when` one step more than `case`.'])
+        end
+      end
+
+      it "accepts a when clause that's 2 spaces deeper than case" do
+        source = ['case a',
+                  '  when 0 then return',
+                  '  else',
+                  '        case b',
+                  '          when 1 then return',
+                  '        end',
+                  'end']
+        inspect_source(cop, source)
+        expect(cop.offenses).to be_empty
+      end
+
+      it "registers an offense for  a when clause that's equally indented " \
+         'with case' do
+        source = ['y = case a',
+                  '    when 0 then break',
+                  '    when 0 then return',
+                  '      z = case b',
+                  '          when 1 then return',
+                  '          when 1 then break',
+                  '          end',
+                  '    end',
+                  'case c',
+                  'when 2 then encoding',
+                  'end',
+                  '']
+        inspect_source(cop, source)
+        expect(cop.messages)
+          .to eq(['Indent `when` one step more than `case`.'] * 5)
+      end
+    end
+  end
+
+  context 'with IndentWhenRelativeTo: end' do
+    context 'with IndentOneStep: false' do
+      let(:cop_config) do
+        { 'IndentWhenRelativeTo' => 'end', 'IndentOneStep' => false }
+      end
+
+      context 'regarding assignment where the right hand side is a case' do
+        it 'accepts a correcty indented assignment' do
+          source = ['output = case variable',
+                    "when 'value1'",
+                    "  'output1'",
+                    'else',
+                    "  'output2'",
+                    'end']
+          inspect_source(cop, source)
+          expect(cop.offenses).to be_empty
+        end
+
+        it 'registers on offense for an assignment indented some other way' do
+          source = ['output = case variable',
+                    "  when 'value1'",
+                    "    'output1'",
+                    '  else',
+                    "    'output2'",
+                    'end']
+          inspect_source(cop, source)
+          expect(cop.messages).to eq(['Indent `when` as deep as `end`.'])
+        end
+      end
+    end
+
+    context 'with IndentOneStep: true' do
+      let(:cop_config) do
+        { 'IndentWhenRelativeTo' => 'end', 'IndentOneStep' => true }
+      end
+
+      context 'regarding assignment where the right hand side is a case' do
+        it 'accepts a correcty indented assignment' do
+          source = ['output = case variable',
+                    "  when 'value1'",
+                    "    'output1'",
+                    '  else',
+                    "    'output2'",
+                    'end']
+          inspect_source(cop, source)
+          expect(cop.offenses).to be_empty
+        end
+
+        it 'registers on offense for an assignment indented as case' do
+          source = ['output = case variable',
+                    "         when 'value1'",
+                    "           'output1'",
+                    '         else',
+                    "           'output2'",
+                    '         end']
+          inspect_source(cop, source)
+          expect(cop.messages)
+            .to eq(['Indent `when` one step more than `end`.'])
+          expect(cop.config_to_allow_offenses).to eq('IndentWhenRelativeTo' =>
+                                                     'case')
+        end
+
+        it 'registers on offense for an assignment indented some other way' do
+          source = ['output = case variable',
+                    "       when 'value1'",
+                    "         'output1'",
+                    '       else',
+                    "         'output2'",
+                    '       end']
+          inspect_source(cop, source)
+          expect(cop.messages)
+            .to eq(['Indent `when` one step more than `end`.'])
+          expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+        end
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/character_literal_spec.rb b/spec/rubocop/cop/style/character_literal_spec.rb
new file mode 100644
index 0000000..b063636
--- /dev/null
+++ b/spec/rubocop/cop/style/character_literal_spec.rb
@@ -0,0 +1,37 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::CharacterLiteral do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for character literals' do
+    inspect_source(cop, ['x = ?x'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for literals like \n' do
+    inspect_source(cop, ['x = ?\n'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts literals like ?\C-\M-d' do
+    inspect_source(cop, ['x = ?\C-\M-d'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts ? in a %w literal' do
+    inspect_source(cop, ['%w{? A}'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it "auto-corrects ?x to 'x'" do
+    new_source = autocorrect_source(cop, 'x = ?x')
+    expect(new_source).to eq("x = 'x'")
+  end
+
+  it 'auto-corrects ?\n to "\\n"' do
+    new_source = autocorrect_source(cop, 'x = ?\n')
+    expect(new_source).to eq('x = "\\n"')
+  end
+end
diff --git a/spec/rubocop/cop/style/class_and_module_camel_case_spec.rb b/spec/rubocop/cop/style/class_and_module_camel_case_spec.rb
new file mode 100644
index 0000000..4ed3f71
--- /dev/null
+++ b/spec/rubocop/cop/style/class_and_module_camel_case_spec.rb
@@ -0,0 +1,40 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::ClassAndModuleCamelCase do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for underscore in class and module name' do
+    inspect_source(cop,
+                   ['class My_Class',
+                    'end',
+                    '',
+                    'module My_Module',
+                    'end'
+                   ])
+    expect(cop.offenses.size).to eq(2)
+  end
+
+  it 'is not fooled by qualified names' do
+    inspect_source(cop,
+                   ['class Top::My_Class',
+                    'end',
+                    '',
+                    'module My_Module::Ala',
+                    'end'
+                   ])
+    expect(cop.offenses.size).to eq(2)
+  end
+
+  it 'accepts CamelCase names' do
+    inspect_source(cop,
+                   ['class MyClass',
+                    'end',
+                    '',
+                    'module Mine',
+                    'end'
+                   ])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/class_and_module_children_spec.rb b/spec/rubocop/cop/style/class_and_module_children_spec.rb
new file mode 100644
index 0000000..5e2ed3c
--- /dev/null
+++ b/spec/rubocop/cop/style/class_and_module_children_spec.rb
@@ -0,0 +1,129 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::ClassAndModuleChildren, :config do
+  subject(:cop) { described_class.new(config) }
+
+  context 'nested style' do
+    let(:cop_config) do
+      {
+        'EnforcedStyle' => 'nested'
+      }
+    end
+
+    it 'registers an offense for not nested classes' do
+      inspect_source(cop, ['class FooClass::BarClass', 'end'])
+
+      expect(cop.offenses.size).to eq 1
+      expect(cop.messages).to eq [
+        'Use nested module/class definitions instead of compact style.'
+      ]
+      expect(cop.highlights).to eq ['FooClass::BarClass']
+    end
+
+    it 'registers an offense for not nested modules' do
+      inspect_source(cop, ['module FooModule::BarModule', 'end'])
+
+      expect(cop.offenses.size).to eq 1
+      expect(cop.messages).to eq [
+        'Use nested module/class definitions instead of compact style.'
+      ]
+      expect(cop.highlights).to eq ['FooModule::BarModule']
+    end
+
+    it 'accepts nested children' do
+      inspect_source(cop,
+                     ['class FooClass',
+                      '  class BarClass',
+                      '  end',
+                      'end',
+                      '',
+                      'module FooModule',
+                      '  module BarModule',
+                      '  end',
+                      'end'
+                     ])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts :: in parent class on inheritance' do
+      inspect_source(cop,
+                     ['class FooClass',
+                      '  class BarClass',
+                      '  end',
+                      'end',
+                      '',
+                      'class BazClass < FooClass::BarClass',
+                      'end'
+                     ])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'compact style' do
+    let(:cop_config) do
+      {
+        'EnforcedStyle' => 'compact'
+      }
+    end
+
+    it 'registers a offense for classes with nested children' do
+      inspect_source(cop,
+                     ['class FooClass',
+                      '  class BarClass',
+                      '  end',
+                      'end'
+                     ])
+      expect(cop.offenses.size).to eq 1
+      expect(cop.messages).to eq [
+        'Use compact module/class definition instead of nested style.'
+      ]
+      expect(cop.highlights).to eq ['FooClass']
+    end
+
+    it 'registers a offense for modules with nested children' do
+      inspect_source(cop,
+                     ['module FooModule',
+                      '  module BarModule',
+                      '  end',
+                      'end'
+                     ])
+      expect(cop.offenses.size).to eq 1
+      expect(cop.messages).to eq [
+        'Use compact module/class definition instead of nested style.'
+      ]
+      expect(cop.highlights).to eq ['FooModule']
+    end
+
+    it 'accepts compact style for classes / modules' do
+      inspect_source(cop,
+                     ['class FooClass::BarClass',
+                      'end',
+                      '',
+                      'module FooClass::BarModule',
+                      'end'
+                     ])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts nesting for classes / modules with more than one child' do
+      inspect_source(cop,
+                     ['class FooClass',
+                      '  class BarClass',
+                      '  end',
+                      '  class BazClass',
+                      '  end',
+                      'end',
+                      '',
+                      'module FooModule',
+                      '  module BarModule',
+                      '  end',
+                      '  class BazModule',
+                      '  end',
+                      'end'
+                     ])
+      expect(cop.offenses).to be_empty
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/class_length_spec.rb b/spec/rubocop/cop/style/class_length_spec.rb
new file mode 100644
index 0000000..5d5e18b
--- /dev/null
+++ b/spec/rubocop/cop/style/class_length_spec.rb
@@ -0,0 +1,131 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::ClassLength, :config do
+  subject(:cop) { described_class.new(config) }
+  let(:cop_config) { { 'Max' => 5, 'CountComments' => false } }
+
+  it 'rejects a class with more than 5 lines' do
+    inspect_source(cop, ['class Test',
+                         '  a = 1',
+                         '  a = 2',
+                         '  a = 3',
+                         '  a = 4',
+                         '  a = 5',
+                         '  a = 6',
+                         'end'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages).to eq(['Class definition is too long. [6/5]'])
+    expect(cop.config_to_allow_offenses).to eq('Max' => 6)
+  end
+
+  it 'accepts a class with 5 lines' do
+    inspect_source(cop, ['class Test',
+                         '  a = 1',
+                         '  a = 2',
+                         '  a = 3',
+                         '  a = 4',
+                         '  a = 5',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a class with less than 5 lines' do
+    inspect_source(cop, ['class Test',
+                         '  a = 1',
+                         '  a = 2',
+                         '  a = 3',
+                         '  a = 4',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not count blank lines' do
+    inspect_source(cop, ['class Test',
+                         '  a = 1',
+                         '  a = 2',
+                         '  a = 3',
+                         '  a = 4',
+                         '',
+                         '',
+                         '  a = 7',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts empty classes' do
+    inspect_source(cop, ['class Test',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  context 'when a class has inner classes' do
+    it 'does not count lines of inner classes' do
+      inspect_source(cop, ['class NamespaceClass',
+                           '  class TestOne',
+                           '    a = 1',
+                           '    a = 2',
+                           '    a = 3',
+                           '    a = 4',
+                           '    a = 5',
+                           '  end',
+                           '  class TestTwo',
+                           '    a = 1',
+                           '    a = 2',
+                           '    a = 3',
+                           '    a = 4',
+                           '    a = 5',
+                           '  end',
+                           '  a = 1',
+                           '  a = 2',
+                           '  a = 3',
+                           '  a = 4',
+                           '  a = 5',
+                           'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'rejects a class with 6 lines that belong to the class directly' do
+      inspect_source(cop, ['class NamespaceClass',
+                           '  class TestOne',
+                           '    a = 1',
+                           '    a = 2',
+                           '    a = 3',
+                           '    a = 4',
+                           '    a = 5',
+                           '  end',
+                           '  class TestTwo',
+                           '    a = 1',
+                           '    a = 2',
+                           '    a = 3',
+                           '    a = 4',
+                           '    a = 5',
+                           '  end',
+                           '  a = 1',
+                           '  a = 2',
+                           '  a = 3',
+                           '  a = 4',
+                           '  a = 5',
+                           '  a = 6',
+                           'end'])
+      expect(cop.offenses.size).to eq(1)
+    end
+  end
+
+  context 'when CountComments is enabled' do
+    before { cop_config['CountComments'] = true }
+
+    it 'also counts commented lines' do
+      inspect_source(cop, ['class Test',
+                           '  a = 1',
+                           '  #a = 2',
+                           '  a = 3',
+                           '  #a = 4',
+                           '  a = 5',
+                           '  a = 6',
+                           'end'])
+      expect(cop.offenses.size).to eq(1)
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/class_methods_spec.rb b/spec/rubocop/cop/style/class_methods_spec.rb
new file mode 100644
index 0000000..8d5939b
--- /dev/null
+++ b/spec/rubocop/cop/style/class_methods_spec.rb
@@ -0,0 +1,68 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::ClassMethods do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for methods using a class name' do
+    inspect_source(cop,
+                   ['class Test',
+                    '  def Test.some_method',
+                    '    do_something',
+                    '  end',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages)
+      .to eq(['Use `self.some_method` instead of `Test.some_method`.'])
+    expect(cop.highlights).to eq(['Test'])
+  end
+
+  it 'registers an offense for methods using a module name' do
+    inspect_source(cop,
+                   ['module Test',
+                    '  def Test.some_method',
+                    '    do_something',
+                    '  end',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages)
+      .to eq(['Use `self.some_method` instead of `Test.some_method`.'])
+    expect(cop.highlights).to eq(['Test'])
+  end
+
+  it 'does not register an offense for methods using self' do
+    inspect_source(cop,
+                   ['module Test',
+                    '  def self.some_method',
+                    '    do_something',
+                    '  end',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense outside class/module bodies' do
+    inspect_source(cop,
+                   ['def Test.some_method',
+                    '  do_something',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'autocorrects class name to self' do
+    src = ['class Test',
+           '  def Test.some_method',
+           '    do_something',
+           '  end',
+           'end']
+
+    correct_source = ['class Test',
+                      '  def self.some_method',
+                      '    do_something',
+                      '  end',
+                      'end'].join("\n")
+
+    new_source = autocorrect_source(cop, src)
+    expect(new_source).to eq(correct_source)
+  end
+end
diff --git a/spec/rubocop/cop/style/class_vars_spec.rb b/spec/rubocop/cop/style/class_vars_spec.rb
new file mode 100644
index 0000000..0dd3511
--- /dev/null
+++ b/spec/rubocop/cop/style/class_vars_spec.rb
@@ -0,0 +1,19 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::ClassVars do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for class variable declaration' do
+    inspect_source(cop, ['class TestClass; @@test = 10; end'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages)
+      .to eq(['Replace class var @@test with a class instance var.'])
+  end
+
+  it 'does not register an offense for class variable usage' do
+    inspect_source(cop, ['@@test.test(20)'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/collection_methods_spec.rb b/spec/rubocop/cop/style/collection_methods_spec.rb
new file mode 100644
index 0000000..12cde23
--- /dev/null
+++ b/spec/rubocop/cop/style/collection_methods_spec.rb
@@ -0,0 +1,48 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::CollectionMethods, :config do
+  cop_config = {
+    'PreferredMethods' => {
+      'collect' => 'map',
+      'inject' => 'reduce',
+      'detect' => 'find',
+      'find_all' => 'select'
+    }
+  }
+
+  subject(:cop) { described_class.new(config) }
+  let(:cop_config) { cop_config }
+
+  cop_config['PreferredMethods'].each do |method, preferred_method|
+    it "registers an offense for #{method} with block" do
+      inspect_source(cop, ["[1, 2, 3].#{method} { |e| e + 1 }"])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(["Prefer `#{preferred_method}` over `#{method}`."])
+    end
+
+    it "registers an offense for #{method} with proc param" do
+      inspect_source(cop, ["[1, 2, 3].#{method}(&:test)"])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(["Prefer `#{preferred_method}` over `#{method}`."])
+    end
+
+    it "accepts #{method} with more than 1 param" do
+      inspect_source(cop, ["[1, 2, 3].#{method}(other, &:test)"])
+      expect(cop.offenses).to be_empty
+    end
+
+    it "accepts #{method} without a block" do
+      inspect_source(cop, ["[1, 2, 3].#{method}"])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'auto-corrects to preferred method' do
+      new_source = autocorrect_source(cop, 'some.collect(&:test)')
+      expect(new_source).to eq('some.map(&:test)')
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/colon_method_call_spec.rb b/spec/rubocop/cop/style/colon_method_call_spec.rb
new file mode 100644
index 0000000..9016802
--- /dev/null
+++ b/spec/rubocop/cop/style/colon_method_call_spec.rb
@@ -0,0 +1,60 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::ColonMethodCall do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for instance method call' do
+    inspect_source(cop,
+                   ['test::method_name'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for instance method call with arg' do
+    inspect_source(cop,
+                   ['test::method_name(arg)'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for class method call' do
+    inspect_source(cop,
+                   ['Class::method_name'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for class method call with arg' do
+    inspect_source(cop,
+                   ['Class::method_name(arg, arg2)'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'does not register an offense for constant access' do
+    inspect_source(cop,
+                   ['Tip::Top::SOME_CONST'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense for nested class' do
+    inspect_source(cop,
+                   ['Tip::Top.some_method'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense for op methods' do
+    inspect_source(cop,
+                   ['Tip::Top.some_method[3]'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense when for constructor methods' do
+    inspect_source(cop,
+                   ['Tip::Top(some_arg)'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'auto-corrects "::" with "."' do
+    new_source = autocorrect_source(cop, 'test::method')
+    expect(new_source).to eq('test.method')
+  end
+end
diff --git a/spec/rubocop/cop/style/comment_annotation_spec.rb b/spec/rubocop/cop/style/comment_annotation_spec.rb
new file mode 100644
index 0000000..cf05169
--- /dev/null
+++ b/spec/rubocop/cop/style/comment_annotation_spec.rb
@@ -0,0 +1,86 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::CommentAnnotation, :config do
+  subject(:cop) { described_class.new(config) }
+  let(:cop_config) do
+    { 'Keywords' => %w(TODO FIXME OPTIMIZE HACK REVIEW) }
+  end
+
+  it 'registers an offense for a missing colon' do
+    inspect_source(cop, ['# TODO make better'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  context 'with configured keyword' do
+    let(:cop_config) { { 'Keywords' => %w(ISSUE) } }
+
+    it 'registers an offense for a missing colon after the word' do
+      inspect_source(cop, ['# ISSUE wrong order'])
+      expect(cop.offenses.size).to eq(1)
+    end
+  end
+
+  context 'when used with the clang formatter' do
+    let(:formatter) { Rubocop::Formatter::ClangStyleFormatter.new(output) }
+    let(:output) { StringIO.new }
+
+    it 'marks the annotation keyword' do
+      inspect_source(cop, ['# TODO:make better'])
+      formatter.report_file('t', cop.offenses)
+      expect(output.string).to eq(["t:1:3: C: #{described_class::MSG}",
+                                   '# TODO:make better',
+                                   '  ^^^^^',
+                                   ''].join("\n"))
+    end
+  end
+
+  it 'registers an offense for lower case' do
+    inspect_source(cop, ['# fixme: does not work'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for capitalized annotation keyword' do
+    inspect_source(cop, ['# Optimize: does not work'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for upper case with colon but no note' do
+    inspect_source(cop, ['# HACK:'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts upper case keyword with colon, space and note' do
+    inspect_source(cop, ['# REVIEW: not sure about this'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts upper case keyword alone' do
+    inspect_source(cop, ['# OPTIMIZE'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a comment that is obviously a code example' do
+    inspect_source(cop, ['# Todo.destroy(1)'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a keyword that is just the beginning of a sentence' do
+    inspect_source(cop,
+                   ["# Optimize if you want. I wouldn't recommend it.",
+                    '# Hack is a fun game.'])
+    expect(cop.offenses).to be_empty
+  end
+
+  context 'when a keyword is not in the configuration' do
+    let(:cop_config) do
+      { 'Keywords' => %w(FIXME OPTIMIZE HACK REVIEW) }
+    end
+
+    it 'accepts the word without colon' do
+      inspect_source(cop, ['# TODO make better'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/constant_name_spec.rb b/spec/rubocop/cop/style/constant_name_spec.rb
new file mode 100644
index 0000000..3f38f26
--- /dev/null
+++ b/spec/rubocop/cop/style/constant_name_spec.rb
@@ -0,0 +1,65 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::ConstantName do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for camel case in const name' do
+    inspect_source(cop,
+                   ['TopCase = 5'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers offenses for camel case in multiple const assignment' do
+    inspect_source(cop,
+                   ['TopCase, Test2, TEST_3 = 5, 6, 7'])
+    expect(cop.offenses.size).to eq(2)
+  end
+
+  it 'registers an offense for snake case in const name' do
+    inspect_source(cop,
+                   ['TOP_test = 5'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'allows screaming snake case in const name' do
+    inspect_source(cop,
+                   ['TOP_TEST = 5'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'allows screaming snake case in multiple const assignment' do
+    inspect_source(cop,
+                   ['TOP_TEST, TEST_2 = 5, 6'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not check names if rhs is a method call' do
+    inspect_source(cop,
+                   ['AnythingGoes = test'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not check names if rhs is a method call with block' do
+    inspect_source(cop,
+                   ['AnythingGoes = test do',
+                    '  do_something',
+                    'end'
+                    ])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not check if rhs is another constant' do
+    inspect_source(cop,
+                   ['Parser::CurrentRuby = Parser::Ruby20'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'checks qualified const names' do
+    inspect_source(cop,
+                   ['::AnythingGoes = 30',
+                    'a::Bar_foo = 10'])
+    expect(cop.offenses.size).to eq(2)
+  end
+end
diff --git a/spec/rubocop/cop/style/cyclomatic_complexity_spec.rb b/spec/rubocop/cop/style/cyclomatic_complexity_spec.rb
new file mode 100644
index 0000000..e41c3a5
--- /dev/null
+++ b/spec/rubocop/cop/style/cyclomatic_complexity_spec.rb
@@ -0,0 +1,204 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::CyclomaticComplexity, :config do
+  subject(:cop) { described_class.new(config) }
+
+  context 'when Max is 1' do
+    let(:cop_config) { { 'Max' => 1 } }
+
+    it 'accepts a method with no decision points' do
+      inspect_source(cop, ['def method_name',
+                           '  call_foo',
+                           'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts complex code outside of methods' do
+      inspect_source(cop,
+                     ['def method_name',
+                      '  call_foo',
+                      'end',
+                      '',
+                      'if first_condition then',
+                      '  call_foo if second_condition && third_condition',
+                      '  call_bar if fourth_condition || fifth_condition',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for an if modifier' do
+      inspect_source(cop, ['def self.method_name',
+                           '  call_foo if some_condition',
+                           'end'])
+      expect(cop.messages)
+        .to eq(['Cyclomatic complexity for method_name is too high. [2/1]'])
+      expect(cop.highlights).to eq(['def'])
+      expect(cop.config_to_allow_offenses).to eq('Max' => 2)
+    end
+
+    it 'registers an offense for an unless modifier' do
+      inspect_source(cop, ['def method_name',
+                           '  call_foo unless some_condition',
+                           'end'])
+      expect(cop.messages)
+        .to eq(['Cyclomatic complexity for method_name is too high. [2/1]'])
+    end
+
+    it 'registers an offense for an elsif block' do
+      inspect_source(cop, ['def method_name',
+                           '  if first_condition then',
+                           '    call_foo',
+                           '  elsif second_condition then',
+                           '    call_bar',
+                           '  else',
+                           '    call_bam',
+                           '  end',
+                           'end'])
+      expect(cop.messages)
+        .to eq(['Cyclomatic complexity for method_name is too high. [3/1]'])
+    end
+
+    it 'registers an offense for a ternary operator' do
+      inspect_source(cop, ['def method_name',
+                           '  value = some_condition ? 1 : 2',
+                           'end'])
+      expect(cop.messages)
+        .to eq(['Cyclomatic complexity for method_name is too high. [2/1]'])
+    end
+
+    it 'registers an offense for a while block' do
+      inspect_source(cop, ['def method_name',
+                           '  while some_condition do',
+                           '    call_foo',
+                           '  end',
+                           'end'])
+      expect(cop.messages)
+        .to eq(['Cyclomatic complexity for method_name is too high. [2/1]'])
+    end
+
+    it 'registers an offense for an until block' do
+      inspect_source(cop, ['def method_name',
+                           '  until some_condition do',
+                           '    call_foo',
+                           '  end',
+                           'end'])
+      expect(cop.messages)
+        .to eq(['Cyclomatic complexity for method_name is too high. [2/1]'])
+    end
+
+    it 'registers an offense for a for block' do
+      inspect_source(cop, ['def method_name',
+                           '  for i in 1..2 do',
+                           '    call_method',
+                           '  end',
+                           'end'])
+      expect(cop.messages)
+        .to eq(['Cyclomatic complexity for method_name is too high. [2/1]'])
+    end
+
+    it 'registers an offense for a rescue block' do
+      inspect_source(cop, ['def method_name',
+                           '  begin',
+                           '    call_foo',
+                           '  rescue Exception',
+                           '    call_bar',
+                           '  end',
+                           'end'])
+      expect(cop.messages)
+        .to eq(['Cyclomatic complexity for method_name is too high. [2/1]'])
+    end
+
+    it 'registers an offense for a case/when block' do
+      inspect_source(cop, ['def method_name',
+                           '  case value',
+                           '  when 1',
+                           '    call_foo',
+                           '  when 2',
+                           '    call_bar',
+                           '  end',
+                           'end'])
+      expect(cop.messages)
+        .to eq(['Cyclomatic complexity for method_name is too high. [3/1]'])
+    end
+
+    it 'registers an offense for &&' do
+      inspect_source(cop, ['def method_name',
+                           '  call_foo && call_bar',
+                           'end'])
+      expect(cop.messages)
+        .to eq(['Cyclomatic complexity for method_name is too high. [2/1]'])
+    end
+
+    it 'registers an offense for and' do
+      inspect_source(cop, ['def method_name',
+                           '  call_foo and call_bar',
+                           'end'])
+      expect(cop.messages)
+        .to eq(['Cyclomatic complexity for method_name is too high. [2/1]'])
+    end
+
+    it 'registers an offense for ||' do
+      inspect_source(cop, ['def method_name',
+                           '  call_foo || call_bar',
+                           'end'])
+      expect(cop.messages)
+        .to eq(['Cyclomatic complexity for method_name is too high. [2/1]'])
+    end
+
+    it 'registers an offense for or' do
+      inspect_source(cop, ['def method_name',
+                           '  call_foo or call_bar',
+                           'end'])
+      expect(cop.messages)
+        .to eq(['Cyclomatic complexity for method_name is too high. [2/1]'])
+    end
+
+    it 'deals with nested if blocks containing && and ||' do
+      inspect_source(cop,
+                     ['def method_name',
+                      '  if first_condition then',
+                      '    call_foo if second_condition && third_condition',
+                      '    call_bar if fourth_condition || fifth_condition',
+                      '  end',
+                      'end'])
+      expect(cop.messages)
+        .to eq(['Cyclomatic complexity for method_name is too high. [6/1]'])
+    end
+
+    it 'counts only a single method' do
+      inspect_source(cop, ['def method_name_1',
+                           '  call_foo if some_condition',
+                           'end',
+                           '',
+                           'def method_name_2',
+                           '  call_foo if some_condition',
+                           'end'])
+      expect(cop.messages)
+        .to eq(['Cyclomatic complexity for method_name_1 is too high. [2/1]',
+                'Cyclomatic complexity for method_name_2 is too high. [2/1]'])
+    end
+  end
+
+  context 'when Max is 2' do
+    let(:cop_config) { { 'Max' => 2 } }
+
+    it 'counts stupid nested if and else blocks' do
+      inspect_source(cop, ['def method_name',
+                           '  if first_condition then',
+                           '    call_foo',
+                           '  else',
+                           '    if second_condition then',
+                           '      call_bar',
+                           '    else',
+                           '      call_bam if third_condition',
+                           '    end',
+                           '    call_baz if fourth_condition',
+                           '  end',
+                           'end'])
+      expect(cop.messages)
+        .to eq(['Cyclomatic complexity for method_name is too high. [5/2]'])
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/def_with_parentheses_spec.rb b/spec/rubocop/cop/style/def_with_parentheses_spec.rb
new file mode 100644
index 0000000..4b1f27e
--- /dev/null
+++ b/spec/rubocop/cop/style/def_with_parentheses_spec.rb
@@ -0,0 +1,39 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::DefWithParentheses do
+  subject(:cop) { described_class.new }
+
+  it 'reports an offense for def with empty parens' do
+    src = ['def func()',
+           'end']
+    inspect_source(cop, src)
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'reports an offense for class def with empty parens' do
+    src = ['def Test.func()',
+           'end']
+    inspect_source(cop, src)
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts def with arg and parens' do
+    src = ['def func(a)',
+           'end']
+    inspect_source(cop, src)
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts empty parentheses in one liners' do
+    src = ["def to_s() join '/' end"]
+    inspect_source(cop, src)
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'auto-removes unneeded parens' do
+    new_source = autocorrect_source(cop, "def test();\nsomething\nend")
+    expect(new_source).to eq("def test;\nsomething\nend")
+  end
+end
diff --git a/spec/rubocop/cop/style/deprecated_hash_methods_spec.rb b/spec/rubocop/cop/style/deprecated_hash_methods_spec.rb
new file mode 100644
index 0000000..c32baa1
--- /dev/null
+++ b/spec/rubocop/cop/style/deprecated_hash_methods_spec.rb
@@ -0,0 +1,45 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::DeprecatedHashMethods do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for has_key? with one arg' do
+    inspect_source(cop,
+                   ['o.has_key?(o)'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages)
+      .to eq(['`Hash#has_key?` is deprecated in favor of `Hash#key?`.'])
+  end
+
+  it 'accepts has_key? with no args' do
+    inspect_source(cop,
+                   ['o.has_key?'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'registers an offense for has_value? with one arg' do
+    inspect_source(cop,
+                   ['o.has_value?(o)'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages)
+      .to eq(['`Hash#has_value?` is deprecated in favor of `Hash#value?`.'])
+  end
+
+  it 'accepts has_value? with no args' do
+    inspect_source(cop,
+                   ['o.has_value?'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'auto-corrects has_key? with key?' do
+    new_source = autocorrect_source(cop, 'hash.has_key?(:test)')
+    expect(new_source).to eq('hash.key?(:test)')
+  end
+
+  it 'auto-corrects has_value? with value?' do
+    new_source = autocorrect_source(cop, 'hash.has_value?(value)')
+    expect(new_source).to eq('hash.value?(value)')
+  end
+end
diff --git a/spec/rubocop/cop/style/documentation_spec.rb b/spec/rubocop/cop/style/documentation_spec.rb
new file mode 100644
index 0000000..e75119a
--- /dev/null
+++ b/spec/rubocop/cop/style/documentation_spec.rb
@@ -0,0 +1,123 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::Documentation do
+
+  subject(:cop) { described_class.new(config) }
+  let(:config) do
+    Rubocop::Config.new('CommentAnnotation' => {
+                          'Keywords' => %w(TODO FIXME OPTIMIZE HACK REVIEW)
+                        })
+  end
+
+  it 'registers an offense for non-empty class' do
+    inspect_source(cop,
+                   ['class My_Class',
+                    '  TEST = 20',
+                    'end'
+                   ])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'does not consider comment followed by empty line to be class ' \
+     'documentation' do
+    inspect_source(cop,
+                   ['# Copyright 2014',
+                    '# Some company',
+                    '',
+                    'class My_Class',
+                    '  TEST = 20',
+                    'end'
+                   ])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for non-namespace' do
+    inspect_source(cop,
+                   ['module My_Class',
+                    '  TEST = 20',
+                    'end'
+                   ])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for empty module without documentation' do
+    # Because why would you have an empty module? It requires some
+    # explanation.
+    inspect_source(cop,
+                   ['module Test',
+                    'end'
+                   ])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts non-empty class with documentation' do
+    inspect_source(cop,
+                   ['# class comment',
+                    'class My_Class',
+                    '  TEST = 20',
+                    'end'
+                   ])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'registers an offense for non-empty class with annotation comment' do
+    inspect_source(cop,
+                   ['# OPTIMIZE: Make this faster.',
+                    'class My_Class',
+                    '  TEST = 20',
+                    'end'
+                   ])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts non-empty module with documentation' do
+    inspect_source(cop,
+                   ['# class comment',
+                    'module My_Class',
+                    '  TEST = 20',
+                    'end'
+                   ])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts empty class without documentation' do
+    inspect_source(cop,
+                   ['class My_Class',
+                    'end'
+                   ])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts namespace module without documentation' do
+    inspect_source(cop,
+                   ['module Test',
+                    '  class A; end',
+                    '  class B; end',
+                    'end'
+                   ])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts namespace class without documentation' do
+    inspect_source(cop,
+                   ['class Test',
+                    '  class A; end',
+                    '  class B; end',
+                    'end'
+                   ])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not raise an error for an implicit match conditional' do
+    expect do
+      inspect_source(cop,
+                     ['class Test',
+                      '  if //',
+                      '  end',
+                      'end'
+                     ])
+    end.to_not raise_error
+  end
+end
diff --git a/spec/rubocop/cop/style/dot_position_spec.rb b/spec/rubocop/cop/style/dot_position_spec.rb
new file mode 100644
index 0000000..afa8a04
--- /dev/null
+++ b/spec/rubocop/cop/style/dot_position_spec.rb
@@ -0,0 +1,91 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::DotPosition, :config do
+  subject(:cop) { described_class.new(config) }
+
+  context 'Leading dots style' do
+    let(:cop_config) { { 'EnforcedStyle' => 'leading' } }
+
+    it 'registers an offense for trailing dot in multi-line call' do
+      inspect_source(cop, ['something.',
+                           '  method_name'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.highlights).to eq(['.'])
+      expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'trailing')
+    end
+
+    it 'registers an offense for correct + opposite' do
+      inspect_source(cop, ['something',
+                           '  .method_name',
+                           'something.',
+                           '  method_name'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'accepts leading do in multi-line method call' do
+      inspect_source(cop, ['something',
+                           '  .method_name'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'does not err on method call with no dots' do
+      inspect_source(cop, ['puts something'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'does not err on method call without a method name' do
+      inspect_source(cop, ['l.', '(1)'])
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it 'does not err on method call on same line' do
+      inspect_source(cop, ['something.method_name'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'Trailing dots style' do
+    let(:cop_config) { { 'EnforcedStyle' => 'trailing' } }
+
+    it 'registers an offense for leading dot in multi-line call' do
+      inspect_source(cop, ['something',
+                           '  .method_name'])
+      expect(cop.messages)
+        .to eq(['Place the . on the previous line, together with the method ' \
+                'call receiver.'])
+      expect(cop.highlights).to eq(['.'])
+      expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'leading')
+    end
+
+    it 'accepts trailing dot in multi-line method call' do
+      inspect_source(cop, ['something.',
+                           '  method_name'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'does not err on method call with no dots' do
+      inspect_source(cop, ['puts something'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'does not err on method call without a method name' do
+      inspect_source(cop, ['l', '.(1)'])
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it 'does not err on method call on same line' do
+      inspect_source(cop, ['something.method_name'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'does not get confused by several lines of chained methods' do
+      inspect_source(cop, ['File.new(something).',
+                           'readlines.map.',
+                           'compact.join("\n")'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/double_negation_spec.rb b/spec/rubocop/cop/style/double_negation_spec.rb
new file mode 100644
index 0000000..767cef9
--- /dev/null
+++ b/spec/rubocop/cop/style/double_negation_spec.rb
@@ -0,0 +1,22 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::DoubleNegation do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for !!' do
+    inspect_source(cop, '!!test.something')
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'does not register an offense for !' do
+    inspect_source(cop, '!test.something')
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense for not not' do
+    inspect_source(cop, 'not not test.something')
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/empty_line_between_defs_spec.rb b/spec/rubocop/cop/style/empty_line_between_defs_spec.rb
new file mode 100644
index 0000000..f345111
--- /dev/null
+++ b/spec/rubocop/cop/style/empty_line_between_defs_spec.rb
@@ -0,0 +1,135 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::EmptyLineBetweenDefs, :config do
+  subject(:cop) { described_class.new(config) }
+  let(:cop_config) { { 'AllowAdjacentOneLineDefs' => false } }
+
+  it 'finds offenses in inner classes' do
+    source = ['class K',
+              '  def m',
+              '  end',
+              '  class J',
+              '    def n',
+              '    end',
+              '    def o',
+              '    end',
+              '  end',
+              '  # checks something',
+              '  def p',
+              '  end',
+              'end']
+    inspect_source(cop, source)
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.offenses.map(&:line).sort).to eq([7])
+  end
+
+  # Only one def, so rule about empty line *between* defs does not
+  # apply.
+  it 'accepts a def that follows a line with code' do
+    source = ['x = 0',
+              'def m',
+              'end']
+    inspect_source(cop, source)
+    expect(cop.offenses).to be_empty
+  end
+
+  # Only one def, so rule about empty line *between* defs does not
+  # apply.
+  it 'accepts a def that follows code and a comment' do
+    source = ['  x = 0',
+              '  # 123',
+              '  def m',
+              '  end']
+    inspect_source(cop, source)
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts the first def without leading empty line in a class' do
+    source = ['class K',
+              '  def m',
+              '  end',
+              'end']
+    inspect_source(cop, source)
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a def that follows an empty line and then a comment' do
+    source = ['class A',
+              '  # calculates value',
+              '  def m',
+              '  end',
+              '',
+              '  private',
+              '  # calculates size',
+              '  def n',
+              '  end',
+              'end'
+             ]
+    inspect_source(cop, source)
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a def that is the first of a module' do
+    source = ['module Util',
+              '  public',
+              '  #',
+              '  def html_escape(s)',
+              '  end',
+              'end'
+             ]
+    inspect_source(cop, source)
+    expect(cop.messages).to be_empty
+  end
+
+  it 'accepts a nested def' do
+    source = ['def mock_model(*attributes)',
+              '  Class.new do',
+              '    def initialize(attrs)',
+              '    end',
+              '  end',
+              'end'
+             ]
+    inspect_source(cop, source)
+    expect(cop.messages).to be_empty
+  end
+
+  it 'registers an offense for adjacent one-liners by default' do
+    source = ['def a; end',
+              'def b; end']
+    inspect_source(cop, source)
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'auto-corrects adjacent one-liners by default' do
+    corrected = autocorrect_source(cop, ['  def a; end',
+                                         '  def b; end'])
+    expect(corrected).to eq(['  def a; end',
+                             '',
+                             '  def b; end'].join("\n"))
+  end
+
+  context 'when AllowAdjacentOneLineDefs is enabled' do
+    let(:cop_config) { { 'AllowAdjacentOneLineDefs' => true } }
+
+    it 'accepts adjacent one-liners' do
+      source = ['def a; end',
+                'def b; end']
+      inspect_source(cop, source)
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for adjacent defs if some are multi-line' do
+      source = ['def a; end',
+                'def b; end',
+                'def c', # Not a one-liner, so this is an offense.
+                'end',
+                # Also an offense since previous was multi-line:
+                'def d; end'
+               ]
+      inspect_source(cop, source)
+      expect(cop.offenses.map(&:line)).to eq([3, 5])
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/empty_lines_around_access_modifier_spec.rb b/spec/rubocop/cop/style/empty_lines_around_access_modifier_spec.rb
new file mode 100644
index 0000000..96ac8c3
--- /dev/null
+++ b/spec/rubocop/cop/style/empty_lines_around_access_modifier_spec.rb
@@ -0,0 +1,56 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::EmptyLinesAroundAccessModifier do
+  subject(:cop) { described_class.new }
+
+  %w(private protected public).each do |access_modifier|
+    it "requires blank line before #{access_modifier}" do
+      inspect_source(cop,
+                     ['class Test',
+                      '  something',
+                      "  #{access_modifier}",
+                      '',
+                      '  def test; end',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(["Keep a blank line before and after `#{access_modifier}`."])
+    end
+
+    it 'requires blank line after #{access_modifier}' do
+      inspect_source(cop,
+                     ['class Test',
+                      '  something',
+                      '',
+                      "  #{access_modifier}",
+                      '  def test; end',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(["Keep a blank line before and after `#{access_modifier}`."])
+    end
+
+    it 'accepts missing blank line when at the beginning of class/module' do
+      inspect_source(cop,
+                     ['class Test',
+                      "  #{access_modifier}",
+                      '',
+                      '  def test; end',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'recognizes blank lines with DOS style line endings' do
+      inspect_source(cop,
+                     ["class Test\r",
+                      "\r",
+                      "  #{access_modifier}\r",
+                      "\r",
+                      "  def test; end\r",
+                      "end\r"])
+      expect(cop.offenses.size).to eq(0)
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/empty_lines_around_body_spec.rb b/spec/rubocop/cop/style/empty_lines_around_body_spec.rb
new file mode 100644
index 0000000..bbad725
--- /dev/null
+++ b/spec/rubocop/cop/style/empty_lines_around_body_spec.rb
@@ -0,0 +1,131 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::EmptyLinesAroundBody do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for method body starting with a blank' do
+    inspect_source(cop,
+                   ['def some_method',
+                    '',
+                    '  do_something',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  # The cop only registers an offense if the extra line is completely emtpy. If
+  # there is trailing whitespace, then that must be dealt with first. Having
+  # two cops registering offense for the line with only spaces would cause
+  # havoc in auto-correction.
+  it 'accepts method body starting with a line with spaces' do
+    inspect_source(cop,
+                   ['def some_method',
+                    '  ',
+                    '  do_something',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'autocorrects method body starting with a blank' do
+    corrected = autocorrect_source(cop,
+                                   ['def some_method',
+                                    '',
+                                    '  do_something',
+                                    'end'])
+    expect(corrected).to eq ['def some_method',
+                             '  do_something',
+                             'end'].join("\n")
+  end
+
+  it 'registers an offense for class method body starting with a blank' do
+    inspect_source(cop,
+                   ['def Test.some_method',
+                    '',
+                    '  do_something',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'autocorrects class method body starting with a blank' do
+    corrected = autocorrect_source(cop,
+                                   ['def Test.some_method',
+                                    '',
+                                    '  do_something',
+                                    'end'])
+    expect(corrected).to eq ['def Test.some_method',
+                             '  do_something',
+                             'end'].join("\n")
+  end
+
+  it 'registers an offense for method body ending with a blank' do
+    inspect_source(cop,
+                   ['def some_method',
+                    '  do_something',
+                    '',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for class method body ending with a blank' do
+    inspect_source(cop,
+                   ['def Test.some_method',
+                    '  do_something',
+                    '',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for class body starting with a blank' do
+    inspect_source(cop,
+                   ['class SomeClass',
+                    '',
+                    '  do_something',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'autocorrects class body containing only a blank' do
+    corrected = autocorrect_source(cop,
+                                   ['class SomeClass',
+                                    '',
+                                    'end'])
+    expect(corrected).to eq ['class SomeClass',
+                             'end'].join("\n")
+  end
+
+  it 'registers an offense for module body starting with a blank' do
+    inspect_source(cop,
+                   ['module SomeModule',
+                    '',
+                    '  do_something',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for class body ending with a blank' do
+    inspect_source(cop,
+                   ['class SomeClass',
+                    '  do_something',
+                    '',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for module body ending with a blank' do
+    inspect_source(cop,
+                   ['module SomeModule',
+                    '  do_something',
+                    '',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'is not fooled by single line methods' do
+    inspect_source(cop,
+                   ['def some_method; do_something; end',
+                    '',
+                    'something_else'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/empty_lines_spec.rb b/spec/rubocop/cop/style/empty_lines_spec.rb
new file mode 100644
index 0000000..9198ad3
--- /dev/null
+++ b/spec/rubocop/cop/style/empty_lines_spec.rb
@@ -0,0 +1,51 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::EmptyLines do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for consecutive empty lines' do
+    inspect_source(cop,
+                   ['test = 5', '', '', '', 'top'])
+    expect(cop.offenses.size).to eq(2)
+  end
+
+  it 'auto-corrects consecutive empty lines' do
+    corrected = autocorrect_source(cop,
+                                   ['test = 5', '', '', '', 'top'])
+    expect(corrected).to eq ['test = 5', '', 'top'].join("\n")
+  end
+
+  it 'works when there are no tokens' do
+    inspect_source(cop,
+                   ['#comment'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'handles comments' do
+    inspect_source(cop,
+                   ['test', '', '#comment', 'top'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense for empty lines in a string' do
+    inspect_source(cop, ['result = "test
+
+
+
+                                  string"'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense for heredocs with empty lines inside' do
+    inspect_source(cop, ['str = <<-TEXT',
+                         'line 1',
+                         '',
+                         '',
+                         'line 2',
+                         'TEXT',
+                         'puts str'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/empty_literal_spec.rb b/spec/rubocop/cop/style/empty_literal_spec.rb
new file mode 100644
index 0000000..8b28039
--- /dev/null
+++ b/spec/rubocop/cop/style/empty_literal_spec.rb
@@ -0,0 +1,100 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::EmptyLiteral do
+  subject(:cop) { described_class.new }
+
+  describe 'Empty Array' do
+    it 'registers an offense for Array.new()' do
+      inspect_source(cop,
+                     ['test = Array.new()'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Use array literal [] instead of Array.new.'])
+    end
+
+    it 'registers an offense for Array.new' do
+      inspect_source(cop,
+                     ['test = Array.new'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Use array literal [] instead of Array.new.'])
+    end
+
+    it 'does not register an offense for Array.new(3)' do
+      inspect_source(cop,
+                     ['test = Array.new(3)'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'auto-corrects Array.new to []' do
+      new_source = autocorrect_source(cop, 'test = Array.new')
+      expect(new_source).to eq('test = []')
+    end
+  end
+
+  describe 'Empty Hash' do
+    it 'registers an offense for Hash.new()' do
+      inspect_source(cop,
+                     ['test = Hash.new()'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Use hash literal {} instead of Hash.new.'])
+    end
+
+    it 'registers an offense for Hash.new' do
+      inspect_source(cop,
+                     ['test = Hash.new'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Use hash literal {} instead of Hash.new.'])
+    end
+
+    it 'does not register an offense for Hash.new(3)' do
+      inspect_source(cop,
+                     ['test = Hash.new(3)'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'does not register an offense for Hash.new { block }' do
+      inspect_source(cop,
+                     ['test = Hash.new { block }'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'auto-corrects Hash.new to {}' do
+      new_source = autocorrect_source(cop, 'test = Hash.new')
+      expect(new_source).to eq('test = {}')
+    end
+  end
+
+  describe 'Empty String' do
+    it 'registers an offense for String.new()' do
+      inspect_source(cop,
+                     ['test = String.new()'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(["Use string literal '' instead of String.new."])
+    end
+
+    it 'registers an offense for String.new' do
+      inspect_source(cop,
+                     ['test = String.new'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(["Use string literal '' instead of String.new."])
+    end
+
+    it 'does not register an offense for String.new("top")' do
+      inspect_source(cop,
+                     ['test = String.new("top")'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'auto-corrects String.new to empty string literal' do
+      new_source = autocorrect_source(cop, 'test = String.new')
+      expect(new_source).to eq("test = ''")
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/encoding_spec.rb b/spec/rubocop/cop/style/encoding_spec.rb
new file mode 100644
index 0000000..8908db4
--- /dev/null
+++ b/spec/rubocop/cop/style/encoding_spec.rb
@@ -0,0 +1,56 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::Encoding do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense when no encoding present', ruby: 1.9 do
+    inspect_source(cop, ['def foo() end'])
+
+    expect(cop.messages).to eq(
+      ['Missing utf-8 encoding comment.'])
+  end
+
+  it 'accepts encoding on first line', ruby: 1.9 do
+    inspect_source(cop, ['# encoding: utf-8',
+                         'def foo() end'])
+
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts encoding on second line when shebang present', ruby: 1.9 do
+    inspect_source(cop, ['#!/usr/bin/env ruby',
+                         '# encoding: utf-8',
+                         'def foo() end'])
+
+    expect(cop.messages).to be_empty
+  end
+
+  it 'books an offense when encoding is in the wrong place', ruby: 1.9 do
+    inspect_source(cop, ['def foo() end',
+                         '# encoding: utf-8'])
+
+    expect(cop.messages).to eq(
+      ['Missing utf-8 encoding comment.'])
+  end
+
+  it 'does not register an offense on Ruby 2.0', ruby: 2.0 do
+    inspect_source(cop, ['def foo() end'])
+
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts encoding inserted by magic_encoding gem', ruby: 1.9 do
+    inspect_source(cop, ['# -*- encoding : utf-8 -*-',
+                         'def foo() end'])
+
+    expect(cop.messages).to be_empty
+  end
+
+  it 'accepts vim-style encoding comments', ruby: 1.9 do
+    inspect_source(cop, ['# vim:fileencoding=utf-8',
+                         'def foo() end'])
+    expect(cop.messages).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/end_block_spec.rb b/spec/rubocop/cop/style/end_block_spec.rb
new file mode 100644
index 0000000..804a6dc
--- /dev/null
+++ b/spec/rubocop/cop/style/end_block_spec.rb
@@ -0,0 +1,13 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::EndBlock do
+  subject(:cop) { described_class.new }
+
+  it 'reports an offense for an END block' do
+    src = ['END { test }']
+    inspect_source(cop, src)
+    expect(cop.offenses.size).to eq(1)
+  end
+end
diff --git a/spec/rubocop/cop/style/end_of_line_spec.rb b/spec/rubocop/cop/style/end_of_line_spec.rb
new file mode 100644
index 0000000..48c2acd
--- /dev/null
+++ b/spec/rubocop/cop/style/end_of_line_spec.rb
@@ -0,0 +1,47 @@
+# encoding: utf-8
+
+require 'spec_helper'
+require 'tempfile'
+
+describe Rubocop::Cop::Style::EndOfLine do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for CR+LF' do
+    inspect_source_file(cop, ['x=0', '', "y=1\r"])
+    expect(cop.messages).to eq(['Carriage return character detected.'])
+  end
+
+  it 'highlights the whole offendng line' do
+    inspect_source_file(cop, ['x=0', '', "y=1\r"])
+    expect(cop.highlights).to eq(["y=1\r"])
+  end
+
+  it 'registers an offense for CR at end of file' do
+    inspect_source_file(cop, ["x=0\r"])
+    expect(cop.messages).to eq(['Carriage return character detected.'])
+  end
+
+  context 'when there are many lines ending with CR+LF' do
+    it 'registers only one offense' do
+      inspect_source_file(cop, ['x=0', '', 'y=1'].join("\r\n"))
+      expect(cop.messages.size).to eq(1)
+    end
+  end
+
+  context 'when the default external encoding is US_ASCII' do
+    before(:each) do
+      @orig_encoding = Encoding.default_external
+      Encoding.default_external = Encoding::US_ASCII
+    end
+    after(:each) { Encoding.default_external = @orig_encoding }
+
+    it 'does not crash on UTF-8 encoded non-ascii characters' do
+      inspect_source_file(cop,
+                          ['# encoding: UTF-8',
+                           'class Epd::ReportsController < EpdAreaController',
+                           "  'terecht bij uw ROM-coördinator.'",
+                           'end'].join("\n"))
+      expect(cop.offenses).to be_empty
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/even_odd_spec.rb b/spec/rubocop/cop/style/even_odd_spec.rb
new file mode 100644
index 0000000..fb04147
--- /dev/null
+++ b/spec/rubocop/cop/style/even_odd_spec.rb
@@ -0,0 +1,75 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::EvenOdd do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for x % 2 == 0' do
+    inspect_source(cop,
+                   ['x % 2 == 0'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages).to eq(['Replace with `Fixnum#even?`.'])
+  end
+
+  it 'registers an offense for x % 2 != 0' do
+    inspect_source(cop,
+                   ['x % 2 != 0'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages).to eq(['Replace with `Fixnum#odd?`.'])
+  end
+
+  it 'registers an offense for (x % 2) == 0' do
+    inspect_source(cop,
+                   ['(x % 2) == 0'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages).to eq(['Replace with `Fixnum#even?`.'])
+  end
+
+  it 'registers an offense for (x % 2) != 0' do
+    inspect_source(cop,
+                   ['(x % 2) != 0'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages).to eq(['Replace with `Fixnum#odd?`.'])
+  end
+
+  it 'registers an offense for x % 2 == 1' do
+    inspect_source(cop,
+                   ['x % 2 == 1'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages).to eq(['Replace with `Fixnum#odd?`.'])
+  end
+
+  it 'registers an offense for x % 2 != 1' do
+    inspect_source(cop,
+                   ['x % 2 != 1'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages).to eq(['Replace with `Fixnum#even?`.'])
+  end
+
+  it 'registers an offense for (x % 2) == 1' do
+    inspect_source(cop,
+                   ['(x % 2) == 1'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages).to eq(['Replace with `Fixnum#odd?`.'])
+  end
+
+  it 'registers an offense for (x % 2) != 1' do
+    inspect_source(cop,
+                   ['(x % 2) != 1'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages).to eq(['Replace with `Fixnum#even?`.'])
+  end
+
+  it 'accepts x % 3 == 0' do
+    inspect_source(cop,
+                   ['x % 3 == 0'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts x % 3 != 0' do
+    inspect_source(cop,
+                   ['x % 3 != 0'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/file_name_spec.rb b/spec/rubocop/cop/style/file_name_spec.rb
new file mode 100644
index 0000000..24abe0a
--- /dev/null
+++ b/spec/rubocop/cop/style/file_name_spec.rb
@@ -0,0 +1,84 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::FileName do
+  subject(:cop) { described_class.new(config) }
+
+  let(:config) do
+    Rubocop::Config.new(
+      { 'AllCops' => { 'Include' => includes } },
+      '/some/.rubocop.yml'
+    )
+  end
+
+  let(:includes) { [] }
+  let(:source) { ['print 1'] }
+  let(:processed_source) { parse_source(source) }
+
+  before do
+    allow(processed_source.buffer)
+    .to receive(:name).and_return(filename)
+    _investigate(cop, processed_source)
+  end
+
+  context 'with camelCase file names ending in .rb' do
+    let(:filename) { '/some/dir/testCase.rb' }
+
+    it 'reports an offense' do
+      expect(cop.offenses.size).to eq(1)
+    end
+  end
+
+  context 'with camelCase file names without file extension' do
+    let(:filename) { '/some/dir/testCase' }
+
+    it 'reports an offense' do
+      expect(cop.offenses.size).to eq(1)
+    end
+  end
+
+  context 'with snake_case file names ending in .rb' do
+    let(:filename) { '/some/dir/test_case.rb' }
+
+    it 'reports an offense' do
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'with snake_case file names without file extension' do
+    let(:filename) { '/some/dir/test_case' }
+
+    it 'does not report an offense' do
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'with snake_case file names with non-rb extension' do
+    let(:filename) { '/some/dir/some_task.rake' }
+
+    it 'does not report an offense' do
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'with snake_case file names with multiple extensions' do
+    let(:filename) { 'some/dir/some_view.html.slim_spec.rb' }
+
+    it 'does not report an offense' do
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'when the file is specified in AllCops/Include' do
+    let(:includes) { ['**/Gemfile'] }
+
+    context 'with a non-snake_case file name' do
+      let(:filename) { '/some/dir/Gemfile' }
+
+      it 'does not report an offense' do
+        expect(cop.offenses).to be_empty
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/final_newline_spec.rb b/spec/rubocop/cop/style/final_newline_spec.rb
new file mode 100644
index 0000000..dbab305
--- /dev/null
+++ b/spec/rubocop/cop/style/final_newline_spec.rb
@@ -0,0 +1,30 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::FinalNewline do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for missing final newline' do
+    source = ['x = 0', 'top']
+    inspect_source(cop, source)
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts a final newline' do
+    source = ['x = 0', 'top', '']
+    inspect_source(cop, source)
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts an empty file' do
+    source = ['']
+    inspect_source(cop, source)
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'auto-corrects missing newline' do
+    new_source = autocorrect_source(cop, ['x = 0'])
+    expect(new_source).to eq(['x = 0', ''].join("\n"))
+  end
+end
diff --git a/spec/rubocop/cop/style/flip_flop_spec.rb b/spec/rubocop/cop/style/flip_flop_spec.rb
new file mode 100644
index 0000000..f604719
--- /dev/null
+++ b/spec/rubocop/cop/style/flip_flop_spec.rb
@@ -0,0 +1,23 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::FlipFlop do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for inclusive flip flops' do
+    inspect_source(cop,
+                   ['DATA.each_line do |line|',
+                    'print line if (line =~ /begin/)..(line =~ /end/)',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for exclusive flip flops' do
+    inspect_source(cop,
+                   ['DATA.each_line do |line|',
+                    'print line if (line =~ /begin/)...(line =~ /end/)',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+  end
+end
diff --git a/spec/rubocop/cop/style/for_spec.rb b/spec/rubocop/cop/style/for_spec.rb
new file mode 100644
index 0000000..6ef5f96
--- /dev/null
+++ b/spec/rubocop/cop/style/for_spec.rb
@@ -0,0 +1,105 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::For, :config do
+  subject(:cop) { described_class.new(config) }
+
+  context 'when each is the enforced style' do
+    let(:cop_config) { { 'EnforcedStyle' => 'each' } }
+
+    it 'registers an offense for for' do
+      inspect_source(cop,
+                     ['def func',
+                      '  for n in [1, 2, 3] do',
+                      '    puts n',
+                      '  end',
+                      'end'])
+      expect(cop.messages).to eq(['Prefer `each` over `for`.'])
+      expect(cop.highlights).to eq(['for'])
+      expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'for')
+    end
+
+    it 'registers an offense for opposite + correct style' do
+      inspect_source(cop,
+                     ['def func',
+                      '  for n in [1, 2, 3] do',
+                      '    puts n',
+                      '  end',
+                      '  [1, 2, 3].each do |n|',
+                      '    puts n',
+                      '  end',
+                      'end'])
+      expect(cop.messages).to eq(['Prefer `each` over `for`.'])
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'accepts multiline each' do
+      inspect_source(cop,
+                     ['def func',
+                      '  [1, 2, 3].each do |n|',
+                      '    puts n',
+                      '  end',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts :for' do
+      inspect_source(cop, ['[:for, :ala, :bala]'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts def for' do
+      inspect_source(cop, ['def for; end'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'when for is the enforced style' do
+    let(:cop_config) { { 'EnforcedStyle' => 'for' } }
+
+    it 'accepts for' do
+      inspect_source(cop,
+                     ['def func',
+                      '  for n in [1, 2, 3] do',
+                      '    puts n',
+                      '  end',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for multiline each' do
+      inspect_source(cop,
+                     ['def func',
+                      '  [1, 2, 3].each do |n|',
+                      '    puts n',
+                      '  end',
+                      'end'])
+      expect(cop.messages).to eq(['Prefer `for` over `each`.'])
+      expect(cop.highlights).to eq(['each'])
+      expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'each')
+    end
+
+    it 'registers an offense for correct + opposite style' do
+      inspect_source(cop,
+                     ['def func',
+                      '  for n in [1, 2, 3] do',
+                      '    puts n',
+                      '  end',
+                      '  [1, 2, 3].each do |n|',
+                      '    puts n',
+                      '  end',
+                      'end'])
+      expect(cop.messages).to eq(['Prefer `for` over `each`.'])
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'accepts single line each' do
+      inspect_source(cop,
+                     ['def func',
+                      '  [1, 2, 3].each { |n| puts n }',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/format_string_spec.rb b/spec/rubocop/cop/style/format_string_spec.rb
new file mode 100644
index 0000000..3b44c78
--- /dev/null
+++ b/spec/rubocop/cop/style/format_string_spec.rb
@@ -0,0 +1,136 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::FormatString, :config do
+  subject(:cop) { described_class.new(config) }
+
+  context 'when enforced style is sprintf' do
+    let(:cop_config) { { 'EnforcedStyle' => 'sprintf' } }
+    it 'registers an offense for a string followed by something' do
+      inspect_source(cop,
+                     ['puts "%d" % 10'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Favor `sprintf` over `String#%`.'])
+    end
+
+    it 'registers an offense for something followed by an array' do
+      inspect_source(cop,
+                     ['puts x % [10, 11]'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Favor `sprintf` over `String#%`.'])
+    end
+
+    it 'does not register an offense for numbers' do
+      inspect_source(cop,
+                     ['puts 10 % 4'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'does not register an offense for ambiguous cases' do
+      inspect_source(cop,
+                     ['puts x % 4'])
+      expect(cop.offenses).to be_empty
+
+      inspect_source(cop,
+                     ['puts x % Y'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'works if the first operand contains embedded expressions' do
+      inspect_source(cop,
+                     ['puts "#{x * 5} %d #{@test}" % 10'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Favor `sprintf` over `String#%`.'])
+    end
+
+    it 'registers an offense for format' do
+      inspect_source(cop,
+                     ['format(something, a, b)'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Favor `sprintf` over `format`.'])
+    end
+  end
+
+  context 'when enforced style is format' do
+    let(:cop_config) { { 'EnforcedStyle' => 'format' } }
+
+    it 'registers an offense for a string followed by something' do
+      inspect_source(cop,
+                     ['puts "%d" % 10'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Favor `format` over `String#%`.'])
+    end
+
+    it 'registers an offense for something followed by an array' do
+      inspect_source(cop,
+                     ['puts x % [10, 11]'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Favor `format` over `String#%`.'])
+    end
+
+    it 'does not register an offense for numbers' do
+      inspect_source(cop,
+                     ['puts 10 % 4'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'does not register an offense for ambiguous cases' do
+      inspect_source(cop,
+                     ['puts x % 4'])
+      expect(cop.offenses).to be_empty
+
+      inspect_source(cop,
+                     ['puts x % Y'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'works if the first operand contains embedded expressions' do
+      inspect_source(cop,
+                     ['puts "#{x * 5} %d #{@test}" % 10'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Favor `format` over `String#%`.'])
+    end
+
+    it 'registers an offense for sprintf' do
+      inspect_source(cop,
+                     ['sprintf(something, a, b)'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Favor `format` over `sprintf`.'])
+    end
+  end
+
+  context 'when enforced style is percent' do
+    let(:cop_config) { { 'EnforcedStyle' => 'percent' } }
+
+    it 'registers an offense for format' do
+      inspect_source(cop,
+                     ['format(something, a, b)'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Favor `String#%` over `format`.'])
+    end
+
+    it 'registers an offense for sprintf' do
+      inspect_source(cop,
+                     ['sprintf(something, a, b)'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Favor `String#%` over `sprintf`.'])
+    end
+
+    it 'accepts String#%' do
+      inspect_source(cop,
+                     ['puts "%d" % 10'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/global_vars_spec.rb b/spec/rubocop/cop/style/global_vars_spec.rb
new file mode 100644
index 0000000..e5dd8a0
--- /dev/null
+++ b/spec/rubocop/cop/style/global_vars_spec.rb
@@ -0,0 +1,34 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::GlobalVars, :config do
+  cop_config = {
+    'AllowedVariables' => ['$allowed']
+  }
+
+  subject(:cop) { described_class.new(config) }
+  let(:cop_config) { cop_config }
+
+  it 'registers an offense for $custom' do
+    inspect_source(cop, ['puts $custom'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'allows user whitelisted variables' do
+    inspect_source(cop, ['puts $allowed'])
+    expect(cop.offenses).to be_empty
+  end
+
+  described_class::BUILT_IN_VARS.each do |var|
+    it "does not register an offense for built-in variable #{var}" do
+      inspect_source(cop, ["puts #{var}"])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  it 'does not register an offense for backrefs like $1' do
+    inspect_source(cop, ['puts $1'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/guard_clause_spec.rb b/spec/rubocop/cop/style/guard_clause_spec.rb
new file mode 100644
index 0000000..173a4ce
--- /dev/null
+++ b/spec/rubocop/cop/style/guard_clause_spec.rb
@@ -0,0 +1,77 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::GuardClause do
+  let(:cop) { described_class.new }
+
+  it 'reports an offense if method body is if without else' do
+    src = ['def func',
+           '  if something',
+           '    work',
+           '    work_more',
+           '  end',
+           'end']
+    inspect_source(cop, src)
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'reports an offense if method body ends with if without else' do
+    src = ['def func',
+           '  test',
+           '  if something',
+           '    work',
+           '    work_more',
+           '  end',
+           'end']
+    inspect_source(cop, src)
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts a method which body is if with else' do
+    src = ['def func',
+           '  if something',
+           '    work',
+           '    work_more',
+           '  else',
+           '    test',
+           '  end',
+           'end']
+    inspect_source(cop, src)
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a method which body does not end with if' do
+    src = ['def func',
+           '  if something',
+           '    work',
+           '    work_more',
+           '  end',
+           '  test',
+           'end']
+    inspect_source(cop, src)
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a method which body does not end with if' do
+    src = ['def func',
+           '  if something',
+           '    work',
+           '    work_more',
+           '  end',
+           '  test',
+           'end']
+    inspect_source(cop, src)
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a method whose body is an if with a one-line body' do
+    src = ['def func',
+           '  if something',
+           '    work',
+           '  end',
+           'end']
+    inspect_source(cop, src)
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/hash_syntax_spec.rb b/spec/rubocop/cop/style/hash_syntax_spec.rb
new file mode 100644
index 0000000..befb98d
--- /dev/null
+++ b/spec/rubocop/cop/style/hash_syntax_spec.rb
@@ -0,0 +1,133 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::HashSyntax, :config do
+  subject(:cop) { described_class.new(config) }
+
+  context 'configured to enforce ruby19 style' do
+    let(:config) do
+      Rubocop::Config.new('HashSyntax' => {
+                            'EnforcedStyle'   => 'ruby19',
+                            'SupportedStyles' => %w(ruby19 hash_rockets)
+                          },
+                          'SpaceAroundOperators' => { 'Enabled' => true })
+    end
+
+    it 'registers offense for hash rocket syntax when new is possible' do
+      inspect_source(cop, ['x = { :a => 0 }'])
+      expect(cop.messages).to eq(['Use the new Ruby 1.9 hash syntax.'])
+      expect(cop.config_to_allow_offenses)
+        .to eq('EnforcedStyle' => 'hash_rockets')
+    end
+
+    it 'registers an offense for mixed syntax when new is possible' do
+      inspect_source(cop, ['x = { :a => 0, b: 1 }'])
+      expect(cop.messages).to eq(['Use the new Ruby 1.9 hash syntax.'])
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'registers an offense for hash rockets in method calls' do
+      inspect_source(cop, ['func(3, :a => 0)'])
+      expect(cop.messages).to eq(['Use the new Ruby 1.9 hash syntax.'])
+    end
+
+    it 'accepts hash rockets when keys have different types' do
+      inspect_source(cop, ['x = { :a => 0, "b" => 1 }'])
+      expect(cop.messages).to be_empty
+    end
+
+    it 'accepts hash rockets when keys have whitespaces in them' do
+      inspect_source(cop, ['x = { :"t o" => 0 }'])
+      expect(cop.messages).to be_empty
+    end
+
+    it 'accepts hash rockets when keys have special symbols in them' do
+      inspect_source(cop, ['x = { :"\tab" => 1 }'])
+      expect(cop.messages).to be_empty
+    end
+
+    it 'accepts hash rockets when keys start with a digit' do
+      inspect_source(cop, ['x = { :"1" => 1 }'])
+      expect(cop.messages).to be_empty
+    end
+
+    it 'registers offense when keys start with an uppercase letter' do
+      inspect_source(cop, ['x = { :A => 0 }'])
+      expect(cop.messages).to eq(['Use the new Ruby 1.9 hash syntax.'])
+    end
+
+    it 'accepts new syntax in a hash literal' do
+      inspect_source(cop, ['x = { a: 0, b: 1 }'])
+      expect(cop.messages).to be_empty
+    end
+
+    it 'accepts new syntax in method calls' do
+      inspect_source(cop, ['func(3, a: 0)'])
+      expect(cop.messages).to be_empty
+    end
+
+    it 'auto-corrects old to new style' do
+      new_source = autocorrect_source(cop, '{ :a => 1, :b   =>  2}')
+      expect(new_source).to eq('{ a: 1, b: 2}')
+    end
+
+    it 'auto-corrects even if it interferes with SpaceAroundOperators' do
+      # Clobbering caused by two cops changing in the same range is dealt with
+      # by the auto-correct loop, so there's no reason to avoid a change.
+      new_source = autocorrect_source(cop, '{ :a=>1, :b=>2 }')
+      expect(new_source).to eq('{ a: 1, b: 2 }')
+    end
+
+    context 'with SpaceAroundOperators disabled' do
+      let(:config) do
+        Rubocop::Config.new('HashSyntax' => {
+                              'EnforcedStyle'   => 'ruby19',
+                              'SupportedStyles' => %w(ruby19 hash_rockets)
+                            },
+                            'SpaceAroundOperators' => { 'Enabled' => false })
+      end
+
+      it 'auto-corrects even if there is no space around =>' do
+        new_source = autocorrect_source(cop, '{ :a=>1, :b=>2 }')
+        expect(new_source).to eq('{ a: 1, b: 2 }')
+      end
+    end
+  end
+
+  context 'configured to enforce hash rockets style' do
+    let(:cop_config) { { 'EnforcedStyle' => 'hash_rockets' } }
+
+    it 'registers offense for Ruby 1.9 style' do
+      inspect_source(cop, ['x = { a: 0 }'])
+      expect(cop.messages).to eq(['Always use hash rockets in hashes.'])
+      expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'ruby19')
+    end
+
+    it 'registers an offense for mixed syntax' do
+      inspect_source(cop, ['x = { :a => 0, b: 1 }'])
+      expect(cop.messages).to eq(['Always use hash rockets in hashes.'])
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'registers an offense for 1.9 style in method calls' do
+      inspect_source(cop, ['func(3, a: 0)'])
+      expect(cop.messages).to eq(['Always use hash rockets in hashes.'])
+    end
+
+    it 'accepts hash rockets in a hash literal' do
+      inspect_source(cop, ['x = { :a => 0, :b => 1 }'])
+      expect(cop.messages).to be_empty
+    end
+
+    it 'accepts hash rockets in method calls' do
+      inspect_source(cop, ['func(3, :a => 0)'])
+      expect(cop.messages).to be_empty
+    end
+
+    it 'auto-corrects new style to hash rockets' do
+      new_source = autocorrect_source(cop, '{ a: 1, b: 2}')
+      expect(new_source).to eq('{ :a => 1, :b => 2}')
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/if_unless_modifier_spec.rb b/spec/rubocop/cop/style/if_unless_modifier_spec.rb
new file mode 100644
index 0000000..fdcb866
--- /dev/null
+++ b/spec/rubocop/cop/style/if_unless_modifier_spec.rb
@@ -0,0 +1,146 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::IfUnlessModifier do
+  include StatementModifierHelper
+
+  subject(:cop) { described_class.new(config) }
+  let(:config) do
+    hash = { 'LineLength' => { 'Max' => 79 } }
+    Rubocop::Config.new(hash)
+  end
+
+  it 'registers an offense for multiline if that fits on one line' do
+    # This if statement fits exactly on one line if written as a
+    # modifier.
+    condition = 'a' * 38
+    body = 'b' * 35
+    expect("  #{body} if #{condition}".length).to eq(79)
+
+    inspect_source(cop,
+                   ["  if #{condition}",
+                    "    #{body}",
+                    '  end'])
+    expect(cop.messages).to eq(
+      ['Favor modifier `if` usage when having a single-line' \
+       ' body. Another good alternative is the usage of control flow' \
+       ' `&&`/`||`.'])
+  end
+
+  it 'registers an offense for short multiline if near an else etc' do
+    inspect_source(cop,
+                   ['if x',
+                    '  y',
+                    'elsif x1',
+                    '  y1',
+                    'else',
+                    '  z',
+                    'end',
+                    'n = a ? 0 : 1',
+                    'm = 3 if m0',
+                    '',
+                    'if a',
+                    '  b',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it "accepts multiline if that doesn't fit on one line" do
+    check_too_long(cop, 'if')
+  end
+
+  it 'accepts multiline if whose body is more than one line' do
+    check_short_multiline(cop, 'if')
+  end
+
+  it 'registers an offense for multiline unless that fits on one line' do
+    inspect_source(cop, ['unless a',
+                         '  b',
+                         'end'])
+    expect(cop.messages).to eq(
+      ['Favor modifier `unless` usage when having a single-line' \
+       ' body. Another good alternative is the usage of control flow' \
+       ' `&&`/`||`.'])
+  end
+
+  it 'accepts code with EOL comment since user might want to keep it' do
+    inspect_source(cop, ['unless a',
+                         '  b # A comment',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts if-else-end' do
+    inspect_source(cop,
+                   ['if args.last.is_a? Hash then args.pop else ' \
+                    'Hash.new end'])
+    expect(cop.messages).to be_empty
+  end
+
+  it 'accepts an empty condition' do
+    check_empty(cop, 'if')
+    check_empty(cop, 'unless')
+  end
+
+  it 'accepts if/elsif' do
+    inspect_source(cop, ['if test',
+                         '  something',
+                         'elsif test2',
+                         '  something_else',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  context 'with implicit match conditional' do
+    let(:source) do
+      [
+        "  if #{conditional}",
+        "    #{body}",
+        '  end'
+      ]
+    end
+
+    let(:body) { 'b' * 35 }
+
+    context 'when a multiline if fits on one line' do
+      let(:conditional) { "/#{'a' * 36}/" }
+
+      it 'registers an offense' do
+        expect("  #{body} if #{conditional}".length).to eq(79)
+
+        inspect_source(cop, source)
+        expect(cop.offenses.size).to eq(1)
+      end
+    end
+
+    context "when a multiline if doesn't fit on one line" do
+      let(:conditional) { "/#{'a' * 37}/" }
+
+      it 'accepts' do
+        expect("  #{body} if #{conditional}".length).to eq(80)
+
+        inspect_source(cop, source)
+        expect(cop.offenses).to be_empty
+      end
+    end
+
+    context 'when the maximum line length is specified by the cop itself' do
+      let(:config) do
+        hash = {
+          'LineLength' => { 'Max' => 100 },
+          'IfUnlessModifier' => { 'MaxLineLength' => 79 }
+        }
+        Rubocop::Config.new(hash)
+      end
+
+      it "accepts multiline if that doesn't fit on one line" do
+        check_too_long(cop, 'if')
+      end
+
+      it "accepts multiline unless that doesn't fit on one line" do
+        check_too_long(cop, 'unless')
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/if_with_semicolon_spec.rb b/spec/rubocop/cop/style/if_with_semicolon_spec.rb
new file mode 100644
index 0000000..4f93fa3
--- /dev/null
+++ b/spec/rubocop/cop/style/if_with_semicolon_spec.rb
@@ -0,0 +1,19 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::IfWithSemicolon do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for one line if/;/end' do
+    inspect_source(cop, ['if cond; run else dont end'])
+    expect(cop.messages).to eq(
+      ['Never use if x; Use the ternary operator instead.'])
+  end
+
+  it 'can handle modifier conditionals' do
+    inspect_source(cop, ['class Hash',
+                         'end if RUBY_VERSION < "1.8.7"'])
+    expect(cop.messages).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/indent_array_spec.rb b/spec/rubocop/cop/style/indent_array_spec.rb
new file mode 100644
index 0000000..472dd30
--- /dev/null
+++ b/spec/rubocop/cop/style/indent_array_spec.rb
@@ -0,0 +1,136 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::IndentArray do
+  subject(:cop) { described_class.new }
+
+  it 'accepts multi-assignments' do
+    inspect_source(cop, 'a, b = b, a')
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts correctly indented only element' do
+    inspect_source(cop,
+                   ['a << [',
+                    '  1',
+                    ']'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'registers an offense for incorrectly indented only element' do
+    inspect_source(cop,
+                   ['a << [',
+                    ' 1',
+                    ']'])
+    expect(cop.highlights).to eq(['1'])
+  end
+
+  it 'auto-corrects incorrectly indented only element' do
+    corrected = autocorrect_source(cop, ['a << [',
+                                         ' 1',
+                                         ']'])
+    expect(corrected).to eq ['a << [',
+                             '  1',
+                             ']'].join("\n")
+  end
+
+  it 'accepts correctly indented first element' do
+    inspect_source(cop,
+                   ['[',
+                    '  x,',
+                    '  y',
+                    ']'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'registers an offense for incorrectly indented first element' do
+    inspect_source(cop,
+                   ['[',
+                    'x,',
+                    '  y',
+                    ']'])
+    expect(cop.highlights).to eq(['x'])
+  end
+
+  it 'accepts several elements per line' do
+    inspect_source(cop,
+                   ['a = [',
+                    '  1, 2',
+                    ']'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a first element on the same line as the left bracket' do
+    inspect_source(cop,
+                   ['a = ["a",',
+                    '     "b"]'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts single line array' do
+    inspect_source(cop,
+                   ['a = [1, 2]'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts an empty array' do
+    inspect_source(cop,
+                   ['a = []'])
+    expect(cop.offenses).to be_empty
+  end
+
+  context 'when array is method argument' do
+    context 'and arguments are surrounded by parentheses' do
+      it 'accepts normal indentation for first argument' do
+        inspect_source(cop,
+                       ['func([',
+                        '  1',
+                        '])'])
+        expect(cop.offenses).to be_empty
+      end
+
+      it 'registers an offense for incorrect indentation' do
+        inspect_source(cop,
+                       ['func([',
+                        '      1',
+                        '     ])'])
+        expect(cop.messages)
+          .to eq(['Use 2 spaces for indentation in an array, relative to ' \
+                  'the start of the line where the left bracket is.'])
+      end
+
+      it 'accepts normal indentation for second argument' do
+        inspect_source(cop,
+                       ['body.should have_tag("input", [',
+                        '  :name])'])
+        expect(cop.offenses).to be_empty
+      end
+    end
+
+    context 'and arguments are not surrounded by parentheses' do
+      it 'accepts single line array' do
+        inspect_source(cop,
+                       ['func x, [1, 2]'])
+        expect(cop.offenses).to be_empty
+      end
+
+      it 'accepts a correctly indented multi-line array' do
+        inspect_source(cop,
+                       ['func x, [',
+                        '  1, 2]'])
+        expect(cop.offenses).to be_empty
+      end
+
+      it 'registers an offense for incorrectly indented multi-line array' do
+        inspect_source(cop,
+                       ['func x, [',
+                        '       1, 2]'])
+        expect(cop.messages)
+          .to eq(['Use 2 spaces for indentation in an array, relative to ' \
+                  'the start of the line where the left bracket is.'])
+        expect(cop.highlights).to eq(['1'])
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/indent_hash_spec.rb b/spec/rubocop/cop/style/indent_hash_spec.rb
new file mode 100644
index 0000000..3713dd9
--- /dev/null
+++ b/spec/rubocop/cop/style/indent_hash_spec.rb
@@ -0,0 +1,310 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::IndentHash do
+  subject(:cop) { described_class.new(config) }
+  let(:config) do
+    supported_styles = {
+      'SupportedStyles' => %w(special_inside_parentheses consistent)
+    }
+    Rubocop::Config.new('AlignHash' => align_hash_config,
+                        'IndentHash' => cop_config.merge(supported_styles))
+  end
+  let(:align_hash_config) do
+    {
+      'Enabled' => true,
+      'EnforcedColonStyle' => 'key',
+      'EnforcedHashRocketStyle' => 'key'
+    }
+  end
+  let(:cop_config) { { 'EnforcedStyle' => 'special_inside_parentheses' } }
+
+  context 'when the AlignHash style is separator for :' do
+    let(:align_hash_config) do
+      {
+        'Enabled' => true,
+        'EnforcedColonStyle' => 'separator',
+        'EnforcedHashRocketStyle' => 'key'
+      }
+    end
+
+    it 'accepts correctly indented first pair' do
+      inspect_source(cop,
+                     ['a << {',
+                      '    a: 1,',
+                      '  aaa: 222',
+                      '}'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for incorrectly indented first pair with :' do
+      inspect_source(cop,
+                     ['a << {',
+                      '       a: 1,',
+                      '     aaa: 222',
+                      '}'])
+      expect(cop.highlights).to eq(['a: 1'])
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+  end
+
+  context 'when the AlignHash style is separator for =>' do
+    let(:align_hash_config) do
+      {
+        'Enabled' => true,
+        'EnforcedColonStyle' => 'key',
+        'EnforcedHashRocketStyle' => 'separator'
+      }
+    end
+
+    it 'accepts correctly indented first pair' do
+      inspect_source(cop,
+                     ['a << {',
+                      "    'a' => 1,",
+                      "  'aaa' => 222",
+                      '}'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for incorrectly indented first pair with =>' do
+      inspect_source(cop,
+                     ['a << {',
+                      "   'a' => 1,",
+                      " 'aaa' => 222",
+                      '}'])
+      expect(cop.highlights).to eq(["'a' => 1"])
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+  end
+
+  context 'when hash is operand' do
+    it 'accepts correctly indented first pair' do
+      inspect_source(cop,
+                     ['a << {',
+                      '  a: 1',
+                      '}'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for incorrectly indented first pair' do
+      inspect_source(cop,
+                     ['a << {',
+                      ' a: 1',
+                      '}'])
+      expect(cop.highlights).to eq(['a: 1'])
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'auto-corrects incorrectly indented first pair' do
+      corrected = autocorrect_source(cop, ['a << {',
+                                           ' a: 1',
+                                           '}'])
+      expect(corrected).to eq ['a << {',
+                               '  a: 1',
+                               '}'].join("\n")
+    end
+  end
+
+  context 'when hash is argument to setter' do
+    it 'accepts correctly indented first pair' do
+      inspect_source(cop,
+                     ['   config.rack_cache = {',
+                      '     :metastore => "rails:/",',
+                      '     :entitystore => "rails:/",',
+                      '     :verbose => false',
+                      '   }'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for incorrectly indented first pair' do
+      inspect_source(cop,
+                     ['   config.rack_cache = {',
+                      '   :metastore => "rails:/",',
+                      '   :entitystore => "rails:/",',
+                      '   :verbose => false',
+                      '   }'])
+      expect(cop.highlights).to eq([':metastore => "rails:/"'])
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+  end
+
+  context 'when hash is right hand side in assignment' do
+    it 'registers an offense for incorrectly indented first pair' do
+      inspect_source(cop, ['a = {',
+                           '    a: 1,',
+                           '  b: 2,',
+                           ' c: 3',
+                           '}'])
+      expect(cop.messages)
+        .to eq(['Use 2 spaces for indentation in a hash, relative to the ' \
+                'start of the line where the left curly brace is.'])
+      expect(cop.highlights).to eq(['a: 1'])
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'auto-corrects incorrectly indented first pair' do
+      corrected = autocorrect_source(cop, ['a = {',
+                                           '    a: 1,',
+                                           '  b: 2,',
+                                           ' c: 3',
+                                           '}'])
+      expect(corrected).to eq ['a = {',
+                               '  a: 1,',
+                               '  b: 2,',
+                               ' c: 3',
+                               '}'].join("\n")
+    end
+
+    it 'accepts correctly indented first pair' do
+      inspect_source(cop,
+                     ['a = {',
+                      '  a: 1',
+                      '}'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts several pairs per line' do
+      inspect_source(cop,
+                     ['a = {',
+                      '  a: 1, b: 2',
+                      '}'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts a first pair on the same line as the left brace' do
+      inspect_source(cop,
+                     ['a = { "a" => 1,',
+                      '      "b" => 2 }'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts single line hash' do
+      inspect_source(cop,
+                     ['a = { a: 1, b: 2 }'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts an empty hash' do
+      inspect_source(cop,
+                     ['a = {}'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'when hash is method argument' do
+    context 'and arguments are surrounded by parentheses' do
+      context 'and EnforcedStyle is special_inside_parentheses' do
+        it 'accepts special indentation for first argument' do
+          inspect_source(cop,
+                         ['func({',
+                          '       a: 1',
+                          '     })'])
+          expect(cop.offenses).to be_empty
+        end
+
+        it 'registers an offense for incorrect indentation' do
+          inspect_source(cop,
+                         ['func({',
+                          '  a: 1',
+                          '})'])
+          expect(cop.messages)
+            .to eq(['Use 2 spaces for indentation in a hash, relative to the' \
+                    ' first position after the preceding left parenthesis.'])
+          expect(cop.config_to_allow_offenses)
+            .to eq('EnforcedStyle' => 'consistent')
+        end
+
+        it 'auto-corrects incorrectly indented first pair' do
+          corrected = autocorrect_source(cop, ['func({',
+                                               '  a: 1',
+                                               '})'])
+          expect(corrected).to eq ['func({',
+                                   '       a: 1',
+                                   '})'].join("\n")
+        end
+
+        it 'accepts special indentation for second argument' do
+          inspect_source(cop,
+                         ['body.should have_tag("input", :attributes => {',
+                          '                       :name => /q\[(id_eq)\]/ })'])
+          expect(cop.offenses).to be_empty
+        end
+
+        it 'accepts normal indentation for hash within hash' do
+          inspect_source(cop,
+                         ['scope = scope.where(',
+                          '  klass.table_name => {',
+                          '    reflection.type => model.base_class.sti_name',
+                          '  }',
+                          ')'])
+          expect(cop.offenses).to be_empty
+        end
+      end
+
+      context 'and EnforcedStyle is consistent' do
+        let(:cop_config) { { 'EnforcedStyle' => 'consistent' } }
+
+        it 'accepts normal indentation for first argument' do
+          inspect_source(cop,
+                         ['func({',
+                          '  a: 1',
+                          '})'])
+          expect(cop.offenses).to be_empty
+        end
+
+        it 'registers an offense for incorrect indentation' do
+          inspect_source(cop,
+                         ['func({',
+                          '       a: 1',
+                          '     })'])
+          expect(cop.messages)
+            .to eq(['Use 2 spaces for indentation in a hash, relative to the' \
+                    ' start of the line where the left curly brace is.'])
+          expect(cop.config_to_allow_offenses)
+            .to eq('EnforcedStyle' => 'special_inside_parentheses')
+        end
+
+        it 'accepts normal indentation for second argument' do
+          inspect_source(cop,
+                         ['body.should have_tag("input", :attributes => {',
+                          '  :name => /q\[(id_eq)\]/ })'])
+          expect(cop.offenses).to be_empty
+        end
+      end
+    end
+
+    context 'and argument are not surrounded by parentheses' do
+      it 'accepts braceless hash' do
+        inspect_source(cop,
+                       ['func a: 1, b: 2'])
+        expect(cop.offenses).to be_empty
+      end
+
+      it 'accepts single line hash with braces' do
+        inspect_source(cop,
+                       ['func x, { a: 1, b: 2 }'])
+        expect(cop.offenses).to be_empty
+      end
+
+      it 'accepts a correctly indented multi-line hash with braces' do
+        inspect_source(cop,
+                       ['func x, {',
+                        '  a: 1, b: 2 }'])
+        expect(cop.offenses).to be_empty
+      end
+
+      it 'registers an offense for incorrectly indented multi-line hash ' \
+         'with braces' do
+        inspect_source(cop,
+                       ['func x, {',
+                        '       a: 1, b: 2 }'])
+        expect(cop.messages)
+          .to eq(['Use 2 spaces for indentation in a hash, relative to the ' \
+                  'start of the line where the left curly brace is.'])
+        expect(cop.highlights).to eq(['a: 1'])
+        expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/indentation_consistency_spec.rb b/spec/rubocop/cop/style/indentation_consistency_spec.rb
new file mode 100644
index 0000000..19aa092
--- /dev/null
+++ b/spec/rubocop/cop/style/indentation_consistency_spec.rb
@@ -0,0 +1,510 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::IndentationConsistency do
+  subject(:cop) { described_class.new }
+
+  context 'with if statement' do
+    it 'registers an offense for bad indentation in an if body' do
+      inspect_source(cop,
+                     ['if cond',
+                      ' func',
+                      '  func',
+                      'end'])
+      expect(cop.messages).to eq(['Inconsistent indentation detected.'])
+    end
+
+    it 'registers an offense for bad indentation in an else body' do
+      inspect_source(cop,
+                     ['if cond',
+                      '  func1',
+                      'else',
+                      ' func2',
+                      '  func2',
+                      'end'])
+      expect(cop.messages).to eq(['Inconsistent indentation detected.'])
+    end
+
+    it 'registers an offense for bad indentation in an elsif body' do
+      inspect_source(cop,
+                     ['if a1',
+                      '  b1',
+                      'elsif a2',
+                      ' b2',
+                      'b3',
+                      'else',
+                      '  c',
+                      'end'])
+      expect(cop.messages).to eq(['Inconsistent indentation detected.'])
+    end
+
+    it 'autocorrects bad indentation' do
+      corrected = autocorrect_source(cop,
+                                     ['if a1',
+                                      '   b1',
+                                      'elsif a2',
+                                      ' b2',
+                                      '  b3',
+                                      'else',
+                                      '    c',
+                                      'end'])
+      expect(corrected).to eq ['if a1',
+                               '   b1',
+                               'elsif a2',
+                               ' b2',
+                               ' b3',
+                               'else',
+                               '    c',
+                               'end'].join("\n")
+    end
+
+    it 'accepts a one line if statement' do
+      inspect_source(cop,
+                     ['if cond then func1 else func2 end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts a correctly aligned if/elsif/else/end' do
+      inspect_source(cop,
+                     ['if a1',
+                      '  b1',
+                      'elsif a2',
+                      '  b2',
+                      'else',
+                      '  c',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts if/elsif/else/end laid out as a table' do
+      inspect_source(cop,
+                     ['if    @io == $stdout then str << "$stdout"',
+                      'elsif @io == $stdin  then str << "$stdin"',
+                      'elsif @io == $stderr then str << "$stderr"',
+                      'else                      str << @io.class.to_s',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts if/then/else/end laid out as another table' do
+      inspect_source(cop,
+                     ["if File.exist?('config.save')",
+                      'then ConfigTable.load',
+                      'else ConfigTable.new',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts an empty if' do
+      inspect_source(cop,
+                     ['if a',
+                      'else',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts an if in assignment with end aligned with variable' do
+      inspect_source(cop,
+                     ['var = if a',
+                      '  0',
+                      'end',
+                      '@var = if a',
+                      '  0',
+                      'end',
+                      '$var = if a',
+                      '  0',
+                      'end',
+                      'var ||= if a',
+                      '  0',
+                      'end',
+                      'var &&= if a',
+                      '  0',
+                      'end',
+                      'var -= if a',
+                      '  0',
+                      'end',
+                      'VAR = if a',
+                      '  0',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts an if/else in assignment with end aligned with variable' do
+      inspect_source(cop,
+                     ['var = if a',
+                      '  0',
+                      'else',
+                      '  1',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts an if/else in assignment with end aligned with variable ' \
+       'and chaining after the end' do
+      inspect_source(cop,
+                     ['var = if a',
+                      '  0',
+                      'else',
+                      '  1',
+                      'end.abc.join("")'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts an if/else in assignment with end aligned with variable ' \
+       'and chaining with a block after the end' do
+      inspect_source(cop,
+                     ['var = if a',
+                      '  0',
+                      'else',
+                      '  1',
+                      'end.abc.tap {}'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts an if in assignment with end aligned with if' do
+      inspect_source(cop,
+                     ['var = if a',
+                      '        0',
+                      '      end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts an if/else in assignment with end aligned with if' do
+      inspect_source(cop,
+                     ['var = if a',
+                      '        0',
+                      '      else',
+                      '        1',
+                      '      end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts an if/else in assignment on next line with end aligned ' \
+       'with if' do
+      inspect_source(cop,
+                     ['var =',
+                      '  if a',
+                      '    0',
+                      '  else',
+                      '    1',
+                      '  end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts an if/else branches with rescue clauses' do
+      # Because of how the rescue clauses come out of Parser, these are
+      # special and need to be tested.
+      inspect_source(cop,
+                     ['if a',
+                      '  a rescue nil',
+                      'else',
+                      '  a rescue nil',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'with unless' do
+    it 'registers an offense for bad indentation in an unless body' do
+      inspect_source(cop,
+                     ['unless cond',
+                      ' func',
+                      '  func',
+                      'end'])
+      expect(cop.messages).to eq(['Inconsistent indentation detected.'])
+    end
+
+    it 'accepts an empty unless' do
+      inspect_source(cop,
+                     ['unless a',
+                      'else',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'with case' do
+    it 'registers an offense for bad indentation in a case/when body' do
+      inspect_source(cop,
+                     ['case a',
+                      'when b',
+                      ' c',
+                      '    d',
+                      'end'])
+      expect(cop.messages).to eq(['Inconsistent indentation detected.'])
+    end
+
+    it 'registers an offense for bad indentation in a case/else body' do
+      inspect_source(cop,
+                     ['case a',
+                      'when b',
+                      '  c',
+                      'when d',
+                      '  e',
+                      'else',
+                      '   f',
+                      '  g',
+                      'end'])
+      expect(cop.messages).to eq(['Inconsistent indentation detected.'])
+    end
+
+    it 'accepts correctly indented case/when/else' do
+      inspect_source(cop,
+                     ['case a',
+                      'when b',
+                      '  c',
+                      '  c',
+                      'when d',
+                      'else',
+                      '  f',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts case/when/else laid out as a table' do
+      inspect_source(cop,
+                     ['case sexp.loc.keyword.source',
+                      "when 'if'     then cond, body, _else = *sexp",
+                      "when 'unless' then cond, _else, body = *sexp",
+                      'else               cond, body = *sexp',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts case/when/else with then beginning a line' do
+      inspect_source(cop,
+                     ['case sexp.loc.keyword.source',
+                      "when 'if'",
+                      'then cond, body, _else = *sexp',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts indented when/else plus indented body' do
+      # "Indent when as deep as case" is the job of another cop.
+      inspect_source(cop,
+                     ['case code_type',
+                      "  when 'ruby', 'sql', 'plain'",
+                      '    code_type',
+                      "  when 'erb'",
+                      "    'ruby; html-script: true'",
+                      '  when "html"',
+                      "    'xml'",
+                      '  else',
+                      "    'plain'",
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'with while/until' do
+    it 'registers an offense for bad indentation in a while body' do
+      inspect_source(cop,
+                     ['while cond',
+                      ' func',
+                      '  func',
+                      'end'])
+      expect(cop.messages).to eq(['Inconsistent indentation detected.'])
+    end
+
+    it 'registers an offense for bad indentation in begin/end/while' do
+      inspect_source(cop,
+                     ['something = begin',
+                      ' func1',
+                      '   func2',
+                      'end while cond'])
+      expect(cop.messages).to eq(['Inconsistent indentation detected.'])
+    end
+
+    it 'registers an offense for bad indentation in an until body' do
+      inspect_source(cop,
+                     ['until cond',
+                      ' func',
+                      '  func',
+                      'end'])
+      expect(cop.messages).to eq(['Inconsistent indentation detected.'])
+    end
+
+    it 'accepts an empty while' do
+      inspect_source(cop,
+                     ['while a',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'with for' do
+    it 'registers an offense for bad indentation in a for body' do
+      inspect_source(cop,
+                     ['for var in 1..10',
+                      ' func',
+                      'func',
+                      'end'])
+      expect(cop.messages).to eq(['Inconsistent indentation detected.'])
+    end
+
+    it 'accepts an empty for' do
+      inspect_source(cop,
+                     ['for var in 1..10',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'with def/defs' do
+    it 'registers an offense for bad indentation in a def body' do
+      inspect_source(cop,
+                     ['def test',
+                      '    func1',
+                      '     func2',
+                      'end'])
+      expect(cop.messages)
+        .to eq(['Inconsistent indentation detected.'])
+    end
+
+    it 'registers an offense for bad indentation in a defs body' do
+      inspect_source(cop,
+                     ['def self.test',
+                      '   func',
+                      '    func',
+                      'end'])
+      expect(cop.messages).to eq(['Inconsistent indentation detected.'])
+    end
+
+    it 'accepts an empty def body' do
+      inspect_source(cop,
+                     ['def test',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts an empty defs body' do
+      inspect_source(cop,
+                     ['def self.test',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'with class' do
+    it 'registers an offense for bad indentation in a class body' do
+      inspect_source(cop,
+                     ['class Test',
+                      '    def func1',
+                      '    end',
+                      '  def func2',
+                      '  end',
+                      'end'])
+      expect(cop.messages)
+        .to eq(['Inconsistent indentation detected.'])
+    end
+
+    it 'accepts an empty class body' do
+      inspect_source(cop,
+                     ['class Test',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts indented public, protected, and private' do
+      inspect_source(cop,
+                     ['class Test',
+                      '  public',
+                      '',
+                      '  def e',
+                      '  end',
+                      '',
+                      '  protected',
+                      '',
+                      '  def f',
+                      '  end',
+                      '',
+                      '  private',
+                      '',
+                      '  def g',
+                      '  end',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for bad indentation in def but not for ' \
+       'outdented public, protected, and private' do
+      inspect_source(cop,
+                     ['class Test',
+                      'public',
+                      '',
+                      '  def e',
+                      '  end',
+                      '',
+                      'protected',
+                      '',
+                      '  def f',
+                      '  end',
+                      '',
+                      'private',
+                      '',
+                      ' def g',
+                      ' end',
+                      'end'])
+      expect(cop.messages).to eq(['Inconsistent indentation detected.'])
+      expect(cop.highlights).to eq(["def g\n end"])
+    end
+  end
+
+  context 'with module' do
+    it 'registers an offense for bad indentation in a module body' do
+      inspect_source(cop,
+                     ['module Test',
+                      '    def func1',
+                      '    end',
+                      '     def func2',
+                      '     end',
+                      'end'])
+      expect(cop.messages).to eq(['Inconsistent indentation detected.'])
+    end
+
+    it 'accepts an empty module body' do
+      inspect_source(cop,
+                     ['module Test',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'with block' do
+    it 'registers an offense for bad indentation in a do/end body' do
+      inspect_source(cop,
+                     ['a = func do',
+                      ' b',
+                      '  c',
+                      'end'])
+      expect(cop.messages).to eq(['Inconsistent indentation detected.'])
+    end
+
+    it 'registers an offense for bad indentation in a {} body' do
+      inspect_source(cop,
+                     ['func {',
+                      '   b',
+                      '  c',
+                      '}'])
+      expect(cop.messages).to eq(['Inconsistent indentation detected.'])
+    end
+
+    it 'accepts a correctly indented block body' do
+      inspect_source(cop,
+                     ['a = func do',
+                      '  b',
+                      '  c',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts an empty block body' do
+      inspect_source(cop,
+                     ['a = func do',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/indentation_width_spec.rb b/spec/rubocop/cop/style/indentation_width_spec.rb
new file mode 100644
index 0000000..5f8c59f
--- /dev/null
+++ b/spec/rubocop/cop/style/indentation_width_spec.rb
@@ -0,0 +1,606 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::IndentationWidth do
+  subject(:cop) { described_class.new(config) }
+  let(:config) do
+    Rubocop::Config.new('EndAlignment' => end_alignment_config)
+  end
+  let(:end_alignment_config) do
+    { 'Enabled' => true, 'AlignWith' => 'variable' }
+  end
+
+  context 'with if statement' do
+    it 'registers an offense for bad indentation of an if body' do
+      inspect_source(cop,
+                     ['if cond',
+                      ' func',
+                      'end'])
+      expect(cop.messages).to eq(['Use 2 (not 1) spaces for indentation.'])
+      expect(cop.highlights).to eq([' '])
+    end
+
+    it 'registers an offense for bad indentation of an else body' do
+      inspect_source(cop,
+                     ['if cond',
+                      '  func1',
+                      'else',
+                      ' func2',
+                      'end'])
+      expect(cop.messages).to eq(['Use 2 (not 1) spaces for indentation.'])
+      expect(cop.highlights).to eq([' '])
+    end
+
+    it 'registers an offense for bad indentation of an elsif body' do
+      inspect_source(cop,
+                     ['if a1',
+                      '  b1',
+                      'elsif a2',
+                      ' b2',
+                      'else',
+                      '  c',
+                      'end'])
+      expect(cop.messages).to eq(['Use 2 (not 1) spaces for indentation.'])
+    end
+
+    it 'registers offense for bad indentation of ternary inside else' do
+      inspect_source(cop,
+                     ['if a',
+                      '  b',
+                      'else',
+                      '     x ? y : z',
+                      'end'])
+      expect(cop.messages)
+        .to eq(['Use 2 (not 5) spaces for indentation.'])
+      expect(cop.highlights).to eq(['     '])
+    end
+
+    it 'registers offense for bad indentation of modifier if in else' do
+      inspect_source(cop,
+                     ['if a',
+                      '  b',
+                      'else',
+                      '   x if y',
+                      'end'])
+      expect(cop.messages)
+        .to eq(['Use 2 (not 3) spaces for indentation.'])
+    end
+
+    it 'autocorrects bad indentation' do
+      corrected = autocorrect_source(cop,
+                                     ['if a1',
+                                      '   b1',
+                                      '   b1',
+                                      'elsif a2',
+                                      ' b2',
+                                      'else',
+                                      '    c',
+                                      'end'])
+      expect(corrected)
+        .to eq ['if a1',
+                '  b1',
+                '   b1', # Will be corrected by IndentationConsistency.
+                'elsif a2',
+                '  b2',
+                'else',
+                '  c',
+                'end'].join("\n")
+    end
+
+    it 'accepts a one line if statement' do
+      inspect_source(cop,
+                     ['if cond then func1 else func2 end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts a correctly aligned if/elsif/else/end' do
+      inspect_source(cop,
+                     ['if a1',
+                      '  b1',
+                      'elsif a2',
+                      '  b2',
+                      'else',
+                      '  c',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts if/elsif/else/end laid out as a table' do
+      inspect_source(cop,
+                     ['if    @io == $stdout then str << "$stdout"',
+                      'elsif @io == $stdin  then str << "$stdin"',
+                      'elsif @io == $stderr then str << "$stderr"',
+                      'else                      str << @io.class.to_s',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts if/then/else/end laid out as another table' do
+      inspect_source(cop,
+                     ["if File.exist?('config.save')",
+                      'then ConfigTable.load',
+                      'else ConfigTable.new',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts an empty if' do
+      inspect_source(cop,
+                     ['if a',
+                      'else',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    context 'with assignment' do
+      context 'when alignment style is variable' do
+        context 'and end is aligned with variable' do
+          it 'accepts an if with end aligned with variable' do
+            inspect_source(cop,
+                           ['var = if a',
+                            '  0',
+                            'end',
+                            '@var = if a',
+                            '  0',
+                            'end',
+                            '$var = if a',
+                            '  0',
+                            'end',
+                            'var ||= if a',
+                            '  0',
+                            'end',
+                            'var &&= if a',
+                            '  0',
+                            'end',
+                            'var -= if a',
+                            '  0',
+                            'end',
+                            'VAR = if a',
+                            '  0',
+                            'end'])
+            expect(cop.offenses).to be_empty
+          end
+
+          it 'accepts an if/else' do
+            inspect_source(cop,
+                           ['var = if a',
+                            '  0',
+                            'else',
+                            '  1',
+                            'end'])
+            expect(cop.offenses).to be_empty
+          end
+
+          it 'accepts an if/else with chaining after the end' do
+            inspect_source(cop,
+                           ['var = if a',
+                            '  0',
+                            'else',
+                            '  1',
+                            'end.abc.join("")'])
+            expect(cop.offenses).to be_empty
+          end
+
+          it 'accepts an if/else with chaining with a block after the end' do
+            inspect_source(cop,
+                           ['var = if a',
+                            '  0',
+                            'else',
+                            '  1',
+                            'end.abc.tap {}'])
+            expect(cop.offenses).to be_empty
+          end
+        end
+
+        context 'and end is aligned with keyword' do
+          it 'registers an offense for an if' do
+            inspect_source(cop,
+                           ['var = if a',
+                            '        0',
+                            '      end'])
+            expect(cop.messages)
+              .to eq(['Use 2 (not 8) spaces for indentation.'])
+          end
+
+          it 'registers an offense for a while' do
+            inspect_source(cop,
+                           ['var = while a',
+                            '        b',
+                            '      end'])
+            expect(cop.messages)
+              .to eq(['Use 2 (not 8) spaces for indentation.'])
+          end
+
+          it 'registers an offense for an until' do
+            inspect_source(cop,
+                           ['var = until a',
+                            '        b',
+                            '      end'])
+            expect(cop.messages)
+              .to eq(['Use 2 (not 8) spaces for indentation.'])
+          end
+        end
+      end
+
+      shared_examples 'assignment and if with keyword alignment' do
+        context 'and end is aligned with variable' do
+          it 'registers an offense for an if' do
+            inspect_source(cop,
+                           ['var = if a',
+                            '  0',
+                            'end'])
+            expect(cop.messages)
+              .to eq(['Use 2 (not -4) spaces for indentation.'])
+          end
+
+          it 'registers an offense for a while' do
+            inspect_source(cop,
+                           ['var = while a',
+                            '  b',
+                            'end'])
+            expect(cop.messages)
+              .to eq(['Use 2 (not -4) spaces for indentation.'])
+          end
+
+          it 'autocorrects bad indentation' do
+            corrected = autocorrect_source(cop,
+                                           ['var = if a',
+                                            '  b',
+                                            'end',
+                                            '',
+                                            'var = while a',
+                                            '  b',
+                                            'end'])
+            expect(corrected).to eq ['var = if a',
+                                     '        b',
+                                     'end', # Not this cop's job to fix end.
+                                     '',
+                                     'var = while a',
+                                     '        b',
+                                     'end'].join("\n")
+          end
+        end
+
+        context 'and end is aligned with keyword' do
+          it 'accepts an if in assignment' do
+            inspect_source(cop,
+                           ['var = if a',
+                            '        0',
+                            '      end'])
+            expect(cop.offenses).to be_empty
+          end
+
+          it 'accepts an if/else in assignment' do
+            inspect_source(cop,
+                           ['var = if a',
+                            '        0',
+                            '      else',
+                            '        1',
+                            '      end'])
+            expect(cop.offenses).to be_empty
+          end
+
+          it 'accepts an if/else in assignment on next line' do
+            inspect_source(cop,
+                           ['var =',
+                            '  if a',
+                            '    0',
+                            '  else',
+                            '    1',
+                            '  end'])
+            expect(cop.offenses).to be_empty
+          end
+
+          it 'accepts a while in assignment' do
+            inspect_source(cop,
+                           ['var = while a',
+                            '        b',
+                            '      end'])
+            expect(cop.offenses).to be_empty
+          end
+
+          it 'accepts an until in assignment' do
+            inspect_source(cop,
+                           ['var = until a',
+                            '        b',
+                            '      end'])
+            expect(cop.offenses).to be_empty
+          end
+        end
+      end
+
+      context 'when alignment style is keyword by choice' do
+        let(:end_alignment_config) do
+          { 'Enabled' => true, 'AlignWith' => 'keyword' }
+        end
+
+        include_examples 'assignment and if with keyword alignment'
+      end
+
+      context 'when alignment style is keyword by default' do
+        let(:end_alignment_config) do
+          { 'Enabled' => false, 'AlignWith' => 'variable' }
+        end
+
+        include_examples 'assignment and if with keyword alignment'
+      end
+    end
+
+    it 'accepts an if/else branches with rescue clauses' do
+      # Because of how the rescue clauses come out of Parser, these are
+      # special and need to be tested.
+      inspect_source(cop,
+                     ['if a',
+                      '  a rescue nil',
+                      'else',
+                      '  a rescue nil',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'with unless' do
+    it 'registers an offense for bad indentation of an unless body' do
+      inspect_source(cop,
+                     ['unless cond',
+                      ' func',
+                      'end'])
+      expect(cop.messages).to eq(['Use 2 (not 1) spaces for indentation.'])
+    end
+
+    it 'accepts an empty unless' do
+      inspect_source(cop,
+                     ['unless a',
+                      'else',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'with case' do
+    it 'registers an offense for bad indentation in a case/when body' do
+      inspect_source(cop,
+                     ['case a',
+                      'when b',
+                      ' c',
+                      'end'])
+      expect(cop.messages).to eq(['Use 2 (not 1) spaces for indentation.'])
+    end
+
+    it 'registers an offense for bad indentation in a case/else body' do
+      inspect_source(cop,
+                     ['case a',
+                      'when b',
+                      '  c',
+                      'when d',
+                      '  e',
+                      'else',
+                      '   f',
+                      'end'])
+      expect(cop.messages).to eq(['Use 2 (not 3) spaces for indentation.'])
+    end
+
+    it 'accepts correctly indented case/when/else' do
+      inspect_source(cop,
+                     ['case a',
+                      'when b',
+                      '  c',
+                      '  c',
+                      'when d',
+                      'else',
+                      '  f',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts case/when/else laid out as a table' do
+      inspect_source(cop,
+                     ['case sexp.loc.keyword.source',
+                      "when 'if'     then cond, body, _else = *sexp",
+                      "when 'unless' then cond, _else, body = *sexp",
+                      'else               cond, body = *sexp',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts case/when/else with then beginning a line' do
+      inspect_source(cop,
+                     ['case sexp.loc.keyword.source',
+                      "when 'if'",
+                      'then cond, body, _else = *sexp',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts indented when/else plus indented body' do
+      # "Indent when as deep as case" is the job of another cop.
+      inspect_source(cop,
+                     ['case code_type',
+                      "  when 'ruby', 'sql', 'plain'",
+                      '    code_type',
+                      "  when 'erb'",
+                      "    'ruby; html-script: true'",
+                      '  when "html"',
+                      "    'xml'",
+                      '  else',
+                      "    'plain'",
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'with while/until' do
+    it 'registers an offense for bad indentation of a while body' do
+      inspect_source(cop,
+                     ['while cond',
+                      ' func',
+                      'end'])
+      expect(cop.messages).to eq(['Use 2 (not 1) spaces for indentation.'])
+    end
+
+    it 'registers an offense for bad indentation of begin/end/while' do
+      inspect_source(cop,
+                     ['something = begin',
+                      ' func1',
+                      '   func2',
+                      'end while cond'])
+      expect(cop.messages).to eq(['Use 2 (not 1) spaces for indentation.'])
+    end
+
+    it 'registers an offense for bad indentation of an until body' do
+      inspect_source(cop,
+                     ['until cond',
+                      ' func',
+                      'end'])
+      expect(cop.messages).to eq(['Use 2 (not 1) spaces for indentation.'])
+    end
+
+    it 'accepts an empty while' do
+      inspect_source(cop,
+                     ['while a',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'with for' do
+    it 'registers an offense for bad indentation of a for body' do
+      inspect_source(cop,
+                     ['for var in 1..10',
+                      ' func',
+                      'end'])
+      expect(cop.messages).to eq(['Use 2 (not 1) spaces for indentation.'])
+    end
+
+    it 'accepts an empty for' do
+      inspect_source(cop,
+                     ['for var in 1..10',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'with def/defs' do
+    it 'registers an offense for bad indentation of a def body' do
+      inspect_source(cop,
+                     ['def test',
+                      '    func1',
+                      '     func2', # No offense registered for this.
+                      'end'])
+      expect(cop.messages).to eq(['Use 2 (not 4) spaces for indentation.'])
+    end
+
+    it 'registers an offense for bad indentation of a defs body' do
+      inspect_source(cop,
+                     ['def self.test',
+                      '   func',
+                      'end'])
+      expect(cop.messages).to eq(['Use 2 (not 3) spaces for indentation.'])
+    end
+
+    it 'accepts an empty def body' do
+      inspect_source(cop,
+                     ['def test',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts an empty defs body' do
+      inspect_source(cop,
+                     ['def self.test',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'with class' do
+    it 'registers an offense for bad indentation of a class body' do
+      inspect_source(cop,
+                     ['class Test',
+                      '    def func',
+                      '    end',
+                      'end'])
+      expect(cop.messages).to eq(['Use 2 (not 4) spaces for indentation.'])
+    end
+
+    it 'accepts an empty class body' do
+      inspect_source(cop,
+                     ['class Test',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts indented public, protected, and private' do
+      inspect_source(cop,
+                     ['class Test',
+                      '  public',
+                      '',
+                      '  def e',
+                      '  end',
+                      '',
+                      '  protected',
+                      '',
+                      '  def f',
+                      '  end',
+                      '',
+                      '  private',
+                      '',
+                      '  def g',
+                      '  end',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'with module' do
+    it 'registers an offense for bad indentation of a module body' do
+      inspect_source(cop,
+                     ['module Test',
+                      '    def func',
+                      '    end',
+                      'end'])
+      expect(cop.messages).to eq(['Use 2 (not 4) spaces for indentation.'])
+    end
+
+    it 'accepts an empty module body' do
+      inspect_source(cop,
+                     ['module Test',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'with block' do
+    it 'registers an offense for bad indentation of a do/end body' do
+      inspect_source(cop,
+                     ['a = func do',
+                      ' b',
+                      'end'])
+      expect(cop.messages).to eq(['Use 2 (not 1) spaces for indentation.'])
+    end
+
+    it 'registers an offense for bad indentation of a {} body' do
+      inspect_source(cop,
+                     ['func {',
+                      '   b',
+                      '}'])
+      expect(cop.messages).to eq(['Use 2 (not 3) spaces for indentation.'])
+    end
+
+    it 'accepts a correctly indented block body' do
+      inspect_source(cop,
+                     ['a = func do',
+                      '  b',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts an empty block body' do
+      inspect_source(cop,
+                     ['a = func do',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/lambda_call_spec.rb b/spec/rubocop/cop/style/lambda_call_spec.rb
new file mode 100644
index 0000000..8220286
--- /dev/null
+++ b/spec/rubocop/cop/style/lambda_call_spec.rb
@@ -0,0 +1,65 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::LambdaCall, :config do
+  subject(:cop) { described_class.new(config) }
+
+  context 'when style is set to call' do
+    let(:cop_config) { { 'EnforcedStyle' => 'call' } }
+
+    it 'registers an offense for x.()' do
+      inspect_source(cop,
+                     ['x.(a, b)'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'braces')
+    end
+
+    it 'registers an offense for correct + opposite' do
+      inspect_source(cop,
+                     ['x.call(a, b)',
+                      'x.(a, b)'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'accepts x.call()' do
+      inspect_source(cop, ['x.call(a, b)'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'auto-corrects x.() to x.call()' do
+      new_source = autocorrect_source(cop, ['a.(x)'])
+      expect(new_source).to eq('a.call(x)')
+    end
+  end
+
+  context 'when style is set to braces' do
+    let(:cop_config) { { 'EnforcedStyle' => 'braces' } }
+
+    it 'registers an offense for x.call()' do
+      inspect_source(cop,
+                     ['x.call(a, b)'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'call')
+    end
+
+    it 'registers an offense for opposite + correct' do
+      inspect_source(cop,
+                     ['x.call(a, b)',
+                      'x.(a, b)'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'accepts x.()' do
+      inspect_source(cop, ['x.(a, b)'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'auto-corrects x.call() to x.()' do
+      new_source = autocorrect_source(cop, ['a.call(x)'])
+      expect(new_source).to eq('a.(x)')
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/lambda_spec.rb b/spec/rubocop/cop/style/lambda_spec.rb
new file mode 100644
index 0000000..65f6683
--- /dev/null
+++ b/spec/rubocop/cop/style/lambda_spec.rb
@@ -0,0 +1,41 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::Lambda do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for an old single-line lambda call' do
+    inspect_source(cop, ['f = lambda { |x| x }'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages)
+      .to eq(['Use the new lambda literal syntax `->(params) {...}`.'])
+  end
+
+  it 'accepts the new lambda literal with single-line body' do
+    inspect_source(cop, ['lambda = ->(x) { x }',
+                         'lambda.(1)'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'registers an offense for a new multi-line lambda call' do
+    inspect_source(cop, ['f = ->(x) do',
+                         '  x',
+                         'end'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages)
+      .to eq(['Use the `lambda` method for multi-line lambdas.'])
+  end
+
+  it 'accepts the old lambda syntax with multi-line body' do
+    inspect_source(cop, ['l = lambda do |x|',
+                         '  x',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts the lambda call outside of block' do
+    inspect_source(cop, ['l = lambda.test'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/leading_comment_space_spec.rb b/spec/rubocop/cop/style/leading_comment_space_spec.rb
new file mode 100644
index 0000000..29d35ae
--- /dev/null
+++ b/spec/rubocop/cop/style/leading_comment_space_spec.rb
@@ -0,0 +1,64 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::LeadingCommentSpace do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for comment without leading space' do
+    inspect_source(cop,
+                   ['#missing space'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'does not register an offense for # followed by no text' do
+    inspect_source(cop,
+                   ['#'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense for more than one space' do
+    inspect_source(cop,
+                   ['#   heavily indented'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense for more than one #' do
+    inspect_source(cop,
+                   ['###### heavily indented'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense for only #s' do
+    inspect_source(cop,
+                   ['######'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense for #! on first line' do
+    inspect_source(cop,
+                   ['#!/usr/bin/ruby',
+                    'test'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'registers an offense for #! after the first line' do
+    inspect_source(cop,
+                   ['test', '#!/usr/bin/ruby'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts rdoc syntax' do
+    inspect_source(cop,
+                   ['#++',
+                    '#--',
+                    '#:nodoc:'])
+
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'auto-corrects missing space' do
+    new_source = autocorrect_source(cop, '#comment')
+    expect(new_source).to eq('# comment')
+  end
+end
diff --git a/spec/rubocop/cop/style/line_end_concatenation_spec.rb b/spec/rubocop/cop/style/line_end_concatenation_spec.rb
new file mode 100644
index 0000000..03ee6fe
--- /dev/null
+++ b/spec/rubocop/cop/style/line_end_concatenation_spec.rb
@@ -0,0 +1,62 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::LineEndConcatenation do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for string concat at line end' do
+    inspect_source(cop,
+                   ['top = "test" +',
+                    '"top"'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for string concat with << at line end' do
+    inspect_source(cop,
+                   ['top = "test" <<',
+                    '"top"'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for dynamic string concat at line end' do
+    inspect_source(cop,
+                   ['top = "test#{x}" +',
+                    '"top"'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for dynamic string concat with << at line end' do
+    inspect_source(cop,
+                   ['top = "test#{x}" <<',
+                    '"top"'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts string concat on the same line' do
+    inspect_source(cop,
+                   ['top = "test" + "top"'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts string concat at line end when followed by comment' do
+    inspect_source(cop,
+                   ['top = "test" + # something',
+                    '"top"'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts string concat at line end when % literals are involved' do
+    inspect_source(cop,
+                   ['top = %(test) +',
+                    '"top"'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'autocorrects by replacing + with \\' do
+    corrected = autocorrect_source(cop,
+                                   ['top = "test" +',
+                                    '"top"'])
+    expect(corrected).to eq ['top = "test" \\', '"top"'].join("\n")
+  end
+end
diff --git a/spec/rubocop/cop/style/line_length_spec.rb b/spec/rubocop/cop/style/line_length_spec.rb
new file mode 100644
index 0000000..7d00d29
--- /dev/null
+++ b/spec/rubocop/cop/style/line_length_spec.rb
@@ -0,0 +1,20 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::LineLength, :config do
+  subject(:cop) { described_class.new(config) }
+  let(:cop_config) { { 'Max' => 79 } }
+
+  it "registers an offense for a line that's 80 characters wide" do
+    inspect_source(cop, ['#' * 80])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.offenses.first.message).to eq('Line is too long. [80/79]')
+    expect(cop.config_to_allow_offenses).to eq('Max' => 80)
+  end
+
+  it "accepts a line that's 79 characters wide" do
+    inspect_source(cop, ['#' * 79])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/method_call_parentheses_spec.rb b/spec/rubocop/cop/style/method_call_parentheses_spec.rb
new file mode 100644
index 0000000..c451f18
--- /dev/null
+++ b/spec/rubocop/cop/style/method_call_parentheses_spec.rb
@@ -0,0 +1,59 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::MethodCallParentheses, :config do
+  subject(:cop) { described_class.new(config) }
+  let(:config) do
+    Rubocop::Config.new('EmptyLiteral' => { 'Enabled' => true })
+  end
+
+  it 'registers an offense for parens in method call without args' do
+    inspect_source(cop, ['top.test()'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts parentheses for methods starting with an upcase letter' do
+    inspect_source(cop, ['Test()'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts no parens in method call without args' do
+    inspect_source(cop, ['top.test'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts parens in method call with args' do
+    inspect_source(cop, ['top.test(a)'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'auto-corrects by removing unneeded braces' do
+    new_source = autocorrect_source(cop, 'test()')
+    expect(new_source).to eq('test')
+  end
+
+  it 'does not auto-correct calls that will be changed to empty literals' do
+    original = ['Hash.new()',
+                'Array.new()',
+                'String.new()']
+    new_source = autocorrect_source(cop, original)
+    expect(new_source).to eq(original.join("\n"))
+  end
+
+  context 'when EmptyLiteral is disabled' do
+    let(:config) do
+      Rubocop::Config.new('EmptyLiteral' => { 'Enabled' => false })
+    end
+
+    it 'auto-corrects calls that could be empty literals' do
+      original = ['Hash.new()',
+                  'Array.new()',
+                  'String.new()']
+      new_source = autocorrect_source(cop, original)
+      expect(new_source).to eq(['Hash.new',
+                                'Array.new',
+                                'String.new'].join("\n"))
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/method_called_on_do_end_block_spec.rb b/spec/rubocop/cop/style/method_called_on_do_end_block_spec.rb
new file mode 100644
index 0000000..d9fa603
--- /dev/null
+++ b/spec/rubocop/cop/style/method_called_on_do_end_block_spec.rb
@@ -0,0 +1,60 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::MethodCalledOnDoEndBlock do
+  subject(:cop) { described_class.new }
+
+  context 'with a multi-line do..end block' do
+    it 'registers an offense for a chained call' do
+      inspect_source(cop, ['a do',
+                           '  b',
+                           'end.c'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.highlights).to eq(['end.c'])
+    end
+
+    it 'accepts it if there is no chained call' do
+      inspect_source(cop, ['a do',
+                           '  b',
+                           'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts a chained block' do
+      inspect_source(cop, ['a do',
+                           '  b',
+                           'end.c do',
+                           '  d',
+                           'end'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'with a single-line do..end block' do
+    it 'registers an offense for a chained call' do
+      inspect_source(cop, ['a do b end.c'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.highlights).to eq(['end.c'])
+    end
+
+    it 'accepts a single-line do..end block with a chained block' do
+      inspect_source(cop, ['a do b end.c do d end'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'with a {} block' do
+    it 'accepts a multi-line block with a chained call' do
+      inspect_source(cop, ['a {',
+                           '  b',
+                           '}.c'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts a single-line block with a chained call' do
+      inspect_source(cop, ['a { b }.c'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/method_def_parentheses_spec.rb b/spec/rubocop/cop/style/method_def_parentheses_spec.rb
new file mode 100644
index 0000000..eabd515
--- /dev/null
+++ b/spec/rubocop/cop/style/method_def_parentheses_spec.rb
@@ -0,0 +1,106 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::MethodDefParentheses, :config do
+  subject(:cop) { described_class.new(config) }
+
+  context 'require_parentheses' do
+    let(:cop_config) { { 'EnforcedStyle' => 'require_parentheses' } }
+
+    it 'reports an offense for def with parameters but no parens' do
+      src = ['def func a, b',
+             'end']
+      inspect_source(cop, src)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' =>
+                                                 'require_no_parentheses')
+    end
+
+    it 'reports an offense for correct + opposite' do
+      src = ['def func(a, b)',
+             'end',
+             'def func a, b',
+             'end']
+      inspect_source(cop, src)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'reports an offense for class def with parameters but no parens' do
+      src = ['def Test.func a, b',
+             'end']
+      inspect_source(cop, src)
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it 'accepts def with no args and no parens' do
+      src = ['def func',
+             'end']
+      inspect_source(cop, src)
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'auto-adds required parens for a def' do
+      new_source = autocorrect_source(cop, 'def test param; end')
+      expect(new_source).to eq('def test(param); end')
+    end
+
+    it 'auto-adds required parens for a defs' do
+      new_source = autocorrect_source(cop, 'def self.test param; end')
+      expect(new_source).to eq('def self.test(param); end')
+    end
+
+    it 'auto-adds required parens to argument lists on multiple lines' do
+      new_source = autocorrect_source(cop, ['def test one,', 'two', 'end'])
+      expect(new_source).to eq("def test(one,\ntwo)\nend")
+    end
+  end
+
+  context 'require_no_parentheses' do
+    let(:cop_config) { { 'EnforcedStyle' => 'require_no_parentheses' } }
+
+    it 'reports an offense for def with parameters with parens' do
+      src = ['def func(a, b)',
+             'end']
+      inspect_source(cop, src)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' =>
+                                                 'require_parentheses')
+    end
+
+    it 'reports an offense for opposite + correct' do
+      src = ['def func(a, b)',
+             'end',
+             'def func a, b',
+             'end']
+      inspect_source(cop, src)
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'reports an offense for class def with parameters with parens' do
+      src = ['def Test.func(a, b)',
+             'end']
+      inspect_source(cop, src)
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it 'reports an offense for def with no args and parens' do
+      src = ['def func()',
+             'end']
+      inspect_source(cop, src)
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it 'auto-removes the parens' do
+      new_source = autocorrect_source(cop, 'def test(param); end')
+      expect(new_source).to eq('def test param; end')
+    end
+
+    it 'auto-removes the parens for defs' do
+      new_source = autocorrect_source(cop, 'def self.test(param); end')
+      expect(new_source).to eq('def self.test param; end')
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/method_length_spec.rb b/spec/rubocop/cop/style/method_length_spec.rb
new file mode 100644
index 0000000..ddd9b64
--- /dev/null
+++ b/spec/rubocop/cop/style/method_length_spec.rb
@@ -0,0 +1,147 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::MethodLength, :config do
+  subject(:cop) { described_class.new(config) }
+  let(:cop_config) { { 'Max' => 5, 'CountComments' => false } }
+
+  it 'rejects a method with more than 5 lines' do
+    inspect_source(cop, ['def m()',
+                         '  a = 1',
+                         '  a = 2',
+                         '  a = 3',
+                         '  a = 4',
+                         '  a = 5',
+                         '  a = 6',
+                         'end'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.offenses.map(&:line).sort).to eq([1])
+    expect(cop.config_to_allow_offenses).to eq('Max' => 6)
+  end
+
+  it 'accepts a method with less than 5 lines' do
+    inspect_source(cop, ['def m()',
+                         '  a = 1',
+                         '  a = 2',
+                         '  a = 3',
+                         '  a = 4',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not count blank lines' do
+    inspect_source(cop, ['def m()',
+                         '  a = 1',
+                         '  a = 2',
+                         '  a = 3',
+                         '  a = 4',
+                         '',
+                         '',
+                         '  a = 7',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts empty methods' do
+    inspect_source(cop, ['def m()',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'is not fooled by one-liner methods, syntax #1' do
+    inspect_source(cop, ['def one_line; 10 end',
+                         'def self.m()',
+                         '  a = 1',
+                         '  a = 2',
+                         '  a = 4',
+                         '  a = 5',
+                         '  a = 6',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'is not fooled by one-liner methods, syntax #2' do
+    inspect_source(cop, ['def one_line(test) 10 end',
+                         'def self.m()',
+                         '  a = 1',
+                         '  a = 2',
+                         '  a = 4',
+                         '  a = 5',
+                         '  a = 6',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'checks class methods, syntax #1' do
+    inspect_source(cop, ['def self.m()',
+                         '  a = 1',
+                         '  a = 2',
+                         '  a = 3',
+                         '  a = 4',
+                         '  a = 5',
+                         '  a = 6',
+                         'end'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.offenses.map(&:line).sort).to eq([1])
+  end
+
+  it 'checks class methods, syntax #2' do
+    inspect_source(cop, ['class K',
+                         '  class << self',
+                         '    def m()',
+                         '      a = 1',
+                         '      a = 2',
+                         '      a = 3',
+                         '      a = 4',
+                         '      a = 5',
+                         '      a = 6',
+                         '    end',
+                         '  end',
+                         'end'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.offenses.map(&:line).sort).to eq([3])
+  end
+
+  it 'properly counts lines when method ends with block' do
+    inspect_source(cop, ['def m()',
+                         '  something do',
+                         '    a = 2',
+                         '    a = 3',
+                         '    a = 4',
+                         '    a = 5',
+                         '  end',
+                         'end'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.offenses.map(&:line).sort).to eq([1])
+  end
+
+  it 'does not count commented lines by default' do
+    inspect_source(cop, ['def m()',
+                         '  a = 1',
+                         '  #a = 2',
+                         '  a = 3',
+                         '  #a = 4',
+                         '  a = 5',
+                         '  a = 6',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  context 'when CountComments is enabled' do
+    before { cop_config['CountComments'] = true }
+
+    it 'also counts commented lines' do
+      inspect_source(cop, ['def m()',
+                           '  a = 1',
+                           '  #a = 2',
+                           '  a = 3',
+                           '  #a = 4',
+                           '  a = 5',
+                           '  a = 6',
+                           'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.map(&:line).sort).to eq([1])
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/method_name_spec.rb b/spec/rubocop/cop/style/method_name_spec.rb
new file mode 100644
index 0000000..96a8faa
--- /dev/null
+++ b/spec/rubocop/cop/style/method_name_spec.rb
@@ -0,0 +1,125 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::MethodName, :config do
+  subject(:cop) { described_class.new(config) }
+
+  shared_examples 'never accepted' do
+    it 'registers an offense for mixed snake case and camel case' do
+      inspect_source(cop, ['def visit_Arel_Nodes_SelectStatement',
+                           'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.highlights).to eq(['visit_Arel_Nodes_SelectStatement'])
+    end
+
+    it 'registers an offense for capitalized camel case' do
+      inspect_source(cop, ['def MyMethod',
+                           'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.highlights).to eq(['MyMethod'])
+    end
+  end
+
+  shared_examples 'always accepted' do
+    it 'accepts one line methods' do
+      inspect_source(cop, "def body; '' end")
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts operator definitions' do
+      inspect_source(cop, ['def +(other)',
+                           '  # ...',
+                           'end'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'when configured for snake_case' do
+    let(:cop_config) { { 'EnforcedStyle' => 'snake_case' } }
+
+    it 'registers an offense for camel case in instance method name' do
+      inspect_source(cop, ['def myMethod',
+                           '  # ...',
+                           'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.highlights).to eq(['myMethod'])
+      expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' =>
+                                                 'camelCase')
+    end
+
+    it 'registers an offense for opposite + correct' do
+      inspect_source(cop, ['def my_method',
+                           'end',
+                           'def myMethod',
+                           'end'])
+      expect(cop.highlights).to eq(['myMethod'])
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'registers an offense for camel case in singleton method name' do
+      inspect_source(cop, ['def self.myMethod',
+                           '  # ...',
+                           'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.highlights).to eq(['myMethod'])
+    end
+
+    it 'accepts snake case in names' do
+      inspect_source(cop, ['def my_method',
+                           'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    include_examples 'never accepted'
+    include_examples 'always accepted'
+  end
+
+  context 'when configured for camelCase' do
+    let(:cop_config) { { 'EnforcedStyle' => 'camelCase' } }
+
+    it 'accepts camel case in instance method name' do
+      inspect_source(cop, ['def myMethod',
+                           '  # ...',
+                           'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts camel case in singleton method name' do
+      inspect_source(cop, ['def self.myMethod',
+                           '  # ...',
+                           'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for snake case in names' do
+      inspect_source(cop, ['def my_method',
+                           'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.highlights).to eq(['my_method'])
+      expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' =>
+                                                 'snake_case')
+    end
+
+    it 'registers an offense for correct + opposite' do
+      inspect_source(cop, ['def my_method',
+                           'end',
+                           'def myMethod',
+                           'end'])
+      expect(cop.highlights).to eq(['my_method'])
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    include_examples 'always accepted'
+    include_examples 'never accepted'
+  end
+
+  context 'when configured with a bad value' do
+    let(:cop_config) { { 'EnforcedStyle' => 'other' } }
+
+    it 'fails' do
+      expect { inspect_source(cop, ['def a', 'end']) }
+        .to raise_error(RuntimeError)
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/module_function_spec.rb b/spec/rubocop/cop/style/module_function_spec.rb
new file mode 100644
index 0000000..2b8ab96
--- /dev/null
+++ b/spec/rubocop/cop/style/module_function_spec.rb
@@ -0,0 +1,24 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::ModuleFunction do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for extend self in module' do
+    inspect_source(cop,
+                   ['module Test',
+                    '  extend self',
+                    '  def test; end',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts extend self in class' do
+    inspect_source(cop,
+                   ['class Test',
+                    '  extend self',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/multiline_block_chain_spec.rb b/spec/rubocop/cop/style/multiline_block_chain_spec.rb
new file mode 100644
index 0000000..bedbc72
--- /dev/null
+++ b/spec/rubocop/cop/style/multiline_block_chain_spec.rb
@@ -0,0 +1,78 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::MultilineBlockChain do
+  subject(:cop) { described_class.new }
+
+  context 'with multi-line block chaining' do
+    it 'registers an offense for a simple case' do
+      inspect_source(cop, ['a do',
+                           '  b',
+                           'end.c do',
+                           '  d',
+                           'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.highlights).to eq(['end.c'])
+    end
+
+    it 'registers an offense for a slightly more complicated case' do
+      inspect_source(cop, ['a do',
+                           '  b',
+                           'end.c1.c2 do',
+                           '  d',
+                           'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.highlights).to eq(['end.c1.c2'])
+    end
+
+    it 'registers two offenses for a chain of three blocks' do
+      inspect_source(cop, ['a do',
+                           '  b',
+                           'end.c do',
+                           '  d',
+                           'end.e do',
+                           '  f',
+                           'end'])
+      expect(cop.offenses.size).to eq(2)
+      expect(cop.highlights).to eq(['end.c', 'end.e'])
+    end
+
+    it 'registers an offense for a chain where the second block is ' \
+       'single-line' do
+      inspect_source(cop, ['Thread.list.find_all { |t|',
+                           '  t.alive?',
+                           '}.map { |thread| thread.object_id }'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.highlights).to eq(['}.map'])
+    end
+
+    it 'accepts a chain where the first block is single-line' do
+      inspect_source(cop,
+                     ['Thread.list.find_all { |t| t.alive? }.map { |t| ',
+                      '  t.object_id',
+                      '}'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  it 'accepts a chain of blocks spanning one line' do
+    inspect_source(cop, ['a { b }.c { d }',
+                         'w do x end.y do z end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a multi-line block chained with calls on one line' do
+    inspect_source(cop, ['a do',
+                         '  b',
+                         'end.c.d'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a chain of calls followed by a multi-line block' do
+    inspect_source(cop, ['a1.a2.a3 do',
+                         '  b',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/multiline_if_then_spec.rb b/spec/rubocop/cop/style/multiline_if_then_spec.rb
new file mode 100644
index 0000000..a09cb28
--- /dev/null
+++ b/spec/rubocop/cop/style/multiline_if_then_spec.rb
@@ -0,0 +1,107 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::MultilineIfThen do
+  subject(:cop) { described_class.new }
+
+  # if
+
+  it 'registers an offense for then in multiline if' do
+    inspect_source(cop, ['if cond then',
+                         'end',
+                         "if cond then\t",
+                         'end',
+                         'if cond then  ',
+                         'end',
+                         'if cond',
+                         'then',
+                         'end',
+                         'if cond then # bad',
+                         'end'])
+    expect(cop.offenses.map(&:line)).to eq([1, 3, 5, 7, 10])
+  end
+
+  it 'accepts multiline if without then' do
+    inspect_source(cop, ['if cond',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts table style if/then/elsif/ends' do
+    inspect_source(cop,
+                   ['if    @io == $stdout then str << "$stdout"',
+                    'elsif @io == $stdin  then str << "$stdin"',
+                    'elsif @io == $stderr then str << "$stderr"',
+                    'else                      str << @io.class.to_s',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not get confused by a then in a when' do
+    inspect_source(cop,
+                   ['if a',
+                    '  case b',
+                    '  when c then',
+                    '  end',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not get confused by a commented-out then' do
+    inspect_source(cop,
+                   ['if a # then',
+                    '  b',
+                    'end',
+                    'if c # then',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not raise an error for an implicit match if' do
+    expect do
+      inspect_source(cop,
+                     ['if //',
+                      'end'])
+    end.not_to raise_error
+  end
+
+  # unless
+
+  it 'registers an offense for then in multiline unless' do
+    inspect_source(cop, ['unless cond then',
+                         'end'])
+    expect(cop.messages).to eq(
+      ['Never use `then` for multi-line `unless`.'])
+  end
+
+  it 'accepts multiline unless without then' do
+    inspect_source(cop, ['unless cond',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not get confused by a postfix unless' do
+    inspect_source(cop,
+                   ['two unless one'
+                   ])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not get confused by a nested postfix unless' do
+    inspect_source(cop,
+                   ['if two',
+                    '  puts 1',
+                    'end unless two'
+                   ])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not raise an error for an implicit match unless' do
+    expect do
+      inspect_source(cop,
+                     ['unless //',
+                      'end'])
+    end.not_to raise_error
+  end
+end
diff --git a/spec/rubocop/cop/style/multiline_ternary_operator_spec.rb b/spec/rubocop/cop/style/multiline_ternary_operator_spec.rb
new file mode 100644
index 0000000..62ac8d5
--- /dev/null
+++ b/spec/rubocop/cop/style/multiline_ternary_operator_spec.rb
@@ -0,0 +1,18 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::MultilineTernaryOperator do
+  subject(:cop) { described_class.new }
+
+  it 'registers offense for a multiline ternary operator expression' do
+    inspect_source(cop, ['a = cond ?',
+                         '  b : c'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts a single line ternary operator expression' do
+    inspect_source(cop, ['a = cond ? b : c'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/negated_if_spec.rb b/spec/rubocop/cop/style/negated_if_spec.rb
new file mode 100644
index 0000000..dfeb39c
--- /dev/null
+++ b/spec/rubocop/cop/style/negated_if_spec.rb
@@ -0,0 +1,98 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::NegatedIf do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for if with exclamation point condition' do
+    inspect_source(cop,
+                   ['if !a_condition',
+                    '  some_method',
+                    'end',
+                    'some_method if !a_condition'
+                   ])
+    expect(cop.messages).to eq(
+      ['Favor `unless` over `if` for negative ' \
+       'conditions.'] * 2)
+  end
+
+  it 'registers an offense for unless with exclamation point condition' do
+    inspect_source(cop,
+                   ['unless !a_condition',
+                    '  some_method',
+                    'end',
+                    'some_method unless !a_condition'
+                   ])
+    expect(cop.messages).to eq(['Favor `if` over `unless` for negative ' \
+                                'conditions.'] * 2)
+  end
+
+  it 'registers an offense for if with "not" condition' do
+    inspect_source(cop,
+                   ['if not a_condition',
+                    '  some_method',
+                    'end',
+                    'some_method if not a_condition'])
+    expect(cop.messages).to eq(
+      ['Favor `unless` over `if` for negative ' \
+       'conditions.'] * 2)
+    expect(cop.offenses.map(&:line)).to eq([1, 4])
+  end
+
+  it 'accepts an if/else with negative condition' do
+    inspect_source(cop,
+                   ['if !a_condition',
+                    '  some_method',
+                    'else',
+                    '  something_else',
+                    'end',
+                    'if not a_condition',
+                    '  some_method',
+                    'elsif other_condition',
+                    '  something_else',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts an if where only part of the contition is negated' do
+    inspect_source(cop,
+                   ['if !condition && another_condition',
+                    '  some_method',
+                    'end',
+                    'if not condition or another_condition',
+                    '  some_method',
+                    'end',
+                    'some_method if not condition or another_condition'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'is not confused by negated elsif' do
+    inspect_source(cop,
+                   ['if test.is_a?(String)',
+                    '  3',
+                    'elsif test.is_a?(Array)',
+                    '  2',
+                    'elsif !test.nil?',
+                    '  1',
+                    'end'])
+
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not blow up for ternary ops' do
+    inspect_source(cop, 'a ? b : c')
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'autocorrects by replacing if not with unless' do
+    corrected = autocorrect_source(cop, 'something if !x.even?')
+    expect(corrected).to eq 'something unless x.even?'
+  end
+
+  it 'autocorrects by replacing unless not with if' do
+    corrected = autocorrect_source(cop, 'something unless !x.even?')
+    expect(corrected).to eq 'something if x.even?'
+  end
+
+end
diff --git a/spec/rubocop/cop/style/negated_while_spec.rb b/spec/rubocop/cop/style/negated_while_spec.rb
new file mode 100644
index 0000000..5442363
--- /dev/null
+++ b/spec/rubocop/cop/style/negated_while_spec.rb
@@ -0,0 +1,62 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::NegatedWhile do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for while with exclamation point condition' do
+    inspect_source(cop,
+                   ['while !a_condition',
+                    '  some_method',
+                    'end',
+                    'some_method while !a_condition'
+                   ])
+    expect(cop.messages).to eq(
+      ['Favor `until` over `while` for negative conditions.'] * 2)
+  end
+
+  it 'registers an offense for until with exclamation point condition' do
+    inspect_source(cop,
+                   ['until !a_condition',
+                    '  some_method',
+                    'end',
+                    'some_method until !a_condition'
+                   ])
+    expect(cop.messages)
+      .to eq(['Favor `while` over `until` for negative conditions.'] * 2)
+  end
+
+  it 'registers an offense for while with "not" condition' do
+    inspect_source(cop,
+                   ['while (not a_condition)',
+                    '  some_method',
+                    'end',
+                    'some_method while not a_condition'])
+    expect(cop.messages).to eq(
+      ['Favor `until` over `while` for negative conditions.'] * 2)
+    expect(cop.offenses.map(&:line)).to eq([1, 4])
+  end
+
+  it 'accepts an while where only part of the contition is negated' do
+    inspect_source(cop,
+                   ['while !a_condition && another_condition',
+                    '  some_method',
+                    'end',
+                    'while not a_condition or another_condition',
+                    '  some_method',
+                    'end',
+                    'some_method while not a_condition or other_cond'])
+    expect(cop.messages).to be_empty
+  end
+
+  it 'autocorrects by replacing while not with until' do
+    corrected = autocorrect_source(cop, 'something while !x.even?')
+    expect(corrected).to eq 'something until x.even?'
+  end
+
+  it 'autocorrects by replacing until not with while' do
+    corrected = autocorrect_source(cop, 'something until !x.even?')
+    expect(corrected).to eq 'something while x.even?'
+  end
+end
diff --git a/spec/rubocop/cop/style/nested_ternary_operator_spec.rb b/spec/rubocop/cop/style/nested_ternary_operator_spec.rb
new file mode 100644
index 0000000..8c7f063
--- /dev/null
+++ b/spec/rubocop/cop/style/nested_ternary_operator_spec.rb
@@ -0,0 +1,21 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::NestedTernaryOperator do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for a nested ternary operator expression' do
+    inspect_source(cop, ['a ? (b ? b1 : b2) : a2'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts a non-nested ternary operator within an if' do
+    inspect_source(cop, ['a = if x',
+                         '  cond ? b : c',
+                         'else',
+                         '  d',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/nil_comparison_spec.rb b/spec/rubocop/cop/style/nil_comparison_spec.rb
new file mode 100644
index 0000000..1f4b938
--- /dev/null
+++ b/spec/rubocop/cop/style/nil_comparison_spec.rb
@@ -0,0 +1,29 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::NilComparison do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for == nil' do
+    inspect_source(cop, 'x == nil')
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.highlights).to eq(['=='])
+  end
+
+  it 'registers an offense for === nil' do
+    inspect_source(cop, 'x === nil')
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.highlights).to eq(['==='])
+  end
+
+  it 'autocorrects by replacing == nil with .nil?' do
+    corrected = autocorrect_source(cop, 'x == nil')
+    expect(corrected).to eq 'x.nil?'
+  end
+
+  it 'autocorrects by replacing === nil with .nil?' do
+    corrected = autocorrect_source(cop, 'x === nil')
+    expect(corrected).to eq 'x.nil?'
+  end
+end
diff --git a/spec/rubocop/cop/style/non_nil_check_spec.rb b/spec/rubocop/cop/style/non_nil_check_spec.rb
new file mode 100644
index 0000000..7bee833
--- /dev/null
+++ b/spec/rubocop/cop/style/non_nil_check_spec.rb
@@ -0,0 +1,70 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::NonNilCheck do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for != nil' do
+    inspect_source(cop, 'x != nil')
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.highlights).to eq(['!='])
+  end
+
+  it 'registers an offense for !x.nil?' do
+    inspect_source(cop, '!x.nil?')
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.highlights).to eq(['!x.nil?'])
+  end
+
+  it 'registers an offense for not x.nil?' do
+    inspect_source(cop, 'not x.nil?')
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.highlights).to eq(['not x.nil?'])
+  end
+
+  it 'does not register an offense if only expression in predicate' do
+    inspect_source(cop, ['def signed_in?',
+                         '  !current_user.nil?',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense if only expression in class predicate' do
+    inspect_source(cop, ['def Test.signed_in?',
+                         '  !current_user.nil?',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense if last expression in predicate' do
+    inspect_source(cop, ['def signed_in?',
+                         '  something',
+                         '  !current_user.nil?',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense if last expression in class predicate' do
+    inspect_source(cop, ['def Test.signed_in?',
+                         '  something',
+                         '  !current_user.nil?',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'autocorrects by removing != nil' do
+    corrected = autocorrect_source(cop, 'x != nil')
+    expect(corrected).to eq 'x'
+  end
+
+  it 'autocorrects by removing non-nil (!x.nil?) check' do
+    corrected = autocorrect_source(cop, '!x.nil?')
+    expect(corrected).to eq 'x'
+  end
+
+  it 'does not blow up when autocorrecting implicit receiver' do
+    corrected = autocorrect_source(cop, '!nil?')
+    expect(corrected).to eq 'self'
+  end
+end
diff --git a/spec/rubocop/cop/style/not_spec.rb b/spec/rubocop/cop/style/not_spec.rb
new file mode 100644
index 0000000..348157a
--- /dev/null
+++ b/spec/rubocop/cop/style/not_spec.rb
@@ -0,0 +1,28 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::Not do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for not' do
+    inspect_source(cop, 'not test')
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'does not register an offense for !' do
+    inspect_source(cop, '!test')
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'auto-corrects "not" with !' do
+    new_source = autocorrect_source(cop, 'x = 10 if not y')
+    expect(new_source).to eq('x = 10 if !y')
+  end
+
+  it 'leaves "not" as is if auto-correction changes the meaning' do
+    src = 'not x < y'
+    new_source = autocorrect_source(cop, src)
+    expect(new_source).to eq(src)
+  end
+end
diff --git a/spec/rubocop/cop/style/numeric_literals_spec.rb b/spec/rubocop/cop/style/numeric_literals_spec.rb
new file mode 100644
index 0000000..6622957
--- /dev/null
+++ b/spec/rubocop/cop/style/numeric_literals_spec.rb
@@ -0,0 +1,70 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::NumericLiterals, :config do
+  subject(:cop) { described_class.new(config) }
+  let(:cop_config) { { 'MinDigits' => 5 } }
+
+  it 'registers an offense for a long undelimited integer' do
+    inspect_source(cop, ['a = 12345'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.config_to_allow_offenses).to eq('MinDigits' => 6)
+  end
+
+  it 'registers an offense for a float with a long undelimited integer part' do
+    inspect_source(cop, ['a = 123456.789'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.config_to_allow_offenses).to eq('MinDigits' => 7)
+  end
+
+  it 'registers an offense for an integer with misplaced underscore' do
+    inspect_source(cop, ['a = 123_456_78_90_00'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+  end
+
+  it 'accepts long numbers with underscore' do
+    inspect_source(cop, ['a = 123_456',
+                         'b = 123_456.55'])
+    expect(cop.messages).to be_empty
+  end
+
+  it 'accepts a short integer without underscore' do
+    inspect_source(cop, ['a = 123'])
+    expect(cop.messages).to be_empty
+  end
+
+  it 'does not count a leading minus sign as a digit' do
+    inspect_source(cop, ['a = -1230'])
+    expect(cop.messages).to be_empty
+  end
+
+  it 'accepts short numbers without underscore' do
+    inspect_source(cop, ['a = 123',
+                         'b = 123.456'])
+    expect(cop.messages).to be_empty
+  end
+
+  it 'ignores non-decimal literals' do
+    inspect_source(cop, ['a = 0b1010101010101',
+                         'b = 01717171717171',
+                         'c = 0xab11111111bb'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'autocorrects a long integer offense' do
+    corrected = autocorrect_source(cop, ['a = 123456'])
+    expect(corrected).to eq 'a = 123_456'
+  end
+
+  it 'autocorrects an integer with misplaced underscore' do
+    corrected = autocorrect_source(cop, ['a = 123_456_78_90_00'])
+    expect(corrected).to eq 'a = 123_456_789_000'
+  end
+
+  it 'autocorrects negative numbers' do
+    corrected = autocorrect_source(cop, ['a = -123456'])
+    expect(corrected).to eq 'a = -123_456'
+  end
+end
diff --git a/spec/rubocop/cop/style/one_line_conditional_spec.rb b/spec/rubocop/cop/style/one_line_conditional_spec.rb
new file mode 100644
index 0000000..b5f2918
--- /dev/null
+++ b/spec/rubocop/cop/style/one_line_conditional_spec.rb
@@ -0,0 +1,13 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::OneLineConditional do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for one line if/then/end' do
+    inspect_source(cop, ['if cond then run else dont end'])
+    expect(cop.messages).to eq(['Favor the ternary operator (?:)' \
+                                ' over if/then/else/end constructs.'])
+  end
+end
diff --git a/spec/rubocop/cop/style/op_method_spec.rb b/spec/rubocop/cop/style/op_method_spec.rb
new file mode 100644
index 0000000..6734b87
--- /dev/null
+++ b/spec/rubocop/cop/style/op_method_spec.rb
@@ -0,0 +1,82 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::OpMethod do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for arg not named other' do
+    inspect_source(cop,
+                   ['def +(another)',
+                    '  another',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages)
+      .to eq(['When defining the `+` operator, name its argument `other`.'])
+  end
+
+  it 'works properly even if the argument not surrounded with braces' do
+    inspect_source(cop,
+                   ['def + another',
+                    '  another',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages)
+      .to eq(['When defining the `+` operator, name its argument `other`.'])
+  end
+
+  it 'does not register an offense for arg named other' do
+    inspect_source(cop,
+                   ['def +(other)',
+                    '  other',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense for arg named _other' do
+    inspect_source(cop,
+                   ['def <=>(_other)',
+                    '  0',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense for []' do
+    inspect_source(cop,
+                   ['def [](index)',
+                    '  other',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense for []=' do
+    inspect_source(cop,
+                   ['def []=(index, value)',
+                    '  other',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense for <<' do
+    inspect_source(cop,
+                   ['def <<(cop)',
+                    '  other',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense for non binary operators' do
+    inspect_source(cop,
+                   ['def -@', # Unary minus
+                    'end',
+                    '',
+                    # This + is not a unary operator. It can only be
+                    # called with dot notation.
+                    'def +',
+                    'end',
+                    '',
+                    'def *(a, b)', # Quite strange, but legal ruby.
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/parameter_lists_spec.rb b/spec/rubocop/cop/style/parameter_lists_spec.rb
new file mode 100644
index 0000000..cc21d5c
--- /dev/null
+++ b/spec/rubocop/cop/style/parameter_lists_spec.rb
@@ -0,0 +1,44 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::ParameterLists, :config do
+  subject(:cop) { described_class.new(config) }
+  let(:cop_config) do
+    {
+      'Max' => 4,
+      'CountKeywordArgs' => true
+    }
+  end
+
+  it 'registers an offense for a method def with 5 parameters' do
+    inspect_source(cop, ['def meth(a, b, c, d, e)',
+                         'end'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.config_to_allow_offenses).to eq('Max' => 5)
+  end
+
+  it 'accepts a method def with 4 parameters' do
+    inspect_source(cop, ['def meth(a, b, c, d)',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  context 'When CountKeywordArgs is true' do
+    it 'counts keyword arguments as well', ruby: 2.0 do
+      inspect_source(cop, ['def meth(a, b, c, d: 1, e: 2)',
+                           'end'])
+      expect(cop.offenses.size).to eq(1)
+    end
+  end
+
+  context 'When CountKeywordArgs is false' do
+    before { cop_config['CountKeywordArgs'] = false }
+
+    it 'it does not count keyword arguments', ruby: 2.0 do
+      inspect_source(cop, ['def meth(a, b, c, d: 1, e: 2)',
+                           'end'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/parentheses_around_condition_spec.rb b/spec/rubocop/cop/style/parentheses_around_condition_spec.rb
new file mode 100644
index 0000000..80b59e1
--- /dev/null
+++ b/spec/rubocop/cop/style/parentheses_around_condition_spec.rb
@@ -0,0 +1,123 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::ParenthesesAroundCondition, :config do
+  subject(:cop) { described_class.new(config) }
+  let(:cop_config) { { 'AllowSafeAssignment' => true } }
+
+  it 'registers an offense for parentheses around condition' do
+    inspect_source(cop, ['if (x > 10)',
+                         'elsif (x < 3)',
+                         'end',
+                         'unless (x > 10)',
+                         'end',
+                         'while (x > 10)',
+                         'end',
+                         'until (x > 10)',
+                         'end',
+                         'x += 1 if (x < 10)',
+                         'x += 1 unless (x < 10)',
+                         'x += 1 until (x < 10)',
+                         'x += 1 while (x < 10)'
+                        ])
+    expect(cop.offenses.size).to eq(9)
+    expect(cop.messages.first)
+      .to eq("Don't use parentheses around the condition of an `if`.")
+    expect(cop.messages.last)
+      .to eq("Don't use parentheses around the condition of a `while`.")
+  end
+
+  it 'accepts parentheses if there is no space between the keyword and (.' do
+    inspect_source(cop, ['if(x > 5) then something end',
+                         'do_something until(x > 5)'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'auto-corrects parentheses around condition' do
+    corrected = autocorrect_source(cop, ['if (x > 10)',
+                                         'elsif (x < 3)',
+                                         'end',
+                                         'unless (x > 10)',
+                                         'end',
+                                         'while (x > 10)',
+                                         'end',
+                                         'until (x > 10)',
+                                         'end',
+                                         'x += 1 if (x < 10)',
+                                         'x += 1 unless (x < 10)',
+                                         'x += 1 while (x < 10)',
+                                         'x += 1 until (x < 10)'
+                                        ])
+    expect(corrected).to eq ['if x > 10',
+                             'elsif x < 3',
+                             'end',
+                             'unless x > 10',
+                             'end',
+                             'while x > 10',
+                             'end',
+                             'until x > 10',
+                             'end',
+                             'x += 1 if x < 10',
+                             'x += 1 unless x < 10',
+                             'x += 1 while x < 10',
+                             'x += 1 until x < 10'
+                            ].join("\n")
+  end
+
+  it 'accepts condition without parentheses' do
+    inspect_source(cop, ['if x > 10',
+                         'end',
+                         'unless x > 10',
+                         'end',
+                         'while x > 10',
+                         'end',
+                         'until x > 10',
+                         'end',
+                         'x += 1 if x < 10',
+                         'x += 1 unless x < 10',
+                         'x += 1 while x < 10',
+                         'x += 1 until x < 10'
+                        ])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts parentheses around condition in a ternary' do
+    inspect_source(cop, '(a == 0) ? b : a')
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'is not confused by leading parenthesis in subexpression' do
+    inspect_source(cop, ['(a > b) && other ? one : two'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'is not confused by unbalanced parentheses' do
+    inspect_source(cop, ['if (a + b).c()',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  context 'safe assignment is allowed' do
+    it 'accepts = in condition surrounded with parentheses' do
+      inspect_source(cop,
+                     ['if (test = 10)',
+                      'end'
+                     ])
+      expect(cop.offenses).to be_empty
+    end
+
+  end
+
+  context 'safe assignment is not allowed' do
+    let(:cop_config) { { 'AllowSafeAssignment' => false } }
+
+    it 'does not accept = in condition surrounded with parentheses' do
+      inspect_source(cop,
+                     ['if (test = 10)',
+                      'end'
+                     ])
+      expect(cop.offenses.size).to eq(1)
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/percent_literal_delimiters_spec.rb b/spec/rubocop/cop/style/percent_literal_delimiters_spec.rb
new file mode 100644
index 0000000..370a21b
--- /dev/null
+++ b/spec/rubocop/cop/style/percent_literal_delimiters_spec.rb
@@ -0,0 +1,262 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::PercentLiteralDelimiters, :config do
+  subject(:cop) { described_class.new(config) }
+
+  let(:cop_config) do
+    {
+      'PreferredDelimiters' => {
+        '%'  => '[]',
+        '%i' => '[]',
+        '%q' => '[]',
+        '%Q' => '[]',
+        '%r' => '[]',
+        '%s' => '[]',
+        '%w' => '[]',
+        '%W' => '[]',
+        '%x' => '[]'
+      }
+    }
+  end
+
+  context '`%` interpolated string' do
+    it 'does not register an offense for preferred delimiters' do
+      inspect_source(cop, ['%[string]'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for other delimiters' do
+      inspect_source(cop, ['%(string)'])
+      expect(cop.messages).to eq([
+        '`%`-literals should be delimited by `[` and `]`'
+      ])
+    end
+
+    it 'does not register an offense for other delimiters ' \
+       'when containing preferred delimiter characters' do
+      inspect_source(cop, ['%([string])'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for other delimiters ' \
+       'when containing preferred delimiter characters in interpolation' do
+      inspect_source(cop, ['%(#{[1].first})'])
+      expect(cop.messages.size).to eq(1)
+    end
+  end
+
+  context '`%q` string' do
+    it 'does not register an offense for preferred delimiters' do
+      inspect_source(cop, ['%q[string]'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for other delimiters' do
+      inspect_source(cop, ['%q(string)'])
+      expect(cop.messages).to eq([
+        '`%q`-literals should be delimited by `[` and `]`'
+      ])
+    end
+
+    it 'does not register an offense for other delimiters ' \
+       'when containing preferred delimiter characters' do
+      inspect_source(cop, ['%q([string])'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context '`%Q` interpolated string' do
+    it 'does not register an offense for preferred delimiters' do
+      inspect_source(cop, ['%Q[string]'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for other delimiters' do
+      inspect_source(cop, ['%Q(string)'])
+      expect(cop.messages).to eq([
+        '`%Q`-literals should be delimited by `[` and `]`'
+      ])
+    end
+
+    it 'does not register an offense for other delimiters ' \
+       'when containing preferred delimiter characters' do
+      inspect_source(cop, ['%Q([string])'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for other delimiters ' \
+       'when containing preferred delimiter characters in interpolation' do
+      inspect_source(cop, ['%Q(#{[1].first})'])
+      expect(cop.messages.size).to eq(1)
+    end
+  end
+
+  context '`%w` string array' do
+    it 'does not register an offense for preferred delimiters' do
+      inspect_source(cop, ['%w[some words]'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for other delimiters' do
+      inspect_source(cop, ['%w(some words)'])
+      expect(cop.messages).to eq([
+        '`%w`-literals should be delimited by `[` and `]`'
+      ])
+    end
+
+    it 'does not register an offense for other delimiters ' \
+       'when containing preferred delimiter characters' do
+      inspect_source(cop, ['%w([some] [words])'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context '`%W` interpolated string array' do
+    it 'does not register an offense for preferred delimiters' do
+      inspect_source(cop, ['%W[some words]'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for other delimiters' do
+      inspect_source(cop, ['%W(some words)'])
+      expect(cop.messages).to eq([
+        '`%W`-literals should be delimited by `[` and `]`'
+      ])
+    end
+
+    it 'does not register an offense for other delimiters ' \
+       'when containing preferred delimiter characters' do
+      inspect_source(cop, ['%W([some] [words])'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for other delimiters ' \
+       'when containing preferred delimiter characters in interpolation' do
+      inspect_source(cop, ['%W(#{[1].first})'])
+      expect(cop.messages.size).to eq(1)
+    end
+  end
+
+  context '`%r` interpolated regular expression' do
+    it 'does not register an offense for preferred delimiters' do
+      inspect_source(cop, ['%r[regexp]'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for other delimiters' do
+      inspect_source(cop, ['%r(regexp)'])
+      expect(cop.messages).to eq([
+        '`%r`-literals should be delimited by `[` and `]`'
+      ])
+    end
+
+    it 'does not register an offense for other delimiters ' \
+       'when containing preferred delimiter characters' do
+      inspect_source(cop, ['%r([regexp])'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for other delimiters ' \
+       'when containing preferred delimiter characters in interpolation' do
+      inspect_source(cop, ['%r(#{[1].first})'])
+      expect(cop.messages.size).to eq(1)
+    end
+  end
+
+  context '`%i` symbol array', ruby: 2.0 do
+    it 'does not register an offense for preferred delimiters' do
+      inspect_source(cop, ['%i[some symbols]'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for other delimiters' do
+      inspect_source(cop, ['%i(some symbols)'])
+      expect(cop.messages).to eq([
+        '`%i`-literals should be delimited by `[` and `]`'
+      ])
+    end
+  end
+
+  context '`%s` symbol' do
+    it 'does not register an offense for preferred delimiters' do
+      inspect_source(cop, ['%s[symbol]'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for other delimiters' do
+      inspect_source(cop, ['%s(symbol)'])
+      expect(cop.messages).to eq([
+        '`%s`-literals should be delimited by `[` and `]`'
+      ])
+    end
+  end
+
+  context '`%x` interpolated system call' do
+    it 'does not register an offense for preferred delimiters' do
+      inspect_source(cop, ['%x[command]'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for other delimiters' do
+      inspect_source(cop, ['%x(command)'])
+      expect(cop.messages).to eq([
+        '`%x`-literals should be delimited by `[` and `]`'
+      ])
+    end
+
+    it 'does not register an offense for other delimiters ' \
+       'when containing preferred delimiter characters' do
+      inspect_source(cop, ['%x([command])'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for other delimiters ' \
+       'when containing preferred delimiter characters in interpolation' do
+      inspect_source(cop, ['%x(#{[1].first})'])
+      expect(cop.messages.size).to eq(1)
+    end
+  end
+
+  context 'auto-correct' do
+    it 'fixes a string' do
+      new_source = autocorrect_source(cop, '%(string)')
+      expect(new_source).to eq('%[string]')
+    end
+
+    it 'fixes a string array' do
+      new_source = autocorrect_source(cop, '%w(some words)')
+      expect(new_source).to eq('%w[some words]')
+    end
+
+    it 'fixes a regular expression' do
+      original_source = '%r(.*)'
+      new_source = autocorrect_source(cop, original_source)
+      expect(new_source).to eq('%r[.*]')
+    end
+
+    it 'fixes a string with interpolation' do
+      original_source = '%Q|#{with_interpolation}|'
+      new_source = autocorrect_source(cop, original_source)
+      expect(new_source).to eq('%Q[#{with_interpolation}]')
+    end
+
+    it 'fixes a regular expression with interpolation' do
+      original_source = '%r|#{with_interpolation}|'
+      new_source = autocorrect_source(cop, original_source)
+      expect(new_source).to eq('%r[#{with_interpolation}]')
+    end
+
+    it 'fixes a regular expression with option' do
+      original_source = '%r(.*)i'
+      new_source = autocorrect_source(cop, original_source)
+      expect(new_source).to eq('%r[.*]i')
+    end
+
+    it 'preserves line breaks when fixing a multiline array' do
+      new_source = autocorrect_source(cop, ['%w(', 'some', 'words', ')'])
+      expect(new_source).to eq("%w[\nsome\nwords\n]")
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/perl_backrefs_spec.rb b/spec/rubocop/cop/style/perl_backrefs_spec.rb
new file mode 100644
index 0000000..cde4c4a
--- /dev/null
+++ b/spec/rubocop/cop/style/perl_backrefs_spec.rb
@@ -0,0 +1,17 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::PerlBackrefs do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for $1' do
+    inspect_source(cop, ['puts $1'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'auto-corrects $1 to Regexp.last_match[1]' do
+    new_source = autocorrect_source(cop, '$1')
+    expect(new_source).to eq('Regexp.last_match[1]')
+  end
+end
diff --git a/spec/rubocop/cop/style/predicate_name_spec.rb b/spec/rubocop/cop/style/predicate_name_spec.rb
new file mode 100644
index 0000000..d64c10f
--- /dev/null
+++ b/spec/rubocop/cop/style/predicate_name_spec.rb
@@ -0,0 +1,26 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::PredicateName, :config do
+  subject(:cop) { described_class.new(config) }
+  let(:cop_config) { { 'NamePrefixBlacklist' => %w(has_ is_) } }
+
+  %w(has is).each do |prefix|
+    it 'registers an offense for blacklisted method_name' do
+      inspect_source(cop, ["def #{prefix}_attr",
+                           '  # ...',
+                           'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages).to eq(["Rename `#{prefix}_attr` to `attr?`."])
+      expect(cop.highlights).to eq(["#{prefix}_attr"])
+    end
+  end
+
+  it 'accepts non-blacklisted method name' do
+    inspect_source(cop, ['def have_attr',
+                         '  # ...',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/proc_spec.rb b/spec/rubocop/cop/style/proc_spec.rb
new file mode 100644
index 0000000..8935f73
--- /dev/null
+++ b/spec/rubocop/cop/style/proc_spec.rb
@@ -0,0 +1,27 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::Proc do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for a Proc.new call' do
+    inspect_source(cop, ['f = Proc.new { |x| puts x }'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts the proc method' do
+    inspect_source(cop, ['f = proc { |x| puts x }'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts the Proc.new call outside of block' do
+    inspect_source(cop, ['p = Proc.new'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'auto-corrects Proc.new to proc' do
+    corrected = autocorrect_source(cop, ['Proc.new { test }'])
+    expect(corrected).to eq 'proc { test }'
+  end
+end
diff --git a/spec/rubocop/cop/style/raise_args_spec.rb b/spec/rubocop/cop/style/raise_args_spec.rb
new file mode 100644
index 0000000..43bf271
--- /dev/null
+++ b/spec/rubocop/cop/style/raise_args_spec.rb
@@ -0,0 +1,87 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::RaiseArgs, :config do
+  subject(:cop) { described_class.new(config) }
+
+  context 'when enforced style is compact' do
+    let(:cop_config) { { 'EnforcedStyle' => 'compact' } }
+
+    it 'reports an offense for a raise with 2 args' do
+      inspect_source(cop, ['raise RuntimeError, msg'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'exploded')
+    end
+
+    it 'reports an offense for correct + opposite' do
+      inspect_source(cop, ['if a',
+                           '  raise RuntimeError, msg',
+                           'else',
+                           '  raise Ex.new(msg)',
+                           'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Provide an exception object as an argument to `raise`.'])
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'reports an offense for a raise with 3 args' do
+      inspect_source(cop, ['raise RuntimeError, msg, caller'])
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it 'accepts a raise with msg argument' do
+      inspect_source(cop, ['raise msg'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts a raise with an exception argument' do
+      inspect_source(cop, ['raise Ex.new(msg)'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'when enforced style is exploded' do
+    let(:cop_config) { { 'EnforcedStyle' => 'exploded' } }
+
+    it 'reports an offense for a raise with exception object' do
+      inspect_source(cop, ['raise Ex.new(msg)'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Provide an exception class and message ' \
+                'as arguments to `raise`.'])
+      expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'compact')
+    end
+
+    it 'reports an offense for opposite + correct' do
+      inspect_source(cop, ['if a',
+                           '  raise RuntimeError, msg',
+                           'else',
+                           '  raise Ex.new(msg)',
+                           'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'accepts exception constructor with more than 1 argument' do
+      inspect_source(cop, ['raise RuntimeError.new(a1, a2, a3)'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts a raise with 3 args' do
+      inspect_source(cop, ['raise RuntimeError, msg, caller'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts a raise with 2 args' do
+      inspect_source(cop, ['raise RuntimeError, msg'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts a raise with msg argument' do
+      inspect_source(cop, ['raise msg'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/redundant_begin_spec.rb b/spec/rubocop/cop/style/redundant_begin_spec.rb
new file mode 100644
index 0000000..9f9b18b
--- /dev/null
+++ b/spec/rubocop/cop/style/redundant_begin_spec.rb
@@ -0,0 +1,57 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::RedundantBegin do
+  subject(:cop) { described_class.new }
+
+  it 'reports an offense for def with redundant begin block' do
+    src = ['def func',
+           '  begin',
+           '    ala',
+           '  rescue => e',
+           '    bala',
+           '  end',
+           'end']
+    inspect_source(cop, src)
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'reports an offense for defs with redundant begin block' do
+    src = ['def Test.func',
+           '  begin',
+           '    ala',
+           '  rescue => e',
+           '    bala',
+           '  end',
+           'end']
+    inspect_source(cop, src)
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts a def with required begin block' do
+    src = ['def func',
+           '  begin',
+           '    ala',
+           '  rescue => e',
+           '    bala',
+           '  end',
+           '  something',
+           'end']
+    inspect_source(cop, src)
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a defs with required begin block' do
+    src = ['def Test.func',
+           '  begin',
+           '    ala',
+           '  rescue => e',
+           '    bala',
+           '  end',
+           '  something',
+           'end']
+    inspect_source(cop, src)
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/redundant_exception_spec.rb b/spec/rubocop/cop/style/redundant_exception_spec.rb
new file mode 100644
index 0000000..6d775b7
--- /dev/null
+++ b/spec/rubocop/cop/style/redundant_exception_spec.rb
@@ -0,0 +1,27 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::RedundantException do
+  subject(:cop) { described_class.new }
+
+  it 'reports an offense for a raise with RuntimeError' do
+    inspect_source(cop, ['raise RuntimeError, msg'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'reports an offense for a fail with RuntimeError' do
+    inspect_source(cop, ['fail RuntimeError, msg'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts a raise with RuntimeError if it does not have 2 args' do
+    inspect_source(cop, ['raise RuntimeError, msg, caller'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a fail with RuntimeError if it does not have 2 args' do
+    inspect_source(cop, ['fail RuntimeError, msg, caller'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/redundant_return_spec.rb b/spec/rubocop/cop/style/redundant_return_spec.rb
new file mode 100644
index 0000000..d9eb34d
--- /dev/null
+++ b/spec/rubocop/cop/style/redundant_return_spec.rb
@@ -0,0 +1,171 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::RedundantReturn, :config do
+  subject(:cop) { described_class.new(config) }
+  let(:cop_config) { { 'AllowMultipleReturnValues' => false } }
+
+  it 'reports an offense for def with only a return' do
+    src = ['def func',
+           '  return something',
+           'end']
+    inspect_source(cop, src)
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'reports an offense for defs with only a return' do
+    src = ['def Test.func',
+           '  return something',
+           'end']
+    inspect_source(cop, src)
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'reports an offense for def ending with return' do
+    src = ['def func',
+           '  one',
+           '  two',
+           '  return something',
+           'end']
+    inspect_source(cop, src)
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'reports an offense for defs ending with return' do
+    src = ['def func',
+           '  one',
+           '  two',
+           '  return something',
+           'end']
+    inspect_source(cop, src)
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts return in a non-final position' do
+    src = ['def func',
+           '  return something if something_else',
+           'end']
+    inspect_source(cop, src)
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not blow up on empty method body' do
+    src = ['def func',
+           'end']
+    inspect_source(cop, src)
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'auto-corrects by removing redundant returns' do
+    src = ['def func',
+           '  one',
+           '  two',
+           '  return something',
+           'end'].join("\n")
+    result_src = ['def func',
+                  '  one',
+                  '  two',
+                  '  something',
+                  'end'].join("\n")
+    new_source = autocorrect_source(cop, src)
+    expect(new_source).to eq(result_src)
+  end
+
+  context 'when multi-value returns are not allowed' do
+    it 'reports an offense for def with only a return' do
+      src = ['def func',
+             '  return something, test',
+             'end']
+      inspect_source(cop, src)
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it 'reports an offense for defs with only a return' do
+      src = ['def Test.func',
+             '  return something, test',
+             'end']
+      inspect_source(cop, src)
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it 'reports an offense for def ending with return' do
+      src = ['def func',
+             '  one',
+             '  two',
+             '  return something, test',
+             'end']
+      inspect_source(cop, src)
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it 'reports an offense for defs ending with return' do
+      src = ['def func',
+             '  one',
+             '  two',
+             '  return something, test',
+             'end']
+      inspect_source(cop, src)
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it 'auto-corrects by making implicit arrays explicit' do
+      src = ['def func',
+             '  return  1, 2',
+             'end'].join("\n")
+      result_src = ['def func',
+                    '  [1, 2]', # Just 1, 2 is not valid Ruby.
+                    'end'].join("\n")
+      new_source = autocorrect_source(cop, src)
+      expect(new_source).to eq(result_src)
+    end
+  end
+
+  context 'when multi-value returns are allowed' do
+    let(:cop_config) { { 'AllowMultipleReturnValues' => true } }
+
+    it 'accepts def with only a return' do
+      src = ['def func',
+             '  return something, test',
+             'end']
+      inspect_source(cop, src)
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts defs with only a return' do
+      src = ['def Test.func',
+             '  return something, test',
+             'end']
+      inspect_source(cop, src)
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts def ending with return' do
+      src = ['def func',
+             '  one',
+             '  two',
+             '  return something, test',
+             'end']
+      inspect_source(cop, src)
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts defs ending with return' do
+      src = ['def func',
+             '  one',
+             '  two',
+             '  return something, test',
+             'end']
+      inspect_source(cop, src)
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'does not auto-correct' do
+      src = ['def func',
+             '  return  1, 2',
+             'end'].join("\n")
+      new_source = autocorrect_source(cop, src)
+      expect(new_source).to eq(src)
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/redundant_self_spec.rb b/spec/rubocop/cop/style/redundant_self_spec.rb
new file mode 100644
index 0000000..00fb4f3
--- /dev/null
+++ b/spec/rubocop/cop/style/redundant_self_spec.rb
@@ -0,0 +1,142 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::RedundantSelf do
+  subject(:cop) { described_class.new }
+
+  it 'reports an offense a self receiver on an rvalue' do
+    src = ['a = self.b']
+    inspect_source(cop, src)
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts a self receiver on an lvalue of an assignment' do
+    src = ['self.a = b']
+    inspect_source(cop, src)
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a self receiver on an lvalue of an or-assignment' do
+    src = ['self.logger ||= Rails.logger']
+    inspect_source(cop, src)
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a self receiver on an lvalue of an and-assignment' do
+    src = ['self.flag &&= value']
+    inspect_source(cop, src)
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a self receiver on an lvalue of a plus-assignment' do
+    src = ['self.sum += 10']
+    inspect_source(cop, src)
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a self receiver with the square bracket operator' do
+    src = ['self[a]']
+    inspect_source(cop, src)
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a self receiver with the double less-than operator' do
+    src = ['self << a']
+    inspect_source(cop, src)
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a self receiver for methods named like ruby keywords' do
+    src = ['a = self.class',
+           'self.for(deps, [], true)',
+           'self.and(other)',
+           'self.or(other)',
+           'self.alias',
+           'self.begin',
+           'self.break',
+           'self.case',
+           'self.def',
+           'self.defined',
+           'self.do',
+           'self.else',
+           'self.elsif',
+           'self.end',
+           'self.ensure',
+           'self.false',
+           'self.if',
+           'self.in',
+           'self.module',
+           'self.next',
+           'self.nil',
+           'self.not',
+           'self.redo',
+           'self.rescue',
+           'self.retry',
+           'self.return',
+           'self.self',
+           'self.super',
+           'self.then',
+           'self.true',
+           'self.undef',
+           'self.unless',
+           'self.until',
+           'self.when',
+           'self.while',
+           'self.yield'
+          ]
+    inspect_source(cop, src)
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a self receiver used to distinguish from blockarg' do
+    src = ['def requested_specs(&groups)',
+           '  some_method(self.groups)',
+           'end'
+          ]
+    inspect_source(cop, src)
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a self receiver used to distinguish from argument' do
+    src = ['def requested_specs(groups)',
+           '  some_method(self.groups)',
+           'end'
+          ]
+    inspect_source(cop, src)
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a self receiver used to distinguish from argument' do
+    src = ['def requested_specs(final = true)',
+           '  something if self.final != final',
+           'end'
+          ]
+    inspect_source(cop, src)
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a self receiver used to distinguish from local variable' do
+    src = ['def requested_specs',
+           '  @requested_specs ||= begin',
+           '    groups = self.groups - Bundler.settings.without',
+           '    groups.map! { |g| g.to_sym }',
+           '    specs_for(groups)',
+           '  end',
+           'end'
+          ]
+    inspect_source(cop, src)
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a self receiver used to distinguish from constant' do
+    src = ['self.Foo']
+    inspect_source(cop, src)
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'auto-corrects by removing redundant self' do
+    new_source = autocorrect_source(cop, ['self.x'])
+    expect(new_source).to eq('x')
+  end
+end
diff --git a/spec/rubocop/cop/style/regexp_literal_spec.rb b/spec/rubocop/cop/style/regexp_literal_spec.rb
new file mode 100644
index 0000000..74b5d3e
--- /dev/null
+++ b/spec/rubocop/cop/style/regexp_literal_spec.rb
@@ -0,0 +1,104 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::RegexpLiteral, :config do
+  subject(:cop) { described_class.new(config) }
+
+  context 'when MaxSlashes is -1' do
+    let(:cop_config) { { 'MaxSlashes' => -1 } }
+
+    it 'fails' do
+      expect { inspect_source(cop, ['x =~ /home/']) }
+        .to raise_error(RuntimeError)
+    end
+  end
+
+  context 'when MaxSlashes is 0' do
+    let(:cop_config) { { 'MaxSlashes' => 0 } }
+
+    it 'registers an offense for one slash in // regexp' do
+      inspect_source(cop, ['x =~ /home\//'])
+      expect(cop.messages)
+        .to eq(['Use %r for regular expressions matching more ' \
+                "than 0 '/' characters."])
+      expect(cop.config_to_allow_offenses).to eq('MaxSlashes' => 1)
+    end
+
+    it 'accepts zero slashes in // regexp' do
+      inspect_source(cop, ['z =~ /a/'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for zero slashes in %r regexp' do
+      inspect_source(cop, ['y =~ %r(etc)'])
+      expect(cop.messages)
+        .to eq(['Use %r only for regular expressions matching more ' \
+                "than 0 '/' characters."])
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'accepts %r regexp with one slash' do
+      inspect_source(cop, ['x =~ %r(/home)'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'when MaxSlashes is 1' do
+    let(:cop_config) { { 'MaxSlashes' => 1 } }
+
+    it 'registers an offense for two slashes in // regexp' do
+      inspect_source(cop, ['x =~ /home\/\//',
+                           'y =~ /etc\/top\//'])
+      expect(cop.messages)
+        .to eq(['Use %r for regular expressions matching more ' \
+                "than 1 '/' character."] * 2)
+      expect(cop.config_to_allow_offenses).to eq('MaxSlashes' => 2)
+    end
+
+    it 'registers offenses for slashes with too many and %r with too few' do
+      inspect_source(cop, ['x =~ /home\/\//',
+                           'y =~ %r{home}'])
+      expect(cop.messages)
+        .to eq(['Use %r for regular expressions matching more ' \
+                "than 1 '/' character.",
+                'Use %r only for regular expressions matching more ' \
+                "than 1 '/' character."])
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'registers offenses for %r with too few and slashes with too many' do
+      inspect_source(cop, ['y =~ %r{home}',
+                           'x =~ /home\/\//'])
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'accepts zero or one slash in // regexp' do
+      inspect_source(cop, ['x =~ /\/home/',
+                           'y =~ /\//',
+                           'w =~ /\//m',
+                           'z =~ /a/'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'ignores slashes do not belong // regexp' do
+      inspect_source(cop, ['x =~ /\s{#{x[/\s+/].length}}/'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for zero or one slash in %r regexp' do
+      inspect_source(cop, ['x =~ %r(/home)',
+                           'y =~ %r(etc)'])
+      expect(cop.messages)
+        .to eq(['Use %r only for regular expressions matching more ' \
+                "than 1 '/' character."] * 2)
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'accepts %r regexp with two or more slashes' do
+      inspect_source(cop, ['x =~ %r(/home/)',
+                           'y =~ %r(/////)'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/rescue_modifier_spec.rb b/spec/rubocop/cop/style/rescue_modifier_spec.rb
new file mode 100644
index 0000000..477cf48
--- /dev/null
+++ b/spec/rubocop/cop/style/rescue_modifier_spec.rb
@@ -0,0 +1,116 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::RescueModifier do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for modifier rescue' do
+    inspect_source(cop,
+                   ['method rescue handle'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages)
+      .to eq(['Avoid using `rescue` in its modifier form.'])
+  end
+
+  it 'handles more complex expression with modifier rescue' do
+    inspect_source(cop,
+                   ['method1 or method2 rescue handle'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages)
+      .to eq(['Avoid using `rescue` in its modifier form.'])
+  end
+
+  it 'handles modifier rescue in normal rescue' do
+    inspect_source(cop,
+                   ['begin',
+                    '  test rescue modifier_handle',
+                    'rescue',
+                    '  normal_handle',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.offenses.first.line).to eq(2)
+  end
+
+  it 'does not register an offense for normal rescue' do
+    inspect_source(cop,
+                   ['begin',
+                    '  test',
+                    'rescue',
+                    '  handle',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense for normal rescue with ensure' do
+    inspect_source(cop,
+                   ['begin',
+                    '  test',
+                    'rescue',
+                    '  handle',
+                    'ensure',
+                    '  cleanup',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense for nested normal rescue' do
+    inspect_source(cop,
+                   ['begin',
+                    '  begin',
+                    '    test',
+                    '  rescue',
+                    '    handle_inner',
+                    '  end',
+                    'rescue',
+                    '  handle_outer',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  context 'when an instance method has implicit begin' do
+    it 'accepts normal rescue' do
+      inspect_source(cop,
+                     ['def some_method',
+                      '  test',
+                      'rescue',
+                      '  handle',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'handles modifier rescue in body of implicit begin' do
+      inspect_source(cop,
+                     ['def some_method',
+                      '  test rescue modifier_handle',
+                      'rescue',
+                      '  normal_handle',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.line).to eq(2)
+    end
+  end
+
+  context 'when a singleton method has implicit begin' do
+    it 'accepts normal rescue' do
+      inspect_source(cop,
+                     ['def self.some_method',
+                      '  test',
+                      'rescue',
+                      '  handle',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'handles modifier rescue in body of implicit begin' do
+      inspect_source(cop,
+                     ['def self.some_method',
+                      '  test rescue modifier_handle',
+                      'rescue',
+                      '  normal_handle',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses.first.line).to eq(2)
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/self_assignment_spec.rb b/spec/rubocop/cop/style/self_assignment_spec.rb
new file mode 100644
index 0000000..27af01a
--- /dev/null
+++ b/spec/rubocop/cop/style/self_assignment_spec.rb
@@ -0,0 +1,43 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::SelfAssignment do
+  subject(:cop) { described_class.new }
+
+  described_class::OPS.product(['x', '@x', '@@x']).each do |op, var|
+    it "registers an offense for non-shorthand assignment #{op} and #{var}" do
+      inspect_source(cop,
+                     ["#{var} = #{var} #{op} y"])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(["Use self-assignment shorthand `#{op}=`."])
+    end
+
+    it "accepts shorthand assignment for #{op} and #{var}" do
+      inspect_source(cop,
+                     ["#{var} = #{var} #{op} y"])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(["Use self-assignment shorthand `#{op}=`."])
+    end
+  end
+
+  ['||', '&&'].product(['x', '@x', '@@x']).each do |op, var|
+    it "registers an offense for non-shorthand assignment #{op} and #{var}" do
+      inspect_source(cop,
+                     ["#{var} = #{var} #{op} y"])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(["Use self-assignment shorthand `#{op}=`."])
+    end
+
+    it "accepts shorthand assignment for #{op} and #{var}" do
+      inspect_source(cop,
+                     ["#{var} = #{var} #{op} y"])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(["Use self-assignment shorthand `#{op}=`."])
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/semicolon_spec.rb b/spec/rubocop/cop/style/semicolon_spec.rb
new file mode 100644
index 0000000..c26dd9f
--- /dev/null
+++ b/spec/rubocop/cop/style/semicolon_spec.rb
@@ -0,0 +1,114 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::Semicolon, :config do
+  subject(:cop) { described_class.new(config) }
+  let(:cop_config) { { 'AllowAsExpressionSeparator' => false } }
+
+  it 'registers an offense for a single expression' do
+    inspect_source(cop,
+                   ['puts "this is a test";'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for several expressions' do
+    inspect_source(cop,
+                   ['puts "this is a test"; puts "So is this"'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for one line method with two statements' do
+    inspect_source(cop,
+                   ['def foo(a) x(1); y(2); z(3); end'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts semicolon before end if so configured' do
+    inspect_source(cop,
+                   ['def foo(a) z(3); end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts semicolon after params if so configured' do
+    inspect_source(cop,
+                   ['def foo(a); z(3) end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts one line method definitions' do
+    inspect_source(cop,
+                   ['def foo1; x(3) end',
+                    'def initialize(*_); end',
+                    'def foo2() x(3); end',
+                    'def foo3; x(3); end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts one line empty class definitions' do
+    inspect_source(cop,
+                   ['# Prefer a single-line format for class ...',
+                    'class Foo < Exception; end',
+                    '',
+                    'class Bar; end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts one line empty method definitions' do
+    inspect_source(cop,
+                   ['# One exception to the rule are empty-body methods',
+                    'def no_op; end',
+                    '',
+                    'def foo; end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts one line empty module definitions' do
+    inspect_source(cop,
+                   ['module Foo; end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'registers an offense for semicolon at the end no matter what' do
+    inspect_source(cop,
+                   ['module Foo; end;'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accept semicolons inside strings' do
+    inspect_source(cop,
+                   ['string = ";',
+                    'multi-line string"'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'auto-corrects semicolons when syntactically possible' do
+    corrected =
+      autocorrect_source(cop,
+                         ['module Foo; end;',
+                          'puts "this is a test";',
+                          'puts "this is a test"; puts "So is this"',
+                          'def foo(a) x(1); y(2); z(3); end'])
+    expect(corrected)
+      .to eq(['module Foo; end',
+              'puts "this is a test"',
+              'puts "this is a test"; puts "So is this"',
+              'def foo(a) x(1); y(2); z(3); end'].join("\n"))
+  end
+
+  context 'when AllowAsExpressionSeparator is true' do
+    let(:cop_config) { { 'AllowAsExpressionSeparator' => true } }
+
+    it 'accepts several expressions' do
+      inspect_source(cop,
+                     ['puts "this is a test"; puts "So is this"'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts one line method with two statements' do
+      inspect_source(cop,
+                     ['def foo(a) x(1); y(2); z(3); end'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/signal_exception_spec.rb b/spec/rubocop/cop/style/signal_exception_spec.rb
new file mode 100644
index 0000000..313bb68
--- /dev/null
+++ b/spec/rubocop/cop/style/signal_exception_spec.rb
@@ -0,0 +1,290 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::SignalException, :config do
+  subject(:cop) { described_class.new(config) }
+
+  context 'when enforced style is `semantic`' do
+    let(:cop_config) { { 'EnforcedStyle' => 'semantic' } }
+
+    it 'registers an offense for raise in begin section' do
+      inspect_source(cop,
+                     ['begin',
+                      '  raise',
+                      'rescue Exception',
+                      '  #do nothing',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Use `fail` instead of `raise` to signal exceptions.'])
+    end
+
+    it 'registers an offense for raise in def body' do
+      inspect_source(cop,
+                     ['def test',
+                      '  raise',
+                      'rescue Exception',
+                      '  #do nothing',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Use `fail` instead of `raise` to signal exceptions.'])
+    end
+
+    it 'registers an offense for fail in rescue section' do
+      inspect_source(cop,
+                     ['begin',
+                      '  fail',
+                      'rescue Exception',
+                      '  fail',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Use `raise` instead of `fail` to rethrow exceptions.'])
+    end
+
+    it 'accepts raise in rescue section' do
+      inspect_source(cop,
+                     ['begin',
+                      '  fail',
+                      'rescue Exception',
+                      '  raise RuntimeError',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts raise in def with multiple rescues' do
+      inspect_source(cop,
+                     ['def test',
+                      '  fail',
+                      'rescue StandardError',
+                      '  # handle error',
+                      'rescue Exception',
+                      '  raise',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for fail in def rescue section' do
+      inspect_source(cop,
+                     ['def test',
+                      '  fail',
+                      'rescue Exception',
+                      '  fail',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Use `raise` instead of `fail` to rethrow exceptions.'])
+    end
+
+    it 'registers an offense for fail in second rescue' do
+      inspect_source(cop,
+                     ['def test',
+                      '  fail',
+                      'rescue StandardError',
+                      '  # handle error',
+                      'rescue Exception',
+                      '  fail',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it 'registers only offense for one raise that should be fail' do
+      # This is a special case that has caused double reporting.
+      inspect_source(cop,
+                     ['map do',
+                      "  raise 'I'",
+                      'end.flatten.compact'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Use `fail` instead of `raise` to signal exceptions.'])
+    end
+
+    it 'accepts raise in def rescue section' do
+      inspect_source(cop,
+                     ['def test',
+                      '  fail',
+                      'rescue Exception',
+                      '  raise',
+                      'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'registers an offense for raise not in a begin/rescue/end' do
+      inspect_source(cop,
+                     ["case cop_config['EnforcedStyle']",
+                      "when 'single_quotes' then true",
+                      "when 'double_quotes' then false",
+                      "else raise 'Unknown StringLiterals style'",
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Use `fail` instead of `raise` to signal exceptions.'])
+    end
+
+    it 'registers one offense for each raise' do
+      inspect_source(cop,
+                     ['cop.stub(:on_def) { raise RuntimeError }',
+                      'cop.stub(:on_def) { raise RuntimeError }'])
+      expect(cop.offenses.size).to eq(2)
+      expect(cop.messages)
+        .to eq(['Use `fail` instead of `raise` to signal exceptions.'] * 2)
+    end
+
+    it 'is not confused by nested begin/rescue' do
+      inspect_source(cop,
+                     ['begin',
+                      '  raise',
+                      '  begin',
+                      '    raise',
+                      '  rescue',
+                      '    fail',
+                      '  end',
+                      'rescue Exception',
+                      '  #do nothing',
+                      'end'])
+      expect(cop.offenses.size).to eq(3)
+      expect(cop.messages)
+        .to eq(['Use `fail` instead of `raise` to signal exceptions.'] * 2 +
+               ['Use `raise` instead of `fail` to rethrow exceptions.'])
+    end
+
+    it 'auto-corrects raise to fail when appropriate' do
+      new_source = autocorrect_source(cop,
+                                      ['begin',
+                                       '  raise',
+                                       'rescue Exception',
+                                       '  raise',
+                                       'end'])
+      expect(new_source).to eq(['begin',
+                                '  fail',
+                                'rescue Exception',
+                                '  raise',
+                                'end'].join("\n"))
+    end
+
+    it 'auto-corrects fail to raise when appropriate' do
+      new_source = autocorrect_source(cop,
+                                      ['begin',
+                                       '  fail',
+                                       'rescue Exception',
+                                       '  fail',
+                                       'end'])
+      expect(new_source).to eq(['begin',
+                                '  fail',
+                                'rescue Exception',
+                                '  raise',
+                                'end'].join("\n"))
+    end
+  end
+
+  context 'when enforced style is `raise`' do
+    let(:cop_config) { { 'EnforcedStyle' => 'only_raise' } }
+
+    it 'registers an offense for fail in begin section' do
+      inspect_source(cop,
+                     ['begin',
+                      '  fail',
+                      'rescue Exception',
+                      '  #do nothing',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Always use `raise` to signal exceptions.'])
+    end
+
+    it 'registers an offense for fail in def body' do
+      inspect_source(cop,
+                     ['def test',
+                      '  fail',
+                      'rescue Exception',
+                      '  #do nothing',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Always use `raise` to signal exceptions.'])
+    end
+
+    it 'registers an offense for fail in rescue section' do
+      inspect_source(cop,
+                     ['begin',
+                      '  raise',
+                      'rescue Exception',
+                      '  fail',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Always use `raise` to signal exceptions.'])
+    end
+
+    it 'auto-corrects fail to raise always' do
+      new_source = autocorrect_source(cop,
+                                      ['begin',
+                                       '  fail',
+                                       'rescue Exception',
+                                       '  fail',
+                                       'end'])
+      expect(new_source).to eq(['begin',
+                                '  raise',
+                                'rescue Exception',
+                                '  raise',
+                                'end'].join("\n"))
+    end
+
+  end
+
+  context 'when enforced style is `fail`' do
+    let(:cop_config) { { 'EnforcedStyle' => 'only_fail' } }
+
+    it 'registers an offense for raise in begin section' do
+      inspect_source(cop,
+                     ['begin',
+                      '  raise',
+                      'rescue Exception',
+                      '  #do nothing',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Always use `fail` to signal exceptions.'])
+    end
+
+    it 'registers an offense for raise in def body' do
+      inspect_source(cop,
+                     ['def test',
+                      '  raise',
+                      'rescue Exception',
+                      '  #do nothing',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Always use `fail` to signal exceptions.'])
+    end
+
+    it 'registers an offense for raise in rescue section' do
+      inspect_source(cop,
+                     ['begin',
+                      '  fail',
+                      'rescue Exception',
+                      '  raise',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.messages)
+        .to eq(['Always use `fail` to signal exceptions.'])
+    end
+
+    it 'auto-corrects raise to fail always' do
+      new_source = autocorrect_source(cop,
+                                      ['begin',
+                                       '  raise',
+                                       'rescue Exception',
+                                       '  raise',
+                                       'end'])
+      expect(new_source).to eq(['begin',
+                                '  fail',
+                                'rescue Exception',
+                                '  fail',
+                                'end'].join("\n"))
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/single_line_block_params_spec.rb b/spec/rubocop/cop/style/single_line_block_params_spec.rb
new file mode 100644
index 0000000..ab0a384
--- /dev/null
+++ b/spec/rubocop/cop/style/single_line_block_params_spec.rb
@@ -0,0 +1,70 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::SingleLineBlockParams, :config do
+  subject(:cop) { described_class.new(config) }
+  let(:cop_config) do
+    { 'Methods' =>
+      [{ 'reduce' => %w(a e) },
+       { 'test' => %w(x y) }]
+    }
+  end
+
+  it 'find wrong argument names in calls with different syntax' do
+    inspect_source(cop,
+                   ['def m',
+                    '  [0, 1].reduce { |c, d| c + d }',
+                    '  [0, 1].reduce{ |c, d| c + d }',
+                    '  [0, 1].reduce(5) { |c, d| c + d }',
+                    '  [0, 1].reduce(5){ |c, d| c + d }',
+                    '  [0, 1].reduce (5) { |c, d| c + d }',
+                    '  [0, 1].reduce(5) { |c, d| c + d }',
+                    '  ala.test { |x, z| bala }',
+                    'end'])
+    expect(cop.offenses.size).to eq(7)
+    expect(cop.offenses.map(&:line).sort).to eq((2..8).to_a)
+    expect(cop.messages.first)
+      .to eq('Name `reduce` block params `|a, e|`.')
+  end
+
+  it 'allows calls with proper argument names' do
+    inspect_source(cop,
+                   ['def m',
+                    '  [0, 1].reduce { |a, e| a + e }',
+                    '  [0, 1].reduce{ |a, e| a + e }',
+                    '  [0, 1].reduce(5) { |a, e| a + e }',
+                    '  [0, 1].reduce(5){ |a, e| a + e }',
+                    '  [0, 1].reduce (5) { |a, e| a + e }',
+                    '  [0, 1].reduce(5) { |a, e| a + e }',
+                    '  ala.test { |x, y| bala }',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'ignores do..end blocks' do
+    inspect_source(cop,
+                   ['def m',
+                    '  [0, 1].reduce do |c, d|',
+                    '    c + d',
+                    '  end',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'ignores :reduce symbols' do
+    inspect_source(cop,
+                   ['def m',
+                    '  call_method(:reduce) { |a, b| a + b}',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not report when destructuring is used' do
+    inspect_source(cop,
+                   ['def m',
+                    '  test.reduce { |a, (id, _)| a + id}',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/single_line_methods_spec.rb b/spec/rubocop/cop/style/single_line_methods_spec.rb
new file mode 100644
index 0000000..50748a8
--- /dev/null
+++ b/spec/rubocop/cop/style/single_line_methods_spec.rb
@@ -0,0 +1,90 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::SingleLineMethods, :config do
+  subject(:cop) { described_class.new(config) }
+  let(:cop_config) { { 'AllowIfMethodIsEmpty' => true } }
+
+  it 'registers an offense for a single-line method' do
+    inspect_source(cop,
+                   ['def some_method; body end',
+                    'def link_to(name, url); {:name => name}; end',
+                    'def @table.columns; super; end'])
+    expect(cop.messages).to eq(
+      ['Avoid single-line method definitions.'] * 3)
+  end
+
+  context 'when AllowIfMethodIsEmpty is disabled' do
+    let(:cop_config) { { 'AllowIfMethodIsEmpty' => false } }
+
+    it 'registers an offense for an empty method' do
+      inspect_source(cop, ['def no_op; end',
+                           'def self.resource_class=(klass); end',
+                           'def @table.columns; end'])
+      expect(cop.offenses.size).to eq(3)
+    end
+  end
+
+  context 'when AllowIfMethodIsEmpty is enabled' do
+    let(:cop_config) { { 'AllowIfMethodIsEmpty' => true } }
+
+    it 'accepts a single-line empty method' do
+      inspect_source(cop, ['def no_op; end',
+                           'def self.resource_class=(klass); end',
+                           'def @table.columns; end'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  it 'accepts a multi-line method' do
+    inspect_source(cop, ['def some_method',
+                         '  body',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not crash on an method with a capitalized name' do
+    inspect_source(cop, ['def NoSnakeCase',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'auto-corrects def with semicolon after method name' do
+    corrected = autocorrect_source(cop,
+                                   ['  def some_method; body end # Cmnt'])
+    expect(corrected).to eq ['  # Cmnt',
+                             '  def some_method; ',
+                             '    body ',
+                             '  end '].join("\n")
+  end
+
+  it 'auto-corrects defs with parentheses after method name' do
+    corrected = autocorrect_source(cop, ['  def self.some_method() body end'])
+    expect(corrected).to eq ['  def self.some_method() ',
+                             '    body ',
+                             '  end'].join("\n")
+  end
+
+  it 'auto-corrects def with argument in parentheses' do
+    corrected = autocorrect_source(cop, ['  def some_method(arg) body end'])
+    expect(corrected).to eq ['  def some_method(arg) ',
+                             '    body ',
+                             '  end'].join("\n")
+  end
+
+  it 'auto-corrects def with argument and no parentheses' do
+    corrected = autocorrect_source(cop, ['  def some_method arg; body end'])
+    expect(corrected).to eq ['  def some_method arg; ',
+                             '    body ',
+                             '  end'].join("\n")
+  end
+
+  it 'auto-corrects def with semicolon before end' do
+    corrected = autocorrect_source(cop, ['  def some_method; b1; b2; end'])
+    expect(corrected).to eq ['  def some_method; ',
+                             '    b1; ',
+                             '    b2; ',
+                             '  end'].join("\n")
+  end
+end
diff --git a/spec/rubocop/cop/style/single_space_before_first_arg_spec.rb b/spec/rubocop/cop/style/single_space_before_first_arg_spec.rb
new file mode 100644
index 0000000..6ba5db7
--- /dev/null
+++ b/spec/rubocop/cop/style/single_space_before_first_arg_spec.rb
@@ -0,0 +1,63 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::SingleSpaceBeforeFirstArg do
+  subject(:cop) { described_class.new }
+
+  context 'for method calls without parentheses' do
+    it 'registers an offense for method call with two spaces before the ' \
+       'first arg' do
+      inspect_source(cop, ['something  x',
+                           'a.something  y, z'])
+      expect(cop.messages)
+        .to eq(['Put one space between the method name and the first ' \
+                'argument.'] * 2)
+      expect(cop.highlights).to eq(['  ', '  '])
+    end
+
+    it 'auto-corrects extra space' do
+      new_source = autocorrect_source(cop, ['something  x',
+                                            'a.something   y, z'])
+      expect(new_source).to eq(['something x',
+                                'a.something y, z'].join("\n"))
+    end
+
+    it 'accepts a method call with one space before the first arg' do
+      inspect_source(cop, ['something x',
+                           'a.something y, z'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts + operator' do
+      inspect_source(cop, ['something +',
+                           '  x'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts setter call' do
+      inspect_source(cop, ['something.x =',
+                           '  y'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts multiple space containing line break' do
+      inspect_source(cop, ['something \\',
+                           '  x'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'for method calls with parentheses' do
+    it 'accepts a method call without space' do
+      inspect_source(cop, ['something(x)',
+                           'a.something(y, z)'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts a method call with space after the left parenthesis' do
+      inspect_source(cop, ['something(  x  )'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/space_after_colon_spec.rb b/spec/rubocop/cop/style/space_after_colon_spec.rb
new file mode 100644
index 0000000..926be61
--- /dev/null
+++ b/spec/rubocop/cop/style/space_after_colon_spec.rb
@@ -0,0 +1,38 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::SpaceAfterColon do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for colon without space after it' do
+    # TODO: There is double reporting of the last colon (also from
+    # SpaceAroundOperators).
+    inspect_source(cop, ['x = w ? {a:3}:4'])
+    expect(cop.messages).to eq(['Space missing after colon.'] * 2)
+    expect(cop.highlights).to eq([':'] * 2)
+  end
+
+  it 'accepts colons in symbols' do
+    inspect_source(cop, ['x = :a'])
+    expect(cop.messages).to be_empty
+  end
+
+  if RUBY_VERSION >= '2.1'
+    it 'accepts colons denoting required keyword argument' do
+      inspect_source(cop, ['def initialize(table:, nodes:)',
+                           'end'])
+      expect(cop.messages).to be_empty
+    end
+  end
+
+  it 'accepts colons in strings' do
+    inspect_source(cop, ["str << ':'"])
+    expect(cop.messages).to be_empty
+  end
+
+  it 'auto-corrects missing space' do
+    new_source = autocorrect_source(cop, 'x = w ? {a:3}:4')
+    expect(new_source).to eq('x = w ? {a: 3}: 4')
+  end
+end
diff --git a/spec/rubocop/cop/style/space_after_comma_spec.rb b/spec/rubocop/cop/style/space_after_comma_spec.rb
new file mode 100644
index 0000000..28af035
--- /dev/null
+++ b/spec/rubocop/cop/style/space_after_comma_spec.rb
@@ -0,0 +1,30 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::SpaceAfterComma do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for block argument commas without space' do
+    inspect_source(cop, ['each { |s,t| }'])
+    expect(cop.messages).to eq(
+      ['Space missing after comma.'])
+  end
+
+  it 'registers an offense for array index commas without space' do
+    inspect_source(cop, ['formats[0,1]'])
+    expect(cop.messages).to eq(
+      ['Space missing after comma.'])
+  end
+
+  it 'registers an offense for method call arg commas without space' do
+    inspect_source(cop, ['a(1,2)'])
+    expect(cop.messages).to eq(
+      ['Space missing after comma.'])
+  end
+
+  it 'auto-corrects missing space' do
+    new_source = autocorrect_source(cop, 'each { |s,t| a(1,formats[0,1])}')
+    expect(new_source).to eq('each { |s, t| a(1, formats[0, 1])}')
+  end
+end
diff --git a/spec/rubocop/cop/style/space_after_control_keyword_spec.rb b/spec/rubocop/cop/style/space_after_control_keyword_spec.rb
new file mode 100644
index 0000000..3115d35
--- /dev/null
+++ b/spec/rubocop/cop/style/space_after_control_keyword_spec.rb
@@ -0,0 +1,84 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::SpaceAfterControlKeyword do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for normal if' do
+    inspect_source(cop,
+                   ['if(test) then result end'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for modifier unless' do
+    inspect_source(cop, ['action unless(test)'])
+
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'does not get confused by keywords' do
+    inspect_source(cop, ['[:if, :unless].action'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not get confused by the ternary operator' do
+    inspect_source(cop, ['a ? b : c'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'registers an offense for if, elsif, and unless' do
+    inspect_source(cop,
+                   ['if(a)',
+                    'elsif(b)',
+                    '  unless(c)',
+                    '  end',
+                    'end'])
+    expect(cop.offenses.map(&:line)).to eq([1, 2, 3])
+  end
+
+  it 'registers an offense for case and when' do
+    inspect_source(cop,
+                   ['case(a)',
+                    'when(0) then 1',
+                    'end'])
+    expect(cop.offenses.map(&:line)).to eq([1, 2])
+  end
+
+  it 'registers an offense for while and until' do
+    inspect_source(cop,
+                   ['while(a)',
+                    '  b until(c)',
+                    'end'])
+    expect(cop.offenses.map(&:line)).to eq([1, 2])
+  end
+
+  it 'auto-corrects missing space' do
+    new_source = autocorrect_source(cop, ['if(test) then result end',
+                                          'action unless(test)',
+                                          'if(a)',
+                                          'elsif(b)',
+                                          '  unless(c)',
+                                          '  end',
+                                          'end',
+                                          'case(a)',
+                                          'when(0) then 1',
+                                          'end',
+                                          'while(a)',
+                                          '  b until(c)',
+                                          'end'])
+    expect(new_source).to eq(['if (test) then result end',
+                              'action unless (test)',
+                              'if (a)',
+                              'elsif (b)',
+                              '  unless (c)',
+                              '  end',
+                              'end',
+                              'case (a)',
+                              'when (0) then 1',
+                              'end',
+                              'while (a)',
+                              '  b until (c)',
+                              'end'].join("\n"))
+  end
+end
diff --git a/spec/rubocop/cop/style/space_after_method_name_spec.rb b/spec/rubocop/cop/style/space_after_method_name_spec.rb
new file mode 100644
index 0000000..9722c51
--- /dev/null
+++ b/spec/rubocop/cop/style/space_after_method_name_spec.rb
@@ -0,0 +1,70 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::SpaceAfterMethodName do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for def with space before the parenthesis' do
+    inspect_source(cop,
+                   ['def func (x)',
+                    '  a',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for defs with space before the parenthesis' do
+    inspect_source(cop,
+                   ['def self.func (x)',
+                    '  a',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts a def without arguments' do
+    inspect_source(cop,
+                   ['def func',
+                    '  a',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a defs without arguments' do
+    inspect_source(cop,
+                   ['def self.func',
+                    '  a',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a def with arguments but no parentheses' do
+    inspect_source(cop,
+                   ['def func x',
+                    '  a',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts a defs with arguments but no parentheses' do
+    inspect_source(cop,
+                   ['def self.func x',
+                    '  a',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'auto-corrects unwanted space' do
+    new_source = autocorrect_source(cop, ['def func (x)',
+                                          '  a',
+                                          'end',
+                                          'def self.func (x)',
+                                          '  a',
+                                          'end'])
+    expect(new_source).to eq(['def func(x)',
+                              '  a',
+                              'end',
+                              'def self.func(x)',
+                              '  a',
+                              'end'].join("\n"))
+  end
+end
diff --git a/spec/rubocop/cop/style/space_after_not_spec.rb b/spec/rubocop/cop/style/space_after_not_spec.rb
new file mode 100644
index 0000000..55e3a1c
--- /dev/null
+++ b/spec/rubocop/cop/style/space_after_not_spec.rb
@@ -0,0 +1,22 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::SpaceAfterNot do
+  subject(:cop) { described_class.new }
+
+  it 'reports an offense for space after !' do
+    inspect_source(cop, ['! something'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts no space after !' do
+    inspect_source(cop, ['!something'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'auto-corrects by removing redundant space' do
+    new_source = autocorrect_source(cop, '!  something')
+    expect(new_source).to eq('!something')
+  end
+end
diff --git a/spec/rubocop/cop/style/space_after_semicolon_spec.rb b/spec/rubocop/cop/style/space_after_semicolon_spec.rb
new file mode 100644
index 0000000..c589aa3
--- /dev/null
+++ b/spec/rubocop/cop/style/space_after_semicolon_spec.rb
@@ -0,0 +1,23 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::SpaceAfterSemicolon do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for semicolon without space after it' do
+    inspect_source(cop, ['x = 1;y = 2'])
+    expect(cop.messages).to eq(
+      ['Space missing after semicolon.'])
+  end
+
+  it 'does not crash if semicolon is the last character of the file' do
+    inspect_source(cop, ['x = 1;'])
+    expect(cop.messages).to be_empty
+  end
+
+  it 'auto-corrects missing space' do
+    new_source = autocorrect_source(cop, 'x = 1;y = 2')
+    expect(new_source).to eq('x = 1; y = 2')
+  end
+end
diff --git a/spec/rubocop/cop/style/space_around_equals_in_parameter_default_spec.rb b/spec/rubocop/cop/style/space_around_equals_in_parameter_default_spec.rb
new file mode 100644
index 0000000..3138d51
--- /dev/null
+++ b/spec/rubocop/cop/style/space_around_equals_in_parameter_default_spec.rb
@@ -0,0 +1,75 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::SpaceAroundEqualsInParameterDefault, :config do
+  subject(:cop) { described_class.new(config) }
+
+  context 'when EnforcedStyle is space' do
+    let(:cop_config) { { 'EnforcedStyle' => 'space' } }
+
+    it 'registers an offense for default value assignment without space' do
+      inspect_source(cop, ['def f(x, y=0, z= 1)', 'end'])
+      expect(cop.messages)
+        .to eq(['Surrounding space missing in default value assignment.'] * 2)
+      expect(cop.highlights).to eq(['=', '= '])
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'registers an offense for assignment empty string without space' do
+      inspect_source(cop, ['def f(x, y="", z=1)', 'end'])
+      expect(cop.offenses.size).to eq(2)
+      expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'no_space')
+    end
+
+    it 'registers an offense for assignment of empty list without space' do
+      inspect_source(cop, ['def f(x, y=[])', 'end'])
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it 'accepts default value assignment with space' do
+      inspect_source(cop, ['def f(x, y = 0, z = {})', 'end'])
+      expect(cop.messages).to be_empty
+    end
+
+    it 'auto-corrects missing space' do
+      new_source = autocorrect_source(cop, ['def f(x, y=0, z=1)', 'end'])
+      expect(new_source).to eq(['def f(x, y = 0, z = 1)', 'end'].join("\n"))
+    end
+  end
+
+  context 'when EnforcedStyle is no_space' do
+    let(:cop_config) { { 'EnforcedStyle' => 'no_space' } }
+
+    it 'registers an offense for default value assignment with space' do
+      inspect_source(cop, ['def f(x, y = 0, z =1, w= 2)', 'end'])
+      expect(cop.messages)
+        .to eq(['Surrounding space detected in default value assignment.'] * 3)
+      expect(cop.highlights).to eq([' = ', ' =', '= '])
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'registers an offense for assignment empty string with space' do
+      inspect_source(cop, ['def f(x, y = "", z = 1)', 'end'])
+      expect(cop.offenses.size).to eq(2)
+      expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'space')
+    end
+
+    it 'registers an offense for assignment of empty list with space' do
+      inspect_source(cop, ['def f(x, y = [])', 'end'])
+      expect(cop.offenses.size).to eq(1)
+    end
+
+    it 'accepts default value assignment without space' do
+      inspect_source(cop, ['def f(x, y=0, z={})', 'end'])
+      expect(cop.messages).to be_empty
+    end
+
+    it 'auto-corrects unwanted space' do
+      new_source = autocorrect_source(cop, ['def f(x, y = 0, z= 1, w= 2)',
+                                            'end'])
+      expect(new_source).to eq(['def f(x, y=0, z=1, w=2)',
+                                'end'].join("\n"))
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/space_around_operators_spec.rb b/spec/rubocop/cop/style/space_around_operators_spec.rb
new file mode 100644
index 0000000..032686b
--- /dev/null
+++ b/spec/rubocop/cop/style/space_around_operators_spec.rb
@@ -0,0 +1,325 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::SpaceAroundOperators do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for assignment without space on both sides' do
+    inspect_source(cop, ['x=0', 'y= 0', 'z =0'])
+    expect(cop.messages).to eq(
+      ["Surrounding space missing for operator '='."] * 3)
+  end
+
+  it 'auto-corrects assignment without space on both sides' do
+    new_source = autocorrect_source(cop, ['x=0', 'y= 0', 'z =0'])
+    expect(new_source).to eq(['x = 0', 'y = 0', 'z = 0'].join("\n"))
+  end
+
+  it 'registers an offense for ternary operator without space' do
+    inspect_source(cop, ['x == 0?1:2'])
+    expect(cop.messages).to eq(
+      ["Surrounding space missing for operator '?'.",
+       "Surrounding space missing for operator ':'."])
+  end
+
+  it 'auto-corrects a ternary operator without space' do
+    new_source = autocorrect_source(cop, 'x == 0?1:2')
+    expect(new_source).to eq('x == 0 ? 1 : 2')
+  end
+
+  it 'registers an offense in presence of modifier if statement' do
+    check_modifier('if')
+  end
+
+  it 'registers an offense in presence of modifier unless statement' do
+    check_modifier('unless')
+  end
+
+  it 'registers an offense in presence of modifier while statement' do
+    check_modifier('unless')
+  end
+
+  it 'registers an offense in presence of modifier until statement' do
+    check_modifier('unless')
+  end
+
+  def check_modifier(keyword)
+    src = ["a=1 #{keyword} condition",
+           'c=2']
+    inspect_source(cop, src)
+    expect(cop.offenses.map(&:line)).to eq([1, 2])
+    expect(cop.messages).to eq(
+      ["Surrounding space missing for operator '='."] * 2)
+
+    new_source = autocorrect_source(cop, src)
+    expect(new_source)
+      .to eq(src.map { |line| line.sub(/=/, ' = ') }.join("\n"))
+  end
+
+  it 'registers an offense for binary operators that could be unary' do
+    inspect_source(cop, ['a-3', 'x&0xff', 'z+0'])
+    expect(cop.messages).to eq(
+      ["Surrounding space missing for operator '-'.",
+       "Surrounding space missing for operator '&'.",
+       "Surrounding space missing for operator '+'."])
+  end
+
+  it 'auto-corrects missing space in binary operators that could be unary' do
+    new_source = autocorrect_source(cop, ['a-3', 'x&0xff', 'z+0'])
+    expect(new_source).to eq(['a - 3', 'x & 0xff', 'z + 0'].join("\n"))
+  end
+
+  it 'registers an offense for arguments to a method' do
+    inspect_source(cop, ['puts 1+2'])
+    expect(cop.messages).to eq(
+      ["Surrounding space missing for operator '+'."])
+  end
+
+  it 'auto-corrects missing space in arguments to a method' do
+    new_source = autocorrect_source(cop, 'puts 1+2')
+    expect(new_source).to eq('puts 1 + 2')
+  end
+
+  it 'accepts operator surrounded by tabs' do
+    inspect_source(cop, ["a\t+\tb"])
+    expect(cop.messages).to be_empty
+  end
+
+  it 'accepts operator symbols' do
+    inspect_source(cop, ['func(:-)'])
+    expect(cop.messages).to be_empty
+  end
+
+  it 'accepts ranges' do
+    inspect_source(cop, ['a, b = (1..2), (1...3)'])
+    expect(cop.messages).to be_empty
+  end
+
+  it 'accepts scope operator' do
+    source = ['@io.class == Zlib::GzipWriter']
+    inspect_source(cop, source)
+    expect(cop.messages).to be_empty
+  end
+
+  it 'accepts ::Kernel::raise' do
+    source = ['::Kernel::raise IllegalBlockError.new']
+    inspect_source(cop, source)
+    expect(cop.messages).to be_empty
+  end
+
+  it 'accepts exclamation point negation' do
+    inspect_source(cop, ['x = !a&&!b'])
+    expect(cop.messages).to eq(
+      ["Surrounding space missing for operator '&&'."])
+  end
+
+  it 'accepts exclamation point definition' do
+    inspect_source(cop, ['  def !',
+                         '    !__getobj__',
+                         '  end'])
+    expect(cop.offenses).to be_empty
+    expect(cop.messages).to be_empty
+  end
+
+  it 'accepts a unary' do
+    inspect_source(cop,
+                   ['  def bm(label_width = 0, *labels, &blk)',
+                    '    benchmark(CAPTION, label_width, FORMAT,',
+                    '              *labels, &blk)',
+                    '  end',
+                    '',
+                    '  def each &block',
+                    '  end',
+                    '',
+                    '  def self.search *args',
+                    '  end',
+                    '',
+                    '  def each *args',
+                    '  end',
+                    ''])
+    expect(cop.messages).to be_empty
+  end
+
+  it 'accepts splat operator' do
+    inspect_source(cop, ['return *list if options'])
+    expect(cop.messages).to be_empty
+  end
+
+  it 'accepts def of operator' do
+    inspect_source(cop, ['def +(other); end',
+                         'def self.===(other); end'])
+    expect(cop.messages).to be_empty
+  end
+
+  it 'accepts an operator at the end of a line' do
+    inspect_source(cop,
+                   ["['Favor unless over if for negative ' +",
+                    " 'conditions.'] * 2"])
+    expect(cop.messages).to eq([])
+  end
+
+  it 'accepts an assignment with spaces' do
+    inspect_source(cop, ['x = 0'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts an operator called with method syntax' do
+    inspect_source(cop, ['Date.today.+(1).to_s'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'registers an offense for operators without spaces' do
+    inspect_source(cop,
+                   ['x+= a+b-c*d/e%f^g|h&i||j',
+                    'y -=k&&l'])
+    expect(cop.messages)
+      .to eq(["Surrounding space missing for operator '+='.",
+              "Surrounding space missing for operator '+'.",
+              "Surrounding space missing for operator '-'.",
+              "Surrounding space missing for operator '*'.",
+              "Surrounding space missing for operator '/'.",
+              "Surrounding space missing for operator '%'.",
+              "Surrounding space missing for operator '^'.",
+              "Surrounding space missing for operator '|'.",
+              "Surrounding space missing for operator '&'.",
+              "Surrounding space missing for operator '||'.",
+              "Surrounding space missing for operator '-='.",
+              "Surrounding space missing for operator '&&'."])
+  end
+
+  it 'auto-corrects missing space' do
+    new_source = autocorrect_source(cop, ['x+= a+b-c*d/e%f^g|h&i||j',
+                                          'y -=k&&l'])
+    expect(new_source).to eq(['x += a + b - c * d / e % f ^ g | h & i || j',
+                              'y -= k && l'].join("\n"))
+  end
+
+  it 'accepts operators with spaces' do
+    inspect_source(cop,
+                   ['x += a + b - c * d / e % f ^ g | h & i || j',
+                    'y -= k && l'])
+    expect(cop.messages).to eq([])
+  end
+
+  it "accepts some operators that are exceptions & don't need spaces" do
+    inspect_source(cop, ['(1..3)',
+                         'ActionController::Base',
+                         'each { |s, t| }'])
+    expect(cop.messages).to eq([])
+  end
+
+  it 'accepts an assignment followed by newline' do
+    inspect_source(cop, ['x =', '0'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'registers an offenses for exponent operator with spaces' do
+    inspect_source(cop, ['x = a * b ** 2'])
+    expect(cop.messages).to eq(
+      ['Space around operator ** detected.'])
+  end
+
+  it 'auto-corrects unwanted space around **' do
+    new_source = autocorrect_source(cop, ['x = a * b ** 2',
+                                          'y = a * b** 2'])
+    expect(new_source).to eq(['x = a * b**2',
+                              'y = a * b**2'].join("\n"))
+  end
+
+  it 'accepts exponent operator without spaces' do
+    inspect_source(cop, ['x = a * b**2'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'registers an offense for a setter call without spaces' do
+    inspect_source(cop, ['x.y=2'])
+    expect(cop.messages).to eq(
+      ["Surrounding space missing for operator '='."])
+  end
+
+  it 'registers an offense for a hash rocket without spaces' do
+    inspect_source(cop, ['{ 1=>2, a: b }'])
+    expect(cop.messages).to eq(
+      ["Surrounding space missing for operator '=>'."])
+  end
+
+  it 'accepts unary operators without space' do
+    inspect_source(cop, ['[].map(&:size)',
+                         '-3',
+                         'arr.collect { |e| -e }',
+                         'x = +2'])
+    expect(cop.messages).to eq([])
+  end
+
+  it 'accepts [] without space' do
+    inspect_source(cop, ['files[2]'])
+    expect(cop.messages).to eq([])
+  end
+
+  it 'accepts argument default values without space' do
+    # These are handled by SpaceAroundEqualsInParameterDefault,
+    # so SpaceAroundOperators leaves them alone.
+    inspect_source(cop,
+                   ['def init(name=nil)',
+                    'end'])
+    expect(cop.messages).to be_empty
+  end
+
+  it 'accepts the construct class <<self with no space after <<' do
+    inspect_source(cop, ['class <<self',
+                         'end'])
+    expect(cop.messages).to be_empty
+  end
+
+  it 'registers an offense for match operators without space' do
+    inspect_source(cop, ['x=~/abc/', 'y !~/abc/'])
+    expect(cop.messages)
+      .to eq(["Surrounding space missing for operator '=~'.",
+              "Surrounding space missing for operator '!~'."])
+  end
+
+  it 'registers an offense for various assignments without space' do
+    inspect_source(cop, ['x||=0', 'y&&=0', 'z*=2',
+                         '@a=0', '@@a=0', 'a,b=0', 'A=0', 'x[3]=0', '$A=0'])
+    expect(cop.messages)
+      .to eq(["Surrounding space missing for operator '||='.",
+              "Surrounding space missing for operator '&&='.",
+              "Surrounding space missing for operator '*='.",
+              "Surrounding space missing for operator '='.",
+              "Surrounding space missing for operator '='.",
+              "Surrounding space missing for operator '='.",
+              "Surrounding space missing for operator '='.",
+              "Surrounding space missing for operator '='.",
+              "Surrounding space missing for operator '='."])
+  end
+
+  it 'registers an offense for equality operators without space' do
+    inspect_source(cop, ['x==0', 'y!=0', 'Hash===z'])
+    expect(cop.messages)
+      .to eq(["Surrounding space missing for operator '=='.",
+              "Surrounding space missing for operator '!='.",
+              "Surrounding space missing for operator '==='."])
+  end
+
+  it 'registers an offense for - without space with negative lhs operand' do
+    inspect_source(cop, ['-1-arg'])
+    expect(cop.messages)
+      .to eq(["Surrounding space missing for operator '-'."])
+  end
+
+  it 'registers an offense for inheritance < without space' do
+    inspect_source(cop, ['class ShowSourceTestClass<ShowSourceTestSuperClass',
+                         'end'])
+    expect(cop.messages)
+      .to eq(["Surrounding space missing for operator '<'."])
+  end
+
+  it 'registers an offense for hash rocket without space at rescue' do
+    inspect_source(cop, ['begin',
+                         'rescue Exception=>e',
+                         'end'])
+    expect(cop.messages)
+      .to eq(["Surrounding space missing for operator '=>'."])
+  end
+end
diff --git a/spec/rubocop/cop/style/space_before_block_braces_spec.rb b/spec/rubocop/cop/style/space_before_block_braces_spec.rb
new file mode 100644
index 0000000..13edac3
--- /dev/null
+++ b/spec/rubocop/cop/style/space_before_block_braces_spec.rb
@@ -0,0 +1,72 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::SpaceBeforeBlockBraces do
+  subject(:cop) { described_class.new(config) }
+  let(:config) do
+    merged = Rubocop::ConfigLoader
+      .default_configuration['SpaceBeforeBlockBraces'].merge(cop_config)
+    Rubocop::Config.new('Blocks' => { 'Enabled' => false },
+                        'SpaceBeforeBlockBraces' => merged)
+  end
+  let(:cop_config) { { 'EnforcedStyle' => 'space' } }
+
+  context 'when EnforcedStyle is space' do
+    it 'accepts braces surrounded by spaces' do
+      inspect_source(cop, ['each { puts }'])
+      expect(cop.messages).to be_empty
+      expect(cop.highlights).to be_empty
+    end
+
+    it 'registers an offense for left brace without outer space' do
+      inspect_source(cop, ['each{ puts }'])
+      expect(cop.messages).to eq(['Space missing to the left of {.'])
+      expect(cop.highlights).to eq(['{'])
+      expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'no_space')
+    end
+
+    it 'registers an offense for opposite + correct style' do
+      inspect_source(cop,
+                     ['each{ puts }',
+                      'each { puts }'])
+      expect(cop.messages).to eq(['Space missing to the left of {.'])
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'auto-corrects missing space' do
+      new_source = autocorrect_source(cop, 'each{}')
+      expect(new_source).to eq('each {}')
+    end
+  end
+
+  context 'when EnforcedStyle is no_space' do
+    let(:cop_config) { { 'EnforcedStyle' => 'no_space' } }
+
+    it 'registers an offense for braces surrounded by spaces' do
+      inspect_source(cop, ['each { puts }'])
+      expect(cop.messages).to eq(['Space detected to the left of {.'])
+      expect(cop.highlights).to eq([' '])
+      expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'space')
+    end
+
+    it 'registers an offense for correct + opposite style' do
+      inspect_source(cop,
+                     ['each{ puts }',
+                      'each { puts }'])
+      expect(cop.messages).to eq(['Space detected to the left of {.'])
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'auto-corrects unwanted space' do
+      new_source = autocorrect_source(cop, 'each {}')
+      expect(new_source).to eq('each{}')
+    end
+
+    it 'accepts left brace without outer space' do
+      inspect_source(cop, ['each{ puts }'])
+      expect(cop.messages).to be_empty
+      expect(cop.highlights).to be_empty
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/space_before_modifier_keyword_spec.rb b/spec/rubocop/cop/style/space_before_modifier_keyword_spec.rb
new file mode 100644
index 0000000..089a08b
--- /dev/null
+++ b/spec/rubocop/cop/style/space_before_modifier_keyword_spec.rb
@@ -0,0 +1,70 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::SpaceBeforeModifierKeyword do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for missing space before if/unless' do
+    inspect_source(cop, ['(a = 3)if a == 2',
+                         'a = "test"if a == 2',
+                         'a = 42unless a == 2',
+                         'a = [1,2,3]unless a == 2',
+                         'a = {:a => "b"}if a == 2'])
+    expect(cop.highlights).to eq([')', '"', '2', ']', '}'])
+  end
+
+  it 'registers an offense for missing space before while/until' do
+    inspect_source(cop, ['(a = 3)while b',
+                         'a = "test"until b',
+                         'a = 42while b',
+                         'a = [1,2,3]until b',
+                         'a = {:a => "b"}while b'])
+    expect(cop.highlights).to eq([')', '"', '2', ']', '}'])
+  end
+
+  it 'accepts modifiers with preceding space' do
+    inspect_source(cop, ['(a = 3) if b',
+                         'a = "test" unless b',
+                         'a = 42 while b',
+                         'a = [1,2,3] until b'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts elsif at beginning of line' do
+    inspect_source(cop, ["if RUBY_VERSION.between?('1.9.2', '2.0.0')",
+                         "  require 'testing/performance/ruby/yarv'",
+                         'elsif RUBY_VERSION.between?("1.8.6", "1.9")',
+                         "  require 'testing/performance/ruby/mri'",
+                         'end'])
+    expect(cop.highlights).to eq([])
+  end
+
+  it 'does not crash on ternary conditionals' do
+    inspect_source(cop, 'a ? b : c')
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'auto-corrects missing space' do
+    new_source = autocorrect_source(cop, ['(a = 3)if a == 2',
+                                          'a = "test"if a == 2',
+                                          'a = 42unless a == 2',
+                                          'a = [1,2,3]unless a == 2',
+                                          'a = {:a => "b"}if a == 2',
+                                          '(a = 3)while b',
+                                          'a = "test"until b',
+                                          'a = 42while b',
+                                          'a = [1,2,3]until b',
+                                          'a = {:a => "b"}while b'])
+    expect(new_source).to eq(['(a = 3) if a == 2',
+                              'a = "test" if a == 2',
+                              'a = 42 unless a == 2',
+                              'a = [1,2,3] unless a == 2',
+                              'a = {:a => "b"} if a == 2',
+                              '(a = 3) while b',
+                              'a = "test" until b',
+                              'a = 42 while b',
+                              'a = [1,2,3] until b',
+                              'a = {:a => "b"} while b'].join("\n"))
+  end
+end
diff --git a/spec/rubocop/cop/style/space_inside_block_braces_spec.rb b/spec/rubocop/cop/style/space_inside_block_braces_spec.rb
new file mode 100644
index 0000000..c810165
--- /dev/null
+++ b/spec/rubocop/cop/style/space_inside_block_braces_spec.rb
@@ -0,0 +1,287 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::SpaceInsideBlockBraces do
+  SUPPORTED_STYLES = %w(space no_space)
+
+  subject(:cop) { described_class.new(config) }
+  let(:config) do
+    merged = Rubocop::ConfigLoader
+      .default_configuration['SpaceInsideBlockBraces'].merge(cop_config)
+    Rubocop::Config.new('Blocks' => { 'Enabled' => false },
+                        'SpaceInsideBlockBraces' => merged)
+  end
+  let(:cop_config) do
+    {
+      'EnforcedStyle' => 'space',
+      'SupportedStyles' => SUPPORTED_STYLES,
+      'SpaceBeforeBlockParameters' => true
+    }
+  end
+
+  context 'with space inside empty braces not allowed' do
+    let(:cop_config) { { 'EnforcedStyleForEmptyBraces' => 'no_space' } }
+
+    it 'accepts empty braces with no space inside' do
+      inspect_source(cop, ['each {}'])
+      expect(cop.messages).to be_empty
+    end
+
+    it 'accepts empty braces with line break inside' do
+      inspect_source(cop, ['  each {',
+                           '  }'])
+      expect(cop.messages).to be_empty
+    end
+
+    it 'accepts empty braces with comment and line break inside' do
+      inspect_source(cop, ['  each { # Comment',
+                           '  }'])
+      expect(cop.messages).to be_empty
+    end
+
+    it 'registers an offense for empty braces with space inside' do
+      inspect_source(cop, ['each { }'])
+      expect(cop.messages).to eq(['Space inside empty braces detected.'])
+      expect(cop.highlights).to eq([' '])
+    end
+
+    it 'auto-corrects unwanted space' do
+      new_source = autocorrect_source(cop, 'each { }')
+      expect(new_source).to eq('each {}')
+    end
+
+    it 'does not auto-correct when braces are not empty' do
+      old_source = <<-END
+        a {
+          b
+        }
+      END
+      new_source = autocorrect_source(cop, old_source)
+      expect(new_source).to eq(old_source)
+    end
+  end
+
+  context 'with space inside empty braces allowed' do
+    let(:cop_config) { { 'EnforcedStyleForEmptyBraces' => 'space' } }
+
+    it 'accepts empty braces with space inside' do
+      inspect_source(cop, ['each { }'])
+      expect(cop.messages).to be_empty
+    end
+
+    it 'registers an offense for empty braces with no space inside' do
+      inspect_source(cop, ['each {}'])
+      expect(cop.messages).to eq(['Space missing inside empty braces.'])
+      expect(cop.highlights).to eq(['{}'])
+    end
+
+    it 'auto-corrects missing space' do
+      new_source = autocorrect_source(cop, 'each {}')
+      expect(new_source).to eq('each { }')
+    end
+  end
+
+  it 'accepts braces surrounded by spaces' do
+    inspect_source(cop, ['each { puts }'])
+    expect(cop.messages).to be_empty
+    expect(cop.highlights).to be_empty
+  end
+
+  it 'accepts left brace without outer space' do
+    inspect_source(cop, ['each{ puts }'])
+    expect(cop.highlights).to be_empty
+  end
+
+  it 'registers an offense for left brace without inner space' do
+    inspect_source(cop, ['each {puts }'])
+    expect(cop.messages).to eq(['Space missing inside {.'])
+    expect(cop.highlights).to eq(['p'])
+  end
+
+  it 'registers an offense for right brace without inner space' do
+    inspect_source(cop, ['each { puts}'])
+    expect(cop.messages).to eq(['Space missing inside }.'])
+    expect(cop.highlights).to eq(['}'])
+    expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+  end
+
+  it 'registers offenses for both braces without inner space' do
+    inspect_source(cop, ['a {}',
+                         'b { }',
+                         'each {puts}'])
+    expect(cop.messages).to eq(['Space inside empty braces detected.',
+                                'Space missing inside {.',
+                                'Space missing inside }.'])
+    expect(cop.highlights).to eq([' ', 'p', '}'])
+
+    # Both correct and incorrect code has been found in relation to
+    # EnforcedStyleForEmptyBraces, but that doesn't matter. EnforcedStyle can
+    # be changed to get rid of the EnforcedStyle offenses.
+    expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' =>
+                                               'no_space')
+  end
+
+  it 'auto-corrects missing space' do
+    new_source = autocorrect_source(cop, 'each {puts}')
+    expect(new_source).to eq('each { puts }')
+  end
+
+  context 'with passed in parameters' do
+    it 'accepts left brace with inner space' do
+      inspect_source(cop, ['each { |x| puts }'])
+      expect(cop.messages).to be_empty
+      expect(cop.highlights).to be_empty
+    end
+
+    it 'registers an offense for left brace without inner space' do
+      inspect_source(cop, ['each {|x| puts }'])
+      expect(cop.messages).to eq(['Space between { and | missing.'])
+      expect(cop.highlights).to eq(['{|'])
+    end
+
+    it 'auto-corrects missing space' do
+      new_source = autocorrect_source(cop, 'each {|x| puts }')
+      expect(new_source).to eq('each { |x| puts }')
+    end
+
+    context 'and Blocks cop enabled' do
+      let(:config) do
+        Rubocop::Config.new('Blocks'                 => { 'Enabled' => true },
+                            'SpaceInsideBlockBraces' => cop_config)
+      end
+
+      it 'does auto-correction for single-line blocks' do
+        new_source = autocorrect_source(cop, 'each {|x| puts}')
+        expect(new_source).to eq('each { |x| puts }')
+      end
+
+      it 'does not do auto-correction for multi-line blocks' do
+        # {} will be changed to do..end by the Blocks cop, and then this cop is
+        # not relevant anymore.
+        old_source = ['each {|x|',
+                      '  puts',
+                      '}']
+        new_source = autocorrect_source(cop, old_source)
+        expect(new_source).to eq(old_source.join("\n"))
+      end
+    end
+
+    context 'and space before block parameters not allowed' do
+      let(:cop_config) do
+        {
+          'EnforcedStyle'              => 'space',
+          'SupportedStyles'            => SUPPORTED_STYLES,
+          'SpaceBeforeBlockParameters' => false
+        }
+      end
+
+      it 'registers an offense for left brace with inner space' do
+        inspect_source(cop, ['each { |x| puts }'])
+        expect(cop.messages).to eq(['Space between { and | detected.'])
+        expect(cop.highlights).to eq([' '])
+      end
+
+      it 'auto-corrects unwanted space' do
+        new_source = autocorrect_source(cop, 'each { |x| puts }')
+        expect(new_source).to eq('each {|x| puts }')
+      end
+
+      it 'accepts left brace without inner space' do
+        inspect_source(cop, ['each {|x| puts }'])
+        expect(cop.messages).to be_empty
+        expect(cop.highlights).to be_empty
+      end
+    end
+  end
+
+  context 'configured with no_space' do
+    let(:cop_config) do
+      {
+        'EnforcedStyle'              => 'no_space',
+        'SupportedStyles'            => SUPPORTED_STYLES,
+        'SpaceBeforeBlockParameters' => true
+      }
+    end
+
+    it 'accepts braces without spaces inside' do
+      inspect_source(cop, ['each {puts}'])
+      expect(cop.messages).to be_empty
+      expect(cop.highlights).to be_empty
+    end
+
+    it 'registers an offense for left brace with inner space' do
+      inspect_source(cop, ['each { puts}'])
+      expect(cop.messages).to eq(['Space inside { detected.'])
+      expect(cop.highlights).to eq([' '])
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'registers an offense for right brace with inner space' do
+      inspect_source(cop, ['each {puts  }'])
+      expect(cop.messages).to eq(['Space inside } detected.'])
+      expect(cop.highlights).to eq(['  '])
+    end
+
+    it 'registers offenses for both braces with inner space' do
+      inspect_source(cop, ['each { puts  }'])
+      expect(cop.messages).to eq(['Space inside { detected.',
+                                  'Space inside } detected.'])
+      expect(cop.highlights).to eq([' ', '  '])
+      expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' =>
+                                                 'space')
+    end
+
+    it 'accepts left brace without outer space' do
+      inspect_source(cop, ['each {puts}'])
+      expect(cop.highlights).to be_empty
+    end
+
+    it 'auto-corrects unwanted space' do
+      new_source = autocorrect_source(cop, 'each{ puts }')
+      expect(new_source).to eq('each{puts}')
+    end
+
+    context 'with passed in parameters' do
+      context 'and space before block parameters allowed' do
+        it 'accepts left brace with inner space' do
+          inspect_source(cop, ['each { |x| puts}'])
+          expect(cop.messages).to eq([])
+          expect(cop.highlights).to eq([])
+        end
+
+        it 'registers an offense for left brace without inner space' do
+          inspect_source(cop, ['each {|x| puts}'])
+          expect(cop.messages).to eq(['Space between { and | missing.'])
+          expect(cop.highlights).to eq(['{|'])
+        end
+
+        it 'auto-corrects missing space' do
+          new_source = autocorrect_source(cop, 'each {|x| puts}')
+          expect(new_source).to eq('each { |x| puts}')
+        end
+      end
+
+      context 'and space before block parameters not allowed' do
+        let(:cop_config) do
+          {
+            'EnforcedStyle'              => 'no_space',
+            'SupportedStyles'            => SUPPORTED_STYLES,
+            'SpaceBeforeBlockParameters' => false
+          }
+        end
+
+        it 'registers an offense for left brace with inner space' do
+          inspect_source(cop, ['each { |x| puts}'])
+          expect(cop.messages).to eq(['Space between { and | detected.'])
+          expect(cop.highlights).to eq([' '])
+        end
+
+        it 'auto-corrects unwanted space' do
+          new_source = autocorrect_source(cop, 'each { |x| puts}')
+          expect(new_source).to eq('each {|x| puts}')
+        end
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/space_inside_brackets_spec.rb b/spec/rubocop/cop/style/space_inside_brackets_spec.rb
new file mode 100644
index 0000000..1900a27
--- /dev/null
+++ b/spec/rubocop/cop/style/space_inside_brackets_spec.rb
@@ -0,0 +1,59 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::SpaceInsideBrackets do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for an array literal with spaces inside' do
+    inspect_source(cop, ['a = [1, 2 ]',
+                         'b = [ 1, 2]'])
+    expect(cop.messages).to eq(
+      ['Space inside square brackets detected.',
+       'Space inside square brackets detected.'])
+  end
+
+  it 'accepts space inside strings within square brackets' do
+    inspect_source(cop, ["['Encoding:',",
+                         " '  Enabled: false']"])
+    expect(cop.messages).to be_empty
+  end
+
+  it 'accepts space inside square brackets if on its own row' do
+    inspect_source(cop, ['a = [',
+                         '     1, 2',
+                         '    ]'])
+    expect(cop.messages).to be_empty
+  end
+
+  it 'accepts space inside square brackets if with comment' do
+    inspect_source(cop, ['a = [ # Comment',
+                         '     1, 2',
+                         '    ]'])
+    expect(cop.messages).to be_empty
+  end
+
+  it 'accepts square brackets as method name' do
+    inspect_source(cop, ['def Vector.[](*array)',
+                         'end'])
+    expect(cop.messages).to be_empty
+  end
+
+  it 'accepts square brackets called with method call syntax' do
+    inspect_source(cop, ['subject.[](0)'])
+    expect(cop.messages).to be_empty
+  end
+
+  it 'only reports a single space once' do
+    inspect_source(cop, ['[ ]'])
+    expect(cop.messages).to eq(
+      ['Space inside square brackets detected.'])
+  end
+
+  it 'auto-corrects unwanted space' do
+    new_source = autocorrect_source(cop, ['a = [1, 2 ]',
+                                          'b = [ 1, 2]'])
+    expect(new_source).to eq(['a = [1, 2]',
+                              'b = [1, 2]'].join("\n"))
+  end
+end
diff --git a/spec/rubocop/cop/style/space_inside_hash_literal_braces_spec.rb b/spec/rubocop/cop/style/space_inside_hash_literal_braces_spec.rb
new file mode 100644
index 0000000..8ba94a6
--- /dev/null
+++ b/spec/rubocop/cop/style/space_inside_hash_literal_braces_spec.rb
@@ -0,0 +1,147 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::SpaceInsideHashLiteralBraces, :config do
+  subject(:cop) { described_class.new(config) }
+  let(:cop_config) { { 'EnforcedStyle' => 'space' } }
+
+  context 'with space inside empty braces not allowed' do
+    let(:cop_config) { { 'EnforcedStyleForEmptyBraces' => 'no_space' } }
+
+    it 'accepts empty braces with no space inside' do
+      inspect_source(cop, ['h = {}'])
+      expect(cop.messages).to be_empty
+    end
+
+    it 'registers an offense for empty braces with space inside' do
+      inspect_source(cop, ['h = { }'])
+      expect(cop.messages)
+        .to eq(['Space inside empty hash literal braces detected.'])
+      expect(cop.highlights).to eq([' '])
+    end
+
+    it 'auto-corrects unwanted space' do
+      new_source = autocorrect_source(cop, 'h = { }')
+      expect(new_source).to eq('h = {}')
+    end
+  end
+
+  context 'with space inside empty braces allowed' do
+    let(:cop_config) { { 'EnforcedStyleForEmptyBraces' => 'space' } }
+
+    it 'accepts empty braces with space inside' do
+      inspect_source(cop, ['h = { }'])
+      expect(cop.messages).to be_empty
+    end
+
+    it 'registers an offense for empty braces with no space inside' do
+      inspect_source(cop, ['h = {}'])
+      expect(cop.messages)
+        .to eq(['Space inside empty hash literal braces missing.'])
+      expect(cop.highlights).to eq(['{'])
+    end
+
+    it 'auto-corrects missing space' do
+      new_source = autocorrect_source(cop, 'h = {}')
+      expect(new_source).to eq('h = { }')
+    end
+  end
+
+  it 'registers an offense for hashes with no spaces if so configured' do
+    inspect_source(cop,
+                   ['h = {a: 1, b: 2}',
+                    'h = {a => 1}'])
+    expect(cop.messages).to eq(['Space inside { missing.',
+                                'Space inside } missing.',
+                                'Space inside { missing.',
+                                'Space inside } missing.'])
+    expect(cop.highlights).to eq(['{', '}', '{', '}'])
+    expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'no_space')
+  end
+
+  it 'registers an offense for correct + opposite' do
+    inspect_source(cop,
+                   ['h = { a: 1}'])
+    expect(cop.messages).to eq(['Space inside } missing.'])
+    expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+  end
+
+  it 'auto-corrects missing space' do
+    new_source = autocorrect_source(cop, ['h = {a: 1, b: 2}',
+                                          'h = {a => 1 }'])
+    expect(new_source).to eq(['h = { a: 1, b: 2 }',
+                              'h = { a => 1 }'].join("\n"))
+  end
+
+  context 'when EnforcedStyle is no_space' do
+    let(:cop_config) { { 'EnforcedStyle' => 'no_space' } }
+
+    it 'registers an offense for hashes with spaces' do
+      inspect_source(cop,
+                     ['h = { a: 1, b: 2 }'])
+      expect(cop.messages).to eq(['Space inside { detected.',
+                                  'Space inside } detected.'])
+      expect(cop.highlights).to eq([' ', ' '])
+      expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'space')
+    end
+
+    it 'registers an offense for opposite + correct' do
+      inspect_source(cop,
+                     ['h = {a: 1 }'])
+      expect(cop.messages).to eq(['Space inside } detected.'])
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'auto-corrects unwanted space' do
+      new_source = autocorrect_source(cop, ['h = { a: 1, b: 2 }',
+                                            'h = {a => 1 }'])
+      expect(new_source).to eq(['h = {a: 1, b: 2}',
+                                'h = {a => 1}'].join("\n"))
+    end
+
+    it 'accepts hashes with no spaces' do
+      inspect_source(cop,
+                     ['h = {a: 1, b: 2}',
+                      'h = {a => 1}'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts multiline hash' do
+      inspect_source(cop,
+                     ['h = {',
+                      '      a: 1,',
+                      '      b: 2,',
+                      '}'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts multiline hash with comment' do
+      inspect_source(cop,
+                     ['h = { # Comment',
+                      '      a: 1,',
+                      '      b: 2,',
+                      '}'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  it 'accepts hashes with spaces by default' do
+    inspect_source(cop,
+                   ['h = { a: 1, b: 2 }',
+                    'h = { a => 1 }'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts hash literals with no braces' do
+    inspect_source(cop, ['x(a: b.c)'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'can handle interpolation in a braceless hash literal' do
+    # A tricky special case where the closing brace of the
+    # interpolation risks getting confused for a hash literal brace.
+    inspect_source(cop, ['f(get: "#{x}")'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/space_inside_parens_spec.rb b/spec/rubocop/cop/style/space_inside_parens_spec.rb
new file mode 100644
index 0000000..18ff2a9
--- /dev/null
+++ b/spec/rubocop/cop/style/space_inside_parens_spec.rb
@@ -0,0 +1,46 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::SpaceInsideParens do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for spaces inside parens' do
+    inspect_source(cop, ['f( 3)',
+                         'g(3 )'])
+    expect(cop.messages).to eq(
+      ['Space inside parentheses detected.',
+       'Space inside parentheses detected.'])
+  end
+
+  it 'accepts parentheses in block parameter list' do
+    inspect_source(cop,
+                   ['list.inject(Tms.new) { |sum, (label, item)|',
+                    '}'])
+    expect(cop.messages).to be_empty
+  end
+
+  it 'accepts parentheses with no spaces' do
+    inspect_source(cop, ['split("\n")'])
+    expect(cop.messages).to be_empty
+  end
+
+  it 'accepts parentheses with line break' do
+    inspect_source(cop, ['f(',
+                         '  1)'])
+    expect(cop.messages).to be_empty
+  end
+
+  it 'accepts parentheses with comment and line break' do
+    inspect_source(cop, ['f( # Comment',
+                         '  1)'])
+    expect(cop.messages).to be_empty
+  end
+
+  it 'auto-corrects unwanted space' do
+    new_source = autocorrect_source(cop, ['f( 3)',
+                                          'g(3 )'])
+    expect(new_source).to eq(['f(3)',
+                              'g(3)'].join("\n"))
+  end
+end
diff --git a/spec/rubocop/cop/style/special_global_vars_spec.rb b/spec/rubocop/cop/style/special_global_vars_spec.rb
new file mode 100644
index 0000000..f08d2ba
--- /dev/null
+++ b/spec/rubocop/cop/style/special_global_vars_spec.rb
@@ -0,0 +1,57 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::SpecialGlobalVars do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for $:' do
+    inspect_source(cop, ['puts $:'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages)
+      .to eq(['Prefer `$LOAD_PATH` over `$:`.'])
+  end
+
+  it 'registers an offense for $"' do
+    inspect_source(cop, ['puts $"'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages)
+      .to eq(['Prefer `$LOADED_FEATURES` over `$"`.'])
+  end
+
+  it 'registers an offense for $0' do
+    inspect_source(cop, ['puts $0'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages)
+      .to eq(['Prefer `$PROGRAM_NAME` over `$0`.'])
+  end
+
+  it 'registers an offense for $$' do
+    inspect_source(cop, ['puts $$'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages)
+      .to eq(['Prefer `$PROCESS_ID` or `$PID` from the English ' \
+              'library over `$$`.'])
+  end
+
+  it 'is clear about variables from the English library vs those not' do
+    inspect_source(cop, ['puts $*'])
+    expect(cop.messages)
+      .to eq(['Prefer `$ARGV` from the English library, or `ARGV` over `$*`.'])
+  end
+
+  it 'does not register an offense for backrefs like $1' do
+    inspect_source(cop, ['puts $1'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'auto-corrects $: to $LOAD_PATH' do
+    new_source = autocorrect_source(cop, '$:')
+    expect(new_source).to eq('$LOAD_PATH')
+  end
+
+  it 'auto-corrects $/ to $INPUT_RECORD_SEPARATOR' do
+    new_source = autocorrect_source(cop, '$/')
+    expect(new_source).to eq('$INPUT_RECORD_SEPARATOR')
+  end
+end
diff --git a/spec/rubocop/cop/style/string_literals_spec.rb b/spec/rubocop/cop/style/string_literals_spec.rb
new file mode 100644
index 0000000..9e7f5a7
--- /dev/null
+++ b/spec/rubocop/cop/style/string_literals_spec.rb
@@ -0,0 +1,212 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::StringLiterals, :config do
+  subject(:cop) { described_class.new(config) }
+
+  context 'configured with single quotes preferred' do
+    let(:cop_config) { { 'EnforcedStyle' => 'single_quotes' } }
+
+    it 'registers offense for double quotes when single quotes ' \
+       'suffice' do
+      inspect_source(cop, ['s = "abc"',
+                           'x = "a\\\\b"',
+                           'y ="\\\\b"',
+                           'z = "a\\\\"'])
+      expect(cop.highlights).to eq(['"abc"',
+                                    '"a\\\\b"',
+                                    '"\\\\b"',
+                                    '"a\\\\"'])
+      expect(cop.messages)
+        .to eq(["Prefer single-quoted strings when you don't need " \
+                'string interpolation or special symbols.'] * 4)
+      expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' =>
+                                                 'double_quotes')
+    end
+
+    it 'registers offense for correct + opposite' do
+      inspect_source(cop, ['s = "abc"',
+                           "x = 'abc'"])
+      expect(cop.messages)
+        .to eq(["Prefer single-quoted strings when you don't need " \
+                'string interpolation or special symbols.'])
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'accepts single quotes' do
+      inspect_source(cop, ["a = 'x'"])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts %q and %Q quotes' do
+      inspect_source(cop, ['a = %q(x) + %Q[x]'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts % quotes' do
+      inspect_source(cop, ['a = %(x)'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts heredocs' do
+      inspect_source(cop,
+                     ['execute <<-SQL',
+                      '  SELECT name from users',
+                      'SQL'])
+
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts double quotes when they are needed' do
+      src = ['a = "\n"',
+             'b = "#{encode_severity}:' \
+             '#{sprintf("%3d", line_number)}: #{m}"',
+             'c = "\'"',
+             'd = "#@test"',
+             'e = "#$test"',
+             'f = "\e"',
+             'g = "#@@test"']
+      inspect_source(cop, src)
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts double quotes at the start of regexp literals' do
+      inspect_source(cop, ['s = /"((?:[^\\"]|\\.)*)"/'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts double quotes with some other special symbols' do
+      # "Substitutions in double-quoted strings"
+      # http://www.ruby-doc.org/docs/ProgrammingRuby/html/language.html
+      src = ['g = "\xf9"',
+             'copyright = "\u00A9"']
+      inspect_source(cop, src)
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts " in a %w' do
+      inspect_source(cop, ['%w(")'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts \\\\\n in a string' do # this would be: "\\\n"
+      inspect_source(cop, ['"foo \\\\\n bar"'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'can handle double quotes within embedded expression' do
+      src = ['"#{"A"}"']
+      inspect_source(cop, src)
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'can handle a built-in constant parsed as string' do
+      # Parser will produce str nodes for constants such as __FILE__.
+      src = ['if __FILE__ == $PROGRAM_NAME',
+             'end']
+      inspect_source(cop, src)
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'can handle character literals' do
+      src = 'a = ?/'
+      inspect_source(cop, src)
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'auto-corrects " with \'' do
+      new_source = autocorrect_source(cop, 's = "abc"')
+      expect(new_source).to eq("s = 'abc'")
+    end
+  end
+
+  context 'configured with double quotes preferred' do
+    let(:cop_config) { { 'EnforcedStyle' => 'double_quotes' } }
+
+    it 'registers offense for single quotes when double quotes would ' \
+      'be equivalent' do
+      inspect_source(cop, ["s = 'abc'"])
+      expect(cop.highlights).to eq(["'abc'"])
+      expect(cop.messages)
+        .to eq(['Prefer double-quoted strings unless you need ' \
+                'single quotes to avoid extra backslashes for ' \
+                'escaping.'])
+      expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' =>
+                                                 'single_quotes')
+    end
+
+    it 'registers offense for opposite + correct' do
+      inspect_source(cop, ['s = "abc"',
+                           "x = 'abc'"])
+      expect(cop.messages)
+        .to eq(['Prefer double-quoted strings unless you need ' \
+                'single quotes to avoid extra backslashes for ' \
+                'escaping.'])
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'accepts double quotes' do
+      inspect_source(cop, ['a = "x"'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts %q and %Q quotes' do
+      inspect_source(cop, ['a = %q(x) + %Q[x]'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts % quotes' do
+      inspect_source(cop, ['a = %(x)'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts heredocs' do
+      inspect_source(cop,
+                     ['execute <<-SQL',
+                      '  SELECT name from users',
+                      'SQL'])
+
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts single quotes when they are needed' do
+      src = ["a = '\\n'",
+             "b = '\"'"]
+      inspect_source(cop, src)
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts single quotes at the start of regexp literals' do
+      inspect_source(cop, ["s = /'((?:[^\\']|\\.)*)'/"])
+      expect(cop.offenses).to be_empty
+    end
+
+    it "accepts ' in a %w" do
+      inspect_source(cop, ["%w(')"])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'can handle a built-in constant parsed as string' do
+      # Parser will produce str nodes for constants such as __FILE__.
+      src = ['if __FILE__ == $PROGRAM_NAME',
+             'end']
+      inspect_source(cop, src)
+      expect(cop.offenses).to be_empty
+    end
+
+    it "auto-corrects ' with \"" do
+      new_source = autocorrect_source(cop, "s = 'abc'")
+      expect(new_source).to eq('s = "abc"')
+    end
+  end
+
+  context 'when configured with a bad value' do
+    let(:cop_config) { { 'EnforcedStyle' => 'other' } }
+
+    it 'fails' do
+      expect { inspect_source(cop, ['a = "b"']) }
+        .to raise_error(RuntimeError)
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/symbol_array_spec.rb b/spec/rubocop/cop/style/symbol_array_spec.rb
new file mode 100644
index 0000000..4adb8fa
--- /dev/null
+++ b/spec/rubocop/cop/style/symbol_array_spec.rb
@@ -0,0 +1,37 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::SymbolArray do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for arrays of symbols', ruby: 2.0 do
+    inspect_source(cop,
+                   ['[:one, :two, :three]'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'does not reg an offense for array with non-syms', ruby: 2.0 do
+    inspect_source(cop,
+                   ['[:one, :two, "three"]'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not reg an offense for array starting with %i', ruby: 2.0 do
+    inspect_source(cop,
+                   ['%i(one two three)'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not reg an offense for array with one element', ruby: 2.0 do
+    inspect_source(cop,
+                   ['[:three]'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does nothing on Ruby 1.9', ruby: 1.9 do
+    inspect_source(cop,
+                   ['[:one, :two, :three]'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/tab_spec.rb b/spec/rubocop/cop/style/tab_spec.rb
new file mode 100644
index 0000000..fa81d29
--- /dev/null
+++ b/spec/rubocop/cop/style/tab_spec.rb
@@ -0,0 +1,17 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::Tab do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for a line indented with tab' do
+    inspect_source(cop, ["\tx = 0"])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts a line with tab in a string' do
+    inspect_source(cop, ["(x = \"\t\")"])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/trailing_blank_lines_spec.rb b/spec/rubocop/cop/style/trailing_blank_lines_spec.rb
new file mode 100644
index 0000000..80a5121
--- /dev/null
+++ b/spec/rubocop/cop/style/trailing_blank_lines_spec.rb
@@ -0,0 +1,43 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::TrailingBlankLines do
+  subject(:cop) { described_class.new(config) }
+  let(:config) do
+    Rubocop::Config.new('TrailingWhitespace' => { 'Enabled' => true })
+  end
+
+  it 'accepts final newline' do
+    inspect_source(cop, ['x = 0', ''])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'registers an offense for multiple trailing blank lines' do
+    inspect_source(cop, ['x = 0', '', '', '', ''])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.messages).to eq(['3 trailing blank lines detected.'])
+  end
+
+  it 'auto-corrects unwanted blank lines' do
+    new_source = autocorrect_source(cop, ['x = 0', '', '', '', ''])
+    expect(new_source).to eq(['x = 0', ''].join("\n"))
+  end
+
+  it 'does not auto-correct if it interferes with TrailingWhitespace' do
+    original = ['x = 0', '', '  ', '', '']
+    new_source = autocorrect_source(cop, original)
+    expect(new_source).to eq(original.join("\n"))
+  end
+
+  context 'with TrailingWhitespace disabled' do
+    let(:config) do
+      Rubocop::Config.new('TrailingWhitespace' => { 'Enabled' => false })
+    end
+
+    it 'auto-corrects even if some lines have space' do
+      new_source = autocorrect_source(cop, ['x = 0', '', '  ', '', ''])
+      expect(new_source).to eq(['x = 0', ''].join("\n"))
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/trailing_comma_spec.rb b/spec/rubocop/cop/style/trailing_comma_spec.rb
new file mode 100644
index 0000000..2942f13
--- /dev/null
+++ b/spec/rubocop/cop/style/trailing_comma_spec.rb
@@ -0,0 +1,230 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::TrailingComma, :config do
+  subject(:cop) { described_class.new(config) }
+  let(:cop_config) { { 'EnforcedStyleForMultiline' => 'no_comma' } }
+
+  context 'with single line list of values' do
+    it 'registers an offense for trailing comma in an Array literal' do
+      inspect_source(cop, 'VALUES = [1001, 2020, 3333, ]')
+      expect(cop.messages)
+        .to eq(['Avoid comma after the last item of an array.'])
+      expect(cop.highlights).to eq([','])
+    end
+
+    it 'registers an offense for trailing comma in a Hash literal' do
+      inspect_source(cop, 'MAP = { a: 1001, b: 2020, c: 3333, }')
+      expect(cop.messages)
+        .to eq(['Avoid comma after the last item of a hash.'])
+      expect(cop.highlights).to eq([','])
+    end
+
+    it 'registers an offense for trailing comma in a method call' do
+      inspect_source(cop, 'some_method(a, b, c, )')
+      expect(cop.messages)
+        .to eq(['Avoid comma after the last parameter of a method call.'])
+      expect(cop.highlights).to eq([','])
+    end
+
+    it 'registers an offense for trailing comma in a method call with hash' \
+       ' parameters at the end' do
+      inspect_source(cop, 'some_method(a, b, c: 0, d: 1, )')
+      expect(cop.messages)
+        .to eq(['Avoid comma after the last parameter of a method call.'])
+      expect(cop.highlights).to eq([','])
+    end
+
+    it 'accepts Array literal without trailing comma' do
+      inspect_source(cop, 'VALUES = [1001, 2020, 3333]')
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts empty Array literal' do
+      inspect_source(cop, 'VALUES = []')
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts rescue clause' do
+      # The list of rescued classes is an array.
+      inspect_source(cop, ['begin',
+                           '  do_something',
+                           'rescue RuntimeError',
+                           'end'])
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts Hash literal without trailing comma' do
+      inspect_source(cop, 'MAP = { a: 1001, b: 2020, c: 3333 }')
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts empty Hash literal' do
+      inspect_source(cop, 'MAP = {}')
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts method call without trailing comma' do
+      inspect_source(cop, 'some_method(a, b, c)')
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts method call without parameters' do
+      inspect_source(cop, 'some_method')
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'with multi-line list of values' do
+    context 'when EnforcedStyleForMultiline is no_comma' do
+      it 'registers an offense for trailing comma in an Array literal' do
+        inspect_source(cop, ['VALUES = [',
+                             '           1001,',
+                             '           2020,',
+                             '           3333,',
+                             '         ]'])
+        expect(cop.highlights).to eq([','])
+      end
+
+      it 'registers an offense for trailing comma in a Hash literal' do
+        inspect_source(cop, ['MAP = { a: 1001,',
+                             '        b: 2020,',
+                             '        c: 3333,',
+                             '      }'])
+        expect(cop.highlights).to eq([','])
+      end
+
+      it 'registers an offense for trailing comma in a method call with ' \
+         'hash parameters at the end' do
+        inspect_source(cop, ['some_method(',
+                             '              a,',
+                             '              b,',
+                             '              c: 0,',
+                             '              d: 1,)'])
+        expect(cop.highlights).to eq([','])
+      end
+
+      it 'accepts an Array literal with no trailing comma' do
+        inspect_source(cop, ['VALUES = [ 1001,',
+                             '           2020,',
+                             '           3333 ]'])
+        expect(cop.offenses).to be_empty
+      end
+
+      it 'accepts a Hash literal with no trailing comma' do
+        inspect_source(cop, ['MAP = {',
+                             '        a: 1001,',
+                             '        b: 2020,',
+                             '        c: 3333',
+                             '      }'])
+        expect(cop.offenses).to be_empty
+      end
+
+      it 'accepts a method call with ' \
+         'hash parameters at the end and no trailing comma' do
+        inspect_source(cop, ['some_method(a,',
+                             '            b,',
+                             '            c: 0,',
+                             '            d: 1',
+                             '           )'])
+        expect(cop.offenses).to be_empty
+      end
+
+      it 'accepts comma inside a heredoc' \
+         ' parameters at the end' do
+        inspect_source(cop, ['route(help: {',
+                             "  'auth' => <<-HELP.chomp",
+                             ',',
+                             'HELP',
+                             '})'])
+        expect(cop.offenses).to be_empty
+      end
+    end
+
+    context 'when EnforcedStyleForMultiline is comma' do
+      let(:cop_config) { { 'EnforcedStyleForMultiline' => 'comma' } }
+
+      it 'registers an offense for no trailing comma in an Array literal' do
+        inspect_source(cop, ['VALUES = [',
+                             '           1001,',
+                             '           2020,',
+                             '           3333]'])
+        expect(cop.messages)
+          .to eq(['Put a comma after the last item of a multiline array.'])
+        expect(cop.highlights).to eq(['3333'])
+      end
+
+      it 'registers an offense for no trailing comma in a Hash literal' do
+        inspect_source(cop, ['MAP = { a: 1001,',
+                             '        b: 2020,',
+                             '        c: 3333 }'])
+        expect(cop.messages)
+          .to eq(['Put a comma after the last item of a multiline hash.'])
+        expect(cop.highlights).to eq(['c: 3333'])
+      end
+
+      it 'registers an offense for no trailing comma in a method call with' \
+         ' hash parameters at the end' do
+        inspect_source(cop, ['some_method(',
+                             '              a,',
+                             '              b,',
+                             '              c: 0,',
+                             '              d: 1',
+                             '           )'])
+        expect(cop.messages)
+          .to eq(['Put a comma after the last parameter of a multiline ' \
+                  'method call.'])
+        expect(cop.highlights).to eq(['d: 1'])
+      end
+
+      it 'accepts trailing comma in an Array literal' do
+        inspect_source(cop, ['VALUES = [1001,',
+                             '          2020,',
+                             '          3333,',
+                             '         ]'])
+        expect(cop.offenses).to be_empty
+      end
+
+      it 'accepts trailing comma in a Hash literal' do
+        inspect_source(cop, ['MAP = {',
+                             '        a: 1001,',
+                             '        b: 2020,',
+                             '        c: 3333,',
+                             '      }'])
+        expect(cop.offenses).to be_empty
+      end
+
+      it 'accepts trailing comma in a method call with hash' \
+         ' parameters at the end' do
+        inspect_source(cop, ['some_method(',
+                             '              a,',
+                             '              b,',
+                             '              c: 0,',
+                             '              d: 1,',
+                             '           )'])
+        expect(cop.offenses).to be_empty
+      end
+
+      it 'accepts a multiline word array' do
+        inspect_source(cop, ['ingredients = %w(',
+                             '  sausage',
+                             '  anchovies',
+                             '  olives',
+                             ')'])
+        expect(cop.offenses).to be_empty
+      end
+
+      it 'accepts missing comma after a heredoc' do
+        # A heredoc that's the last item in a literal or parameter list can not
+        # have a trailing comma. It's a syntax error.
+        inspect_source(cop, ['route(help: {',
+                             "  'auth' => <<-HELP.chomp",
+                             '...',
+                             'HELP',
+                             '},)']) # We still need a comma after the hash.
+        expect(cop.offenses).to be_empty
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/trailing_whitespace_spec.rb b/spec/rubocop/cop/style/trailing_whitespace_spec.rb
new file mode 100644
index 0000000..0607082
--- /dev/null
+++ b/spec/rubocop/cop/style/trailing_whitespace_spec.rb
@@ -0,0 +1,30 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::TrailingWhitespace do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for a line ending with space' do
+    source = ['x = 0 ']
+    inspect_source(cop, source)
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for a line ending with tab' do
+    inspect_source(cop, ["x = 0\t"])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts a line without trailing whitespace' do
+    inspect_source(cop, ["x = 0\n"])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'auto-corrects unwanted space' do
+    new_source = autocorrect_source(cop, ['x = 0 ',
+                                          "x = 0\t"])
+    expect(new_source).to eq(['x = 0',
+                              'x = 0'].join("\n"))
+  end
+end
diff --git a/spec/rubocop/cop/style/trivial_accessors_spec.rb b/spec/rubocop/cop/style/trivial_accessors_spec.rb
new file mode 100644
index 0000000..c10e793
--- /dev/null
+++ b/spec/rubocop/cop/style/trivial_accessors_spec.rb
@@ -0,0 +1,418 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::TrivialAccessors, :config do
+  subject(:cop) { described_class.new(config) }
+  let(:cop_config) { {} }
+
+  it 'finds trivial reader' do
+    inspect_source(cop,
+                   ['def foo',
+                    '  @foo',
+                    'end',
+                    '',
+                    'def Foo',
+                    '  @Foo',
+                    'end'])
+    expect(cop.offenses.size).to eq(2)
+    expect(cop.offenses
+            .map(&:line).sort).to eq([1, 5])
+    expect(cop.messages)
+      .to eq(['Use `attr_reader` to define trivial reader methods.'] * 2)
+  end
+
+  it 'finds trivial reader in a class' do
+    inspect_source(cop,
+                   ['class TrivialFoo',
+                    '  def foo',
+                    '    @foo',
+                    '  end',
+                    '  def bar',
+                    '    !foo',
+                    '  end',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.offenses
+             .map(&:line).sort).to eq([2])
+  end
+
+  it 'finds trivial reader in a class method' do
+    inspect_source(cop,
+                   ['class TrivialFoo',
+                    '  def self.foo',
+                    '    @foo',
+                    '  end',
+                    '  def bar',
+                    '    !foo',
+                    '  end',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.offenses
+             .map(&:line).sort).to eq([2])
+  end
+
+  it 'finds trivial reader in a nested class' do
+    inspect_source(cop,
+                   ['class TrivialFoo',
+                    '  class Nested',
+                    '    def foo',
+                    '      @foo',
+                    '    end',
+                    '  end',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.offenses
+             .map(&:line).sort).to eq([3])
+  end
+
+  it 'finds trivial readers in a little less trivial class' do
+    inspect_source(cop,
+                   ['class TrivialFoo',
+                    '  def foo',
+                    '    @foo',
+                    '  end',
+                    '  def foo_and_bar',
+                    '    @foo_bar = @foo + @bar',
+                    '  end',
+                    '  def foo_bar',
+                    '    @foo_bar',
+                    '  end',
+                    '  def foo?',
+                    '    foo.present?',
+                    '  end',
+                    '  def bar?',
+                    '    !bar',
+                    '  end',
+                    '  def foobar',
+                    '    foo? ? foo.value : "bar"',
+                    '  end',
+                    '  def bar',
+                    '    foo.bar',
+                    '  end',
+                    '  def foo_required?',
+                    '    super && !bar_required?',
+                    '  end',
+                    '  def self.from_omniauth(auth)',
+                    '    foobars.each do |f|',
+                    '      # do stuff',
+                    '    end',
+                    '  end',
+                    '  def regex',
+                    '    %r{\A#{visit node}\Z}',
+                    '  end',
+                    '  def array',
+                    '    [foo, bar].join',
+                    '  end',
+                    '  def string',
+                    '    "string"',
+                    '  end',
+                    '  def class',
+                    '    Foo.class',
+                    '  end',
+                    ' def with_return',
+                    '   return foo',
+                    ' end',
+                    ' def captures',
+                    '   (length - 1).times.map { |i| self[i + 1] }',
+                    ' end',
+                    ' def foo val',
+                    '   super',
+                    '   @val',
+                    ' end',
+                    'end'])
+    expect(cop.offenses.size).to eq(2)
+    expect(cop.offenses
+             .map(&:line).sort).to eq([2, 8])
+  end
+
+  it 'finds trivial reader with braces' do
+    inspect_source(cop,
+                   ['class Test',
+                    '  # trivial reader with braces',
+                    '  def name()',
+                    '    @name',
+                    '  end',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.offenses
+             .map(&:line).sort).to eq([3])
+  end
+
+  it 'finds trivial writer without braces' do
+    inspect_source(cop,
+                   ['class Test',
+                    '  # trivial writer without braces',
+                    '  def name= name',
+                    '    @name = name',
+                    '  end',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.offenses .map(&:line).sort).to eq([3])
+    expect(cop.messages)
+      .to eq(['Use `attr_writer` to define trivial writer methods.'])
+  end
+
+  it 'does not find trivial writer with function calls' do
+    inspect_source(cop,
+                   ['class TrivialTest',
+                    ' def test=(val)',
+                    '   @test = val',
+                    '   some_function_call',
+                    '   or_more_of_them',
+                    ' end',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'finds trivials with less peculiar methods' do
+    inspect_source(cop,
+                   ['class NilStats',
+                    'def most_traded_pair',
+                    'end',
+                    'def win_ratio',
+                    'end',
+                    'def win_ratio_percentage()',
+                    'end',
+                    'def pips_won',
+                    '  0.0',
+                    'end',
+                    'def gain_at(date)',
+                    '  1',
+                    'end',
+                    'def gain_percentage',
+                    '  0',
+                    'end',
+                    'def gain_breakdown(options = {})',
+                    '  []',
+                    'end',
+                    'def copy_to_all_ratio',
+                    '  nil',
+                    'end',
+                    'def trade_population',
+                    '  {}',
+                    'end',
+                    'def average_leverage',
+                    '  1',
+                    'end',
+                    'def with_yield',
+                    '  yield',
+                    'rescue Error => e',
+                    '  #do stuff',
+                    'end',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'treats splats as non-trivial' do
+    inspect_source(cop,
+                   [' def splatomatic(*values)',
+                    '   @splatomatic = values',
+                    ' end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'finds oneliner trivials' do
+    inspect_source(cop,
+                   ['class Oneliner',
+                    '  def foo; @foo; end',
+                    '  def foo= foo; @foo = foo; end',
+                    'end'])
+    expect(cop.offenses.size).to eq(2)
+    expect(cop.offenses
+             .map(&:line).sort).to eq([2, 3])
+  end
+
+  it 'does not find a trivial reader' do
+    inspect_source(cop,
+                   ['def bar',
+                    '  @bar + foo',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'finds trivial writer' do
+    inspect_source(cop,
+                   ['def foo=(val)',
+                    ' @foo = val',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.offenses
+             .map(&:line).sort).to eq([1])
+  end
+
+  it 'finds trivial writer in a class' do
+    inspect_source(cop,
+                   ['class TrivialFoo',
+                    '  def foo=(val)',
+                    '    @foo = val',
+                    '  end',
+                    '  def void(no_value)',
+                    '  end',
+                    '  def inspect(sexp)',
+                    '    each(:def, sexp) do |item|',
+                    '      #do stuff',
+                    '    end',
+                    '  end',
+                    '  def if_method(foo)',
+                    '    if true',
+                    '      unless false',
+                    '        #do stuff',
+                    '      end',
+                    '    end',
+                    '  end',
+                    'end'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.offenses
+             .map(&:line).sort).to eq([2])
+  end
+
+  it 'finds trivial accessors in a little less trivial class' do
+    inspect_source(cop,
+                   ['class TrivialFoo',
+                    ' def foo',
+                    ' @foo',
+                    ' end',
+                    ' def foo_and_bar',
+                    ' @foo_bar = @foo + @bar',
+                    ' end',
+                    ' def foo_bar',
+                    ' @foo_bar',
+                    ' end',
+                    ' def bar=(bar_value)',
+                    ' @bar = bar_value',
+                    ' end',
+                    'end'])
+    expect(cop.offenses.size).to eq(3)
+    expect(cop.offenses
+             .map(&:line).sort).to eq([2, 8, 11])
+  end
+
+  it 'does not find a trivial writer' do
+    inspect_source(cop,
+                   ['def bar=(value)',
+                    ' @bar = value + 42',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'finds trivial writers in a little less trivial class' do
+    inspect_source(cop,
+                   ['class TrivialFoo',
+                    ' def foo_bar=(foo, bar)',
+                    ' @foo_bar = foo + bar',
+                    ' end',
+                    ' def universal=(answer=42)',
+                    ' @universal = answer',
+                    ' end',
+                    ' def bar=(bar_value)',
+                    ' @bar = bar_value',
+                    ' end',
+                    'end'])
+    expect(cop.offenses.size).to eq(2)
+    expect(cop.offenses
+             .map(&:line).sort).to eq([5, 8])
+  end
+
+  it 'does not find trivial accessors with method calls' do
+    inspect_source(cop,
+                   ['class TrivialFoo',
+                    ' def foo_bar(foo)',
+                    '   foo_bar = foo + 42',
+                    ' end',
+                    ' def foo(value)',
+                    '   foo = []',
+                    '   # do stuff',
+                    '   foo',
+                    ' end',
+                    ' def bar',
+                    '   foo_method',
+                    ' end',
+                    'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not find trivial writer with exceptions' do
+    inspect_source(cop,
+                   [' def expiration_formatted=(value)',
+                    '   begin',
+                    '     @expiration = foo_stuff',
+                    '   rescue ArgumentError',
+                    '     @expiration = nil',
+                    '   end',
+                    '   self[:expiration] = @expiration',
+                    ' end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts an initialize method looking like a writer' do
+    inspect_source(cop,
+                   [' def initialize(value)',
+                    '   @top = value',
+                    ' end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  context 'exact name match required' do
+    let(:cop_config) { { 'ExactNameMatch' => true } }
+
+    it 'finds only 1 trivial reader' do
+      inspect_source(cop,
+                     ['def foo',
+                      '  @foo',
+                      'end',
+                      '',
+                      'def bar',
+                      '  @barr',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses
+               .map(&:line).sort).to eq([1])
+    end
+
+    it 'finds only 1 trivial writer' do
+      inspect_source(cop,
+                     ['def foo=(foo)',
+                      '  @foo = foo',
+                      'end',
+                      '',
+                      'def bar=(bar)',
+                      '  @barr = bar',
+                      'end'])
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.offenses
+               .map(&:line).sort).to eq([1])
+    end
+  end
+
+  context 'with predicates allowed' do
+    let(:cop_config) { { 'AllowPredicates' => true } }
+
+    it 'ignores accessors ending with a question mark' do
+      inspect_source(cop,
+                     [' def foo?',
+                      '   @foo',
+                      ' end'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'with whitelist defined' do
+    let(:cop_config) { { 'Whitelist' => ['to_foo', 'bar='] } }
+
+    it 'ignores accessors in the whitelist' do
+      inspect_source(cop,
+                     [' def to_foo',
+                      '   @foo',
+                      ' end'])
+      expect(cop.offenses).to be_empty
+    end
+    it 'ignores writers in the whitelist' do
+      inspect_source(cop,
+                     [' def bar=(bar)',
+                      '   @bar = bar',
+                      ' end'])
+      expect(cop.offenses).to be_empty
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/unless_else_spec.rb b/spec/rubocop/cop/style/unless_else_spec.rb
new file mode 100644
index 0000000..d56b52e
--- /dev/null
+++ b/spec/rubocop/cop/style/unless_else_spec.rb
@@ -0,0 +1,23 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::UnlessElse do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for an unless with else' do
+    inspect_source(cop, ['unless x',
+                         '  a = 1',
+                         'else',
+                         '  a = 0',
+                         'end'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts an unless without else' do
+    inspect_source(cop, ['unless x',
+                         '  a = 1',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+end
diff --git a/spec/rubocop/cop/style/variable_interpolation_spec.rb b/spec/rubocop/cop/style/variable_interpolation_spec.rb
new file mode 100644
index 0000000..0cc1ab9
--- /dev/null
+++ b/spec/rubocop/cop/style/variable_interpolation_spec.rb
@@ -0,0 +1,56 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::VariableInterpolation do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for interpolated global variables' do
+    inspect_source(cop,
+                   ['puts "this is a #$test"'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.highlights).to eq(['$test'])
+    expect(cop.messages)
+      .to eq(['Replace interpolated variable `$test`' \
+              ' with expression `#{$test}`.'])
+  end
+
+  it 'registers an offense for interpolated regexp back references' do
+    inspect_source(cop,
+                   ['puts "this is a #$1"'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.highlights).to eq(['$1'])
+    expect(cop.messages)
+      .to eq(['Replace interpolated variable `$1` with expression `#{$1}`.'])
+  end
+
+  it 'registers an offense for interpolated instance variables' do
+    inspect_source(cop,
+                   ['puts "this is a #@test"'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.highlights).to eq(['@test'])
+    expect(cop.messages)
+      .to eq(['Replace interpolated variable `@test`' \
+              ' with expression `#{@test}`.'])
+  end
+
+  it 'registers an offense for interpolated class variables' do
+    inspect_source(cop,
+                   ['puts "this is a #@@t"'])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.highlights).to eq(['@@t'])
+    expect(cop.messages)
+      .to eq(['Replace interpolated variable `@@t` with expression `#{@@t}`.'])
+  end
+
+  it 'does not register an offense for variables in expressions' do
+    inspect_source(cop,
+                   ['puts "this is a #{@test} #{@@t} #{$t} #{$1}"'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'autocorrects by adding the missing {}' do
+    corrected = autocorrect_source(cop, ['"some #@var"'])
+    expect(corrected).to eq '"some #{@var}"'
+  end
+end
diff --git a/spec/rubocop/cop/style/variable_name_spec.rb b/spec/rubocop/cop/style/variable_name_spec.rb
new file mode 100644
index 0000000..c2e5751
--- /dev/null
+++ b/spec/rubocop/cop/style/variable_name_spec.rb
@@ -0,0 +1,107 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::VariableName, :config do
+  subject(:cop) { described_class.new(config) }
+
+  shared_examples 'always accepted' do
+    it 'accepts screaming snake case globals' do
+      inspect_source(cop, '$MY_GLOBAL = 0')
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts screaming snake case constants' do
+      inspect_source(cop, 'MY_CONSTANT = 0')
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts assigning to camel case constant' do
+      inspect_source(cop, 'Paren = Struct.new :left, :right, :kind')
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts assignment with indexing of self' do
+      inspect_source(cop, 'self[:a] = b')
+      expect(cop.offenses).to be_empty
+    end
+  end
+
+  context 'when configured for snake_case' do
+    let(:cop_config) { { 'EnforcedStyle' => 'snake_case' } }
+
+    it 'registers an offense for camel case in local variable name' do
+      inspect_source(cop, 'myLocal = 1')
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.highlights).to eq(['myLocal'])
+      expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' =>
+                                                 'camelCase')
+    end
+
+    it 'registers an offense for correct + opposite' do
+      inspect_source(cop, ['my_local = 1',
+                           'myLocal = 1'])
+      expect(cop.highlights).to eq(['myLocal'])
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'registers an offense for camel case in instance variable name' do
+      inspect_source(cop, '@myAttribute = 3')
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.highlights).to eq(['@myAttribute'])
+    end
+
+    it 'registers an offense for camel case in setter name' do
+      inspect_source(cop, 'self.mySetter = 2')
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.highlights).to eq(['mySetter'])
+    end
+
+    include_examples 'always accepted'
+  end
+
+  context 'when configured for camelCase' do
+    let(:cop_config) { { 'EnforcedStyle' => 'camelCase' } }
+
+    it 'registers an offense for snake case in local variable name' do
+      inspect_source(cop, 'my_local = 1')
+      expect(cop.offenses.size).to eq(1)
+      expect(cop.highlights).to eq(['my_local'])
+      expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' =>
+                                                 'snake_case')
+    end
+
+    it 'registers an offense for opposite + correct' do
+      inspect_source(cop, ['my_local = 1',
+                           'myLocal = 1'])
+      expect(cop.highlights).to eq(['my_local'])
+      expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
+    end
+
+    it 'accepts camel case in local variable name' do
+      inspect_source(cop, 'myLocal = 1')
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts camel case in instance variable name' do
+      inspect_source(cop, '@myAttribute = 3')
+      expect(cop.offenses).to be_empty
+    end
+
+    it 'accepts camel case in setter name' do
+      inspect_source(cop, 'self.mySetter = 2')
+      expect(cop.offenses).to be_empty
+    end
+
+    include_examples 'always accepted'
+  end
+
+  context 'when configured with a bad value' do
+    let(:cop_config) { { 'EnforcedStyle' => 'other' } }
+
+    it 'fails' do
+      expect { inspect_source(cop, 'a = 3') }
+        .to raise_error(RuntimeError)
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/when_then_spec.rb b/spec/rubocop/cop/style/when_then_spec.rb
new file mode 100644
index 0000000..1877a5e
--- /dev/null
+++ b/spec/rubocop/cop/style/when_then_spec.rb
@@ -0,0 +1,40 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::WhenThen do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for when x;' do
+    inspect_source(cop, ['case a',
+                         'when b; c',
+                         'end'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts when x then' do
+    inspect_source(cop, ['case a',
+                         'when b then c',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts ; separating statements in the body of when' do
+    inspect_source(cop, ['case a',
+                         'when b then c; d',
+                         'end',
+                         '',
+                         'case e',
+                         'when f',
+                         '  g; h',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'auto-corrects "when x;" with "when x then"' do
+    new_source = autocorrect_source(cop, ['case a',
+                                          'when b; c',
+                                          'end'])
+    expect(new_source).to eq("case a\nwhen b then c\nend")
+  end
+end
diff --git a/spec/rubocop/cop/style/while_until_do_spec.rb b/spec/rubocop/cop/style/while_until_do_spec.rb
new file mode 100644
index 0000000..ccbe739
--- /dev/null
+++ b/spec/rubocop/cop/style/while_until_do_spec.rb
@@ -0,0 +1,53 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::WhileUntilDo do
+  subject(:cop) { described_class.new }
+
+  it 'registers an offense for do in multiline while' do
+    inspect_source(cop, ['while cond do',
+                         'end'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for do in multiline until' do
+    inspect_source(cop, ['until cond do',
+                         'end'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'accepts do in single-line while' do
+    inspect_source(cop, ['while cond do something end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts do in single-line until' do
+    inspect_source(cop, ['until cond do something end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'it accepts multi-line while without do' do
+    inspect_source(cop, ['while cond',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'it accepts multi-line until without do' do
+    inspect_source(cop, ['until cond',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'auto-corrects the usage of "do" in multiline while' do
+    new_source = autocorrect_source(cop, ['while cond do',
+                                          'end'])
+    expect(new_source).to eq("while cond\nend")
+  end
+
+  it 'auto-corrects the usage of "do" in multiline until' do
+    new_source = autocorrect_source(cop, ['until cond do',
+                                          'end'])
+    expect(new_source).to eq("until cond\nend")
+  end
+end
diff --git a/spec/rubocop/cop/style/while_until_modifier_spec.rb b/spec/rubocop/cop/style/while_until_modifier_spec.rb
new file mode 100644
index 0000000..ebaf398
--- /dev/null
+++ b/spec/rubocop/cop/style/while_until_modifier_spec.rb
@@ -0,0 +1,93 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::WhileUntilModifier do
+  include StatementModifierHelper
+
+  subject(:cop) { described_class.new(config) }
+  let(:config) do
+    hash = { 'LineLength' => { 'Max' => 79 } }
+    Rubocop::Config.new(hash)
+  end
+
+  it "accepts multiline unless that doesn't fit on one line" do
+    check_too_long(cop, 'unless')
+  end
+
+  it 'accepts multiline unless whose body is more than one line' do
+    check_short_multiline(cop, 'unless')
+  end
+
+  it 'registers an offense for multiline while that fits on one line' do
+    check_really_short(cop, 'while')
+  end
+
+  it "accepts multiline while that doesn't fit on one line" do
+    check_too_long(cop, 'while')
+  end
+
+  it 'accepts multiline while whose body is more than one line' do
+    check_short_multiline(cop, 'while')
+  end
+
+  it 'accepts oneline while when condition has local variable assignment' do
+    inspect_source(cop, ['lines = %w{first second third}',
+                         'while (line = lines.shift)',
+                         '  puts line',
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'registers an offense for oneline while when assignment is in body' do
+    inspect_source(cop, ['while true',
+                         '  x = 0',
+                         'end'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for multiline until that fits on one line' do
+    check_really_short(cop, 'until')
+  end
+
+  it "accepts multiline until that doesn't fit on one line" do
+    check_too_long(cop, 'until')
+  end
+
+  it 'accepts multiline until whose body is more than one line' do
+    check_short_multiline(cop, 'until')
+  end
+
+  it 'accepts an empty condition' do
+    check_empty(cop, 'while')
+    check_empty(cop, 'until')
+  end
+
+  it 'accepts modifier while' do
+    inspect_source(cop, ['ala while bala'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'accepts modifier until' do
+    inspect_source(cop, ['ala until bala'])
+    expect(cop.offenses).to be_empty
+  end
+
+  context 'when the maximum line length is specified by the cop itself' do
+    let(:config) do
+      hash = {
+        'LineLength' => { 'Max' => 100 },
+        'WhileUntilModifier' => { 'MaxLineLength' => 79 }
+      }
+      Rubocop::Config.new(hash)
+    end
+
+    it "accepts multiline while that doesn't fit on one line" do
+      check_too_long(cop, 'while')
+    end
+
+    it "accepts multiline until that doesn't fit on one line" do
+      check_too_long(cop, 'until')
+    end
+  end
+end
diff --git a/spec/rubocop/cop/style/word_array_spec.rb b/spec/rubocop/cop/style/word_array_spec.rb
new file mode 100644
index 0000000..e18b112
--- /dev/null
+++ b/spec/rubocop/cop/style/word_array_spec.rb
@@ -0,0 +1,97 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Style::WordArray, :config do
+  subject(:cop) { described_class.new(config) }
+  let(:cop_config) { { 'MinSize' => 0 } }
+
+  it 'registers an offense for arrays of single quoted strings' do
+    inspect_source(cop,
+                   ["['one', 'two', 'three']"])
+    expect(cop.offenses.size).to eq(1)
+    expect(cop.config_to_allow_offenses).to eq('MinSize' => 3)
+  end
+
+  it 'registers an offense for arrays of double quoted strings' do
+    inspect_source(cop,
+                   ['["one", "two", "three"]'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'registers an offense for arrays with character constants' do
+    inspect_source(cop,
+                   ['["one", ?\n]'])
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'does not register an offense for array of non-words' do
+    inspect_source(cop,
+                   ['["one space", "two", "three"]'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense for array containing non-string' do
+    inspect_source(cop,
+                   ['["one", "two", 3]'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense for array starting with %w' do
+    inspect_source(cop,
+                   ['%w(one two three)'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense for array with one element' do
+    inspect_source(cop,
+                   ['["three"]'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense for array with empty strings' do
+    inspect_source(cop,
+                   ['["", "two", "three"]'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense for array with allowed number of strings' do
+    cop_config['MinSize'] = 3
+
+    inspect_source(cop,
+                   ['["one", "two", "three"]'])
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'does not register an offense for an array with comments in it' do
+    inspect_source(cop,
+                   ['[',
+                    '"foo", # comment here',
+                    '"bar", # this thing was done because of a bug',
+                    '"baz" # do not delete this line',
+                    ']'])
+
+    expect(cop.offenses).to be_empty
+  end
+
+  it 'registers an offense for an array with comments outside of it' do
+    inspect_source(cop,
+                   ['[',
+                    '"foo",',
+                    '"bar",',
+                    '"baz"',
+                    '] # test'])
+
+    expect(cop.offenses.size).to eq(1)
+  end
+
+  it 'auto-corrects an array of words' do
+    new_source = autocorrect_source(cop, "['one', %q(two), 'three']")
+    expect(new_source).to eq('%w(one two three)')
+  end
+
+  it 'auto-corrects an array of words and character constants' do
+    new_source = autocorrect_source(cop, '[%{one}, %Q(two), ?\n, ?\t]')
+    expect(new_source).to eq('%W(one two \n \t)')
+  end
+end
diff --git a/spec/rubocop/cop/team_spec.rb b/spec/rubocop/cop/team_spec.rb
new file mode 100644
index 0000000..fe528a7
--- /dev/null
+++ b/spec/rubocop/cop/team_spec.rb
@@ -0,0 +1,142 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Team do
+  subject(:team) { described_class.new(cop_classes, config, options) }
+  let(:cop_classes) { Rubocop::Cop::Cop.non_rails }
+  let(:config) { Rubocop::ConfigLoader.default_configuration }
+  let(:options) { nil }
+
+  describe '#autocorrect?' do
+    subject { team.autocorrect? }
+
+    context 'when the option argument of .new is omitted' do
+      subject { described_class.new(cop_classes, config).autocorrect? }
+      it { should be_false }
+    end
+
+    context 'when { auto_correct: true } is passed to .new' do
+      let(:options) { { auto_correct: true } }
+      it { should be_true }
+    end
+  end
+
+  describe '#debug?' do
+    subject { team.debug? }
+
+    context 'when the option argument of .new is omitted' do
+      subject { described_class.new(cop_classes, config).debug? }
+      it { should be_false }
+    end
+
+    context 'when { debug: true } is passed to .new' do
+      let(:options) { { debug: true } }
+      it { should be_true }
+    end
+  end
+
+  describe '#inspect_file', :isolated_environment do
+    include FileHelper
+
+    let(:file_path) { '/tmp/example.rb' }
+    let(:offenses) do
+      team.inspect_file(Rubocop::SourceParser.parse_file(file_path))
+    end
+
+    before do
+      create_file(file_path, [
+        '#' * 90,
+        'puts test;'
+      ])
+    end
+
+    it 'returns offenses' do
+      expect(offenses).not_to be_empty
+      expect(offenses.all? { |o| o.is_a?(Rubocop::Cop::Offense) }).to be_true
+    end
+
+    context 'when Parser reports non-fatal warning for the file' do
+      before do
+        create_file(file_path, [
+          '# encoding: utf-8',
+          '#' * 90,
+          'puts *test'
+        ])
+      end
+
+      let(:cop_names) { offenses.map(&:cop_name) }
+
+      it 'returns Parser warning offenses' do
+        expect(cop_names).to include('AmbiguousOperator')
+      end
+
+      it 'returns offenses from cops' do
+        expect(cop_names).to include('LineLength')
+      end
+    end
+
+    context 'when autocorrection is enabled' do
+      let(:options) { { auto_correct: true } }
+
+      before do
+        create_file(file_path, [
+          '# encoding: utf-8',
+          'puts "string"'
+        ])
+      end
+
+      it 'does autocorrection' do
+        team.inspect_file(Rubocop::SourceParser.parse_file(file_path))
+        corrected_source = File.read(file_path)
+        expect(corrected_source).to eq([
+          '# encoding: utf-8',
+          "puts 'string'",
+          ''
+        ].join("\n"))
+      end
+
+      it 'still returns offenses' do
+        expect(offenses.first.cop_name).to eq('StringLiterals')
+      end
+    end
+  end
+
+  describe '#cops' do
+    subject(:cops) { team.cops }
+
+    it 'returns cop instances' do
+      expect(cops).not_to be_empty
+      expect(cops.all? { |c| c.is_a?(Rubocop::Cop::Cop) }).to be_true
+    end
+
+    context 'when only some cop classes are passed to .new' do
+      let(:cop_classes) do
+        [Rubocop::Cop::Lint::Void, Rubocop::Cop::Style::LineLength]
+      end
+
+      it 'returns only intances of the classes' do
+        expect(cops.size).to eq(2)
+        cops.sort! { |a, b| a.name <=> b.name }
+        expect(cops[0].name).to eq('LineLength')
+        expect(cops[1].name).to eq('Void')
+      end
+    end
+
+    context 'when some classes are disabled with config' do
+      before do
+        %w(Void LineLength).each do |cop_name|
+          config.for_cop(cop_name)['Enabled'] = false
+        end
+      end
+
+      let(:cop_names) { cops.map(&:name) }
+
+      it 'does not return intances of the classes' do
+        expect(cops).not_to be_empty
+        expect(cop_names).not_to include('Void')
+        expect(cop_names).not_to include('LineLength')
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/cop/util_spec.rb b/spec/rubocop/cop/util_spec.rb
new file mode 100644
index 0000000..75736e3
--- /dev/null
+++ b/spec/rubocop/cop/util_spec.rb
@@ -0,0 +1,49 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::Util do
+  describe '#line_range' do
+    include ASTHelper
+
+    let(:source) do
+      <<-END
+        foo = 1
+        bar = 2
+        class Test
+          def some_method
+            do_something
+          end
+        end
+        baz = 8
+      END
+    end
+
+    let(:ast) do
+      processed_source = parse_source(source)
+      processed_source.ast
+    end
+
+    let(:node) do
+      target_node = scan_node(ast) do |node|
+        break node if node.type == :class
+      end
+      fail 'No target node found!' unless target_node
+      target_node
+    end
+
+    context 'when Source::Range object is passed' do
+      it 'returns line range of that' do
+        line_range = Rubocop::Cop::Util.line_range(node.loc.expression)
+        expect(line_range).to eq(3..7)
+      end
+    end
+
+    context 'when AST::Node object is passed' do
+      it 'returns line range of the expression' do
+        line_range = Rubocop::Cop::Util.line_range(node)
+        expect(line_range).to eq(3..7)
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/cop/variable_inspector/assignment_spec.rb b/spec/rubocop/cop/variable_inspector/assignment_spec.rb
new file mode 100644
index 0000000..9902df5
--- /dev/null
+++ b/spec/rubocop/cop/variable_inspector/assignment_spec.rb
@@ -0,0 +1,213 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::VariableInspector::Assignment do
+  include ASTHelper
+  include AST::Sexp
+
+  let(:ast) do
+    processed_source = Rubocop::SourceParser.parse(source)
+    processed_source.ast
+  end
+
+  let(:source) do
+    <<-END
+      class SomeClass
+        def some_method(flag)
+          puts 'Hello World!'
+
+          if flag > 0
+            foo = 1
+          end
+        end
+      end
+    END
+  end
+
+  let(:def_node) do
+    found_node = scan_node(ast, include_origin_node: true) do |node|
+      break node if node.type == :def
+    end
+    fail 'No def node found!' unless found_node
+    found_node
+  end
+
+  let(:lvasgn_node) do
+    found_node = scan_node(ast) do |node|
+      break node if node.type == :lvasgn
+    end
+    fail 'No lvasgn node found!' unless found_node
+    found_node
+  end
+
+  let(:name) { lvasgn_node.children.first }
+  let(:scope) { Rubocop::Cop::VariableInspector::Scope.new(def_node) }
+  let(:variable) do
+    Rubocop::Cop::VariableInspector::Variable.new(name, lvasgn_node, scope)
+  end
+  let(:assignment) { described_class.new(lvasgn_node, variable) }
+
+  describe '.new' do
+    let(:variable) { double('variable') }
+
+    context 'when an assignment node is passed' do
+      it 'does not raise error' do
+        node = s(:lvasgn, :foo)
+        expect { described_class.new(node, variable) }.not_to raise_error
+      end
+    end
+
+    context 'when an argument declaration node is passed' do
+      it 'raises error' do
+        node = s(:arg, :foo)
+        expect { described_class.new(node, variable) }
+          .to raise_error(ArgumentError)
+      end
+    end
+
+    context 'when any other type node is passed' do
+      it 'raises error' do
+        node = s(:def)
+        expect { described_class.new(node, variable) }
+          .to raise_error(ArgumentError)
+      end
+    end
+  end
+
+  describe '#name' do
+    it 'returns the variable name' do
+      expect(assignment.name).to eq(:foo)
+    end
+  end
+
+  describe '#meta_assignment_node' do
+    context 'when it is += operator assignment' do
+      let(:source) do
+        <<-END
+          def some_method
+            foo += 1
+          end
+        END
+      end
+
+      it 'returns op_asgn node' do
+        expect(assignment.meta_assignment_node.type).to eq(:op_asgn)
+      end
+    end
+
+    context 'when it is ||= operator assignment' do
+      let(:source) do
+        <<-END
+          def some_method
+            foo ||= 1
+          end
+        END
+      end
+
+      it 'returns or_asgn node' do
+        expect(assignment.meta_assignment_node.type).to eq(:or_asgn)
+      end
+    end
+
+    context 'when it is &&= operator assignment' do
+      let(:source) do
+        <<-END
+          def some_method
+            foo &&= 1
+          end
+        END
+      end
+
+      it 'returns and_asgn node' do
+        expect(assignment.meta_assignment_node.type).to eq(:and_asgn)
+      end
+    end
+
+    context 'when it is multiple assignment' do
+      let(:source) do
+        <<-END
+          def some_method
+            foo, bar = [1, 2]
+          end
+        END
+      end
+
+      it 'returns masgn node' do
+        expect(assignment.meta_assignment_node.type).to eq(:masgn)
+      end
+    end
+  end
+
+  describe '#operator' do
+    context 'when it is normal assignment' do
+      let(:source) do
+        <<-END
+          def some_method
+            foo = 1
+          end
+        END
+      end
+
+      it 'returns =' do
+        expect(assignment.operator).to eq('=')
+      end
+    end
+
+    context 'when it is += operator assignment' do
+      let(:source) do
+        <<-END
+          def some_method
+            foo += 1
+          end
+        END
+      end
+
+      it 'returns +=' do
+        expect(assignment.operator).to eq('+=')
+      end
+    end
+
+    context 'when it is ||= operator assignment' do
+      let(:source) do
+        <<-END
+          def some_method
+            foo ||= 1
+          end
+        END
+      end
+
+      it 'returns ||=' do
+        expect(assignment.operator).to eq('||=')
+      end
+    end
+
+    context 'when it is &&= operator assignment' do
+      let(:source) do
+        <<-END
+          def some_method
+            foo &&= 1
+          end
+        END
+      end
+
+      it 'returns &&=' do
+        expect(assignment.operator).to eq('&&=')
+      end
+    end
+
+    context 'when it is multiple assignment' do
+      let(:source) do
+        <<-END
+          def some_method
+            foo, bar = [1, 2]
+          end
+        END
+      end
+
+      it 'returns =' do
+        expect(assignment.operator).to eq('=')
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/cop/variable_inspector/locatable_spec.rb b/spec/rubocop/cop/variable_inspector/locatable_spec.rb
new file mode 100644
index 0000000..0114020
--- /dev/null
+++ b/spec/rubocop/cop/variable_inspector/locatable_spec.rb
@@ -0,0 +1,734 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::VariableInspector::Locatable do
+  include ASTHelper
+  include AST::Sexp
+
+  class LocatableObject
+    include Rubocop::Cop::VariableInspector::Locatable
+
+    attr_reader :node, :scope
+
+    def initialize(node, scope)
+      @node = node
+      @scope = scope
+    end
+  end
+
+  let(:ast) do
+    processed_source = Rubocop::SourceParser.parse(source)
+    processed_source.ast
+  end
+
+  let(:def_node) do
+    found_node = scan_node(ast, include_origin_node: true) do |node|
+      break node if node.type == :def
+    end
+    fail 'No def node found!' unless found_node
+    found_node
+  end
+
+  let(:lvasgn_node) do
+    found_node = scan_node(ast) do |node|
+      break node if node.type == :lvasgn
+    end
+    fail 'No lvasgn node found!' unless found_node
+    found_node
+  end
+
+  let(:scope) { Rubocop::Cop::VariableInspector::Scope.new(def_node) }
+  let(:assignment) { LocatableObject.new(lvasgn_node, scope) }
+
+  describe '#ancestor_nodes_in_scope' do
+    let(:source) do
+      <<-END
+        class SomeClass
+          def some_method(flag)
+            puts 'Hello World!'
+
+            if flag > 0
+              foo = 1
+            end
+          end
+        end
+      END
+    end
+
+    it 'returns its ancestor nodes in the scope excluding scope node' do
+      ancestor_types = assignment.ancestor_nodes_in_scope.map(&:type)
+      expect(ancestor_types).to eq([:begin, :if])
+    end
+  end
+
+  describe '#branch_point_node' do
+    context 'when it is not in branch' do
+      let(:source) do
+        <<-END
+          def some_method(flag)
+            foo = 1
+          end
+        END
+      end
+
+      it 'returns nil' do
+        expect(assignment.branch_point_node).to be_nil
+      end
+    end
+
+    context 'when it is inside of if' do
+      let(:source) do
+        <<-END
+          def some_method(flag)
+            if flag
+              foo = 1
+            end
+          end
+        END
+      end
+
+      it 'returns the if node' do
+        expect(assignment.branch_point_node.type).to eq(:if)
+      end
+    end
+
+    context 'when it is inside of else of if' do
+      let(:source) do
+        <<-END
+          def some_method(flag)
+            if flag
+            else
+              foo = 1
+            end
+          end
+        END
+      end
+
+      it 'returns the if node' do
+        expect(assignment.branch_point_node.type).to eq(:if)
+      end
+    end
+
+    context 'when it is inside of if condition' do
+      let(:source) do
+        <<-END
+          def some_method(flag)
+            if foo = 1
+              do_something
+            end
+          end
+        END
+      end
+
+      it 'returns nil' do
+        expect(assignment.branch_point_node).to be_nil
+      end
+    end
+
+    context 'when multiple if are nested' do
+      context 'and it is inside of inner if' do
+        let(:source) do
+          <<-END
+            def some_method(a, b)
+              if a
+                if b
+                  foo = 1
+                end
+              end
+            end
+          END
+        end
+
+        it 'returns inner if node' do
+          if_node = assignment.branch_point_node
+          expect(if_node.type).to eq(:if)
+          condition_node = if_node.children.first
+          expect(condition_node).to eq(s(:lvar, :b))
+        end
+      end
+
+      context 'and it is inside of inner if condition' do
+        let(:source) do
+          <<-END
+            def some_method(a, b)
+              if a
+                if foo = 1
+                  do_something
+                end
+              end
+            end
+          END
+        end
+
+        it 'returns the next outer if node' do
+          if_node = assignment.branch_point_node
+          expect(if_node.type).to eq(:if)
+          condition_node = if_node.children.first
+          expect(condition_node).to eq(s(:lvar, :a))
+        end
+      end
+    end
+
+    context 'when it is inside of when of case' do
+      let(:source) do
+        <<-END
+          def some_method(flag)
+            case flag
+            when 1
+              foo = 1
+            end
+          end
+        END
+      end
+
+      it 'returns the case node' do
+        expect(assignment.branch_point_node.type).to eq(:case)
+      end
+    end
+
+    context 'when it is on the left side of &&' do
+      let(:source) do
+        <<-END
+          def some_method
+            (foo = 1) && do_something
+          end
+        END
+      end
+
+      it 'returns nil' do
+        expect(assignment.branch_point_node).to be_nil
+      end
+    end
+
+    context 'when it is on the right side of &&' do
+      let(:source) do
+        <<-END
+          def some_method
+            do_something && (foo = 1)
+          end
+        END
+      end
+
+      it 'returns the and node' do
+        expect(assignment.branch_point_node.type).to eq(:and)
+      end
+    end
+
+    context 'when it is on the left side of ||' do
+      let(:source) do
+        <<-END
+          def some_method
+            (foo = 1) || do_something
+          end
+        END
+      end
+
+      it 'returns nil' do
+        expect(assignment.branch_point_node).to be_nil
+      end
+    end
+
+    context 'when it is on the right side of ||' do
+      let(:source) do
+        <<-END
+          def some_method
+            do_something || (foo = 1)
+          end
+        END
+      end
+
+      it 'returns the or node' do
+        expect(assignment.branch_point_node.type).to eq(:or)
+      end
+    end
+
+    context 'when multiple && are chained' do
+      context 'and it is on the right side of the right &&' do
+        let(:source) do
+          <<-END
+            def some_method
+              do_something && do_anything && (foo = 1)
+            end
+          END
+        end
+
+        it 'returns the right and node' do
+          and_node = assignment.branch_point_node
+          expect(and_node.type).to eq(:and)
+          right_side_node = and_node.children[1]
+          expect(right_side_node.type).to eq(:begin)
+        end
+      end
+
+      context 'and it is on the right side of the left &&' do
+        let(:source) do
+          <<-END
+            def some_method
+              do_something && (foo = 1) && do_anything
+            end
+          END
+        end
+
+        it 'returns the left and node' do
+          and_node = assignment.branch_point_node
+          expect(and_node.type).to eq(:and)
+          right_side_node = and_node.children[1]
+          expect(right_side_node.type).to eq(:begin)
+        end
+      end
+    end
+
+    context 'when it is inside of begin with rescue' do
+      let(:source) do
+        <<-END
+          def some_method(flag)
+            begin
+              foo = 1
+            rescue
+              do_something
+            end
+          end
+        END
+      end
+
+      it 'returns the rescue node' do
+        expect(assignment.branch_point_node.type).to eq(:rescue)
+      end
+    end
+
+    context 'when it is inside of rescue' do
+      let(:source) do
+        <<-END
+          def some_method(flag)
+            begin
+              do_something
+            rescue
+              foo = 1
+            end
+          end
+        END
+      end
+
+      it 'returns the rescue node' do
+        expect(assignment.branch_point_node.type).to eq(:rescue)
+      end
+    end
+
+    context 'when it is inside of begin with ensure' do
+      let(:source) do
+        <<-END
+          def some_method(flag)
+            begin
+              foo = 1
+            ensure
+              do_something
+            end
+          end
+        END
+      end
+
+      it 'returns the ensure node' do
+        expect(assignment.branch_point_node.type).to eq(:ensure)
+      end
+    end
+
+    context 'when it is inside of ensure' do
+      let(:source) do
+        <<-END
+          def some_method(flag)
+            begin
+              do_something
+            ensure
+              foo = 1
+            end
+          end
+        END
+      end
+
+      it 'returns nil' do
+        expect(assignment.branch_point_node).to be_nil
+      end
+    end
+
+    context 'when it is inside of begin without rescue' do
+      let(:source) do
+        <<-END
+          def some_method(flag)
+            begin
+              foo = 1
+            end
+          end
+        END
+      end
+
+      it 'returns nil' do
+        expect(assignment.branch_point_node).to be_nil
+      end
+    end
+  end
+
+  describe '#branch_body_node' do
+    context 'when it is not in branch' do
+      let(:source) do
+        <<-END
+          def some_method(flag)
+            foo = 1
+          end
+        END
+      end
+
+      it 'returns nil' do
+        expect(assignment.branch_body_node).to be_nil
+      end
+    end
+
+    context 'when it is inside body of if' do
+      let(:source) do
+        <<-END
+          def some_method(flag)
+            if flag
+              foo = 1
+              puts foo
+            end
+          end
+        END
+      end
+
+      it 'returns the body node' do
+        expect(assignment.branch_body_node.type).to eq(:begin)
+      end
+    end
+
+    context 'when it is inside body of else of if' do
+      let(:source) do
+        <<-END
+          def some_method(flag)
+            if flag
+              do_something
+            else
+              foo = 1
+              puts foo
+            end
+          end
+        END
+      end
+
+      it 'returns the body node' do
+        expect(assignment.branch_body_node.type).to eq(:begin)
+      end
+    end
+
+    context 'when it is on the right side of &&' do
+      let(:source) do
+        <<-END
+          def some_method
+            do_something && (foo = 1)
+          end
+        END
+      end
+
+      it 'returns the right side node' do
+        expect(assignment.branch_body_node.type).to eq(:begin)
+      end
+    end
+
+    context 'when it is on the right side of ||' do
+      let(:source) do
+        <<-END
+          def some_method
+            do_something || (foo = 1)
+          end
+        END
+      end
+
+      it 'returns the right side node' do
+        expect(assignment.branch_body_node.type).to eq(:begin)
+      end
+    end
+
+    context 'when it is inside of begin with rescue' do
+      let(:source) do
+        <<-END
+          def some_method(flag)
+            begin
+              foo = 1
+            rescue
+              do_something
+            end
+          end
+        END
+      end
+
+      it 'returns the body node' do
+        expect(assignment.branch_body_node.type).to eq(:lvasgn)
+      end
+    end
+
+    context 'when it is inside of rescue' do
+      let(:source) do
+        <<-END
+          def some_method(flag)
+            begin
+              do_something
+            rescue
+              foo = 1
+            end
+          end
+        END
+      end
+
+      it 'returns the resbody node' do
+        expect(assignment.branch_body_node.type).to eq(:resbody)
+      end
+    end
+
+    context 'when it is inside of begin with ensure' do
+      let(:source) do
+        <<-END
+          def some_method(flag)
+            begin
+              foo = 1
+            ensure
+              do_something
+            end
+          end
+        END
+      end
+
+      it 'returns the body node' do
+        expect(assignment.branch_body_node.type).to eq(:lvasgn)
+      end
+    end
+  end
+
+  describe '#branch_id' do
+    context 'when it is not in branch' do
+      let(:source) do
+        <<-END
+          def some_method(flag)
+            foo = 1
+          end
+        END
+      end
+
+      it 'returns nil' do
+        expect(assignment.branch_id).to be_nil
+      end
+    end
+
+    context 'when it is inside body of if' do
+      let(:source) do
+        <<-END
+          def some_method(flag)
+            if flag
+              foo = 1
+              puts foo
+            end
+          end
+        END
+      end
+
+      it 'returns BRANCHNODEID_if_true' do
+        expect(assignment.branch_id).to match(/^\d+_if_true/)
+      end
+    end
+
+    context 'when it is inside body of else of if' do
+      let(:source) do
+        <<-END
+          def some_method(flag)
+            if flag
+              do_something
+            else
+              foo = 1
+              puts foo
+            end
+          end
+        END
+      end
+
+      it 'returns BRANCHNODEID_if_false' do
+        expect(assignment.branch_id).to match(/^\d+_if_false/)
+      end
+    end
+
+    context 'when it is inside body of when of case' do
+      let(:source) do
+        <<-END
+          def some_method(flag)
+            case flag
+            when first
+              do_something
+            when second
+              foo = 1
+              puts foo
+            else
+              do_something
+            end
+          end
+        END
+      end
+
+      it 'returns BRANCHNODEID_case_whenINDEX' do
+        expect(assignment.branch_id).to match(/^\d+_case_when1/)
+      end
+    end
+
+    context 'when it is inside body of when of case' do
+      let(:source) do
+        <<-END
+          def some_method(flag)
+            case flag
+            when first
+              do_something
+            when second
+              do_something
+            else
+              foo = 1
+              puts foo
+            end
+          end
+        END
+      end
+
+      it 'returns BRANCHNODEID_case_else' do
+        expect(assignment.branch_id).to match(/^\d+_case_else/)
+      end
+    end
+
+    context 'when it is on the left side of &&' do
+      let(:source) do
+        <<-END
+          def some_method
+            (foo = 1) && do_something
+          end
+        END
+      end
+
+      it 'returns nil' do
+        expect(assignment.branch_id).to be_nil
+      end
+    end
+
+    context 'when it is on the right side of &&' do
+      let(:source) do
+        <<-END
+          def some_method
+            do_something && (foo = 1)
+          end
+        END
+      end
+
+      it 'returns BRANCHNODEID_and_right' do
+        expect(assignment.branch_id).to match(/^\d+_and_right/)
+      end
+    end
+
+    context 'when it is on the left side of ||' do
+      let(:source) do
+        <<-END
+          def some_method
+            (foo = 1) || do_something
+          end
+        END
+      end
+
+      it 'returns nil' do
+        expect(assignment.branch_id).to be_nil
+      end
+    end
+
+    context 'when it is on the right side of ||' do
+      let(:source) do
+        <<-END
+          def some_method
+            do_something || (foo = 1)
+          end
+        END
+      end
+
+      it 'returns BRANCHNODEID_or_right' do
+        expect(assignment.branch_id).to match(/^\d+_or_right/)
+      end
+    end
+
+    context 'when it is inside of begin with rescue' do
+      let(:source) do
+        <<-END
+          def some_method(flag)
+            begin
+              foo = 1
+            rescue
+              do_something
+            end
+          end
+        END
+      end
+
+      it 'returns BRANCHNODEID_rescue_main' do
+        expect(assignment.branch_id).to match(/^\d+_rescue_main/)
+      end
+    end
+
+    context 'when it is inside of rescue' do
+      let(:source) do
+        <<-END
+          def some_method(flag)
+            begin
+              do_something
+            rescue FirstError
+              do_something
+            rescue SecondError
+              foo = 1
+            end
+          end
+        END
+      end
+
+      it 'returns BRANCHNODEID_rescue_rescueINDEX' do
+        expect(assignment.branch_id).to match(/^\d+_rescue_rescue1/)
+      end
+    end
+
+    context 'when it is inside of else of rescue' do
+      let(:source) do
+        <<-END
+          def some_method(flag)
+            begin
+              do_something
+            rescue FirstError
+              do_something
+            rescue SecondError
+              do_something
+            else
+              foo = 1
+            end
+          end
+        END
+      end
+
+      it 'returns BRANCHNODEID_rescue_else' do
+        expect(assignment.branch_id).to match(/^\d+_rescue_else/)
+      end
+    end
+
+    context 'when it is inside of begin with ensure' do
+      let(:source) do
+        <<-END
+          def some_method(flag)
+            begin
+              foo = 1
+            ensure
+              do_something
+            end
+          end
+        END
+      end
+
+      it 'returns BRANCHNODEID_ensure_main' do
+        expect(assignment.branch_id).to match(/^\d+_ensure_main/)
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/cop/variable_inspector/scope_spec.rb b/spec/rubocop/cop/variable_inspector/scope_spec.rb
new file mode 100644
index 0000000..1888e6e
--- /dev/null
+++ b/spec/rubocop/cop/variable_inspector/scope_spec.rb
@@ -0,0 +1,184 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::VariableInspector::Scope do
+  include ASTHelper
+  include AST::Sexp
+
+  describe '.new' do
+    context 'when non scope node is passed' do
+      it 'raises error' do
+        node = s(:lvasgn)
+        expect { described_class.new(node) }.to raise_error(ArgumentError)
+      end
+    end
+
+    context 'when begin node is passed' do
+      it 'accepts that as pseudo scope for top level scope' do
+        node = s(:begin)
+        expect { described_class.new(node) }.not_to raise_error
+      end
+    end
+  end
+
+  let(:ast) do
+    ast = Rubocop::SourceParser.parse(source).ast
+    Rubocop::Cop::VariableInspector.wrap_with_top_level_node(ast)
+  end
+
+  let(:scope_node_type) { :def }
+
+  let(:scope_node) do
+    found_node = scan_node(ast, include_origin_node: true) do |node|
+      break node if node.type == scope_node_type
+    end
+    fail 'No scope node found!' unless found_node
+    found_node
+  end
+
+  subject(:scope) { described_class.new(scope_node) }
+
+  describe '#ancestors_of_node' do
+    let(:source) do
+      <<-END
+        puts 1
+
+        class SomeClass
+          def some_method
+            foo = 1
+
+            if foo > 0
+              while foo < 10
+                this_is_target
+                foo += 1
+              end
+            else
+              do_something
+            end
+          end
+        end
+      END
+    end
+
+    let(:target_node) do
+      found_node = scan_node(ast) do |node|
+        next unless node.type == :send
+        _receiver_node, method_name = *node
+        break node if method_name == :this_is_target
+      end
+      fail 'No target node found!' unless found_node
+      found_node
+    end
+
+    it 'returns nodes in between the scope node and the passed node' do
+      ancestor_nodes = scope.ancestors_of_node(target_node)
+      ancestor_types = ancestor_nodes.map(&:type)
+      expect(ancestor_types).to eq([:begin, :if, :while, :begin])
+    end
+  end
+
+  describe '#body_node' do
+    shared_examples 'returns the body node' do
+      it 'returns the body node' do
+        expect(scope.body_node.children[1]).to eq(:this_is_target)
+      end
+    end
+
+    context 'when the scope is instance method' do
+      let(:source) do
+        <<-END
+          def some_method
+            this_is_target
+          end
+        END
+      end
+
+      let(:scope_node_type) { :def }
+
+      include_examples 'returns the body node'
+    end
+
+    context 'when the scope is singleton method' do
+      let(:source) do
+        <<-END
+          def self.some_method
+            this_is_target
+          end
+        END
+      end
+
+      let(:scope_node_type) { :defs }
+
+      include_examples 'returns the body node'
+    end
+
+    context 'when the scope is module' do
+      let(:source) do
+        <<-END
+          module SomeModule
+            this_is_target
+          end
+        END
+      end
+
+      let(:scope_node_type) { :module }
+
+      include_examples 'returns the body node'
+    end
+
+    context 'when the scope is class' do
+      let(:source) do
+        <<-END
+          class SomeClass
+            this_is_target
+          end
+        END
+      end
+
+      let(:scope_node_type) { :class }
+
+      include_examples 'returns the body node'
+    end
+
+    context 'when the scope is singleton class' do
+      let(:source) do
+        <<-END
+          class << self
+            this_is_target
+          end
+        END
+      end
+
+      let(:scope_node_type) { :sclass }
+
+      include_examples 'returns the body node'
+    end
+
+    context 'when the scope is block' do
+      let(:source) do
+        <<-END
+          1.times do
+            this_is_target
+          end
+        END
+      end
+
+      let(:scope_node_type) { :block }
+
+      include_examples 'returns the body node'
+    end
+
+    context 'when the scope is top level' do
+      let(:source) do
+        <<-END
+          this_is_target
+        END
+      end
+
+      let(:scope_node_type) { :top_level }
+
+      include_examples 'returns the body node'
+    end
+  end
+end
diff --git a/spec/rubocop/cop/variable_inspector/variable_spec.rb b/spec/rubocop/cop/variable_inspector/variable_spec.rb
new file mode 100644
index 0000000..94873ed
--- /dev/null
+++ b/spec/rubocop/cop/variable_inspector/variable_spec.rb
@@ -0,0 +1,73 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::VariableInspector::Variable do
+  include AST::Sexp
+
+  describe '.new' do
+    context 'when non variable declaration node is passed' do
+      it 'raises error' do
+        name = :foo
+        declaration_node = s(:def)
+        scope = Rubocop::Cop::VariableInspector::Scope.new(s(:class))
+        expect { described_class.new(name, declaration_node, scope) }
+          .to raise_error(ArgumentError)
+      end
+    end
+  end
+
+  describe '#referenced?' do
+    let(:name) { :foo }
+    let(:declaration_node) { s(:arg, name) }
+    let(:scope) { double('scope') }
+    let(:variable) { described_class.new(name, declaration_node, scope) }
+
+    subject { variable.referenced? }
+
+    context 'when the variable is not yet assigned' do
+      it { should be_false }
+    end
+
+    context 'when the variable has an assignment' do
+      before do
+        variable.assign(s(:lvasgn, :foo))
+      end
+
+      context 'and the assignment is not yet referenced' do
+        it { should be_false }
+      end
+
+      context 'and the assignment is referenced' do
+        before do
+          variable.assignments.first.reference!
+        end
+
+        it { should be_true }
+      end
+    end
+
+    context 'when the variable has multiple assignments' do
+      before do
+        variable.assign(s(:lvasgn, :foo))
+        variable.assign(s(:lvasgn, :foo))
+      end
+
+      context 'and only once assignment is referenced' do
+        before do
+          variable.assignments[1].reference!
+        end
+
+        it { should be_true }
+      end
+
+      context 'and all assignments are referenced' do
+        before do
+          variable.assignments.each { |a| a.reference! }
+        end
+
+        it { should be_true }
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/cop/variable_inspector/variable_table_spec.rb b/spec/rubocop/cop/variable_inspector/variable_table_spec.rb
new file mode 100644
index 0000000..be08f53
--- /dev/null
+++ b/spec/rubocop/cop/variable_inspector/variable_table_spec.rb
@@ -0,0 +1,269 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::VariableInspector::VariableTable do
+  include AST::Sexp
+
+  subject(:variable_table) { described_class.new }
+
+  describe '#push_scope' do
+    it 'returns pushed scope object' do
+      node = s(:def)
+      scope = variable_table.push_scope(node)
+      expect(scope).to equal(variable_table.current_scope)
+      expect(scope.node).to equal(node)
+    end
+  end
+
+  describe '#pop_scope' do
+    before do
+      node = s(:def)
+      variable_table.push_scope(node)
+    end
+
+    it 'returns popped scope object' do
+      last_scope = variable_table.current_scope
+      popped_scope = variable_table.pop_scope
+      expect(popped_scope).to equal(last_scope)
+    end
+  end
+
+  describe '#current_scope_level' do
+    before do
+      variable_table.push_scope(s(:def))
+    end
+
+    it 'increases by pushing scope' do
+      last_scope_level = variable_table.current_scope_level
+      variable_table.push_scope(s(:def))
+      expect(variable_table.current_scope_level)
+        .to eq(last_scope_level + 1)
+    end
+
+    it 'decreases by popping scope' do
+      last_scope_level = variable_table.current_scope_level
+      variable_table.pop_scope
+      expect(variable_table.current_scope_level)
+        .to eq(last_scope_level - 1)
+    end
+  end
+
+  describe '#declare_variable' do
+    before do
+      2.times do
+        node = s(:def)
+        variable_table.push_scope(node)
+      end
+    end
+
+    it 'adds variable to current scope with its name as key' do
+      node = s(:lvasgn, :foo)
+      variable_table.declare_variable(:foo, node)
+      expect(variable_table.current_scope.variables)
+        .to have_key(:foo)
+      expect(variable_table.scope_stack[-2].variables)
+        .to be_empty
+      variable = variable_table.current_scope.variables[:foo]
+      expect(variable.declaration_node).to equal(node)
+    end
+
+    it 'returns the added variable' do
+      node = s(:lvasgn, :foo)
+      variable = variable_table.declare_variable(:foo, node)
+      expect(variable.declaration_node).to equal(node)
+    end
+  end
+
+  describe '#find_variable' do
+    before do
+      variable_table.push_scope(s(:class))
+      variable_table.declare_variable(:baz, s(:lvasgn, :baz))
+
+      variable_table.push_scope(s(:def))
+      variable_table.declare_variable(:bar, s(:lvasgn, :bar))
+    end
+
+    context 'when current scope is block' do
+      before do
+        variable_table.push_scope(s(:block))
+      end
+
+      context 'when a variable with the target name exists ' \
+              'in current scope' do
+        before do
+          variable_table.declare_variable(:foo, s(:lvasgn, :foo))
+        end
+
+        context 'and does not exist in outer scope' do
+          it 'returns the current scope variable' do
+            found_variable = variable_table.find_variable(:foo)
+            expect(found_variable.name).to eq(:foo)
+          end
+        end
+
+        context 'and also exists in outer scope' do
+          before do
+            variable_table.declare_variable(:bar, s(:lvasgn, :bar))
+          end
+
+          it 'returns the current scope variable' do
+            found_variable = variable_table.find_variable(:bar)
+            expect(found_variable.name).to equal(:bar)
+            expect(variable_table.current_scope.variables)
+              .to have_value(found_variable)
+            expect(variable_table.scope_stack[-2].variables)
+              .not_to have_value(found_variable)
+          end
+        end
+      end
+
+      context 'when a variable with the target name does not exist ' \
+              'in current scope' do
+        context 'but exists in the direct outer scope' do
+          it 'returns the direct outer scope variable' do
+            found_variable = variable_table.find_variable(:bar)
+            expect(found_variable.name).to equal(:bar)
+          end
+        end
+
+        context 'but exists in a indirect outer scope' do
+          context 'when the direct outer scope is block' do
+            before do
+              variable_table.pop_scope
+              variable_table.pop_scope
+
+              variable_table.push_scope(s(:block))
+              variable_table.push_scope(s(:block))
+            end
+
+            it 'returns the indirect outer scope variable' do
+              found_variable = variable_table.find_variable(:baz)
+              expect(found_variable.name).to equal(:baz)
+            end
+          end
+
+          context 'when the direct outer scope is not block' do
+            it 'returns nil' do
+              found_variable = variable_table.find_variable(:baz)
+              expect(found_variable).to be_nil
+            end
+          end
+        end
+
+        context 'and does not exist in all outer scopes' do
+          it 'returns nil' do
+            found_variable = variable_table.find_variable(:non)
+            expect(found_variable).to be_nil
+          end
+        end
+      end
+    end
+
+    context 'when current scope is not block' do
+      before do
+        variable_table.push_scope(s(:def))
+      end
+
+      context 'when a variable with the target name exists ' \
+              'in current scope' do
+        before do
+          variable_table.declare_variable(:foo, s(:lvasgn, :foo))
+        end
+
+        context 'and does not exist in outer scope' do
+          it 'returns the current scope variable' do
+            found_variable = variable_table.find_variable(:foo)
+            expect(found_variable.name).to eq(:foo)
+          end
+        end
+
+        context 'and also exists in outer scope' do
+          it 'returns the current scope variable' do
+            found_variable = variable_table.find_variable(:foo)
+            expect(found_variable.name).to equal(:foo)
+            expect(variable_table.current_scope.variables)
+              .to have_value(found_variable)
+            expect(variable_table.scope_stack[-2].variables)
+              .not_to have_value(found_variable)
+          end
+        end
+      end
+
+      context 'when a variable with the target name does not exist ' \
+              'in current scope' do
+        context 'but exists in the direct outer scope' do
+          it 'returns nil' do
+            found_variable = variable_table.find_variable(:bar)
+            expect(found_variable).to be_nil
+          end
+        end
+
+        context 'and does not exist in all outer scopes' do
+          it 'returns nil' do
+            found_variable = variable_table.find_variable(:non)
+            expect(found_variable).to be_nil
+          end
+        end
+      end
+    end
+  end
+
+  describe '#accessible_variables' do
+    let(:accessible_variable_names) do
+      variable_table.accessible_variables.map(&:name)
+    end
+
+    before do
+      variable_table.push_scope(s(:class))
+    end
+
+    context 'when there are no variables' do
+      it 'returns empty array' do
+        expect(variable_table.accessible_variables).to be_empty
+      end
+    end
+
+    context 'when the current scope has some variables' do
+      before do
+        variable_table.declare_variable(:foo, s(:lvasgn, :foo))
+        variable_table.declare_variable(:bar, s(:lvasgn, :bar))
+      end
+
+      it 'returns all the variables' do
+        expect(accessible_variable_names).to match_array([:foo, :bar])
+      end
+    end
+
+    context 'when the direct outer scope has some variables' do
+      before do
+        variable_table.declare_variable(:foo, s(:lvasgn, :foo))
+      end
+
+      context 'and the current scope is block' do
+        before do
+          variable_table.push_scope(s(:block))
+          variable_table.declare_variable(:bar, s(:lvasgn, :bar))
+          variable_table.declare_variable(:baz, s(:lvasgn, :baz))
+        end
+
+        it 'returns the current and direct outer scope variables' do
+          expect(accessible_variable_names)
+            .to match_array([:foo, :bar, :baz])
+        end
+      end
+
+      context 'and the current scope is not block' do
+        before do
+          variable_table.push_scope(s(:def))
+          variable_table.declare_variable(:bar, s(:lvasgn, :bar))
+          variable_table.declare_variable(:baz, s(:lvasgn, :baz))
+        end
+
+        it 'returns only the current scope variables' do
+          expect(accessible_variable_names).to match_array([:bar, :baz])
+        end
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/cop/variable_inspector_spec.rb b/spec/rubocop/cop/variable_inspector_spec.rb
new file mode 100644
index 0000000..4704871
--- /dev/null
+++ b/spec/rubocop/cop/variable_inspector_spec.rb
@@ -0,0 +1,29 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Cop::VariableInspector do
+  include AST::Sexp
+
+  class ExampleInspector
+    include Rubocop::Cop::VariableInspector
+  end
+
+  subject(:inspector) { ExampleInspector.new }
+
+  describe '#process_node' do
+    before do
+      inspector.variable_table.push_scope(s(:def))
+    end
+
+    context 'when processing lvar node' do
+      let(:node) { s(:lvar, :foo) }
+
+      context 'when the variable is not yet declared' do
+        it 'does not raise error' do
+          expect { inspector.process_node(node) }.not_to raise_error
+        end
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/file_inspector_spec.rb b/spec/rubocop/file_inspector_spec.rb
new file mode 100644
index 0000000..a6613ad
--- /dev/null
+++ b/spec/rubocop/file_inspector_spec.rb
@@ -0,0 +1,84 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+module Rubocop
+  class FileInspector
+    attr_writer :errors # Needed only for testing.
+  end
+end
+
+describe Rubocop::FileInspector do
+  subject(:inspector) { described_class.new(options) }
+  let(:options) { {} }
+  let(:offenses) { [] }
+  let(:errors) { [] }
+
+  before(:each) do
+    $stdout = StringIO.new
+    $stderr = StringIO.new
+
+    allow(inspector).to receive(:process_source) do
+      [double('ProcessedSource').as_null_object, []]
+    end
+
+    allow(inspector).to receive(:inspect_file) do
+      inspector.errors = errors
+      [offenses, !:updated_source_file]
+    end
+  end
+
+  after(:each) do
+    $stdout = STDOUT
+    $stderr = STDERR
+  end
+
+  describe '#display_error_summary' do
+    let(:errors) do
+      ['An error occurred while Encoding cop was inspecting file.rb.']
+    end
+
+    it 'displays an error message to stderr when errors are present' do
+      inspector.process_files(['file.rb'], nil) {}
+      inspector.display_error_summary
+      expect($stderr.string.lines.to_a[-6..-5])
+        .to eq(["1 error occurred:\n", "#{errors.first}\n"])
+    end
+  end
+
+  describe '#process_files' do
+    context 'if there are no offenses in inspected files' do
+      it 'returns false' do
+        result = inspector.process_files(['file.rb'], nil) {}
+        expect(result).to eq(false)
+      end
+    end
+
+    context 'if there is an offense in an inspected file' do
+      let(:offenses) do
+        [Rubocop::Cop::Offense.new(:convention,
+                                   Struct.new(:line, :column,
+                                              :source_line).new(1, 0, ''),
+                                   'Use alias_method instead of alias.',
+                                   'Alias')]
+      end
+
+      it 'returns true' do
+        expect(inspector.process_files(['file.rb'], nil) {}).to eq(true)
+      end
+
+      it 'sends the offense to a formatter' do
+        inspector.process_files(['file.rb'], nil) {}
+        expect($stdout.string.split("\n"))
+          .to eq(['Inspecting 1 file',
+                  'C',
+                  '',
+                  'Offenses:',
+                  '',
+                  "file.rb:1:1: C: #{offenses.first.message}",
+                  '',
+                  '1 file inspected, 1 offense detected'])
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/formatter/base_formatter_spec.rb b/spec/rubocop/formatter/base_formatter_spec.rb
new file mode 100644
index 0000000..77ae15a
--- /dev/null
+++ b/spec/rubocop/formatter/base_formatter_spec.rb
@@ -0,0 +1,191 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+module Rubocop
+  module Formatter
+    describe BaseFormatter do
+      include FileHelper
+
+      describe 'how the API methods are invoked', :isolated_environment do
+        subject(:formatter) { double('formatter').as_null_object }
+        let(:cli) { CLI.new }
+        let(:output) { $stdout.string }
+
+        before do
+          create_file('1_offense.rb', [
+            '# encoding: utf-8',
+            '#' * 90
+          ])
+
+          create_file('4_offenses.rb', [
+            '# encoding: utf-8',
+            'puts x ',
+            'test;',
+            'top;',
+            '#' * 90
+          ])
+
+          create_file('no_offense.rb', [
+            '# encoding: utf-8'
+          ])
+
+          allow(SimpleTextFormatter).to receive(:new).and_return(formatter)
+          $stdout = StringIO.new
+        end
+
+        after do
+          $stdout = STDOUT
+        end
+
+        def run
+          cli.run([])
+        end
+
+        describe 'invocation order' do
+          subject(:formatter) do
+            formatter = double('formatter')
+            def formatter.method_missing(method_name, *args)
+              return if method_name == :output
+              puts method_name
+            end
+            formatter
+          end
+
+          it 'is called in the proper sequence' do
+            run
+            expect(output).to eq([
+              'started',
+              'file_started',
+              'file_finished',
+              'file_started',
+              'file_finished',
+              'file_started',
+              'file_finished',
+              'finished',
+              ''
+            ].join("\n"))
+          end
+        end
+
+        shared_examples 'receives all file paths' do |method_name|
+          it 'receives all file paths' do
+            expected_paths = [
+              '1_offense.rb',
+              '4_offenses.rb',
+              'no_offense.rb'
+            ].map { |path| File.expand_path(path) }.sort
+
+            expect(formatter).to receive(method_name) do |all_files|
+              expect(all_files.sort).to eq(expected_paths)
+            end
+
+            run
+          end
+
+          describe 'the passed files paths' do
+            it 'is frozen' do
+              expect(formatter).to receive(method_name) do |all_files|
+                all_files.each do |path|
+                  expect(path).to be_frozen
+                end
+              end
+              run
+            end
+          end
+        end
+
+        describe '#started' do
+          include_examples 'receives all file paths', :started
+        end
+
+        describe '#finished' do
+          context 'when RuboCop finished inspecting all files normally' do
+            include_examples 'receives all file paths', :started
+          end
+
+          context 'when RuboCop is interrupted by user' do
+            it 'received processed file paths' do
+              class << formatter
+                attr_reader :processed_file_count
+
+                def file_finished(file, offenses)
+                  @processed_file_count ||= 0
+                  @processed_file_count += 1
+                end
+              end
+
+              allow(cli).to receive(:wants_to_quit?) do
+                formatter.processed_file_count == 2
+              end
+
+              expect(formatter).to receive(:finished) do |processed_files|
+                expect(processed_files.size).to eq(2)
+              end
+
+              run
+            end
+          end
+        end
+
+        shared_examples 'receives a file path' do |method_name|
+          it 'receives a file path' do
+            expect(formatter).to receive(method_name)
+              .with(File.expand_path('1_offense.rb'), anything)
+
+            expect(formatter).to receive(method_name)
+              .with(File.expand_path('4_offenses.rb'), anything)
+
+            expect(formatter).to receive(method_name)
+              .with(File.expand_path('no_offense.rb'), anything)
+
+            run
+          end
+
+          describe 'the passed path' do
+            it 'is frozen' do
+              expect(formatter)
+                .to receive(method_name).exactly(3).times do |path|
+                expect(path).to be_frozen
+              end
+              run
+            end
+          end
+        end
+
+        describe '#file_started' do
+          include_examples 'receives a file path', :file_started
+
+          it 'receives file specific information hash' do
+            expect(formatter).to receive(:file_started)
+              .with(anything, an_instance_of(Hash)).exactly(3).times
+            run
+          end
+        end
+
+        describe '#file_finished' do
+          include_examples 'receives a file path', :file_finished
+
+          it 'receives an array of detected offenses for the file' do
+            expect(formatter).to receive(:file_finished)
+            .exactly(3).times do |file, offenses|
+              case File.basename(file)
+              when '1_offense.rb'
+                expect(offenses.size).to eq(1)
+              when '4_offenses.rb'
+                expect(offenses.size).to eq(4)
+              when 'no_offense.rb'
+                expect(offenses).to be_empty
+              else
+                fail
+              end
+              expect(offenses.all? { |o| o.is_a?(Rubocop::Cop::Offense) })
+                .to be_true
+            end
+            run
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/formatter/clang_style_formatter_spec.rb b/spec/rubocop/formatter/clang_style_formatter_spec.rb
new file mode 100644
index 0000000..1944de3
--- /dev/null
+++ b/spec/rubocop/formatter/clang_style_formatter_spec.rb
@@ -0,0 +1,114 @@
+# encoding: utf-8
+
+require 'spec_helper'
+require 'stringio'
+
+module Rubocop
+  module Formatter
+    describe ClangStyleFormatter do
+      subject(:formatter) { described_class.new(output) }
+      let(:output) { StringIO.new }
+
+      describe '#report_file' do
+        it 'displays text containing the offending source line' do
+          cop = Cop::Cop.new
+          source_buffer = Parser::Source::Buffer.new('test', 1)
+          source_buffer.source = ('aa'..'az').to_a.join($RS)
+          cop.add_offense(nil,
+                          Parser::Source::Range.new(source_buffer, 0, 2),
+                          'message 1')
+          cop.add_offense(nil,
+                          Parser::Source::Range.new(source_buffer, 30, 32),
+                          'message 2')
+
+          formatter.report_file('test', cop.offenses)
+          expect(output.string).to eq ['test:1:1: C: message 1',
+                                       'aa',
+                                       '^^',
+                                       'test:11:1: C: message 2',
+                                       'ak',
+                                       '^^',
+                                       ''].join("\n")
+        end
+
+        context 'when the source line is blank' do
+          it 'does not display offending source line' do
+            cop = Cop::Cop.new
+            source_buffer = Parser::Source::Buffer.new('test', 1)
+            source_buffer.source = (['     ', 'yaba']).to_a.join($RS)
+            cop.add_offense(nil,
+                            Parser::Source::Range.new(source_buffer, 0, 2),
+                            'message 1')
+            cop.add_offense(nil,
+                            Parser::Source::Range.new(source_buffer, 6, 10),
+                            'message 2')
+
+            formatter.report_file('test', cop.offenses)
+            expect(output.string).to eq ['test:1:1: C: message 1',
+                                         'test:2:1: C: message 2',
+                                         'yaba',
+                                         '^^^^',
+                                         ''].join("\n")
+          end
+        end
+
+        context 'when the offending source spans multiple lines' do
+          it 'displays the first line' do
+            source = ['do_something([this,',
+                      '              is,',
+                      '              target])'].join($RS)
+
+            source_buffer = Parser::Source::Buffer.new('test', 1)
+            source_buffer.source = source
+
+            location = Parser::Source::Range.new(source_buffer,
+                                                 source.index('['),
+                                                 source.index(']') + 1)
+
+            cop = Cop::Cop.new
+            cop.add_offense(nil, location, 'message 1')
+
+            formatter.report_file('test', cop.offenses)
+            expect(output.string).to eq ['test:1:14: C: message 1',
+                                         'do_something([this,',
+                                         '             ^^^^^^',
+                                         ''].join("\n")
+          end
+        end
+
+        let(:file) { '/path/to/file' }
+
+        let(:offense) do
+          Cop::Offense.new(:convention, location,
+                           'This is a message.', 'CopName', corrected)
+        end
+
+        let(:location) do
+          source_buffer = Parser::Source::Buffer.new('test', 1)
+          source_buffer.source = "a\n"
+          Parser::Source::Range.new(source_buffer, 0, 1)
+        end
+
+        context 'when the offense is not corrected' do
+          let(:corrected) { false }
+
+          it 'prints message as-is' do
+            formatter.report_file(file, [offense])
+            expect(output.string)
+              .to include(': This is a message.')
+          end
+        end
+
+        context 'when the offense is automatically corrected' do
+          let(:corrected) { true }
+
+          it 'prints [Corrected] along with message' do
+            formatter.report_file(file, [offense])
+            expect(output.string)
+              .to include(': [Corrected] This is a message.')
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/formatter/colorizable_spec.rb b/spec/rubocop/formatter/colorizable_spec.rb
new file mode 100644
index 0000000..ed17898
--- /dev/null
+++ b/spec/rubocop/formatter/colorizable_spec.rb
@@ -0,0 +1,107 @@
+# encoding: utf-8
+
+require 'spec_helper'
+require 'rubocop/formatter/colorizable'
+require 'stringio'
+
+module Rubocop
+  module Formatter
+    describe Colorizable do
+      let(:formatter_class) do
+        Class.new(BaseFormatter) do
+          include Colorizable
+        end
+      end
+
+      let(:formatter) do
+        formatter_class.new(output)
+      end
+
+      let(:output) { double('output') }
+
+      around do |example|
+        original_state = Rainbow.enabled
+
+        begin
+          example.run
+        ensure
+          Rainbow.enabled = original_state
+        end
+      end
+
+      describe '#colorize' do
+        subject { formatter.colorize('foo', :red) }
+
+        shared_examples 'does nothing' do
+          it 'does nothing' do
+            should == 'foo'
+          end
+        end
+
+        context 'when the global Rainbow.enabled is true' do
+          before do
+            Rainbow.enabled = true
+          end
+
+          context "and the formatter's output is a tty" do
+            before do
+              allow(output).to receive(:tty?).and_return(true)
+            end
+
+            it 'colorize the passed string' do
+              should == "\e[31mfoo\e[0m"
+            end
+          end
+
+          context "and the formatter's output is not a tty" do
+            before do
+              allow(output).to receive(:tty?).and_return(false)
+            end
+
+            include_examples 'does nothing'
+          end
+        end
+
+        context 'when the global Rainbow.enabled is false' do
+          before do
+            Rainbow.enabled = false
+          end
+
+          context "and the formatter's output is a tty" do
+            before do
+              allow(output).to receive(:tty?).and_return(true)
+            end
+
+            include_examples 'does nothing'
+          end
+
+          context "and the formatter's output is not a tty" do
+            before do
+              allow(output).to receive(:tty?).and_return(false)
+            end
+
+            include_examples 'does nothing'
+          end
+        end
+      end
+
+      [
+        :black,
+        :red,
+        :green,
+        :yellow,
+        :blue,
+        :magenta,
+        :cyan,
+        :white
+      ].each do |color|
+        describe "##{color}" do
+          it "invokes #colorize(string, #{color}" do
+            expect(formatter).to receive(:colorize).with('foo', color)
+            formatter.send(color, 'foo')
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/formatter/disabled_config_formatter_spec.rb b/spec/rubocop/formatter/disabled_config_formatter_spec.rb
new file mode 100644
index 0000000..8aac58c
--- /dev/null
+++ b/spec/rubocop/formatter/disabled_config_formatter_spec.rb
@@ -0,0 +1,50 @@
+# encoding: utf-8
+
+require 'spec_helper'
+require 'stringio'
+require 'ostruct'
+
+module Rubocop
+  module Formatter
+    describe DisabledConfigFormatter do
+      subject(:formatter) { described_class.new(output) }
+      let(:output) do
+        o = StringIO.new
+        def o.path
+          'rubocop-todo.yml'
+        end
+        o
+      end
+      let(:offenses) do
+        [Rubocop::Cop::Offense.new(:convention, location, 'message', 'Cop1'),
+         Rubocop::Cop::Offense.new(:convention, location, 'message', 'Cop2')]
+      end
+      let(:location) { OpenStruct.new(line: 1, column: 5) }
+      before { $stdout = StringIO.new }
+
+      describe '#finished' do
+        it 'displays YAML configuration disabling all cops with offenses' do
+          formatter.file_finished('test.rb', offenses)
+          formatter.finished(['test.rb'])
+          expect(output.string).to eq(described_class::HEADING +
+                                      ['',
+                                       '',
+                                       '# Offense count: 1',
+                                       'Cop1:',
+                                       '  Enabled: false',
+                                       '',
+                                       '# Offense count: 1',
+                                       'Cop2:',
+                                       '  Enabled: false',
+                                       ''].join("\n"))
+          expect($stdout.string)
+            .to eq(['Created rubocop-todo.yml.',
+                    'Run `rubocop --config rubocop-todo.yml`, or',
+                    'add inherit_from: rubocop-todo.yml in a .rubocop.yml ' \
+                    'file.',
+                    ''].join("\n"))
+        end
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/formatter/disabled_lines_formatter_spec.rb b/spec/rubocop/formatter/disabled_lines_formatter_spec.rb
new file mode 100644
index 0000000..032efe4
--- /dev/null
+++ b/spec/rubocop/formatter/disabled_lines_formatter_spec.rb
@@ -0,0 +1,69 @@
+# encoding: utf-8
+
+require 'spec_helper'
+require 'stringio'
+require 'tempfile'
+
+module Rubocop
+  module Formatter
+    describe DisabledLinesFormatter do
+      subject(:formatter) { described_class.new(output) }
+      let(:output) { StringIO.new }
+
+      let(:files) do
+        %w(lib/rubocop.rb spec/spec_helper.rb bin/rubocop).map do |path|
+          File.expand_path(path)
+        end
+      end
+
+      let(:file_started) do
+        formatter.file_started(files.first, cop_disabled_line_ranges)
+      end
+
+      describe '#file_started' do
+        before { formatter.started(files) }
+
+        context 'when no disable cop comments are detected' do
+          let(:cop_disabled_line_ranges) { {} }
+          it 'shouldn\'t add to cop_disabled_line_ranges' do
+            expect { file_started }.to_not(
+            change { formatter.cop_disabled_line_ranges })
+          end
+        end
+
+        context 'when any disable cop comments are detected' do
+          let(:cop_disabled_line_ranges) do
+            { cop_disabled_line_ranges: { 'LineLength' => [1..1] } }
+          end
+          it 'should merge the changes into cop_disabled_line_ranges' do
+            expect { file_started }.to(
+            change { formatter.cop_disabled_line_ranges })
+          end
+        end
+      end
+
+      describe '#finished' do
+        context 'when there disabled cops detected' do
+          let(:cop_disabled_line_ranges) do
+            { cop_disabled_line_ranges: { 'LineLength' => [1..1] } }
+          end
+
+          before do
+            formatter.started(files)
+            formatter.file_started('lib/rubocop.rb', cop_disabled_line_ranges)
+          end
+
+          it 'lists disabled cops by file' do
+            formatter.finished(files)
+            expect(output.string).to eq(
+            ['',
+             'Cops disabled line ranges:',
+             '',
+             'lib/rubocop.rb:1..1: LineLength',
+             ''].join("\n"))
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/formatter/emacs_style_formatter_spec.rb b/spec/rubocop/formatter/emacs_style_formatter_spec.rb
new file mode 100644
index 0000000..d46f528
--- /dev/null
+++ b/spec/rubocop/formatter/emacs_style_formatter_spec.rb
@@ -0,0 +1,62 @@
+# encoding: utf-8
+
+require 'spec_helper'
+require 'stringio'
+
+module Rubocop
+  module Formatter
+    describe EmacsStyleFormatter do
+      subject(:formatter) { described_class.new(output) }
+      let(:output) { StringIO.new }
+
+      describe '#file_finished' do
+        it 'displays parsable text' do
+          cop = Cop::Cop.new
+          source_buffer = Parser::Source::Buffer.new('test', 1)
+          source_buffer.source = %w(a b cdefghi).join("\n")
+
+          cop.add_offense(nil,
+                          Parser::Source::Range.new(source_buffer, 0, 1),
+                          'message 1')
+          cop.add_offense(nil,
+                          Parser::Source::Range.new(source_buffer, 9, 10),
+                          'message 2')
+
+          formatter.file_finished('test', cop.offenses)
+          expect(output.string).to eq ['test:1:1: C: message 1',
+                                       "test:3:6: C: message 2\n"].join("\n")
+        end
+
+        context 'when the offense is automatically corrected' do
+          let(:file) { '/path/to/file' }
+
+          let(:offense) do
+            Cop::Offense.new(:convention, location,
+                             'This is a message.', 'CopName', corrected)
+          end
+
+          let(:location) do
+            source_buffer = Parser::Source::Buffer.new('test', 1)
+            source_buffer.source = "a\n"
+            Parser::Source::Range.new(source_buffer, 0, 1)
+          end
+
+          let(:corrected) { true }
+
+          it 'prints [Corrected] along with message' do
+            formatter.file_finished(file, [offense])
+            expect(output.string)
+              .to include(': [Corrected] This is a message.')
+          end
+        end
+      end
+
+      describe '#finished' do
+        it 'does not report summary' do
+          formatter.finished(['/path/to/file'])
+          expect(output.string).to be_empty
+        end
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/formatter/file_list_formatter_spec.rb b/spec/rubocop/formatter/file_list_formatter_spec.rb
new file mode 100644
index 0000000..54896d6
--- /dev/null
+++ b/spec/rubocop/formatter/file_list_formatter_spec.rb
@@ -0,0 +1,33 @@
+# encoding: utf-8
+
+require 'spec_helper'
+require 'stringio'
+
+module Rubocop
+  module Formatter
+    describe FileListFormatter do
+      subject(:formatter) { described_class.new(output) }
+      let(:output) { StringIO.new }
+
+      describe '#file_finished' do
+        it 'displays parsable text' do
+          cop = Cop::Cop.new
+          source_buffer = Parser::Source::Buffer.new('test', 1)
+          source_buffer.source = %w(a b cdefghi).join("\n")
+
+          cop.add_offense(nil,
+                          Parser::Source::Range.new(source_buffer, 0, 1),
+                          'message 1')
+          cop.add_offense(nil,
+                          Parser::Source::Range.new(source_buffer, 9, 10),
+                          'message 2')
+
+          formatter.file_finished('test', cop.offenses)
+          formatter.file_finished('test_2', cop.offenses)
+          expect(output.string).to eq ['test',
+                                       "test_2\n"].join("\n")
+        end
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/formatter/formatter_set_spec.rb b/spec/rubocop/formatter/formatter_set_spec.rb
new file mode 100644
index 0000000..186047f
--- /dev/null
+++ b/spec/rubocop/formatter/formatter_set_spec.rb
@@ -0,0 +1,132 @@
+# encoding: utf-8
+
+require 'spec_helper'
+require 'tempfile'
+
+module Rubocop
+  module Formatter
+    describe FormatterSet do
+      subject(:formatter_set) { described_class.new }
+
+      it 'responds to all formatter API methods' do
+        [:started, :file_started, :file_finished, :finished].each do |method|
+          expect(formatter_set).to respond_to(method)
+        end
+      end
+
+      describe 'formatter API method' do
+        before do
+          formatter_set.add_formatter('simple')
+          formatter_set.add_formatter('emacs')
+        end
+
+        let(:files) { ['/path/to/file1', '/path/to/file2'] }
+
+        it 'invokes same method of all containing formatters' do
+          formatter_set.each do |formatter|
+            expect(formatter).to receive(:started).with(files)
+          end
+          formatter_set.started(files)
+        end
+      end
+
+      describe 'add_formatter' do
+        it 'adds a formatter to itself' do
+          formatter_set.add_formatter('simple')
+          expect(formatter_set.size).to eq(1)
+        end
+
+        it 'adds a formatter with specified formatter type' do
+          formatter_set.add_formatter('simple')
+          expect(formatter_set.first.class).to eq(SimpleTextFormatter)
+        end
+
+        it 'can add multiple formatters by being invoked multiple times' do
+          formatter_set.add_formatter('simple')
+          formatter_set.add_formatter('emacs')
+          expect(formatter_set[0].class).to eq(SimpleTextFormatter)
+          expect(formatter_set[1].class).to eq(EmacsStyleFormatter)
+        end
+
+        context 'when output path is omitted' do
+          it 'adds a formatter outputs to $stdout' do
+            formatter_set.add_formatter('simple')
+            expect(formatter_set.first.output).to eq($stdout)
+          end
+        end
+
+        context 'when output path is specified' do
+          it 'adds a formatter outputs to the specified file' do
+            output_path = Tempfile.new('').path
+            formatter_set.add_formatter('simple', output_path)
+            expect(formatter_set.first.output.class).to eq(File)
+            expect(formatter_set.first.output.path).to eq(output_path)
+          end
+        end
+      end
+
+      describe '#close_output_files' do
+        before do
+          2.times do
+            output_path = Tempfile.new('').path
+            formatter_set.add_formatter('simple', output_path)
+          end
+          formatter_set.add_formatter('simple')
+        end
+
+        it 'closes all output files' do
+          formatter_set.close_output_files
+          formatter_set[0..1].each do |formatter|
+            expect(formatter.output).to be_closed
+          end
+        end
+
+        it 'does not close non file output' do
+          expect(formatter_set[2].output).not_to be_closed
+        end
+      end
+
+      describe '#builtin_formatter_class' do
+        def builtin_formatter_class(string)
+          described_class.new.send(:builtin_formatter_class, string)
+        end
+
+        it 'returns class which matches passed alias name exactly' do
+          expect(builtin_formatter_class('simple'))
+            .to eq(SimpleTextFormatter)
+        end
+
+        it 'returns class whose first letter of alias name ' \
+           'matches passed letter' do
+          expect(builtin_formatter_class('s'))
+            .to eq(SimpleTextFormatter)
+        end
+      end
+
+      describe '#custom_formatter_class' do
+        def custom_formatter_class(string)
+          described_class.new.send(:custom_formatter_class, string)
+        end
+
+        it 'returns constant represented by the passed string' do
+          expect(custom_formatter_class('Rubocop')).to eq(Rubocop)
+        end
+
+        it 'can handle namespaced constant name' do
+          expect(custom_formatter_class('Rubocop::CLI')).to eq(Rubocop::CLI)
+        end
+
+        it 'can handle top level namespaced constant name' do
+          expect(custom_formatter_class('::Rubocop::CLI')).to eq(Rubocop::CLI)
+        end
+
+        context 'when non-existent constant name is passed' do
+          it 'raises error' do
+            expect { custom_formatter_class('Rubocop::NonExistentClass') }
+              .to raise_error(NameError)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/formatter/fuubar_style_formatter_spec.rb b/spec/rubocop/formatter/fuubar_style_formatter_spec.rb
new file mode 100644
index 0000000..893899e
--- /dev/null
+++ b/spec/rubocop/formatter/fuubar_style_formatter_spec.rb
@@ -0,0 +1,129 @@
+# encoding: utf-8
+
+require 'spec_helper'
+require 'stringio'
+
+module Rubocop
+  describe Formatter::FuubarStyleFormatter do
+    subject(:formatter) { described_class.new(output) }
+    let(:output) { StringIO.new }
+
+    let(:files) do
+      %w(lib/rubocop.rb spec/spec_helper.rb).map do |path|
+        File.expand_path(path)
+      end
+    end
+
+    describe '#with_color' do
+      around do |example|
+        original_state = formatter.rainbow.enabled
+
+        begin
+          example.run
+        ensure
+          formatter.rainbow.enabled = original_state
+        end
+      end
+
+      context 'when color is enabled' do
+        before do
+          formatter.rainbow.enabled = true
+        end
+
+        it 'outputs coloring sequence code at the beginning and the end' do
+          formatter.with_color { formatter.output.write 'foo' }
+          expect(output.string).to eq("\e[32mfoo\e[0m")
+        end
+      end
+
+      context 'when color is enabled' do
+        before do
+          formatter.rainbow.enabled = false
+        end
+
+        it 'outputs nothing' do
+          formatter.with_color { formatter.output.write 'foo' }
+          expect(output.string).to eq('foo')
+        end
+      end
+    end
+
+    describe '#progressbar_color' do
+      before do
+        formatter.started(files)
+      end
+
+      def offense(severity, corrected = false)
+        source_range = double('source_range').as_null_object
+        Cop::Offense.new(severity, source_range, 'message', 'Cop', corrected)
+      end
+
+      context 'initially' do
+        it 'is green' do
+          expect(formatter.progressbar_color).to eq(:green)
+        end
+      end
+
+      context 'when no offenses are detected in a file' do
+        before do
+          formatter.file_finished(files[0], [])
+        end
+
+        it 'is still green' do
+          expect(formatter.progressbar_color).to eq(:green)
+        end
+      end
+
+      context 'when a convention offense is detected in a file' do
+        before do
+          formatter.file_finished(files[0], [offense(:convention)])
+        end
+
+        it 'is yellow' do
+          expect(formatter.progressbar_color).to eq(:yellow)
+        end
+      end
+
+      context 'when an error offense is detected in a file' do
+        before do
+          formatter.file_finished(files[0], [offense(:error)])
+        end
+
+        it 'is red' do
+          expect(formatter.progressbar_color).to eq(:red)
+        end
+
+        context 'and then a convention offense is detected in the next file' do
+          before do
+            formatter.file_finished(files[1], [offense(:convention)])
+          end
+
+          it 'is still red' do
+            expect(formatter.progressbar_color).to eq(:red)
+          end
+        end
+      end
+
+      context 'when convention and error offenses are detected in a file' do
+        before do
+          offenses = [offense(:convention), offense(:error)]
+          formatter.file_finished(files[0], offenses)
+        end
+
+        it 'is red' do
+          expect(formatter.progressbar_color).to eq(:red)
+        end
+      end
+
+      context 'when a offense is detected in a file and auto-corrected' do
+        before do
+          formatter.file_finished(files[0], [offense(:convention, true)])
+        end
+
+        it 'is green' do
+          expect(formatter.progressbar_color).to eq(:green)
+        end
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/formatter/json_formatter_spec.rb b/spec/rubocop/formatter/json_formatter_spec.rb
new file mode 100644
index 0000000..c980fb5
--- /dev/null
+++ b/spec/rubocop/formatter/json_formatter_spec.rb
@@ -0,0 +1,152 @@
+# encoding: utf-8
+
+require 'spec_helper'
+require 'stringio'
+
+module Rubocop
+  describe Formatter::JSONFormatter do
+    subject(:formatter) { described_class.new(output) }
+    let(:output) { StringIO.new }
+    let(:files) { %w(/path/to/file1 /path/to/file2) }
+    let(:location) do
+      source_buffer = Parser::Source::Buffer.new('test', 1)
+      source_buffer.source = %w(a b cdefghi).join("\n")
+      Parser::Source::Range.new(source_buffer, 9, 10)
+    end
+    let(:offense) do
+      Cop::Offense.new(:convention, location,
+                       'This is message', 'CopName', true)
+    end
+
+    describe '#started' do
+      let(:summary) { formatter.output_hash[:summary] }
+
+      it 'sets target file count in summary' do
+        expect(summary[:target_file_count]).to be_nil
+        formatter.started(%w(/path/to/file1 /path/to/file2))
+        expect(summary[:target_file_count]).to eq(2)
+      end
+    end
+
+    describe '#file_finished' do
+      before do
+        count = 0
+        allow(formatter).to receive(:hash_for_file) do
+          count += 1
+        end
+      end
+
+      let(:summary) { formatter.output_hash[:summary] }
+
+      it 'adds detected offense count in summary' do
+        expect(summary[:offense_count]).to eq(0)
+
+        formatter.file_started(files[0], {})
+        expect(summary[:offense_count]).to eq(0)
+        formatter.file_finished(files[0], [
+          double('offense1'), double('offense2')
+        ])
+        expect(summary[:offense_count]).to eq(2)
+      end
+
+      it 'adds value of #hash_for_file to #output_hash[:files]' do
+        expect(formatter.output_hash[:files]).to be_empty
+
+        formatter.file_started(files[0], {})
+        expect(formatter.output_hash[:files]).to be_empty
+        formatter.file_finished(files[0], [])
+        expect(formatter.output_hash[:files]).to eq([1])
+
+        formatter.file_started(files[1], {})
+        expect(formatter.output_hash[:files]).to eq([1])
+        formatter.file_finished(files[1], [])
+        expect(formatter.output_hash[:files]).to eq([1, 2])
+      end
+    end
+
+    describe '#finished' do
+      let(:summary) { formatter.output_hash[:summary] }
+
+      it 'sets inspected file count in summary' do
+        expect(summary[:inspected_file_count]).to be_nil
+        formatter.finished(%w(/path/to/file1 /path/to/file2))
+        expect(summary[:inspected_file_count]).to eq(2)
+      end
+
+      it 'outputs #output_hash as JSON' do
+        formatter.finished(files)
+        json = output.string
+        restored_hash = JSON.parse(json, symbolize_names: true)
+        expect(restored_hash).to eq(formatter.output_hash)
+      end
+    end
+
+    describe '#hash_for_file' do
+      subject(:hash) { formatter.hash_for_file(file, offenses) }
+      let(:file) { File.expand_path('spec/spec_helper.rb') }
+      let(:offenses) { [double('offense1'), double('offense2')] }
+
+      it 'sets relative file path for :path key' do
+        expect(hash[:path]).to eq('spec/spec_helper.rb')
+      end
+
+      before do
+        count = 0
+        allow(formatter).to receive(:hash_for_offense) do
+          count += 1
+        end
+      end
+
+      it 'sets an array of #hash_for_offense values for :offenses key' do
+        expect(hash[:offenses]).to eq([1, 2])
+      end
+    end
+
+    describe '#hash_for_offense' do
+      subject(:hash) { formatter.hash_for_offense(offense) }
+
+      it 'sets Offense#severity value for :severity key' do
+        expect(hash[:severity]).to eq(:convention)
+      end
+
+      it 'sets Offense#message value for :message key' do
+        expect(hash[:message]).to eq('This is message')
+      end
+
+      it 'sets Offense#cop_name value for :cop_name key' do
+        expect(hash[:cop_name]).to eq('CopName')
+      end
+
+      it 'sets Offense#corrected? value for :corrected key' do
+        expect(hash[:corrected]).to be_true
+      end
+
+      before do
+        allow(formatter)
+          .to receive(:hash_for_location).and_return(location_hash)
+      end
+
+      let(:location_hash) { { line: 1, column: 2 } }
+
+      it 'sets value of #hash_for_location for :location key' do
+        expect(hash[:location]).to eq(location_hash)
+      end
+    end
+
+    describe '#hash_for_location' do
+      subject(:hash) { formatter.hash_for_location(offense) }
+
+      it 'sets line value for :line key' do
+        expect(hash[:line]).to eq(3)
+      end
+
+      it 'sets column value for :column key' do
+        expect(hash[:column]).to eq(6)
+      end
+
+      it 'sets length value for :length key' do
+        expect(hash[:length]).to eq(1)
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/formatter/offense_count_formatter_spec.rb b/spec/rubocop/formatter/offense_count_formatter_spec.rb
new file mode 100644
index 0000000..6469612
--- /dev/null
+++ b/spec/rubocop/formatter/offense_count_formatter_spec.rb
@@ -0,0 +1,77 @@
+# encoding: utf-8
+
+require 'spec_helper'
+require 'stringio'
+require 'tempfile'
+
+module Rubocop
+  module Formatter
+    describe OffenseCountFormatter do
+      subject(:formatter) { described_class.new(output) }
+      let(:output) { StringIO.new }
+
+      let(:files) do
+        %w(lib/rubocop.rb spec/spec_helper.rb bin/rubocop).map do |path|
+          File.expand_path(path)
+        end
+      end
+
+      let(:finish) { formatter.file_finished(files.first, offenses) }
+
+      describe '#file_finished' do
+        before { formatter.started(files) }
+
+        context 'when no offenses are detected' do
+          let(:offenses) { [] }
+          it 'shouldn\'t add to offense_counts' do
+            expect { finish }.to_not change { formatter.offense_counts }
+          end
+        end
+
+        context 'when any offenses are detected' do
+          let(:offenses) { [double('offense', cop_name: 'OffendedCop')] }
+          it 'should increment the count for the cop in offense_counts' do
+            expect { finish }.to change { formatter.offense_counts }
+          end
+        end
+      end
+
+      describe '#report_summary' do
+        context 'when an offense is detected' do
+          let(:cop_counts) { { 'OffendedCop' => 1 } }
+          it 'shows the cop and the offense count' do
+            formatter.report_summary(1, cop_counts)
+            expect(output.string).to include(
+              "\n1  OffendedCop\n--\n1  Total")
+          end
+        end
+      end
+
+      describe '#finished' do
+        context 'when there are many offenses' do
+          let(:offenses) do
+            %w(CopB CopA CopC CopC).map { |c| double('offense', cop_name: c) }
+          end
+
+          before do
+            formatter.started(files)
+            finish
+          end
+
+          it 'sorts by offense count first and then by cop name' do
+            formatter.finished(files)
+            expect(output.string).to eq(['',
+                                         '2  CopC',
+                                         '1  CopA',
+                                         '1  CopB',
+                                         '--',
+                                         '4  Total',
+                                         '',
+                                         ''].join("\n"))
+          end
+        end
+      end
+
+    end
+  end
+end
diff --git a/spec/rubocop/formatter/progress_formatter_spec.rb b/spec/rubocop/formatter/progress_formatter_spec.rb
new file mode 100644
index 0000000..2ad98e3
--- /dev/null
+++ b/spec/rubocop/formatter/progress_formatter_spec.rb
@@ -0,0 +1,182 @@
+# encoding: utf-8
+
+require 'spec_helper'
+require 'stringio'
+
+module Rubocop
+  describe Formatter::ProgressFormatter do
+    subject(:formatter) { described_class.new(output) }
+    let(:output) { StringIO.new }
+
+    let(:files) do
+      %w(lib/rubocop.rb spec/spec_helper.rb bin/rubocop).map do |path|
+        File.expand_path(path)
+      end
+    end
+
+    describe '#file_finished' do
+      before do
+        formatter.started(files)
+        formatter.file_started(files.first, {})
+      end
+
+      shared_examples 'calls #report_file_as_mark' do
+        it 'calls #report_as_with_mark' do
+          expect(formatter).to receive(:report_file_as_mark)
+          formatter.file_finished(files.first, offenses)
+        end
+      end
+
+      context 'when no offenses are detected' do
+        let(:offenses) { [] }
+        include_examples 'calls #report_file_as_mark'
+      end
+
+      context 'when any offenses are detected' do
+        let(:offenses) { [double('offense').as_null_object] }
+        include_examples 'calls #report_file_as_mark'
+      end
+    end
+
+    describe '#report_file_as_mark' do
+      before do
+        formatter.report_file_as_mark(files.first, offenses)
+      end
+
+      def offense_with_severity(severity)
+        source_buffer = Parser::Source::Buffer.new('test', 1)
+        source_buffer.source = "a\n"
+        Cop::Offense.new(severity,
+                         Parser::Source::Range.new(source_buffer, 0, 1),
+                         'message',
+                         'CopName')
+      end
+
+      context 'when no offenses are detected' do
+        let(:offenses) { [] }
+
+        it 'prints "."' do
+          expect(output.string).to eq('.')
+        end
+      end
+
+      context 'when a refactor severity offense is detected' do
+        let(:offenses) { [offense_with_severity(:refactor)] }
+
+        it 'prints "R"' do
+          expect(output.string).to eq('R')
+        end
+      end
+
+      context 'when a refactor convention offense is detected' do
+        let(:offenses) { [offense_with_severity(:convention)] }
+
+        it 'prints "C"' do
+          expect(output.string).to eq('C')
+        end
+      end
+
+      context 'when different severity offenses are detected' do
+        let(:offenses) do
+          [
+            offense_with_severity(:refactor),
+            offense_with_severity(:error)
+          ]
+        end
+
+        it 'prints highest level mark' do
+          expect(output.string).to eq('E')
+        end
+      end
+    end
+
+    describe '#finished' do
+      before do
+        formatter.started(files)
+      end
+
+      context 'when any offenses are detected' do
+        before do
+          source_buffer = Parser::Source::Buffer.new('test', 1)
+          source = 9.times.map do |index|
+            "This is line #{index + 1}."
+          end
+          source_buffer.source = source.join("\n")
+          line_length = source[0].length + "\n".length
+
+          formatter.file_started(files[0], {})
+          formatter.file_finished(files[0], [
+            Cop::Offense.new(
+              :convention,
+              Parser::Source::Range.new(source_buffer,
+                                        line_length + 2,
+                                        line_length + 3),
+              'foo',
+              'Cop'
+            )
+          ])
+
+          formatter.file_started(files[1], {})
+          formatter.file_finished(files[1], [
+          ])
+
+          formatter.file_started(files[2], {})
+          formatter.file_finished(files[2], [
+            Cop::Offense.new(
+              :error,
+              Parser::Source::Range.new(source_buffer,
+                                        4 * line_length + 1,
+                                        4 * line_length + 2),
+              'bar',
+              'Cop'
+            ),
+            Cop::Offense.new(
+              :convention,
+              Parser::Source::Range.new(source_buffer,
+                                        5 * line_length,
+                                        5 * line_length + 1),
+              'foo',
+              'Cop'
+            )
+          ])
+        end
+
+        it 'reports all detected offenses for all failed files' do
+          formatter.finished(files)
+          expect(output.string).to include([
+            'Offenses:',
+            '',
+            'lib/rubocop.rb:2:3: C: foo',
+            'This is line 2.',
+            '  ^',
+            'bin/rubocop:5:2: E: bar',
+            'This is line 5.',
+            ' ^',
+            'bin/rubocop:6:1: C: foo',
+            'This is line 6.',
+            '^'
+          ].join("\n"))
+        end
+      end
+
+      context 'when no offenses are detected' do
+        before do
+          files.each do |file|
+            formatter.file_started(file, {})
+            formatter.file_finished(file, [])
+          end
+        end
+
+        it 'does not report offenses' do
+          formatter.finished(files)
+          expect(output.string).not_to include('Offenses:')
+        end
+      end
+
+      it 'calls #report_summary' do
+        expect(formatter).to receive(:report_summary)
+        formatter.finished(files)
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/formatter/simple_text_formatter_spec.rb b/spec/rubocop/formatter/simple_text_formatter_spec.rb
new file mode 100644
index 0000000..0a02c8a
--- /dev/null
+++ b/spec/rubocop/formatter/simple_text_formatter_spec.rb
@@ -0,0 +1,123 @@
+# encoding: utf-8
+
+require 'spec_helper'
+require 'stringio'
+require 'tempfile'
+
+module Rubocop
+  module Formatter
+    describe SimpleTextFormatter do
+      subject(:formatter) { described_class.new(output) }
+      let(:output) { StringIO.new }
+
+      describe '#report_file' do
+        before do
+          formatter.report_file(file, [offense])
+        end
+
+        let(:file) { '/path/to/file' }
+
+        let(:offense) do
+          Cop::Offense.new(:convention, location,
+                           'This is a message.', 'CopName', corrected)
+        end
+
+        let(:location) do
+          source_buffer = Parser::Source::Buffer.new('test', 1)
+          source_buffer.source = "a\n"
+          Parser::Source::Range.new(source_buffer, 0, 1)
+        end
+
+        let(:corrected) { false }
+
+        context 'the file is under the current working directory' do
+          let(:file) { File.expand_path('spec/spec_helper.rb') }
+
+          it 'prints as relative path' do
+            expect(output.string).to include('== spec/spec_helper.rb ==')
+          end
+        end
+
+        context 'the file is outside of the current working directory' do
+          let(:file) do
+            tempfile = Tempfile.new('')
+            tempfile.close
+            File.expand_path(tempfile.path)
+          end
+
+          it 'prints as absolute path' do
+            expect(output.string).to include("== #{file} ==")
+          end
+        end
+
+        context 'when the offense is not corrected' do
+          let(:corrected) { false }
+
+          it 'prints message as-is' do
+            expect(output.string)
+              .to include(': This is a message.')
+          end
+        end
+
+        context 'when the offense is automatically corrected' do
+          let(:corrected) { true }
+
+          it 'prints [Corrected] along with message' do
+            expect(output.string)
+              .to include(': [Corrected] This is a message.')
+          end
+        end
+      end
+
+      describe '#report_summary' do
+        context 'when no files inspected' do
+          it 'handles pluralization correctly' do
+            formatter.report_summary(0, 0, 0)
+            expect(output.string).to eq(
+              "\n0 files inspected, no offenses detected\n")
+          end
+        end
+
+        context 'when a file inspected and no offenses detected' do
+          it 'handles pluralization correctly' do
+            formatter.report_summary(1, 0, 0)
+            expect(output.string).to eq(
+              "\n1 file inspected, no offenses detected\n")
+          end
+        end
+
+        context 'when a offense detected' do
+          it 'handles pluralization correctly' do
+            formatter.report_summary(1, 1, 0)
+            expect(output.string).to eq(
+              "\n1 file inspected, 1 offense detected\n")
+          end
+        end
+
+        context 'when 2 offenses detected' do
+          it 'handles pluralization correctly' do
+            formatter.report_summary(2, 2, 0)
+            expect(output.string).to eq(
+              "\n2 files inspected, 2 offenses detected\n")
+          end
+        end
+
+        context 'when an offense is corrected' do
+          it 'prints about correction' do
+            formatter.report_summary(1, 1, 1)
+            expect(output.string).to eq(
+              "\n1 file inspected, 1 offense detected, 1 offense corrected\n")
+          end
+        end
+
+        context 'when 2 offenses are corrected' do
+          it 'handles pluralization correctly' do
+            formatter.report_summary(1, 1, 2)
+            expect(output.string).to eq(
+              "\n1 file inspected, 1 offense detected, 2 offenses corrected\n")
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/options_spec.rb b/spec/rubocop/options_spec.rb
new file mode 100644
index 0000000..da9a5a9
--- /dev/null
+++ b/spec/rubocop/options_spec.rb
@@ -0,0 +1,176 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Options, :isolated_environment do
+  include FileHelper
+
+  subject(:options) { described_class.new }
+
+  before(:each) do
+    $stdout = StringIO.new
+    $stderr = StringIO.new
+  end
+
+  after(:each) do
+    $stdout = STDOUT
+    $stderr = STDERR
+  end
+
+  def abs(path)
+    File.expand_path(path)
+  end
+
+  describe 'option' do
+    describe '-h/--help' do
+      it 'exits cleanly' do
+        expect { options.parse ['-h'] }.to exit_with_code(0)
+        expect { options.parse ['--help'] }.to exit_with_code(0)
+      end
+
+      it 'shows help text' do
+        begin
+          options.parse(['--help'])
+        rescue SystemExit # rubocop:disable HandleExceptions
+        end
+
+        expected_help = <<-END
+Usage: rubocop [options] [file1, file2, ...]
+        --only COP                   Run just one cop.
+    -c, --config FILE                Specify configuration file.
+        --auto-gen-config            Generate a configuration file acting as a
+                                     TODO list.
+        --force-exclusion            Force excluding files specified in the
+                                     configuration `Exclude` even if they are
+                                     explicitly passed as arguments.
+    -f, --format FORMATTER           Choose an output formatter. This option
+                                     can be specified multiple times to enable
+                                     multiple formatters at the same time.
+                                       [p]rogress (default)
+                                       [s]imple
+                                       [c]lang
+                                       [d]isabled cops via inline comments
+                                       [fu]ubar
+                                       [e]macs
+                                       [j]son
+                                       [fi]les
+                                       [o]ffenses
+                                       custom formatter class name
+    -o, --out FILE                   Write output to a file instead of STDOUT.
+                                     This option applies to the previously
+                                     specified --format, or the default format
+                                     if no format is specified.
+    -r, --require FILE               Require Ruby file.
+        --fail-level SEVERITY        Minimum severity for exit with error code.
+        --show-cops [cop1,cop2,...]  Shows the given cops, or all cops by
+                                     default, and their configurations for the
+                                     current directory.
+    -d, --debug                      Display debug info.
+    -D, --display-cop-names          Display cop names in offense messages.
+    -R, --rails                      Run extra Rails cops.
+    -l, --lint                       Run only lint cops.
+    -a, --auto-correct               Auto-correct offenses.
+    -n, --no-color                   Disable color output.
+    -v, --version                    Display version.
+    -V, --verbose-version            Display verbose version.
+      END
+
+        expect($stdout.string).to eq(expected_help)
+      end
+
+      it 'lists all builtin formatters' do
+        begin
+          options.parse(['--help'])
+        rescue SystemExit # rubocop:disable HandleExceptions
+        end
+
+        option_sections = $stdout.string.lines.slice_before(/^\s*-/)
+
+        format_section = option_sections.find do |lines|
+          lines.first =~ /^\s*-f/
+        end
+
+        formatter_keys = format_section.reduce([]) do |keys, line|
+          match = line.match(/^[ ]{39}(\[[a-z\]]+)/)
+          next keys unless match
+          keys << match.captures.first.gsub(/\[|\]/, '')
+        end.sort
+
+        expected_formatter_keys =
+          Rubocop::Formatter::FormatterSet::BUILTIN_FORMATTERS_FOR_KEYS
+          .keys.sort
+
+        expect(formatter_keys).to eq(expected_formatter_keys)
+      end
+    end
+
+    describe 'incompatible cli options' do
+      it 'fails with argument correct error' do
+        msg = 'Incompatible cli options: [:version, :verbose_version]'
+        expect { options.parse %w(-vV) }
+          .to raise_error(ArgumentError, msg)
+      end
+
+      it 'fails with argument correct error' do
+        msg = 'Incompatible cli options: [:version, :show_cops]'
+        expect { options.parse %w(-v --show-cops) }
+          .to raise_error(ArgumentError, msg)
+      end
+
+      it 'fails with argument correct error' do
+        msg = 'Incompatible cli options: [:verbose_version, :show_cops]'
+        expect { options.parse %w(-V --show-cops) }
+          .to raise_error(ArgumentError, msg)
+      end
+
+      it 'fails with argument correct error' do
+        msg = ['Incompatible cli options: [:version, :verbose_version,',
+               ' :show_cops]'].join
+        expect { options.parse %w(-vV --show-cops) }
+          .to raise_error(ArgumentError, msg)
+      end
+    end
+
+    describe '--only' do
+      it 'exits with error if an incorrect cop name is passed' do
+        expect { options.parse(%w(--only 123)) }
+          .to raise_error(ArgumentError, /Unrecognized cop name: 123./)
+      end
+    end
+
+    describe '--require' do
+      let(:required_file_path) { './path/to/required_file.rb' }
+
+      before do
+        create_file('example.rb', '# encoding: utf-8')
+
+        create_file(required_file_path, ['# encoding: utf-8',
+                                         "puts 'Hello from required file!'"])
+      end
+
+      it 'requires the passed path' do
+        options.parse(['--require', required_file_path, 'example.rb'])
+        expect($stdout.string).to start_with('Hello from required file!')
+      end
+    end
+  end
+
+  unless Rubocop::Version::STRING.start_with?('0')
+    describe '-e/--emacs option' do
+      it 'is dropped in RuboCop 1.0.0' do
+        # This spec can be removed once the option is dropped.
+        expect { options.parse(['--emacs']) }
+          .to raise_error(OptionParser::InvalidOption)
+      end
+    end
+
+    describe '-s/--silent option' do
+      it 'raises error in RuboCop 1.0.0' do
+        # This spec can be removed
+        # once Options#ignore_dropped_options is removed.
+        expect { options.parse(['--silent']) }
+          .to raise_error(OptionParser::InvalidOption)
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/path_util_spec.rb b/spec/rubocop/path_util_spec.rb
new file mode 100644
index 0000000..42c0990
--- /dev/null
+++ b/spec/rubocop/path_util_spec.rb
@@ -0,0 +1,42 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::PathUtil do
+  describe '#relative_path' do
+    pending 'builds paths relative to the current project by default'
+    it 'builds paths relative to PWD by default as a stop-gap' do
+      relative = File.join(Dir.pwd, 'relative')
+      expect(subject.relative_path(relative)).to eq('relative')
+    end
+
+    it 'supports custom base paths' do
+      expect(subject.relative_path('/foo/bar', '/foo')).to eq('bar')
+    end
+  end
+
+  describe '#match_path?' do
+    it 'matches strings to the basename' do
+      expect(subject.match_path?('file', '/dir/file')).to be_true
+      expect(subject.match_path?('file', '/dir/files')).to be_false
+      expect(subject.match_path?('dir', '/dir/file')).to be_false
+    end
+
+    it 'matches strings to the full path' do
+      expect(subject.match_path?('/dir/file', '/dir/file')).to be_true
+      expect(subject.match_path?('/dir/file', '/dir/dir/file')).to be_false
+    end
+
+    it 'matches glob expressions' do
+      expect(subject.match_path?('dir/*', 'dir/file')).to be_true
+      expect(subject.match_path?('dir/*', 'dir/sub/file')).to be_true
+      expect(subject.match_path?('dir/**/*', 'dir/sub/file')).to be_true
+      expect(subject.match_path?('sub/*', 'dir/sub/file')).to be_false
+    end
+
+    it 'matches regexps' do
+      expect(subject.match_path?(/^d.*e$/, 'dir/file')).to be_true
+      expect(subject.match_path?(/^d.*e$/, 'dir/filez')).to be_false
+    end
+  end
+end
diff --git a/spec/rubocop/processed_source_spec.rb b/spec/rubocop/processed_source_spec.rb
new file mode 100644
index 0000000..f4de34a
--- /dev/null
+++ b/spec/rubocop/processed_source_spec.rb
@@ -0,0 +1,114 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::ProcessedSource do
+  subject(:processed_source) do
+    described_class.new(
+      buffer,
+      double('ast'),
+      double('comments'),
+      double('tokens'),
+      diagnostics
+    )
+  end
+
+  let(:diagnostics) { double('diagnostics') }
+
+  let(:source) do
+    [
+      'def some_method',
+      "  puts 'foo'",
+      'end',
+      'some_method'
+    ].join("\n")
+  end
+
+  let(:buffer) do
+    buffer = Parser::Source::Buffer.new('(string)', 1)
+    buffer.source = source
+    buffer
+  end
+
+  describe '#lines' do
+    it 'is an array' do
+      expect(processed_source.lines).to be_a(Array)
+    end
+
+    it 'has same number of elements as line count' do
+      expect(processed_source.lines.size).to eq(4)
+    end
+
+    it 'contains lines as string without linefeed' do
+      first_line = processed_source.lines.first
+      expect(first_line).to eq('def some_method')
+    end
+  end
+
+  describe '#[]' do
+    context 'when an index is passed' do
+      it 'returns the line' do
+        expect(processed_source[2]).to eq('end')
+      end
+    end
+
+    context 'when a range is passed' do
+      it 'returns the array of lines' do
+        expect(processed_source[2..3]).to eq(%w(end some_method))
+      end
+    end
+
+    context 'when start index and length are passed' do
+      it 'returns the array of lines' do
+        expect(processed_source[2, 2]).to eq(%w(end some_method))
+      end
+    end
+  end
+
+  describe 'valid_syntax?' do
+    def create_diagnostics(level)
+      Parser::Diagnostic.new(level, :odd_hash, [], double('location'))
+    end
+
+    let(:diagnostics) do
+      [create_diagnostics(level)]
+    end
+
+    context 'when the source has diagnostic with error level' do
+      let(:level) { :error }
+
+      it 'returns false' do
+        expect(processed_source.valid_syntax?).to be_false
+      end
+    end
+
+    context 'when the source has diagnostic with fatal level' do
+      let(:level) { :fatal }
+
+      it 'returns false' do
+        expect(processed_source.valid_syntax?).to be_false
+      end
+    end
+
+    context 'when the source has diagnostic with warning level' do
+      let(:level) { :warning }
+
+      it 'returns true' do
+        expect(processed_source.valid_syntax?).to be_true
+      end
+    end
+
+    context 'when the source has diagnostics with error and warning level' do
+      let(:diagnostics) do
+        [
+          create_diagnostics(:error),
+          create_diagnostics(:warning)
+        ]
+      end
+
+      it 'returns false' do
+        expect(processed_source.valid_syntax?).to be_false
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/source_parser_spec.rb b/spec/rubocop/source_parser_spec.rb
new file mode 100644
index 0000000..59daf88
--- /dev/null
+++ b/spec/rubocop/source_parser_spec.rb
@@ -0,0 +1,85 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::SourceParser, :isolated_environment do
+  include FileHelper
+
+  describe '.parse_file' do
+    let(:file) { 'example.rb' }
+
+    let(:source) do
+      [
+        '# encoding: utf-8',
+        '',
+        'def some_method',
+        "  puts 'foo'",
+        'end',
+        '',
+        'some_method'
+      ]
+    end
+
+    before do
+      create_file(file, source)
+    end
+
+    let(:processed_source) do
+      described_class.parse_file(file)
+    end
+
+    it 'returns ProcessedSource' do
+      expect(processed_source).to be_a(Rubocop::ProcessedSource)
+    end
+
+    describe 'the returned processed source' do
+      it 'has the root node of AST' do
+        expect(processed_source.ast).to be_a(Parser::AST::Node)
+      end
+
+      it 'has an array of comments' do
+        expect(processed_source.comments).to be_a(Array)
+        expect(processed_source.comments.first)
+          .to be_a(Parser::Source::Comment)
+      end
+
+      it 'has an array of tokens' do
+        expect(processed_source.tokens).to be_a(Array)
+        expect(processed_source.tokens.first).to be_a(Rubocop::Token)
+      end
+
+      it 'has a source buffer' do
+        expect(processed_source.buffer).to be_a(Parser::Source::Buffer)
+      end
+
+      context 'when the source is valid' do
+        it 'does not have diagnostics' do
+          expect(processed_source.diagnostics).to be_a(Array)
+          expect(processed_source.diagnostics).to be_empty
+        end
+      end
+
+      context 'when the source has invalid syntax' do
+        let(:source) do
+          [
+            '# encoding: utf-8',
+            '',
+            'def some_method',
+            "  puts 'foo'",
+            'end',
+            '',
+            'some_method',
+            '',
+            '?invalid_syntax'
+          ]
+        end
+
+        it 'has an array of diagnostics' do
+          expect(processed_source.diagnostics).to be_a(Array)
+          expect(processed_source.diagnostics.first)
+            .to be_a(Parser::Diagnostic)
+        end
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/target_finder_spec.rb b/spec/rubocop/target_finder_spec.rb
new file mode 100644
index 0000000..ee3474c
--- /dev/null
+++ b/spec/rubocop/target_finder_spec.rb
@@ -0,0 +1,211 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::TargetFinder, :isolated_environment do
+  include FileHelper
+
+  subject(:target_finder) do
+    described_class.new(config_store, options)
+  end
+  let(:config_store) { Rubocop::ConfigStore.new }
+  let(:options) { { force_exclusion: force_exclusion, debug: debug } }
+  let(:force_exclusion) { false }
+  let(:debug) { false }
+
+  before do
+    create_file('dir1/ruby1.rb',   '# encoding: utf-8')
+    create_file('dir1/ruby2.rb',   '# encoding: utf-8')
+    create_file('dir1/file.txt',   '# encoding: utf-8')
+    create_file('dir1/file',       '# encoding: utf-8')
+    create_file('dir1/executable', '#!/usr/bin/env ruby')
+    create_file('dir2/ruby3.rb',   '# encoding: utf-8')
+  end
+
+  describe '#find' do
+    let(:found_files) { target_finder.find(args) }
+    let(:found_basenames) { found_files.map { |f| File.basename(f) } }
+    let(:args) { [] }
+
+    it 'returns absolute paths' do
+      expect(found_files).not_to be_empty
+      found_files.each do |file|
+        expect(file).to start_with('/')
+      end
+    end
+
+    context 'when no argument is passed' do
+      let(:args) { [] }
+
+      it 'finds files under the current directory' do
+        Dir.chdir('dir1') do
+          expect(found_files).not_to be_empty
+          found_files.each do |file|
+            expect(file).to include('/dir1/')
+            expect(file).not_to include('/dir2/')
+          end
+        end
+      end
+    end
+
+    context 'when a directory path is passed' do
+      let(:args) { ['../dir2'] }
+
+      it 'finds files under the specified directory' do
+        Dir.chdir('dir1') do
+          expect(found_files).not_to be_empty
+          found_files.each do |file|
+            expect(file).to include('/dir2/')
+            expect(file).not_to include('/dir1/')
+          end
+        end
+      end
+    end
+
+    context 'when a file is passed' do
+      let(:args) { ['dir2/file'] }
+
+      it 'picks the file' do
+        expect(found_basenames).to eq(['file'])
+      end
+    end
+
+    context 'when a pattern is passed' do
+      let(:args) { ['dir1/*2.rb'] }
+
+      it 'finds files which match the pattern' do
+        expect(found_basenames).to eq(['ruby2.rb'])
+      end
+    end
+
+    context 'when same paths are passed' do
+      let(:args) { %w(dir1 dir1) }
+
+      it 'does not return duplicated file paths' do
+        count = found_basenames.count { |f| f == 'ruby1.rb' }
+        expect(count).to eq(1)
+      end
+    end
+
+    context 'when some paths are specified in the configuration Exclude ' \
+            'and they are explicitly passed as arguments' do
+      before do
+        create_file('.rubocop.yml', [
+          'AllCops:',
+          '  Exclude:',
+          '    - dir1/ruby1.rb',
+          "    - 'dir2/*'"
+        ])
+
+        create_file('dir1/.rubocop.yml', [
+          'AllCops:',
+          '  Exclude:',
+          '    - executable'
+        ])
+      end
+
+      let(:args) do
+        ['dir1/ruby1.rb', 'dir1/ruby2.rb', 'dir1/exe*', 'dir2/ruby3.rb']
+      end
+
+      context 'normally' do
+        it 'does not exludes them' do
+          expect(found_basenames)
+            .to eq(['ruby1.rb', 'ruby2.rb', 'executable', 'ruby3.rb'])
+        end
+      end
+
+      context "when it's forced to adhere file exclusion configuration" do
+        let(:force_exclusion) { true }
+
+        it 'exludes them' do
+          expect(found_basenames).to eq(['ruby2.rb'])
+        end
+      end
+    end
+  end
+
+  describe '#target_files_in_dir' do
+    let(:found_files) { target_finder.target_files_in_dir(base_dir) }
+    let(:found_basenames) { found_files.map { |f| File.basename(f) } }
+    let(:base_dir) { '.' }
+
+    it 'picks files with extension .rb' do
+      rb_file_count = found_files.count { |f| f.end_with?('.rb') }
+      expect(rb_file_count).to eq(3)
+    end
+
+    it 'picks ruby executable files with no extension' do
+      expect(found_basenames).to include('executable')
+    end
+
+    it 'does not pick files with no extension and no ruby shebang' do
+      expect(found_basenames).not_to include('file')
+    end
+
+    it 'picks ruby executable files with no extension' do
+      expect(found_basenames).to include('executable')
+    end
+
+    it 'does not pick directories' do
+      found_basenames = found_files.map { |f| File.basename(f) }
+      expect(found_basenames).not_to include('dir1')
+    end
+
+    it 'picks files specified to be included in config' do
+      config = double('config')
+      allow(config).to receive(:file_to_include?) do |file|
+        File.basename(file) == 'file'
+      end
+      allow(config).to receive(:file_to_exclude?).and_return(false)
+      allow(config_store).to receive(:for).and_return(config)
+
+      expect(found_basenames).to include('file')
+    end
+
+    it 'does not pick files specified to be excluded in config' do
+      config = double('config').as_null_object
+      allow(config).to receive(:file_to_include?).and_return(false)
+      allow(config).to receive(:file_to_exclude?) do |file|
+        File.basename(file) == 'ruby2.rb'
+      end
+      allow(config_store).to receive(:for).and_return(config)
+
+      expect(found_basenames).not_to include('ruby2.rb')
+    end
+
+    context 'when an exception is raised while reading file' do
+      around do |example|
+        original_stderr = $stderr
+        $stderr = StringIO.new
+        begin
+          example.run
+        ensure
+          $stderr = original_stderr
+        end
+      end
+
+      before do
+        allow_any_instance_of(File).to receive(:readline).and_raise(EOFError)
+      end
+
+      context 'and debug mode is enabled' do
+        let(:debug) { true }
+
+        it 'outputs error message' do
+          found_files
+          expect($stderr.string).to include('Unprocessable file')
+        end
+      end
+
+      context 'and debug mode is disabled' do
+        let(:debug) { false }
+
+        it 'outputs nothing' do
+          found_files
+          expect($stderr.string).to be_empty
+        end
+      end
+    end
+  end
+end
diff --git a/spec/rubocop/token_spec.rb b/spec/rubocop/token_spec.rb
new file mode 100644
index 0000000..d818a8b
--- /dev/null
+++ b/spec/rubocop/token_spec.rb
@@ -0,0 +1,25 @@
+# encoding: utf-8
+
+require 'spec_helper'
+
+describe Rubocop::Token do
+  describe '.from_parser_token' do
+    subject(:token) { described_class.from_parser_token(parser_token) }
+    let(:parser_token) { [type, [text, range]] }
+    let(:type) { :kDEF }
+    let(:text) { 'def' }
+    let(:range) { double('range') }
+
+    it "sets parser token's type to rubocop token's type" do
+      expect(token.type).to eq(type)
+    end
+
+    it "sets parser token's text to rubocop token's text" do
+      expect(token.text).to eq(text)
+    end
+
+    it "sets parser token's range to rubocop token's pos" do
+      expect(token.pos).to eq(range)
+    end
+  end
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
new file mode 100644
index 0000000..c8c26be
--- /dev/null
+++ b/spec/spec_helper.rb
@@ -0,0 +1,149 @@
+# encoding: utf-8
+
+if ENV['TRAVIS'] && RUBY_ENGINE == 'jruby'
+  # Force JRuby not to select working directory
+  # as temporary directory on Travis CI.
+  # https://github.com/jruby/jruby/issues/405
+  require 'fileutils'
+  tmp_dir = ENV['TMPDIR'] || ENV['TMP'] || ENV['TEMP'] ||
+            Etc.systmpdir || '/tmp'
+  non_world_writable_tmp_dir = File.join(tmp_dir, 'rubocop')
+  FileUtils.makedirs(non_world_writable_tmp_dir, mode: 0700)
+  ENV['TMPDIR'] = non_world_writable_tmp_dir
+end
+
+if ENV['TRAVIS'] || ENV['COVERAGE']
+  require 'simplecov'
+
+  if ENV['TRAVIS']
+    require 'coveralls'
+    SimpleCov.formatter = Coveralls::SimpleCov::Formatter
+  end
+
+  SimpleCov.start do
+    add_filter '/spec/'
+    add_filter '/vendor/bundle/'
+  end
+end
+
+$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
+$LOAD_PATH.unshift(File.dirname(__FILE__))
+require 'rspec'
+require 'rubocop'
+require 'rubocop/cli'
+
+# disable colors in specs
+Rainbow.enabled = false
+
+module ExitCodeMatchers
+  RSpec::Matchers.define :exit_with_code do |code|
+    actual = nil
+    match do |block|
+      begin
+        block.call
+      rescue SystemExit => e
+        actual = e.status
+      end
+      actual && actual == code
+    end
+    failure_message_for_should do |block|
+      "expected block to call exit(#{code}) but exit" +
+        (actual.nil? ? ' not called' : "(#{actual}) was called")
+    end
+    failure_message_for_should_not do |block|
+      "expected block not to call exit(#{code})"
+    end
+    description do
+      "expect block to call exit(#{code})"
+    end
+  end
+end
+
+RSpec.configure do |config|
+  config.treat_symbols_as_metadata_keys_with_true_values = true
+
+  # These two settings work together to allow you to limit a spec run
+  # to individual examples or groups you care about by tagging them with
+  # `:focus` metadata. When nothing is tagged with `:focus`, all examples
+  # get run.
+  config.filter_run :focus
+  config.run_all_when_everything_filtered = true
+
+  broken_filter = lambda do |v|
+    v.is_a?(Symbol) ? RUBY_ENGINE == v.to_s : v
+  end
+  config.filter_run_excluding ruby: ->(v) { !RUBY_VERSION.start_with?(v.to_s) }
+  config.filter_run_excluding broken: broken_filter
+
+  config.expect_with :rspec do |c|
+    c.syntax = :expect # disables `should`
+  end
+
+  config.mock_with :rspec do |c|
+    c.syntax = :expect # disables `should_receive` and `stub`
+  end
+
+  config.include(ExitCodeMatchers)
+end
+
+def inspect_source_file(cop, source)
+  Tempfile.open('tmp') { |f| inspect_source(cop, source, f) }
+end
+
+def inspect_source(cop, source, file = nil)
+  Rubocop::Formatter::DisabledConfigFormatter.config_to_allow_offenses = {}
+  processed_source = parse_source(source, file)
+  fail 'Error parsing example code' unless processed_source.valid_syntax?
+  _investigate(cop, processed_source)
+end
+
+def parse_source(source, file = nil)
+  source = source.join($RS) if source.is_a?(Array)
+  if file.is_a? String
+    Rubocop::SourceParser.parse(source, file)
+  elsif file
+    file.write(source)
+    file.rewind
+    Rubocop::SourceParser.parse(source, file.path)
+  else
+    Rubocop::SourceParser.parse(source)
+  end
+end
+
+def autocorrect_source_file(cop, source)
+  Tempfile.open('tmp') { |f| autocorrect_source(cop, source, f) }
+end
+
+def autocorrect_source(cop, source, file = nil)
+  cop.instance_variable_get(:@options)[:auto_correct] = true
+  processed_source = parse_source(source, file)
+  _investigate(cop, processed_source)
+
+  corrector =
+    Rubocop::Cop::Corrector.new(processed_source.buffer, cop.corrections)
+  corrector.rewrite
+end
+
+def _investigate(cop, processed_source)
+  commissioner = Rubocop::Cop::Commissioner.new([cop], raise_error: true)
+  commissioner.investigate(processed_source)
+  commissioner
+end
+
+module Rubocop
+  module Cop
+    class Cop
+      def messages
+        offenses.sort.map(&:message)
+      end
+
+      def highlights
+        offenses.sort.map { |o| o.location.source }
+      end
+    end
+  end
+end
+
+# Requires supporting files with custom matchers and macros, etc,
+# in ./support/ and its subdirectories.
+Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
diff --git a/spec/support/ast_helper.rb b/spec/support/ast_helper.rb
new file mode 100644
index 0000000..591b007
--- /dev/null
+++ b/spec/support/ast_helper.rb
@@ -0,0 +1,15 @@
+# encoding: utf-8
+
+module ASTHelper
+  def scan_node(node, options = {}, &block)
+    yield node if options[:include_origin_node]
+
+    node.children.each do |child|
+      next unless child.is_a?(Parser::AST::Node)
+      yield child
+      scan_node(child, &block)
+    end
+
+    nil
+  end
+end
diff --git a/spec/support/file_helper.rb b/spec/support/file_helper.rb
new file mode 100644
index 0000000..af71d27
--- /dev/null
+++ b/spec/support/file_helper.rb
@@ -0,0 +1,21 @@
+# encoding: utf-8
+
+require 'fileutils'
+
+module FileHelper
+  def create_file(file_path, content)
+    file_path = File.expand_path(file_path)
+
+    dir_path = File.dirname(file_path)
+    FileUtils.makedirs dir_path unless File.exist?(dir_path)
+
+    File.open(file_path, 'w') do |file|
+      case content
+      when String
+        file.puts content
+      when Array
+        file.puts content.join("\n")
+      end
+    end
+  end
+end
diff --git a/spec/support/isolated_environment.rb b/spec/support/isolated_environment.rb
new file mode 100644
index 0000000..58eaee3
--- /dev/null
+++ b/spec/support/isolated_environment.rb
@@ -0,0 +1,34 @@
+# encoding: utf-8
+
+require 'tmpdir'
+require 'fileutils'
+
+shared_context 'isolated environment', :isolated_environment do
+  around do |example|
+    Dir.mktmpdir do |tmpdir|
+      original_home = ENV['HOME']
+
+      # Make sure to expand all symlinks in the path first. Otherwise we may
+      # get mismatched pathnames when loading config files later on.
+      tmpdir = File.realpath(tmpdir)
+
+      # Make upwards search for .rubocop.yml files stop at this directory.
+      Rubocop::ConfigLoader.root_level = tmpdir
+
+      begin
+        virtual_home = File.expand_path(File.join(tmpdir, 'home'))
+        Dir.mkdir(virtual_home)
+        ENV['HOME'] = virtual_home
+
+        working_dir = File.join(tmpdir, 'work')
+        Dir.mkdir(working_dir)
+
+        Dir.chdir(working_dir) do
+          example.run
+        end
+      ensure
+        ENV['HOME'] = original_home
+      end
+    end
+  end
+end
diff --git a/spec/support/mri_syntax_checker.rb b/spec/support/mri_syntax_checker.rb
new file mode 100644
index 0000000..552f0c4
--- /dev/null
+++ b/spec/support/mri_syntax_checker.rb
@@ -0,0 +1,73 @@
+# encoding: utf-8
+
+require 'open3'
+
+# The reincarnation of syntax cop :)
+module MRISyntaxChecker
+  module_function
+
+  def offenses_for_source(source, fake_cop_name = 'Syntax', grep_message = nil)
+    if source.is_a?(Array)
+      source_lines = source
+      source = source_lines.join("\n")
+    else
+      source_lines = source.each_line.to_a
+    end
+
+    source_buffer = Parser::Source::Buffer.new('test', 1)
+    source_buffer.source = source
+
+    offenses = check_syntax(source).each_line.map do |line|
+      check_line(line, source_lines, source_buffer, fake_cop_name,
+                 grep_message)
+    end
+
+    offenses.compact
+  end
+
+  def check_line(line, source_lines, source_buffer, fake_cop_name,
+                 grep_message)
+    line_number, severity, message = process_line(line)
+    return unless line_number
+    return if grep_message && !message.include?(grep_message)
+    begin_pos = source_lines[0...(line_number - 1)].reduce(0) do |a, e|
+      a + e.length + "\n".length
+    end
+    Rubocop::Cop::Offense.new(severity,
+                              Parser::Source::Range.new(source_buffer,
+                                                        begin_pos,
+                                                        begin_pos + 1),
+                              message.capitalize,
+                              fake_cop_name)
+  end
+
+  def check_syntax(source)
+    fail 'Must be running with MRI' unless RUBY_ENGINE == 'ruby'
+
+    stdin, stderr, thread = nil
+
+    # It's extremely important to run the syntax check in a
+    # clean environment - otherwise it will be extremely slow.
+    if defined? Bundler
+      Bundler.with_clean_env do
+        stdin, _, stderr, thread = Open3.popen3('ruby', '-cw')
+      end
+    else
+      stdin, _, stderr, thread = Open3.popen3('ruby', '-cw')
+    end
+
+    stdin.write(source)
+    stdin.close
+    thread.join
+
+    stderr.read
+  end
+
+  def process_line(line)
+    match_data = line.match(/.+:(\d+): (warning: )?(.+)/)
+    return nil unless match_data
+    line_number, warning, message = match_data.captures
+    severity = warning ? :warning : :error
+    [line_number.to_i, severity, message]
+  end
+end
diff --git a/spec/support/shared_context.rb b/spec/support/shared_context.rb
new file mode 100644
index 0000000..a23bf94
--- /dev/null
+++ b/spec/support/shared_context.rb
@@ -0,0 +1,22 @@
+# encoding: utf-8
+
+# `cop_config` must be declared with #let.
+shared_context 'config', :config do
+  let(:config) do
+    # Module#<
+    unless described_class < Rubocop::Cop::Cop
+      fail '`config` must be used in `describe SomeCopClass do .. end`'
+    end
+
+    unless cop_config.is_a?(Hash)
+      fail '`cop_config` must be declared with #let'
+    end
+
+    cop_name = described_class.cop_name
+    hash = {
+      cop_name =>
+      Rubocop::ConfigLoader.default_configuration[cop_name].merge(cop_config)
+    }
+    Rubocop::Config.new(hash, "#{Dir.pwd}/.rubocop.yml")
+  end
+end
diff --git a/spec/support/shared_examples.rb b/spec/support/shared_examples.rb
new file mode 100644
index 0000000..32abbfe
--- /dev/null
+++ b/spec/support/shared_examples.rb
@@ -0,0 +1,33 @@
+# encoding: utf-8
+
+# `cop` and `source` must be declared with #let.
+
+shared_examples_for 'accepts' do
+  it 'accepts' do
+    inspect_source(cop, source)
+    expect(cop.offenses).to be_empty
+  end
+end
+
+shared_examples_for 'mimics MRI 2.1' do |grep_mri_warning|
+  if RUBY_ENGINE == 'ruby' && RUBY_VERSION.start_with?('2.1')
+    it "mimics MRI #{RUBY_VERSION} built-in syntax checking" do
+      inspect_source(cop, source)
+      offenses_by_mri = MRISyntaxChecker.offenses_for_source(
+        source, cop.name, grep_mri_warning
+      )
+
+      # Compare objects before comparing counts for clear failure output.
+      cop.offenses.each_with_index do |offense_by_cop, index|
+        offense_by_mri = offenses_by_mri[index]
+        # Exclude column attribute since MRI does not
+        # output column number.
+        [:severity, :line, :cop_name].each do |a|
+          expect(offense_by_cop.send(a)).to eq(offense_by_mri.send(a))
+        end
+      end
+
+      expect(cop.offenses.count).to eq(offenses_by_mri.count)
+    end
+  end
+end
diff --git a/spec/support/statement_modifier_helper.rb b/spec/support/statement_modifier_helper.rb
new file mode 100644
index 0000000..996268b
--- /dev/null
+++ b/spec/support/statement_modifier_helper.rb
@@ -0,0 +1,41 @@
+# encoding: utf-8
+
+module StatementModifierHelper
+  def check_empty(cop, keyword)
+    inspect_source(cop, ["#{keyword} cond",
+                         'end'])
+    expect(cop.offenses).to be_empty
+  end
+
+  def check_really_short(cop, keyword)
+    inspect_source(cop, ["#{keyword} a",
+                         '  b',
+                         'end'])
+    expect(cop.messages).to eq(
+      ["Favor modifier `#{keyword}` usage when having a single-line body."])
+    expect(cop.offenses.map { |o| o.location.source }).to eq([keyword])
+  end
+
+  def check_too_long(cop, keyword)
+    # This statement is one character too long to fit.
+    condition = 'a' * (40 - keyword.length)
+    body = 'b' * 36
+    expect("  #{body} #{keyword} #{condition}".length).to eq(80)
+
+    inspect_source(cop,
+                   ["  #{keyword} #{condition}",
+                    "    #{body}",
+                    '  end'])
+
+    expect(cop.offenses).to be_empty
+  end
+
+  def check_short_multiline(cop, keyword)
+    inspect_source(cop,
+                   ["#{keyword} ENV['COVERAGE']",
+                    "  require 'simplecov'",
+                    '  SimpleCov.start',
+                    'end'])
+    expect(cop.messages).to be_empty
+  end
+end

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ruby-extras/rubocop.git



More information about the Pkg-ruby-extras-commits mailing list