Class: RuboCop::Cop::Flexport::InclusiveCode
- Inherits:
-
RuboCop::Cop
- Object
- RuboCop::Cop
- RuboCop::Cop::Flexport::InclusiveCode
- Includes:
- RangeHelp
- Defined in:
- lib/rubocop/cop/inclusive_code.rb
Overview
This cop encourages use of inclusive language to help programmers avoid using terminology that is derogatory, hurtful, or perpetuates discrimination, either directly or indirectly, in their code.
Constant Summary collapse
- SEVERITY =
'warning'
- FLAG_ONLY_MSG =
'🚫 Use of non_inclusive word: `%<non_inclusive_word>s`.'
- FULL_FLAG_MSG =
"#{FLAG_ONLY_MSG} Consider using these suggested alternatives: `%<suggestions>s`."
- ALLOWED_TERM_MASK_CHAR =
'*'.freeze
Instance Method Summary collapse
- #autocorrect(arg_pair) ⇒ Object
-
#initialize(config = nil, options = nil, source_file = nil) ⇒ InclusiveCode
constructor
A new instance of InclusiveCode.
- #investigate(processed_source) ⇒ Object
Constructor Details
#initialize(config = nil, options = nil, source_file = nil) ⇒ InclusiveCode
Returns a new instance of InclusiveCode.
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/rubocop/cop/inclusive_code.rb', line 35 def initialize(config = nil, = nil, source_file = nil) super(config, ) source_file ||= YAML.load_file(cop_config['GlobalConfigPath']) @non_inclusive_words_alternatives_hash = source_file['flagged_terms'] @all_non_inclusive_words = @non_inclusive_words_alternatives_hash.keys @non_inclusive_words_regex = concatenated_regex(@all_non_inclusive_words) @allowed_terms = {} @allowed_files = {} @all_non_inclusive_words.each do |word| @allowed_terms[word] = get_allowed_string(word) @allowed_files[word] = source_file['flagged_terms'][word]['allowed_files'] || [] end @allowed_regex = @allowed_terms.values.reject(&:blank?).join('|') @allowed_regex = if @allowed_regex.blank? Regexp.new(/^$/) else Regexp.new(@allowed_regex, Regexp::IGNORECASE) end end |
Instance Method Details
#autocorrect(arg_pair) ⇒ Object
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/rubocop/cop/inclusive_code.rb', line 114 def autocorrect(arg_pair) return if cop_config['DisableAutoCorrect'] word_to_correct = arg_pair.source correction = correction_for_word(word_to_correct) return if correction['suggestions'].blank? corrected = correction['suggestions'][0] # Only respects case if it is capitalized or uniform (all upper or all lower) to_upcase = word_to_correct == word_to_correct.upcase if to_upcase corrected = corrected.upcase elsif word_to_correct == word_to_correct.capitalize corrected = corrected.capitalize end lambda do |corrector| corrector.insert_before(arg_pair, corrected) corrector.remove(arg_pair) end end |
#investigate(processed_source) ⇒ Object
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 |
# File 'lib/rubocop/cop/inclusive_code.rb', line 58 def investigate(processed_source) non_inclusive_words_for_current_file = @all_non_inclusive_words.reject do |non_inclusive_word| Dir.glob("{#{@allowed_files[non_inclusive_word].join(',')}}").include?(processed_source.path) end processed_source.lines.each_with_index do |line, line_number| next unless line.match(@non_inclusive_words_regex) non_inclusive_words_for_current_file.each do |non_inclusive_word| allowed = @allowed_terms[non_inclusive_word] scan_regex = /(?=#{non_inclusive_word})/i if allowed.present? line = line.gsub(/(#{allowed})/i){ |match| ALLOWED_TERM_MASK_CHAR * match.size } end locations = line.enum_for( :scan, scan_regex ).map { Regexp.last_match&.offset(0)&.first } non_inclusive_words = line.scan(/#{non_inclusive_word}/i) locations = locations.zip(non_inclusive_words).to_h next if locations.blank? locations.each do |location, word| range = source_range( processed_source.buffer, line_number + 1, location, word.length ) add_offense( range, location: range, message: (word), severity: SEVERITY ) end end end # Also error for non-inclusive language in file names path = processed_source.path return if path.nil? non_inclusive_words_match = path.match(concatenated_regex(non_inclusive_words_for_current_file)) return unless non_inclusive_words_match && !path.match(@allowed_regex) range = source_range(processed_source.buffer, 1, 0) add_offense( range, location: range, message: (non_inclusive_words_match[0]), severity: SEVERITY ) end |