slimcop 0.3.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e43c25d5b3588ae90dd33cff028ef9c42ada8905782d8ac97049324948e0e8f6
4
- data.tar.gz: b487022dc36d88c433ff0cf5b2666fe97e27a0e88b3def78fcbc51a2f33d753c
3
+ metadata.gz: 03e13f6191b529e4c4b0ca6bc1fbbd6d1144eb029e62158ae04f43111f4dd96e
4
+ data.tar.gz: 4eb2dccd29708a5de535d9fb4971eb56084e3d45644fd9ad9f0731416ad22ec7
5
5
  SHA512:
6
- metadata.gz: fba92c121be30436567f9cc30cb22570a8bc3f6316d8564681d9d124a2400296590fed6f0c11b7b3cb3ea16d3e48ebd3f53ba9719bc085bf76b731f1c7115e29
7
- data.tar.gz: df506c25b9b513589bf05391555b83228e976b000c4117e55d85b8e209ef613c25beef1b8e981a871e8c17382048d472a59dce3386cd1f034164ec81e528b547
6
+ metadata.gz: '09705a482591105427cf3bc97f6ba86ab317d78e845fb0ca91d677730fa7081b5466c54112449127d83dc350431aea1de288bfc67034e10045e47dfcda57a7b3'
7
+ data.tar.gz: '09384443d865bb4cd1edf7d44e0ee1eb84dcf6729910220b4cad9970eba1dd16b0cb00b26b40f5845223a61488097a5fd9b8c48f25c8e69349ba47d1739cea2c'
data/.rubocop.yml CHANGED
@@ -1,3 +1,6 @@
1
+ require:
2
+ - rubocop-rspec
3
+
1
4
  AllCops:
2
5
  NewCops: enable
3
6
  SuggestExtensions: false
@@ -9,5 +12,20 @@ Layout/LineLength:
9
12
  Metrics:
10
13
  Enabled: false
11
14
 
15
+ RSpec/AnyInstance:
16
+ Enabled: false
17
+
18
+ RSpec/ExampleLength:
19
+ Enabled: false
20
+
21
+ RSpec/ImplicitSubject:
22
+ Enabled: false
23
+
24
+ RSpec/MultipleExpectations:
25
+ Enabled: false
26
+
27
+ RSpec/NamedSubject:
28
+ Enabled: false
29
+
12
30
  Style/Documentation:
13
31
  Enabled: false
data/CHANGELOG.md CHANGED
@@ -2,6 +2,46 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ### 0.7.0 - 2021-12-28
6
+
7
+ ### Changed
8
+
9
+ - Re-use RuboCop's progress formatter as our default formatter.
10
+
11
+ ## 0.6.0 - 2021-12-28
12
+
13
+ ### Added
14
+
15
+ - Add -c, --config CLI option to customize RuboCop config.
16
+
17
+ ### Changed
18
+
19
+ - Not investigate all files then auto-correct them, but do it for each file.
20
+ - Sort processed files in alphabetical order.
21
+ - Disable Lint/UselessAssignment by default.
22
+
23
+ ## 0.5.0 - 2021-12-27
24
+
25
+ ### Changed
26
+
27
+ - Disable Lint/EmptyFile by default.
28
+ - Disable Style/RescueModifier by default.
29
+
30
+ ### Fixed
31
+
32
+ - Fix NoMethodError on some RuboCop offenses.
33
+ - Fix bug when uncorrectable RuboCop offense exists.
34
+
35
+ ## 0.4.0 - 2021-12-26
36
+
37
+ ### Added
38
+
39
+ - Support glob pattern on arguments of executable.
40
+
41
+ ### Fixed
42
+
43
+ - Fix bug on parsing invalid syntax Ruby code.
44
+
5
45
  ## 0.3.0 - 2021-12-25
6
46
 
7
47
  ### Added
data/Gemfile CHANGED
@@ -2,11 +2,9 @@
2
2
 
