/
suggest_extensions.rb
126 lines (100 loc) · 3.79 KB
/
suggest_extensions.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# frozen_string_literal: true
module RuboCop
class CLI
module Command
# Suggest RuboCop extensions to install based on Gemfile dependencies.
# Only primary dependencies are evaluated, so if a dependency depends on a
# gem with an extension, it is not suggested. However, if an extension is
# a transitive dependency, it will not be suggested.
# @api private
class SuggestExtensions < Base
# Combination of short and long formatter names.
INCLUDED_FORMATTERS = %w[p progress fu fuubar pa pacman].freeze
self.command_name = :suggest_extensions
def run
return if skip? || extensions.none?
print_install_suggestions if not_installed_extensions.any?
print_load_suggestions if installed_and_not_loaded_extensions.any?
print_opt_out_instruction
puts if @options[:display_time]
end
private
def skip?
# Disable outputting the notification:
# 1. On CI
# 2. When given RuboCop options that it doesn't make sense for
# 3. For all formatters except specified in `INCLUDED_FORMATTERS'`
ENV.fetch('CI', nil) ||
@options[:only] || @options[:debug] || @options[:list_target_files] ||
@options[:out] || @options[:stdin] ||
!INCLUDED_FORMATTERS.include?(current_formatter)
end
def print_install_suggestions
puts
puts 'Tip: Based on detected gems, the following ' \
'RuboCop extension libraries might be helpful:'
not_installed_extensions.sort.each do |extension|
puts " * #{extension} (https://rubygems.org/gems/#{extension})"
end
end
def print_load_suggestions
puts
puts 'The following RuboCop extension libraries are installed but not loaded in config:'
installed_and_not_loaded_extensions.sort.each do |extension|
puts " * #{extension}"
end
end
def print_opt_out_instruction
puts
puts 'You can opt out of this message by adding the following to your config ' \
'(see https://docs.rubocop.org/rubocop/extensions.html#extension-suggestions ' \
'for more options):'
puts ' AllCops:'
puts ' SuggestExtensions: false'
end
def current_formatter
@options[:format] || @config_store.for_pwd.for_all_cops['DefaultFormatter'] || 'p'
end
def all_extensions
return [] unless lockfile.dependencies.any?
extensions = @config_store.for_pwd.for_all_cops['SuggestExtensions']
case extensions
when true
extensions = ConfigLoader.default_configuration.for_all_cops['SuggestExtensions']
when false, nil
extensions = {}
end
extensions.select { |_, v| (Array(v) & dependent_gems).any? }.keys
end
def extensions
not_installed_extensions + installed_and_not_loaded_extensions
end
def installed_extensions
all_extensions & installed_gems
end
def not_installed_extensions
all_extensions - installed_gems
end
def loaded_extensions
@config_store.for_pwd.loaded_features.to_a
end
def installed_and_not_loaded_extensions
installed_extensions - loaded_extensions
end
def lockfile
@lockfile ||= Lockfile.new
end
def dependent_gems
lockfile.dependencies.map(&:name)
end
def installed_gems
lockfile.gems.map(&:name)
end
def puts(*args)
output = (@options[:stderr] ? $stderr : $stdout)
output.puts(*args)
end
end
end
end
end