supercop 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a69ce9a6b65284cfe4c831111c5eee5e7361d91d
4
+ data.tar.gz: c3ca2a2d82a22bd5acedaa22033a700f26ee7d4e
5
+ SHA512:
6
+ metadata.gz: ec097698283f997ae6b1f0b1c66b1428c428c774b6ddb85ac1f525cee6b5599bfd0555d868c964595fa4f91a6037f7b4478445ec3c6cc84a0cf54ab1a593bba3
7
+ data.tar.gz: 7bbe552029a0dcaa38000c06db531f0d8441411327f3b5f8add50b192a643369af54e592f9ed50f7586b0305b739af83bc717ae6b74de3d82f384d51d8a5065a
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,11 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.2.3
5
+ - 2.3.1
6
+ - 2.3.3
7
+ before_install:
8
+ - gem install bundler -v 1.13.1
9
+ - gem install rubocop
10
+ before_script:
11
+ - bundle exec rake supercop:generate_config
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in supercop.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Artem Kuznetsov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,94 @@
1
+ # Supercop
2
+ [![Build Status](https://travis-ci.org/artemasmith/supercop.svg?branch=master)](https://travis-ci.org/artemasmith/supercop)
3
+
4
+ This gem allows you to combine multiple linters with their configs in one place and run all checks by one command with tabled-view summary report (see below).
5
+ You should specify which linters you would like to use, for example rubocop, reek,
6
+ scss_linter etc. Gem would load them if they are not installed and run checks.
7
+
8
+ One gem for rule them all:)
9
+
10
+ ### Versions
11
+
12
+ It works for 2.2.3, 2.3.1, 2.3.3 versions of Ruby MRI.
13
+
14
+ ## Installation
15
+
16
+ Add this line to your application's Gemfile:
17
+
18
+ ```ruby
19
+ gem 'supercop'
20
+ ```
21
+
22
+ And then execute:
23
+
24
+ $ bundle
25
+
26
+ Or install it yourself as:
27
+
28
+ $ gem install supercop
29
+
30
+ ### Install into another gem
31
+
32
+ Add supercop tasks to the Rakefile:
33
+
34
+ ```ruby
35
+ spec = Gem::Specification.find_by_name 'supercop'
36
+ load "#{spec.gem_dir}/lib/tasks/manage_settings.rake"
37
+ load "#{spec.gem_dir}/lib/tasks/check.rake"
38
+ ```
39
+
40
+ ## Usage
41
+
42
+ After install, you should modify supercop.yml and specify prefered linters.
43
+ After that run
44
+
45
+ $ rake supercop:generate_config
46
+
47
+ for non-rails project (like gem) or
48
+
49
+ $ rails g supercop:config
50
+
51
+ for rails project
52
+
53
+ After that, please modify your supercop.yml config file, adding linters you want to use and run
54
+
55
+ $ rake supercop:load_dependencies
56
+
57
+ or you can do it manually by adding gems to your Gemfile (for other gems - to the end of file) and running bundle install.
58
+
59
+ `Note:` You should do it once.
60
+
61
+ Now you can run checks.
62
+
63
+ ### Clean up
64
+
65
+ If you want to restore all affected files and clean up supercop remnants, please run
66
+
67
+ $ rake supercop:cleanup
68
+
69
+ This will delete config file and erase changes made by Supercop to your Gemfile and bundle.
70
+
71
+ ### Running check
72
+
73
+ $ rake supercop:check
74
+
75
+ | linter | alerts | max | status |
76
+ | ------------------ |:------------------:|:------------------:|:------------------:|
77
+ | rubocop | 48 | 99 | ok |
78
+ | reek | 45 | 99 | ok |
79
+ | slim_lint | none | 99 | ok |
80
+ | scss_lint | none | 99 | ok |
81
+
82
+ 'none' - means linter did not work correctly. To figured out why - change 'verbose' option to true
83
+
84
+ ## Development
85
+
86
+ After checking out the repo, run bundle install and make your changes. After commit, create Pull Request and notify me.
87
+
88
+ ## Contributing
89
+
90
+ Bug reports and pull requests are welcome on GitHub at https://github.com/artemasmith/supercop.
91
+
92
+ ## License
93
+
94
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ import './lib/tasks/manage_settings.rake'
5
+ import './lib/tasks/check.rake'
6
+
7
+ RSpec::Core::RakeTask.new(:spec)
8
+
9
+ task default: :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "supercop"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/lib/supercop.rb ADDED
@@ -0,0 +1,36 @@
1
+ require 'active_support'
2
+ require 'active_support/core_ext'
3
+ require 'active_support/core_ext/hash/indifferent_access'
4
+
5
+ require 'supercop/cop'
6
+ require 'supercop/version'
7
+ require 'supercop/checker'
8
+ require 'supercop/configuration'
9
+ require 'supercop/table_formatter'
10
+ require 'supercop/actions/config_copier'
11
+ require 'supercop/actions/file_injector'
12
+ require 'supercop/actions/clean'
13
+ require 'supercop/actions/loaders/base'
14
+ require 'supercop/actions/loaders/dependency'
15
+ require 'supercop/parsers/base'
16
+ require 'supercop/parsers/proxy'
17
+ require 'supercop/parsers/scss_lint'
18
+ require 'supercop/parsers/rubocop'
19
+
20
+ require 'json'
21
+ require 'yaml'
22
+
23
+ if defined?(Rails)
24
+ require 'supercop/railtie'
25
+ require 'rails/generators'
26
+ end
27
+
28
+ module Supercop
29
+ class << self
30
+ attr_accessor :configuration
31
+ end
32
+
33
+ def self.configuration
34
+ @configuration ||= Configuration.new
35
+ end
36
+ end
@@ -0,0 +1,93 @@
1
+ module Supercop
2
+ module Actions
3
+ class Clean
4
+ class << self
5
+ def call
6
+ if clean_gemfile[:changed]
7
+ restore_gemfile
8
+
9
+ update_bundle
10
+ else
11
+ notify_nothing_changed
12
+ end
13
+
14
+ remove_config
15
+ end
16
+
17
+ private
18
+
19
+ def notify_nothing_changed
20
+ puts 'Your Gemfile was not changed. Nothing to restore.'
21
+ end
22
+
23
+ def restore_gemfile
24
+ puts 'Restoring your Gemfile'
25
+
26
+ temp_file = "#{gemfile}.tmp"
27
+
28
+ File.open(temp_file, 'w') do |f|
29
+ f.print(clean_gemfile[:gemfile])
30
+ end
31
+
32
+ FileUtils.mv temp_file, gemfile
33
+ end
34
+
35
+ def update_bundle
36
+ puts 'Updating your bundle, please wait'
37
+
38
+ Bundler.with_clean_env do
39
+ `bundle install`
40
+ end
41
+ end
42
+
43
+ def clean_gemfile
44
+ clean_gemfile = []
45
+ changed = false
46
+
47
+ File.open(gemfile, 'r') do |f|
48
+ until (line = f.gets).nil?
49
+ if line.include?(start_comment)
50
+ changed = true
51
+ until (line = f.gets).nil?
52
+ if line.include?(end_comment)
53
+ line = f.gets
54
+ break
55
+ end
56
+ end
57
+ end
58
+
59
+ clean_gemfile << line
60
+ end
61
+ end
62
+ @_clean_gemfile = { gemfile: clean_gemfile.join, changed: changed }
63
+ end
64
+
65
+ def remove_config
66
+ if File.file?(supercop_config)
67
+ puts 'Removing your supercop.yml'
68
+
69
+ FileUtils.rm(supercop_config)
70
+ end
71
+ end
72
+
73
+ def gemfile
74
+ @_gemfile ||= File.join(Dir.pwd, 'Gemfile')
75
+ end
76
+
77
+ def supercop_config
78
+ root = defined?(Rails) ? File.join(Dir.pwd, 'config') : Dir.pwd
79
+
80
+ @_supercop_config ||= File.join(root, 'supercop.yml')
81
+ end
82
+
83
+ def start_comment
84
+ Supercop::Actions::Loaders::Dependency::START_COMMENT
85
+ end
86
+
87
+ def end_comment
88
+ Supercop::Actions::Loaders::Dependency::END_COMMENT
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,46 @@
1
+ module Supercop
2
+ module Actions
3
+ class ConfigCopier
4
+ require 'fileutils'
5
+ CONFIG_PATH = %w[lib supercop templates].freeze
6
+
7
+ def initialize(args)
8
+ @filename = args.fetch(:filename, 'supercop.yml')
9
+ @destination = args.fetch(:destination)
10
+ @options = args.fetch(:options, {})
11
+ @source = args.fetch(:source, 'supercop.yml')
12
+ end
13
+
14
+ def call
15
+ return "There is no destination #{destination}" if invalid_destination?
16
+ return "#{destination_file} already exists" if File.file?(destination_file)
17
+
18
+ FileUtils.copy(source_file, destination_file, options)
19
+
20
+ "file #{destination_file} was created"
21
+ rescue => e
22
+ "Could not create file. #{e.message}"
23
+ end
24
+
25
+ private
26
+
27
+ attr_reader :filename, :destination, :source, :options
28
+
29
+ def invalid_destination?
30
+ destination.empty? || !Dir.exist?(destination)
31
+ end
32
+
33
+ def source_file
34
+ File.join(root, CONFIG_PATH, source)
35
+ end
36
+
37
+ def destination_file
38
+ File.join(destination, filename)
39
+ end
40
+
41
+ def root
42
+ Gem.loaded_specs['supercop'].full_gem_path
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,35 @@
1
+ module Supercop
2
+ module Actions
3
+ class FileInjector
4
+ attr_reader :filename, :line
5
+
6
+ def initialize(filename:, line:)
7
+ @filename = filename
8
+ @line = line
9
+ end
10
+
11
+ def call
12
+ return if file_include?
13
+
14
+ insert_into_file
15
+ end
16
+
17
+ def file_include?
18
+ File.foreach(filename).grep(sanitized).present?
19
+ end
20
+
21
+ private
22
+
23
+
24
+ def insert_into_file
25
+ File.open(filename, 'a') do |f|
26
+ f.write(line)
27
+ end
28
+ end
29
+
30
+ def sanitized
31
+ line.sub(/\s\n$/, '')
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,58 @@
1
+ module Supercop
2
+ module Actions
3
+ module Loaders
4
+ class Base
5
+ BUNDLE_REQUIRED = :bundle_required
6
+
7
+ attr_reader :gem_name, :config, :injector, :file
8
+
9
+ def initialize(gem_name)
10
+ @gem_name = gem_name
11
+ @config = Supercop.configuration.public_send(gem_name)
12
+ @injector = Supercop::Actions::FileInjector
13
+ @file = Supercop.configuration.path('Gemfile')
14
+ end
15
+
16
+ def installed?
17
+ load_gem
18
+ true
19
+ rescue LoadError
20
+ false
21
+ end
22
+
23
+ def call
24
+ add_gem
25
+
26
+ puts "'#{gem_name}' was added as dependency.\n"
27
+ BUNDLE_REQUIRED
28
+ end
29
+
30
+ private
31
+
32
+ def load_gem
33
+ require gem_name.to_s
34
+ end
35
+
36
+ def add_gem
37
+ puts "Inserting into #{file} \n"
38
+ puts "gem config #{gem_config}\n"
39
+
40
+ injector.new(filename: file, line: gem_config).call
41
+ end
42
+
43
+ def gem_config
44
+ result = ["gem '#{gem_name}'"]
45
+ result << ", #{config[:version]}" if option?(:version)
46
+ result << ", path: '#{config[:path]}'" if option?(:path)
47
+ result << ", git: '#{config[:git]}'" if option?(:git) && !option?(:path)
48
+ result << "\n"
49
+ result.join(' ')
50
+ end
51
+
52
+ def option?(option)
53
+ config.keys.include?(option)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,65 @@
1
+ module Supercop
2
+ module Actions
3
+ module Loaders
4
+ class Dependency
5
+ BUNDLE_REQUIRED = :bundle_required
6
+ START_COMMENT = "####### SUPERCOP #######\n".freeze
7
+ END_COMMENT = "#### ENDOF SUPERCOP ####\n".freeze
8
+
9
+ attr_reader :gem_list, :loader, :file_injector
10
+
11
+ def initialize(loader = nil)
12
+ @gem_list = Supercop.configuration.cops_settings.keys
13
+ @loader = loader || Base
14
+ @file_injector = Supercop::Actions::FileInjector
15
+ end
16
+
17
+ def call
18
+ puts 'Loading dependecies, please wait..'
19
+
20
+ if gems_to_add.empty?
21
+ say_nothing_needed
22
+ else
23
+ wrap_for_gemfile do
24
+ gems_to_add.each { |gem_name| loader.new(gem_name).call }
25
+ end
26
+
27
+ install
28
+ end
29
+ end
30
+
31
+ alias load_dependencies call
32
+
33
+ private
34
+
35
+ def gems_to_add
36
+ gem_list.select { |gem_name| !loaded?(gem_name) }
37
+ end
38
+
39
+ def loaded?(gem_name)
40
+ loader.new(gem_name).installed? ? true : false
41
+ end
42
+
43
+ def install
44
+ puts 'Updating your bundle, please wait'
45
+ Bundler.with_clean_env do
46
+ `bundle install`
47
+ end
48
+ end
49
+
50
+ def say_nothing_needed
51
+ puts 'No need to install anything.'
52
+ end
53
+
54
+ def wrap_for_gemfile(&_block)
55
+ file = Supercop.configuration.path('Gemfile')
56
+ file_injector.new(filename: file, line: START_COMMENT).call
57
+
58
+ yield
59
+
60
+ file_injector.new(filename: file, line: END_COMMENT).call
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,16 @@
1
+ module Supercop
2
+ class Checker
3
+ attr_reader :linters, :printer, :cop
4
+ def initialize(printer = TableFormatter)
5
+ @linters = Supercop.configuration.cops_settings.keys
6
+ @printer = printer
7
+ @cop = Cop
8
+ end
9
+
10
+ def call
11
+ checks_result = linters.map { |linter| cop.new(linter).handle }
12
+
13
+ printer.new.print_table(checks_result)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,61 @@
1
+ module Supercop
2
+ class Configuration
3
+ attr_accessor :cops_settings, :verbose, :file_path
4
+
5
+ def initialize
6
+ @cops_settings = config_file.fetch(:config)
7
+ @verbose = config_file.fetch(:verbose)
8
+ @file_path = config_path
9
+ end
10
+
11
+ def path(file_path)
12
+ defined?(Rails) ? Rails.root.join(file_path) : File.join(Dir.pwd, file_path)
13
+ end
14
+
15
+ private
16
+
17
+ def config_file
18
+ @_config_file ||= YAML.load_file(config_path).with_indifferent_access
19
+ rescue => e
20
+ puts "Can't find or read config file, did you run initialize command? #{e.message}"
21
+ end
22
+
23
+ def config_path
24
+ @_config_path ||= defined?(Rails) ? rails_path : other_path
25
+ end
26
+
27
+ def rails_path
28
+ Rails.root.join('config', 'supercop.yml')
29
+ end
30
+
31
+ def other_path
32
+ File.join(Dir.pwd, 'supercop.yml')
33
+ end
34
+
35
+ def method_missing(m, *args, &block)
36
+ define_dig unless cops_settings.methods.include?(:dig)
37
+
38
+ cops_settings.dig(m) || super
39
+ end
40
+
41
+ # FYI: dirty hack for ruby < 2.3
42
+ def define_dig
43
+ new_method = <<-NEW
44
+ class ::Hash
45
+ def dig(*path)
46
+ path.inject(self) do |location, key|
47
+ location.is_a?(Hash) ? location[key] : nil
48
+ end
49
+ end
50
+ end
51
+ NEW
52
+
53
+ eval(new_method)
54
+ end
55
+
56
+ # https://robots.thoughtbot.com/always-define-respond-to-missing-when-overriding
57
+ def respond_to_missing?(method_name, include_private = false)
58
+ cops_settings.keys.include?(method_name) || super
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,43 @@
1
+ module Supercop
2
+ class Cop
3
+ attr_reader :linter, :cop_config, :parser, :config
4
+
5
+ def initialize(linter)
6
+ @linter = linter
7
+ @parser = Supercop::Parsers::Proxy
8
+ @config = Supercop.configuration
9
+ @cop_config = config.public_send(linter)
10
+ end
11
+
12
+ def handle
13
+ result = parse_cop_config
14
+
15
+ output = %i[linter warnings_actual warnings_max].map { |key| result[key] }
16
+ output << linter_status(result[:warnings_actual], result[:warnings_max])
17
+ end
18
+
19
+ private
20
+
21
+ def linter_status(actual, max)
22
+ actual.to_i < max ? 'ok' : 'fail'
23
+ end
24
+
25
+ def actual_warnings_count
26
+ output = `#{cop_config.fetch('cmd')} #{cop_config.fetch('options')}`
27
+
28
+ parser.new(output, linter).parse.to_s
29
+ end
30
+
31
+ def parse_cop_config
32
+ return if linter.blank?
33
+
34
+ { warnings_actual: actual_warnings_count,
35
+ warnings_max: cop_config.fetch('max'),
36
+ linter: linter }
37
+ rescue => e
38
+ puts "Problems with linter config load. #{e.message}" if config.verbose
39
+
40
+ { linter: linter, warnings_actual: 0, warnings_max: 0 }
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,17 @@
1
+ module Supercop
2
+ module Generators
3
+ class ConfigGenerator < ::Rails::Generators::Base
4
+ source_root File.expand_path('../templates', __dir__)
5
+
6
+ puts '=> Creates a Supercop idefault config for your application.'
7
+
8
+ def copy_config_file
9
+ destination = 'config/supercop.yml'
10
+
11
+ puts "=> Copy config file to #{destination}"
12
+
13
+ copy_file 'supercop.yml', destination
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,38 @@
1
+ module Supercop
2
+ module Parsers
3
+ class Base
4
+ attr_reader :json, :config
5
+
6
+ def initialize(json)
7
+ @json = json
8
+ @config = Supercop.configuration
9
+ end
10
+
11
+ def call
12
+ warnings_count
13
+ end
14
+
15
+ private
16
+
17
+ def parse
18
+ JSON.parse(json).count
19
+ end
20
+
21
+ def warnings_count
22
+ parse
23
+ rescue => e
24
+ parse_error(e)
25
+
26
+ 'none'
27
+ end
28
+
29
+ def parse_error(e)
30
+ msg = %Q[Wrong configuration for linter,
31
+ please check the path and options provided.
32
+ Error: #{e.message}]
33
+
34
+ puts msg if config.verbose
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,33 @@
1
+ module Supercop
2
+ module Parsers
3
+ class Proxy
4
+ RUBOCOP = %w[SlimLint HamlLint].freeze
5
+
6
+ attr_reader :json, :linter, :parser
7
+
8
+ def initialize(json, linter)
9
+ @linter = linter
10
+ @json = json
11
+ @parser = find_parser
12
+ end
13
+
14
+ def parse
15
+ parser.call
16
+ end
17
+
18
+ private
19
+
20
+ def find_parser
21
+ return Rubocop.new(json) if rubocop_like_parser?
22
+
23
+ ('Supercop::Parsers::' + linter.classify).constantize.new(json)
24
+ rescue NameError
25
+ Base.new(json)
26
+ end
27
+
28
+ def rubocop_like_parser?
29
+ RUBOCOP.include?(linter.classify)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,11 @@
1
+ module Supercop
2
+ module Parsers
3
+ class Rubocop < Base
4
+ private
5
+
6
+ def parse
7
+ JSON.parse(json).fetch('summary').fetch('offense_count')
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ module Supercop
2
+ module Parsers
3
+ class ScssLint < Base
4
+ private
5
+
6
+ def parse
7
+ output = JSON.parse(json)
8
+
9
+ output.keys.inject(0) { |warnings, key| warnings + output[key].count }
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ module Supercop
2
+ # FYI: Here we defined rake tasks and generators for Rails use
3
+ require 'rails/railtie'
4
+ class Railtie < ::Rails::Railtie
5
+ rake_tasks do
6
+ load 'tasks/manage_settings.rake'
7
+ load 'tasks/check.rake'
8
+ end
9
+
10
+ generators do
11
+ require_relative 'generators/config_generator'
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,42 @@
1
+ module Supercop
2
+ class TableFormatter
3
+ CELL_WIDTH = 20
4
+ DEFAULT_COLUMNS = %w[linter alerts max status].freeze
5
+
6
+ def initialize(columns = nil)
7
+ @columns = columns || DEFAULT_COLUMNS
8
+ end
9
+
10
+ def print_table(lines)
11
+ puts header
12
+
13
+ lines.each { |elements| puts line(elements) }
14
+
15
+ puts footer
16
+ end
17
+
18
+ private
19
+
20
+ def header
21
+ dash_line + "\n" + line(@columns) + "\n" + dash_line
22
+ end
23
+
24
+ def dash_line
25
+ line = '+'
26
+ @columns.count.times { line += Array.new(CELL_WIDTH, '-').join + '+' }
27
+ line
28
+ end
29
+
30
+ def footer
31
+ dash_line
32
+ end
33
+
34
+ def line(elements)
35
+ '|' + elements.map { |element| cell(element.to_s) }.join
36
+ end
37
+
38
+ def cell(word)
39
+ word.center(word.length + (CELL_WIDTH - word.length).abs) + '|'
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,86 @@
1
+ # FYI: 'cmd', 'options' and 'max' are required.
2
+ # 'path', 'git', 'version' and 'path' are optional params for installation.
3
+ # 'version' would not work with 'path' param.
4
+ # 'path' option is more priority and overrides 'git' option.
5
+ #
6
+ # File Format:
7
+ #
8
+ # linter: - gem name of linter to download
9
+ # cmd*: - command that run in command line
10
+ # option*: - options for cmd command to run. Please spcify here json output for normal parsing
11
+ # version: - version of gem to install
12
+ # git: - repo for gem download
13
+ # path: - local file system path to gem. It overrides git option
14
+ # max*: - maximum errors for linter to define ok or fail status of check
15
+ #
16
+ # * - required
17
+ #
18
+ # `Please note`, that you should specify JSON output param for correct parsing
19
+ #
20
+ # Example:
21
+ #
22
+ # rubocop:
23
+ # cmd: 'rubocop'
24
+ # options: '--jormat default'
25
+ # path: '/home/developer/rubocopgem/'
26
+ # version: '1.0.1'
27
+ # max: 20
28
+ #
29
+ # With git param:
30
+ #
31
+ # rubocop:
32
+ # cmd: 'rubocop'
33
+ # options: '--jormat default'
34
+ # git: 'git@github.com/developer/rubocop.git'
35
+ # version: '1.0.1'
36
+ #
37
+ # `Important!`
38
+ #
39
+ # Please use gem names for the configuration keys, like you add it to your gemfile
40
+ # For example:
41
+ # Correct:
42
+ #
43
+ # sccs_lint:
44
+ # cmd: 'scss-lint'
45
+ # version: '0.69'
46
+ #
47
+ # Incorrect - it wouldn't work
48
+ #
49
+ # scss-lint:
50
+ # cmd: 'scss-lint'
51
+ # version: '0.69'
52
+ #
53
+ # Template config fo rails project with slim
54
+ # max: &max_quantity
55
+ # max: 99
56
+ # verbose: false
57
+ # config:
58
+ # rubocop:
59
+ # cmd: 'rubocop'
60
+ # options: '--format json'
61
+ # git: 'git@github.com:bbatsov/rubocop.git'
62
+ # version: '~0.49'
63
+ # <<: *max_quantity
64
+ # slim_lint:
65
+ # cmd: 'slim-lint'
66
+ # options: 'app/views --reporter json'
67
+ # version: '~> 0.13.0'
68
+ # <<: *max_quantity
69
+ # scss_lint:
70
+ # cmd: 'scss-lint'
71
+ # options: 'app/assets --format JSON'
72
+ # <<: *max_quantity
73
+
74
+ max: &max_quantity
75
+ max: 99
76
+ verbose: false
77
+ config:
78
+ rubocop:
79
+ cmd: 'rubocop'
80
+ options: '--format json'
81
+ git: 'git@github.com:bbatsov/rubocop.git'
82
+ <<: *max_quantity
83
+ reek:
84
+ cmd: 'reek'
85
+ options: '--format json'
86
+ <<: *max_quantity
@@ -0,0 +1,3 @@
1
+ module Supercop
2
+ VERSION = '0.2.1'
3
+ end
@@ -0,0 +1,8 @@
1
+ require 'supercop'
2
+
3
+ desc 'Cops your code with configured linters and prints table report'
4
+ namespace :supercop do
5
+ task :check do
6
+ Supercop::Checker.new.call
7
+ end
8
+ end
@@ -0,0 +1,42 @@
1
+ require 'supercop'
2
+
3
+ namespace :supercop do
4
+ desc 'Create config file in your project, and load dependecies'
5
+ task :generate_config do
6
+ if defined?(Rails)
7
+ generate_for_rails
8
+ else
9
+ generate_for_other
10
+ end
11
+ end
12
+
13
+ desc 'Add missing dependencies to your Gemfile and run bundle install'
14
+ task :load_dependencies do
15
+ loader.load_dependencies
16
+ end
17
+
18
+ desc 'Clean up changes made by supercop: config, gems'
19
+ task :cleanup do
20
+ cleaner.call
21
+ end
22
+
23
+ def generate_for_rails
24
+ puts 'Please, use rails generator instead!'
25
+ end
26
+
27
+ def generate_for_other
28
+ puts 'Generate config for your supercop linters'
29
+
30
+ destination = Dir.pwd
31
+
32
+ puts Supercop::Actions::ConfigCopier.new(destination: destination).call
33
+ end
34
+
35
+ def loader
36
+ Supercop::Actions::Loaders::Dependency.new
37
+ end
38
+
39
+ def cleaner
40
+ Supercop::Actions::Clean
41
+ end
42
+ end
data/supercop.gemspec ADDED
@@ -0,0 +1,34 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'supercop/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'supercop'
8
+ spec.version = Supercop::VERSION
9
+ spec.authors = ['Artem Kuznetsov']
10
+ spec.email = ['artemasmith@gmailcom']
11
+
12
+ spec.summary = %q{Utility for get easy and simple code quality report
13
+ based on different linters, like rubocop or reek}
14
+ spec.description = %q{This gem allows you to use multiply lnters to check
15
+ your code quality and get nice table-view report}
16
+ spec.homepage = 'http://github.com/artemasmith/supercop'
17
+ spec.license = 'MIT'
18
+
19
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
20
+ f.match(%r{^(test|spec|features)/})
21
+ end
22
+ spec.bindir = 'exe'
23
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
+ spec.require_paths = ['lib']
25
+
26
+ spec.add_development_dependency 'bundler', '>= 1.13'
27
+ spec.add_development_dependency 'rake', '>= 10.0'
28
+ spec.add_development_dependency 'rspec', '>= 3.0'
29
+ spec.add_development_dependency 'rspec-its'
30
+ spec.add_development_dependency 'pry'
31
+ spec.add_development_dependency 'fakefs'
32
+ spec.add_development_dependency 'activesupport'
33
+ spec.add_development_dependency 'json'
34
+ end
metadata ADDED
@@ -0,0 +1,189 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: supercop
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ platform: ruby
6
+ authors:
7
+ - Artem Kuznetsov
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-09-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '1.13'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '1.13'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec-its
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: fakefs
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: activesupport
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: json
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: |-
126
+ This gem allows you to use multiply lnters to check
127
+ your code quality and get nice table-view report
128
+ email:
129
+ - artemasmith@gmailcom
130
+ executables: []
131
+ extensions: []
132
+ extra_rdoc_files: []
133
+ files:
134
+ - ".gitignore"
135
+ - ".rspec"
136
+ - ".travis.yml"
137
+ - Gemfile
138
+ - LICENSE.txt
139
+ - README.md
140
+ - Rakefile
141
+ - bin/console
142
+ - bin/setup
143
+ - lib/supercop.rb
144
+ - lib/supercop/actions/clean.rb
145
+ - lib/supercop/actions/config_copier.rb
146
+ - lib/supercop/actions/file_injector.rb
147
+ - lib/supercop/actions/loaders/base.rb
148
+ - lib/supercop/actions/loaders/dependency.rb
149
+ - lib/supercop/checker.rb
150
+ - lib/supercop/configuration.rb
151
+ - lib/supercop/cop.rb
152
+ - lib/supercop/generators/config_generator.rb
153
+ - lib/supercop/parsers/base.rb
154
+ - lib/supercop/parsers/proxy.rb
155
+ - lib/supercop/parsers/rubocop.rb
156
+ - lib/supercop/parsers/scss_lint.rb
157
+ - lib/supercop/railtie.rb
158
+ - lib/supercop/table_formatter.rb
159
+ - lib/supercop/templates/supercop.yml
160
+ - lib/supercop/version.rb
161
+ - lib/tasks/check.rake
162
+ - lib/tasks/manage_settings.rake
163
+ - supercop.gemspec
164
+ homepage: http://github.com/artemasmith/supercop
165
+ licenses:
166
+ - MIT
167
+ metadata: {}
168
+ post_install_message:
169
+ rdoc_options: []
170
+ require_paths:
171
+ - lib
172
+ required_ruby_version: !ruby/object:Gem::Requirement
173
+ requirements:
174
+ - - ">="
175
+ - !ruby/object:Gem::Version
176
+ version: '0'
177
+ required_rubygems_version: !ruby/object:Gem::Requirement
178
+ requirements:
179
+ - - ">="
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
182
+ requirements: []
183
+ rubyforge_project:
184
+ rubygems_version: 2.5.2
185
+ signing_key:
186
+ specification_version: 4
187
+ summary: Utility for get easy and simple code quality report based on different linters,
188
+ like rubocop or reek
189
+ test_files: []