3
3
  source 'https://rubygems.org'
4
4
 
5
- # Specify your gem's dependencies in slimcop.gemspec
6
5
  gemspec
7
6
 
8
7
  gem 'rake', '~> 13.0'
9
-
10
- gem 'rspec', '~> 3.0'
11
-
12
- gem 'rubocop', '~> 1.21'
8
+ gem 'rspec'
9
+ gem 'rubocop'
10
+ gem 'rubocop-rspec'
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- slimcop (0.3.0)
4
+ slimcop (0.7.0)
5
5
  rainbow
6
6
  rubocop (>= 0.87)
7
7
  slimi (>= 0.4)
@@ -42,8 +42,10 @@ GEM
42
42
  unicode-display_width (>= 1.4.0, < 3.0)
43
43
  rubocop-ast (1.15.0)
44
44
  parser (>= 3.0.1.1)
45
+ rubocop-rspec (2.6.0)
46
+ rubocop (~> 1.19)
45
47
  ruby-progressbar (1.11.0)
46
- slimi (0.4.0)
48
+ slimi (0.4.2)
47
49
  temple
48
50
  temple (0.8.2)
49
51
  unicode-display_width (2.1.0)
@@ -53,8 +55,9 @@ PLATFORMS
53
55
 
54
56
  DEPENDENCIES
55
57
  rake (~> 13.0)
56
- rspec (~> 3.0)
57
- rubocop (~> 1.21)
58
+ rspec
59
+ rubocop
60
+ rubocop-rspec
58
61
  slimcop!
59
62
 
60
63
  BUNDLED WITH
data/README.md CHANGED
@@ -33,5 +33,25 @@ Use `slimcop` executable to check offenses and auto-correct them.
33
33
  $ slimcop --help
34
34
  Usage: slimcop [options] [file1, file2, ...]
35
35
  -a, --auto-correct Auto-correct offenses.
36
+ -c, --config= Specify configuration file.
36
37
  --[no-]color Force color output on or off.
