erbcop 0.1.0 → 0.4.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: 83b12a5974c220329d0f7e7afd819ccb684393822e42afb1c313a7222b101ddc
4
- data.tar.gz: 395fb3c1ed1b1d3e06fd5fba735528092825adb6b6152d3de8564d95d90733ed
3
+ metadata.gz: 0f9f5330f08da6f5c0f830990aa71a99dd28a26c298225daac38d7e093e23e9b
4
+ data.tar.gz: dc59cbbe140b340162018f7ad8201ce1dcf93723e917b18b28d2ed95e22bf737
5
5
  SHA512:
6
- metadata.gz: 02f26eb4e0dc4db0047aa0e75bff070073f099b7e7f2f1ce463e27852769bac04af383dea0864985586639f189d848174d3b17bc85d9cf0bbdb91442dfdc0bce
7
- data.tar.gz: ac2022f7afea7cf9b1338bcf61c4b8bd2c14f970ac6eba26be4839ec45b9b96a71e5a71f4f4051013fef1fff354f3cc8723ecbc8bee5c8d552d6f4884156ed1a
6
+ metadata.gz: cfe447c8f1063d4ca7a80f8d8ae27b999de085c98326185b5ba59e74ca7b8d02fef2a9ad3cf92f9d0013f2f4970befcc38ece49b328fbb47ef87c9e0b082cd48
7
+ data.tar.gz: 5bfa9369536dc698dfee9d32df8a8ce893f2fcf663ec2644f1b0f4f2fb38b8da088f95519f206031c808560339a9d4746b613c8f0122a9cffa9b30050d189bbd
data/CHANGELOG.md CHANGED
@@ -2,6 +2,30 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.4.0 - 2022-01-22
6
+
7
+ ### Changed
8
+
9
+ - Disable Style/NestedTernaryOperator by default.
10
+
11
+ ## 0.3.0 - 2022-01-22
12
+
13
+ ### Changed
14
+
15
+ - Disable Style/MultilineTernaryOperator by default.
16
+
17
+ ## 0.2.1 - 2022-01-22
18
+
19
+ ### Fixed
20
+
21
+ - Exclude code in ERB comment.
22
+
23
+ ## 0.2.0 - 2022-01-15
24
+
25
+ ### Changed
26
+
27
+ - Use templatecop.
28
+
5
29
  ## 0.1.0 - 2022-01-15
6
30
 
7
31
  ### Added
data/Gemfile.lock CHANGED
@@ -1,10 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- erbcop (0.1.0)
4
+ erbcop (0.4.0)
5
5
  better_html
6
- rainbow
7
- rubocop (>= 0.87)
6
+ templatecop
8
7
 
9
8
  GEM
10
9
  remote: https://rubygems.org/
@@ -84,6 +83,10 @@ GEM
84
83
  rubocop (~> 1.19)
85
84
  ruby-progressbar (1.11.0)
86
85
  smart_properties (1.17.0)
86
+ templatecop (0.2.0)
87
+ parallel
88
+ parser
89
+ rubocop (>= 0.87)
87
90
  tzinfo (2.0.4)
88
91
  concurrent-ruby (~> 1.0)
89
92
  unicode-display_width (2.1.0)