37
38
  ```
39
+
40
+ ### Example
41
+
42
+ ```console
43
+ $ slimcop "**/*.slim"
44
+ Inspecting 1 file
45
+ C
46
+
47
+ Offenses:
48
+
49
+ spec/fixtures/dummy.slim:1:3: C: [Correctable] Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
50
+ - "a"
51
+ ^^^
52
+ spec/fixtures/dummy.slim:3:5: C: [Correctable] Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
53
+ | #{"c"}
54
+ ^^^
55
+
56
+ 1 file inspected, 2 offenses detected, 2 offenses auto-correctable
57
+ ```
data/default.yml CHANGED
@@ -10,6 +10,9 @@ Layout/BlockAlignment:
10
10
  Layout/ClosingParenthesisIndentation:
11
11
  Enabled: false
12
12
 
13
+ Lint/EmptyFile:
14
+ Enabled: false
15
+
13
16
  Layout/EmptyLineAfterGuardClause:
14
17
  Enabled: false
15
18
 
@@ -76,6 +79,9 @@ Layout/TrailingEmptyLines:
76
79
  Layout/TrailingWhitespace:
77
80
  Enabled: false
78
81
 
82
+ Lint/UselessAssignment:
83
+ Enabled: false
84
+
79
85
  Lint/Void:
80
86
  Enabled: false
81
87
 
@@ -100,6 +106,9 @@ Style/IfUnlessModifier:
100
106
  Style/Next:
101
107
  Enabled: false
102
108
 
109
+ Style/RescueModifier:
110
+ Enabled: false
111
+
103
112
  Style/WhileUntilDo:
104
113
  Enabled: false
105
114
 
data/lib/slimcop/cli.rb CHANGED
@@ -1,69 +1,71 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'rainbow'
4
+ require 'rubocop'
4
5
 
5
6
  module Slimcop
6
7
  class Cli
7
8
  def initialize(argv)
8
9
  @argv = argv.dup
9
- @configuration = Configuration.new
10
- @formatter = Formatter.new
10
+ @formatter = ::RuboCop::Formatter::ProgressFormatter.new($stdout)
11
11
  end
12
12
 
13
13
  def call
14
14
  options = parse!
15
- slim_file_paths = @argv
16
-
17
15
  Rainbow.enabled = options[:color] if options.key?(:color)
16
+ rubocop_config = RuboCopConfigGenerator.new(additional_config_file_path: options[:additional_config_file_path]).call
17
+ file_paths = PathFinder.new(patterns: @argv).call
18
18
 
19
- offenses_set = investigate(auto_correct: options[:auto_correct], slim_file_paths: slim_file_paths)
20
- correct(offenses_set) if options[:auto_correct]
21
- offenses = offenses_set.flat_map { |(_, _, array)| array }
22
- report(offenses)
19
+ @formatter.started(file_paths)
20
+ offenses = file_paths.flat_map do |file_path|
21
+ @formatter.file_started(file_path, {})
22
+ source = ::File.read(file_path)
23
+ offenses_ = investigate(
24
+ auto_correct: options[:auto_correct],
25
+ file_path: file_path,
26
+ rubocop_config: rubocop_config,
27
+ source: source
28
+ )
29
+ if options[:auto_correct]
30
+ correct(
31
+ file_path: file_path,
32
+ offenses: offenses_,
33
+ source: source
34
+ )
35
+ end
36
+ @formatter.file_finished(file_path, offenses_)
37
+ offenses_
38
+ end
39
+ @formatter.finished(file_paths)
23
40
  exit(offenses.empty? ? 0 : 1)
24
41
  end
25
42
 
26
43
  private
27
44
 
28
- # @param [Array] offenses_set
29
- def correct(offenses_set)
30
- offenses_set.each do |(file_path, source, offenses)|
31
- rewritten_source = SlimCorrector.new(
32
- file_path: file_path,
33
- offenses: offenses,
34
- source: source
35
- ).call
36
- ::File.write(file_path, rewritten_source)
37
- end
45
+ # @param [String] file_path
46
+ # @param [Array<Slimcop::Offense>] offenses
47
+ # @param [String] source
48
+ def correct(file_path:, offenses:, source:)
49
+ rewritten_source = SlimCorrector.new(
50
+ file_path: file_path,
51
+ offenses: offenses,
52
+ source: source
53
+ ).call
54
+ ::File.write(file_path, rewritten_source)
38
55
  end
39
56
 
40
57
  # @param [Boolean] auto_correct
41
- # @param [Array] slim_file_paths
42
- # @return [Array]
43
- def investigate(auto_correct:, slim_file_paths:)
44
- slim_file_paths.map do |file_path|
45
- source = ::File.read(file_path)
46
- offenses = SlimOffenseCollector.new(
47
- auto_correct: auto_correct,
48
- file_path: file_path,
49
- rubocop_config: @configuration.rubocop_config,
50
- source: source
51
- ).call
52
- [file_path, source, offenses]
53
- end
54
- end
55
-
56
- # @param [Array<Slimcop::Offense>] offenses
57
- def report(offenses)
58
- result = +''
59
- unless offenses.empty?
60
- result << "\nOffenses:\n\n"
61
- lines = offenses.map do |offense|
62
- @formatter.format_offense(offense)
63
- end
64
- result << lines.join("\n")
65
- end
66
- puts(result)
58
+ # @param [String] file_path
59
+ # @param [String] rubocop_config
60
+ # @param [String] source
61
+ # @return [Array<Slimcop::Offense>]
62
+ def investigate(auto_correct:, file_path:, rubocop_config:, source:)
63
+ SlimOffenseCollector.new(
64
+ auto_correct: auto_correct,
65
+ file_path: file_path,
66
+ rubocop_config: rubocop_config,
67
+ source: source
68
+ ).call
67
69
  end
68
70
 
69
71
  # @return [Hash]
@@ -74,6 +76,9 @@ module Slimcop
74
76
  parser.on('-a', '--auto-correct', 'Auto-correct offenses.') do
75
77
  options[:auto_correct] = true
76
78
  end
79
+ parser.on('-c', '--config=', 'Specify configuration file.') do |file_path|
80
+ options[:additional_config_file_path] = file_path
81
+ end
77
82
  parser.on('--[no-]color', 'Force color output on or off.') do |value|
78
83
  options[:color] = value
79
84
  end
@@ -1,52 +1,53 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'forwardable'
4
+
3
5
  require 'parser'
6
+ require 'rubocop'
4
7
 
5
8
  module Slimcop
6
9
  class Offense
10
+ extend ::Forwardable
11
+
12
+ # @return [String]
13
+ attr_reader :file_path
14
+
7
15
  # @return [Integer]
8
16
  attr_reader :offset
9
17
 
10
- # @return [RuboCop::Cop::Offense]
11
- attr_reader :rubocop_offense
18
+ delegate(
19
+ %i[
20
+ column
21
+ column_length
22
+ correctable?
23
+ corrected_with_todo?
24
+ corrected?
25
+ corrector
26
+ highlighted_area
27
+ line
28
+ message
29
+ real_column
30
+ severity
31
+ ] => :rubocop_offense_with_real_location
32
+ )
12
33
 
13
34
  # @param [Integer] offset
14
35
  # @param [RuboCop::Cop::Offense] rubocop_offense
15
36
  # @param [String] source Slim code.
16
- def initialize(offset:, rubocop_offense:, source:)
37
+ def initialize(file_path:, offset:, rubocop_offense:, source:)
38
+ @file_path = file_path
17
39
  @offset = offset
18
40
  @rubocop_offense = rubocop_offense
19
41
  @source = source
20
42
  end
21
43
 
22
- # @return [RuboCop::Cop::Corrector]
23
- def corrector
24
- @rubocop_offense.corrector
25
- end
26
-
27
- # @return [String]
28
- def file_path
29
- @rubocop_offense.location.source_buffer.name
30
- end
31
-
32
- # @return [Integer]
33
- def line
34
- range.line
35
- end
36
-
37
- # @return [String]
38
- def message
39
- @rubocop_offense.message
40
- end
41
-
42
- # @return [Integer]
43
- def real_column
44
- range.column + 1
45
- end
46
-
47
- # @return [RuboCop::Cop::Severity]
48
- def severity
49
- @rubocop_offense.severity
44
+ # @return [Parser::Source::Range]
45
+ def location
46
+ @location ||= ::Parser::Source::Range.new(
47
+ buffer,
48
+ @rubocop_offense.location.begin_pos + @offset,
49
+ @rubocop_offense.location.end_pos + @offset
50
+ )
50
51
  end
51
52
 
52
53
  private
@@ -59,12 +60,15 @@ module Slimcop
59
60
  )
60
61
  end
61
62
 
62
- # @return [Parser::Source::Range]
63
- def range
64
- @range ||= ::Parser::Source::Range.new(
65
- buffer,
66
- @rubocop_offense.location.begin_pos + @offset,
67
- @rubocop_offense.location.end_pos + @offset
63
+ # @return [RuboCop::Cop::Offense]
64
+ def rubocop_offense_with_real_location
65
+ ::RuboCop::Cop::Offense.new(
66
+ @rubocop_offense.severity.name,
67
+ location,
68
+ @rubocop_offense.message,
69
+ @rubocop_offense.cop_name,
70
+ @rubocop_offense.status,
71
+ @rubocop_offense.corrector
68
72
  )
69
73
  end
70
74
  end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pathname'
4
+
5
+ module Slimcop
6
+ # Collect file paths from given path patterns.
7
+ class PathFinder
8
+ # @param [Array<String>] patterns Patterns normally given as CLI arguments (e.g. `["app/views/**/*.html.slim"]`).
9
+ def initialize(patterns:)
10
+ @patterns = patterns
11
+ end
12
+
13
+ # @return [Array<String>]
14
+ def call
15
+ @patterns.flat_map do |pattern|
16
+ ::Pathname.glob(pattern).select(&:file?).map(&:to_s)
17
+ end.sort
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubocop'
4
+
5
+ module Slimcop
6
+ class RuboCopConfigGenerator
7
+ # @param [String] additional_config_file_path
8
+ def initialize(additional_config_file_path: nil)
9
+ @additional_config_file_path = additional_config_file_path
10
+ end
11
+
12
+ # @return [RuboCop::Config]
13
+ def call
14
+ ::RuboCop::ConfigLoader.merge_with_default(merged_config, loaded_path)
15
+ end
16
+
17
+ private
18
+
19
+ # @return [String]
20
+ def loaded_path
21
+ @additional_config_file_path || slimcop_default_config_file_path
22
+ end
23
+
24
+ # @return [RuboCop::Config]
25
+ def merged_config
26
+ ::RuboCop::Config.create(merged_config_hash, loaded_path)
27
+ end
28
+
29
+ # @return [Hash]
30
+ def merged_config_hash
31
+ result = slimcop_default_config
32
+ result = ::RuboCop::ConfigLoader.merge(result, additional_config) if @additional_config_file_path
33
+ result
34
+ end
35
+
36
+ # @return [RuboCop::Config, nil]
37
+ def additional_config
38
+ ::RuboCop::ConfigLoader.load_file(@additional_config_file_path) if @additional_config_file_path
39
+ end
40
+
41
+ # @return [RuboCop::Config]
42
+ def slimcop_default_config
43
+ ::RuboCop::ConfigLoader.load_file(slimcop_default_config_file_path)
44
+ end
45
+
46
+ # @return [String]
47
+ def slimcop_default_config_file_path
48
+ @slimcop_default_config_file_path ||= ::File.expand_path('../../default.yml', __dir__)
49
+ end
50
+ end
51
+ end
@@ -16,9 +16,10 @@ module Slimcop
16
16
  @source = source
17
17
  end
18
18
 
19
- # @return [Array<RuboCop::Cop::Offense>, nil]
19
+ # @return [Array<RuboCop::Cop::Offense>]
20
20
  def call
21
- return unless rubocop_processed_source.valid_syntax?
21
+ # Skip if invalid syntax Ruby code is given. (e.g. "- if a?")
22
+ return [] unless rubocop_processed_source.valid_syntax?
22
23
 
23
24
  rubocop_team.investigate(rubocop_processed_source).offenses
24
25
  end
@@ -24,7 +24,7 @@ module Slimcop
24
24
 
25
25
  # @return [Array<Proc>]
26
26
  def corrections
27
- @offenses.map do |offense|
27
+ @offenses.select(&:corrector).map do |offense|
28
28
  lambda do |corrector|
29
29
  corrector.import!(offense.corrector, offset: offense.offset)
30
30
  end
@@ -24,6 +24,7 @@ module Slimcop
24
24
  source: snippet[:code]
25
25
  ).call.map do |rubocop_offense|
26
26
  Offense.new(
27
+ file_path: @file_path,
27
28
  offset: snippet[:begin_],
28
29
  rubocop_offense: rubocop_offense,
29
30
  source: @source
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Slimcop
4
- VERSION = '0.3.0'
4
+ VERSION = '0.7.0'
5
5
  end
data/lib/slimcop.rb CHANGED
@@ -4,9 +4,9 @@ require_relative 'slimcop/version'
4
4
 
5
5
  module Slimcop
6
6
  autoload :Cli, 'slimcop/cli'
7
- autoload :Configuration, 'slimcop/configuration'
8
- autoload :Formatter, 'slimcop/formatter'
9
7
  autoload :Offense, 'slimcop/offense'
8
+ autoload :PathFinder, 'slimcop/path_finder'
9
+ autoload :RuboCopConfigGenerator, 'slimcop/rubo_cop_config_generator'
10
10
  autoload :RubyExtractor, 'slimcop/ruby_extractor'
11
11
  autoload :RubyOffenseCollector, 'slimcop/ruby_offense_collector'
12
12
  autoload :SlimCorrector, 'slimcop/slim_corrector'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: slimcop
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryo Nakamura
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-12-24 00:00:00.000000000 Z
11
+ date: 2021-12-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rainbow
@@ -75,9 +75,9 @@ files:
75
75
  - exe/slimcop
76
76
  - lib/slimcop.rb
77
77
  - lib/slimcop/cli.rb
78
- - lib/slimcop/configuration.rb
79
- - lib/slimcop/formatter.rb
80
78
  - lib/slimcop/offense.rb
79
+ - lib/slimcop/path_finder.rb
80
+ - lib/slimcop/rubo_cop_config_generator.rb
81
81
  - lib/slimcop/ruby_extractor.rb
82
82
  - lib/slimcop/ruby_offense_collector.rb
83
83
  - lib/slimcop/slim_corrector.rb
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rubocop'
4
-
5
- module Slimcop
6
- class Configuration
7
- # @return [RuboCop::Config]
8
- def rubocop_config
9
- @rubocop_config ||= begin
10
- config_path = ::File.expand_path('../../default.yml', __dir__)
11
- config = ::RuboCop::ConfigLoader.load_file(config_path)
12
- ::RuboCop::ConfigLoader.merge_with_default(config, config_path)
13
- end
14
- end
15
- end
16
- end
@@ -1,72 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'optparse'
4
- require 'rainbow'
5
-
6
- module Slimcop
7
- # Format String for CLI output.
8
- class Formatter
9
- COLOR_FOR_SEVERITY_CODE = {
10
- convention: :yellow,
11
- error: :red,
12
- fatal: :red,
13
- info: :gray,
14
- refactor: :yellow,
15
- warning: :magenta
16
- }.freeze
17
-
18
- # @param [Slimcop::Offense] offense
19
- # @return [String]
20
- def format_offense(offense)
21
- format(
22
- '%<path>s:%<line>d:%<column>d %<severity>s: %<message>s',
23
- column: offense.real_column,
24
- line: offense.line,
25
- message: message(offense),
26
- path: file_path(offense),
27
- severity: severity(offense)
28
- )
29
- end
30
-
31
- private
32
-
33
- # @param [String] path e.g. "./spec/fixtures/dummy.slim"
34
- # @return [String]
35
- # @example "spec/fixtures/dummy.slim"
36
- def canonicalize_path(path)
37
- ::File.expand_path(path).delete_prefix("#{::Dir.pwd}/")
38
- end
39
-
40
- # @param [Slimcop::Offense] offense
41
- # @return [String]
42
- def file_path(offense)
43
- Rainbow(canonicalize_path(offense.file_path)).cyan
44
- end
45
-
46
- # @param [Slimcop::Offense] offense
47
- # @return [String]
48
- def message(offense)
49
- "#{status(offense)}#{offense.message}"
50
- end
51
-
52
- # @param [Slimcop::Offense] offense
53
- # @return [String]
54
- def severity(offense)
55
- Rainbow(offense.severity.code).color(COLOR_FOR_SEVERITY_CODE[offense.severity.name])
56
- end
57
-
58
- # @param [Slimcop::Offense] offense
59
- # @return [String]
60
- def status(offense)
61
- if offense.rubocop_offense.corrected_with_todo?
62
- Rainbow('[Todo] ').green
63
- elsif offense.rubocop_offense.corrected?
64
- Rainbow('[Corrected] ').green
65
- elsif offense.rubocop_offense.correctable?
66
- Rainbow('[Correctable] ').yellow
67
- else
68
- ''
69
- end
70
- end
71
- end
72
- end