data/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  # Erbcop
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/erbcop.svg)](https://rubygems.org/gems/erbcop)
3
4
  [![test](https://github.com/r7kamura/erbcop/actions/workflows/test.yml/badge.svg)](https://github.com/r7kamura/erbcop/actions/workflows/test.yml)
4
5
 
5
6
  [RuboCop](https://github.com/rubocop/rubocop) runner for ERB template.
data/default.yml CHANGED
@@ -103,6 +103,12 @@ Style/IdenticalConditionalBranches:
103
103
  Style/IfUnlessModifier:
104
104
  Enabled: false
105
105
 
106
+ Style/MultilineTernaryOperator:
107
+ Enabled: false
108
+
109
+ Style/NestedTernaryOperator:
110
+ Enabled: false
111
+
106
112
  Style/Next:
107
113
  Enabled: false
108
114
 
data/erbcop.gemspec CHANGED
@@ -30,6 +30,5 @@ Gem::Specification.new do |spec|
30
30
  spec.metadata['rubygems_mfa_required'] = 'true'
31
31
 
32
32
  spec.add_dependency 'better_html'
33
- spec.add_dependency 'rainbow'
34
- spec.add_dependency 'rubocop', '>= 0.87'
33
+ spec.add_dependency 'templatecop'
35
34
  end
data/exe/erbcop CHANGED
@@ -3,5 +3,12 @@
3
3
 
4
4
  $LOAD_PATH.unshift File.expand_path('../lib', __dir__)
5
5
  require 'erbcop'
6
+ require 'templatecop'
6
7
 
7
- Erbcop::Cli.new(ARGV).call
8
+ Templatecop::Cli.call(
9
+ default_configuration_path: File.expand_path('../default.yml', __dir__),
10
+ default_path_patterns: %w[**/*.erb],
11
+ executable_name: 'erbcop',
12
+ implicit_configuration_paths: %w[.erbcop.yml .rubocop.yml],
13
+ ruby_extractor: Erbcop::RubyExtractor
14
+ )
@@ -2,10 +2,25 @@
2
2
 
3
3
  require 'better_html'
4
4
  require 'better_html/parser'
5
+ require 'templatecop'
5
6
 
6
7
  module Erbcop
7
8
  # Extract Ruby codes from Erb source.
8
9
  class RubyExtractor
10
+ class << self
11
+ # @param [String, nil] file_path
12
+ # @param [String] source
13
+ def call(
14
+ file_path:,
15
+ source:
16
+ )
17
+ new(
18
+ file_path: file_path,
19
+ source: source
20
+ ).call
21
+ end
22
+ end
23
+
9
24
  # @param [String, nil] file_path
10
25
  # @param [String] source
11
26
  def initialize(file_path:, source:)
@@ -17,7 +32,7 @@ module Erbcop
17
32
  def call
18
33
  nodes.map do |node|
19
34
  snippet = node.children.first
20
- clipped = RubyClipper.new(snippet).call
35
+ clipped = ::Templatecop::RubyClipper.new(snippet).call
21
36
  {
22
37
  code: clipped[:code],
23
38
  offset: node.location.begin_pos + clipped[:offset]
@@ -27,36 +42,29 @@ module Erbcop
27
42
 
28
43
  private
29
44
 
45
+ # @return [Array<BetterHtml::AST::Node>]
46
+ def erbs
47
+ root.descendants(:erb).reject do |erb|
48
+ erb.children.first&.type == :indicator && erb.children.first&.to_a&.first == '#'
49
+ end
50
+ end
51
+
30
52
  # @return [Enumerator<BetterHtml::AST::Node>]
31
53
  def nodes
54
+ erbs.flat_map do |erb|
55
+ erb.descendants(:code).to_a
56
+ end
57
+ end
58
+
59
+ # @return [BetterHtml::AST::Node]
60
+ def root
32
61
  ::BetterHtml::Parser.new(
33
62
  ::Parser::Source::Buffer.new(
34
63
  @file_path,
35
64
  source: @source
36
65
  ),
37
66
  template_language: :html
38
- ).ast.descendants(:code)
39
- end
40
-
41
- # @return [Array<Array<Integer>>]
42
- def ranges
43
- result = []
44
- traverse(ast) do |begin_, end_|
45
- result << [begin_, end_]
46
- end
47
- result
48
- end
49
-
50
- def traverse(node, &block)
51
- return unless node.instance_of?(::Array)
52
-
53
- if node[0] == :erbi && node[1] == :position
54
- block.call(node[2], node[3])
55
- else
56
- node.each do |element|
57
- traverse(element, &block)
58
- end
59
- end
67
+ ).ast
60
68
  end
61
69
  end
62
70
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Erbcop
4
- VERSION = '0.1.0'
4
+ VERSION = '0.4.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: erbcop
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.4.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: 2022-01-14 00:00:00.000000000 Z
11
+ date: 2022-01-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: better_html
@@ -25,7 +25,7 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rainbow
28
+ name: templatecop
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
@@ -38,20 +38,6 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: rubocop
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0.87'
48
- type: :runtime
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0.87'
55
41
  description:
56
42
  email:
57
43
  - r7kamura@gmail.com
@@ -73,16 +59,7 @@ files:
73
59
  - erbcop.gemspec
74
60
  - exe/erbcop
75
61
  - lib/erbcop.rb
76
- - lib/erbcop/cli.rb
77
- - lib/erbcop/erb_corrector.rb
78
- - lib/erbcop/erb_offense_collector.rb
79
- - lib/erbcop/offense.rb
80
- - lib/erbcop/path_finder.rb
81
- - lib/erbcop/rubo_cop_config_generator.rb
82
- - lib/erbcop/ruby_clipper.rb
83
62
  - lib/erbcop/ruby_extractor.rb
84
- - lib/erbcop/ruby_offense_collector.rb
85
- - lib/erbcop/runner.rb
86
63
  - lib/erbcop/version.rb
87
64
  homepage: https://github.com/r7kamura/erbcop
88
65
  licenses:
data/lib/erbcop/cli.rb DELETED
@@ -1,49 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rainbow'
4
- require 'rubocop'
5
-
6
- module Erbcop
7
- class Cli
8
- def initialize(argv)
9
- @argv = argv.dup
10
- end
11
-
12
- def call
13
- options = parse!
14
- formatter = ::RuboCop::Formatter::ProgressFormatter.new($stdout, color: options[:color])
15
- rubocop_config = RuboCopConfigGenerator.new(additional_config_file_path: options[:additional_config_file_path]).call
16
- file_paths = PathFinder.new(patterns: @argv).call
17
-
18
- offenses = Runner.new(
19
- auto_correct: options[:auto_correct],
20
- file_paths: file_paths,
21
- formatter: formatter,
22
- rubocop_config: rubocop_config
23
- ).call
24
-
25
- exit(offenses.empty? ? 0 : 1)
26
- end
27
-
28
- private
29
-
30
- # @return [Hash]
31
- def parse!
32
- options = {}
33
- parser = ::OptionParser.new
34
- parser.banner = 'Usage: erbcop [options] [file1, file2, ...]'
35
- parser.version = VERSION
36
- parser.on('-a', '--auto-correct', 'Auto-correct offenses.') do
37
- options[:auto_correct] = true
38
- end
39
- parser.on('-c', '--config=', 'Specify configuration file. (default: .erbcop.yml or .rubocop.yml)') do |file_path|
40
- options[:additional_config_file_path] = file_path
41
- end
42
- parser.on('--[no-]color', 'Force color output on or off.') do |value|
43
- options[:color] = value
44
- end
45
- parser.parse!(@argv)
46
- options
47
- end
48
- end
49
- end
@@ -1,42 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'parser'
4
- require 'rubocop/cop/legacy/corrector'
5
-
6
- module Erbcop
7
- # Apply auto-corrections to Erb file.
8
- class ErbCorrector
9
- # @param [String] file_path
10
- # @param [Array<Erbcop::Offense>] offenses
11
- # @param [String] source
12
- def initialize(file_path:, offenses:, source:)
13
- @file_path = file_path
14
- @offenses = offenses
15
- @source = source
16
- end
17
-
18
- # @return [String] Rewritten Erb code.
19
- def call
20
- ::RuboCop::Cop::Legacy::Corrector.new(source_buffer, corrections).rewrite
21
- end
22
-
23
- private
24
-
25
- # @return [Array<Proc>]
26
- def corrections
27
- @offenses.select(&:corrector).map do |offense|
28
- lambda do |corrector|
29
- corrector.import!(offense.corrector, offset: offense.offset)
30
- end
31
- end
32
- end
33
-
34
- # @return [Parser::Source::Buffer]
35
- def source_buffer
36
- ::Parser::Source::Buffer.new(
37
- @file_path,
38
- source: @source
39
- )
40
- end
41
- end
42
- end
@@ -1,46 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Erbcop
4
- # Collect RuboCop offenses from Erb code.
5
- class ErbOffenseCollector
6
- # @param [Boolean] auto_correct
7
- # @param [String] file_path Erb file path
8
- # @param [RuboCop::Config] rubocop_config
9
- # @param [String] source Erb code
10
- def initialize(auto_correct:, file_path:, rubocop_config:, source:)
11
- @auto_correct = auto_correct
12
- @file_path = file_path
13
- @rubocop_config = rubocop_config
14
- @source = source
15
- end
16
-
17
- # @return [Array<Erbcop::Offense>]
18
- def call
19
- snippets.flat_map do |snippet|
20
- RubyOffenseCollector.new(
21
- auto_correct: @auto_correct,
22
- file_path: @file_path,
23
- rubocop_config: @rubocop_config,
24
- source: snippet[:code]
25
- ).call.map do |rubocop_offense|
26
- Offense.new(
27
- file_path: @file_path,
28
- offset: snippet[:offset],
29
- rubocop_offense: rubocop_offense,
30
- source: @source
31
- )
32
- end
33
- end
34
- end
35
-
36
- private
37
-
38
- # @return [Array<Hash>]
39
- def snippets
40
- RubyExtractor.new(
41
- file_path: @file_path,
42
- source: @source
43
- ).call
44
- end
45
- end
46
- end
@@ -1,75 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'forwardable'
4
-
5
- require 'parser'
6
- require 'rubocop'
7
-
8
- module Erbcop
9
- class Offense
10
- extend ::Forwardable
11
-
12
- # @return [String]
13
- attr_reader :file_path
14
-
15
- # @return [Integer]
16
- attr_reader :offset
17
-
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
- )
33
-
34
- # @param [Integer] offset
35
- # @param [RuboCop::Cop::Offense] rubocop_offense
36
- # @param [String] source Erb code.
37
- def initialize(file_path:, offset:, rubocop_offense:, source:)
38
- @file_path = file_path
39
- @offset = offset
40
- @rubocop_offense = rubocop_offense
41
- @source = source
42
- end
43
-
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
- )
51
- end
52
-
53
- private
54
-
55
- # @return [Parser::Source::Buffer]
56
- def buffer
57
- ::Parser::Source::Buffer.new(
58
- file_path,
59
- source: @source
60
- )
61
- end
62
-
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
72
- )
73
- end
74
- end
75
- end
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'pathname'
4
-
5
- module Erbcop
6
- # Collect file paths from given path patterns.
7
- class PathFinder
8
- DEFAULT_PATH_PATTERNS = %w[
9
- **/*.erb
10
- ].freeze
11
-
12
- # @param [Array<String>] patterns Patterns normally given as CLI arguments (e.g. `["app/views/**/*.html.erb"]`).
13
- def initialize(patterns:)
14
- @patterns = patterns
15
- end
16
-
17
- # @return [Array<String>]
18
- def call
19
- patterns.flat_map do |pattern|
20
- ::Pathname.glob(pattern).select(&:file?).map(&:to_s)
21
- end.uniq.sort
22
- end
23
-
24
- private
25
-
26
- # @return [Array<String>]
27
- def patterns
28
- if @patterns.empty?
29
- DEFAULT_PATH_PATTERNS
30
- else
31
- @patterns
32
- end
33
- end
34
- end
35
- end
@@ -1,65 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rubocop'
4
-
5
- module Erbcop
6
- class RuboCopConfigGenerator
7
- DEFAULT_ADDITIONAL_CONFIG_PATH1 = '.erbcop.yml'
8
- DEFAULT_ADDITIONAL_CONFIG_PATH2 = '.rubocop.yml'
9
-
10
- # @param [String] additional_config_file_path
11
- def initialize(additional_config_file_path: nil)
12
- @additional_config_file_path = additional_config_file_path
13
- end
14
-
15
- # @return [RuboCop::Config]
16
- def call
17
- ::RuboCop::ConfigLoader.merge_with_default(merged_config, loaded_path)
18
- end
19
-
20
- private
21
-
22
- # @return [String]
23
- def loaded_path
24
- @additional_config_file_path || erbcop_default_config_file_path
25
- end
26
-
27
- # @return [RuboCop::Config]
28
- def merged_config
29
- ::RuboCop::Config.create(merged_config_hash, loaded_path)
30
- end
31
-
32
- # @return [Hash]
33
- def merged_config_hash
34
- result = erbcop_default_config
35
- result = ::RuboCop::ConfigLoader.merge(result, additional_config) if additional_config
36
- result
37
- end
38
-
39
- # @return [RuboCop::Config, nil]
40
- def additional_config
41
- if instance_variable_defined?(:@additional_config)
42
- @additional_config
43
- else
44
- @additional_config = \
45
- if @additional_config_file_path
46
- ::RuboCop::ConfigLoader.load_file(@additional_config_file_path)
47
- elsif ::File.exist?(DEFAULT_ADDITIONAL_CONFIG_PATH1)
48
- ::RuboCop::ConfigLoader.load_file(DEFAULT_ADDITIONAL_CONFIG_PATH1)
49
- elsif ::File.exist?(DEFAULT_ADDITIONAL_CONFIG_PATH2)
50
- ::RuboCop::ConfigLoader.load_file(DEFAULT_ADDITIONAL_CONFIG_PATH2)
51
- end
52
- end
53
- end
54
-
55
- # @return [RuboCop::Config]
56
- def erbcop_default_config
57
- ::RuboCop::ConfigLoader.load_file(erbcop_default_config_file_path)
58
- end
59
-
60
- # @return [String]
61
- def erbcop_default_config_file_path
62
- @erbcop_default_config_file_path ||= ::File.expand_path('../../default.yml', __dir__)
63
- end
64
- end
65
- end
@@ -1,93 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Erbcop
4
- # Remove unnecessary part (e.g. `if`, `unless`, `do`, ...) from Ruby code.
5
- class RubyClipper
6
- # @param [String] code
7
- def initialize(code)
8
- @code = code
9
- end
10
-
11
- # @return [Hash]
12
- def call
13
- [
14
- PrecedingKeywordRemover,
15
- TrailingDoRemover
16
- ].each_with_object(
17
- code: @code,
18
- offset: 0
19
- ) do |klass, object|
20
- result = klass.new(object[:code]).call
21
- object[:code] = result[:code]
22
- object[:offset] += result[:offset]
23
- end
24
- end
25
-
26
- class PrecedingKeywordRemover
27
- REGEXP = /
28
- \A
29
- (?:
30
- begin
31
- | case
32
- | else
33
- | elsif
34
- | ensure
35
- | if
36
- | rescue
37
- | unless
38
- | until
39
- | when
40
- | while
41
- | for[ \t]+\w+[ \t]+in
42
- )
43
- [ \t]
44
- /x.freeze
45
-
46
- # @param [String] code
47
- def initialize(code)
48
- @code = code
49
- end
50
-
51
- # @return [Hash]
52
- def call
53
- data = @code.match(REGEXP)
54
- if data
55
- offset = data[0].length
56
- {
57
- code: @code[offset..],
58
- offset: offset
59
- }
60
- else
61
- {
62
- code: @code,
63
- offset: 0
64
- }
65
- end
66
- end
67
- end
68
-
69
- class TrailingDoRemover
70
- REGEXP = /
71
- [ \t]
72
- do
73
- [ \t]*
74
- (\|[^|]*\|)?
75
- [ \t]*
76
- \Z
77
- /x.freeze
78
-
79
- # @param [String] code
80
- def initialize(code)
81
- @code = code
82
- end
83
-
84
- # @return [Hash]
85
- def call
86
- {
87
- code: @code.sub(REGEXP, ''),
88
- offset: 0
89
- }
90
- end
91
- end
92
- end
93
- end
@@ -1,50 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rubocop'
4
-
5
- module Erbcop
6
- # Collect RuboCop offenses from Ruby code.
7
- class RubyOffenseCollector
8
- # @param [Boolean] auto_correct
9
- # @param [String] file_path
10
- # @param [RuboCop::Config] rubocop_config
11
- # @param [String] source
12
- def initialize(auto_correct:, file_path:, rubocop_config:, source:)
13
- @auto_correct = auto_correct
14
- @file_path = file_path
15
- @rubocop_config = rubocop_config
16
- @source = source
17
- end
18
-
19
- # @return [Array<RuboCop::Cop::Offense>]
20
- def call
21
- # Skip if invalid syntax Ruby code is given. (e.g. "- if a?")
22
- return [] unless rubocop_processed_source.valid_syntax?
23
-
24
- rubocop_team.investigate(rubocop_processed_source).offenses.reject(&:disabled?)
25
- end
26
-
27
- private
28
-
29
- # @return [RuboCop::ProcessedSource]
30
- def rubocop_processed_source
31
- @rubocop_processed_source ||= ::RuboCop::ProcessedSource.new(
32
- @source,
33
- @rubocop_config.target_ruby_version,
34
- @file_path
35
- )
36
- end
37
-
38
- # @return [RuboCop::Cop::Team]
39
- def rubocop_team
40
- ::RuboCop::Cop::Team.new(
41
- ::RuboCop::Cop::Registry.new(::RuboCop::Cop::Cop.all),
42
- @rubocop_config,
43
- auto_correct: @auto_correct,
44
- display_cop_names: true,
45
- extra_details: true,
46
- stdin: ''
47
- )
48
- end
49
- end
50
- end
data/lib/erbcop/runner.rb DELETED
@@ -1,115 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Erbcop
4
- # Run investigation and auto-correcttion.
5
- class Runner
6
- # @param [Boolean] auto_correct
7
- # @param [Array<String>] file_paths
8
- # @param [Object] formatter
9
- # @param [RuboCop::Config] rubocop_config
10
- def initialize(
11
- auto_correct:,
12
- file_paths:,
13
- formatter:,
14
- rubocop_config:
15
- )
16
- @auto_correct = auto_correct
17
- @file_paths = file_paths
18
- @formatter = formatter
19
- @rubocop_config = rubocop_config
20
- end
21
-
22
- # @return [Array<RuboCop::Cop::Offense>]
23
- def call
24
- on_started
25
- offenses = investigate_and_correct
26
- on_finished
27
- offenses
28
- end
29
-
30
- private
31
-
32
- # @param [String] file_path
33
- # @param [Array<Erbcop::Offense>] offenses
34
- # @param [String] source
35
- def correct(file_path:, offenses:, source:)
36
- rewritten_source = ErbCorrector.new(
37
- file_path: file_path,
38
- offenses: offenses,
39
- source: source
40
- ).call
41
- ::File.write(file_path, rewritten_source)
42
- end
43
-
44
- # @param [Boolean] auto_correct
45
- # @param [String] file_path
46
- # @param [String] rubocop_config
47
- # @param [String] source
48
- # @return [Array<Erbcop::Offense>]
49
- def investigate(auto_correct:, file_path:, rubocop_config:, source:)
50
- ErbOffenseCollector.new(
51
- auto_correct: auto_correct,
52
- file_path: file_path,
53
- rubocop_config: rubocop_config,
54
- source: source
55
- ).call
56
- end
57
-
58
- # @return [Array<RuboCop::Cop::Offense>]
59
- def investigate_and_correct
60
- @file_paths.flat_map do |file_path|
61
- offenses_per_file = []
62
- max_trials_count.times do
63
- on_file_started(file_path)
64
- source = ::File.read(file_path)
65
- offenses = investigate(
66
- auto_correct: @auto_correct,
67
- file_path: file_path,
68
- rubocop_config: @rubocop_config,
69
- source: source
70
- )
71
- offenses_per_file += offenses
72
- break if offenses.empty?
73
-
74
- next unless @auto_correct
75
-
76
- correct(
77
- file_path: file_path,
78
- offenses: offenses,
79
- source: source
80
- )
81
- end
82
- on_file_finished(file_path, offenses_per_file)
83
- offenses_per_file
84
- end
85
- end
86
-
87
- # @return [Integer]
88
- def max_trials_count
89
- if @auto_correct
90
- 7 # What a heuristic number.
91
- else
92
- 1
93
- end
94
- end
95
-
96
- def on_started
97
- @formatter.started(@file_paths)
98
- end
99
-
100
- # @param [String] file_path
101
- def on_file_started(file_path)
102
- @formatter.file_started(file_path, {})
103
- end
104
-
105
- # @param [String] file_path
106
- # @param [Array<RuboCop::Cop::Offenses]
107
- def on_file_finished(file_path, offenses)
108
- @formatter.file_finished(file_path, offenses)
109
- end
110
-
111
- def on_finished
112
- @formatter.finished(@file_paths)
113
- end
114
- end
115
- end