Class: RuboCop::Cop::FormulaCop Abstract Private

Inherits:
Base
  • Object
show all
Extended by:
T::Helpers
Includes:
RangeHelp, HelperFunctions
Defined in:
rubocops/extend/formula_cop.rb,
sorbet/rbi/dsl/rubo_cop/cop/formula_cop.rbi

Overview

This class is part of a private API. This class may only be used in the Homebrew/brew repository. Third parties should avoid using this class if possible, as it may be removed or changed without warning.

This class is abstract.

It cannot be directly instantiated. Subclasses must implement the abstract methods below.

Abstract base class for all formula cops.

Direct Known Subclasses

RuboCop::Cop::FormulaAudit::AssertStatements, RuboCop::Cop::FormulaAudit::BottleDigestIndentation, RuboCop::Cop::FormulaAudit::BottleFormat, RuboCop::Cop::FormulaAudit::BottleOrder, RuboCop::Cop::FormulaAudit::BottleTagIndentation, RuboCop::Cop::FormulaAudit::Caveats, RuboCop::Cop::FormulaAudit::Checksum, RuboCop::Cop::FormulaAudit::ChecksumCase, RuboCop::Cop::FormulaAudit::ClassInheritance, RuboCop::Cop::FormulaAudit::ClassName, RuboCop::Cop::FormulaAudit::Comments, RuboCop::Cop::FormulaAudit::ComponentsOrder, RuboCop::Cop::FormulaAudit::ComponentsRedundancy, RuboCop::Cop::FormulaAudit::Conflicts, RuboCop::Cop::FormulaAudit::DependencyOrder, RuboCop::Cop::FormulaAudit::DeprecateDisableDate, RuboCop::Cop::FormulaAudit::DeprecateDisableReason, RuboCop::Cop::FormulaAudit::Desc, RuboCop::Cop::FormulaAudit::Files, RuboCop::Cop::FormulaAudit::GenerateCompletionsDSL, RuboCop::Cop::FormulaAudit::GitUrls, RuboCop::Cop::FormulaAudit::Homepage, RuboCop::Cop::FormulaAudit::KegOnly, RuboCop::Cop::FormulaAudit::LicenseArrays, RuboCop::Cop::FormulaAudit::Licenses, RuboCop::Cop::FormulaAudit::Lines, RuboCop::Cop::FormulaAudit::LivecheckRegexCaseInsensitive, RuboCop::Cop::FormulaAudit::LivecheckRegexExtension, RuboCop::Cop::FormulaAudit::LivecheckRegexIfPageMatch, RuboCop::Cop::FormulaAudit::LivecheckRegexParentheses, RuboCop::Cop::FormulaAudit::LivecheckSkip, RuboCop::Cop::FormulaAudit::LivecheckUrlProvided, RuboCop::Cop::FormulaAudit::LivecheckUrlSymbol, RuboCop::Cop::FormulaAudit::MacOSOnLinux, RuboCop::Cop::FormulaAudit::Miscellaneous, RuboCop::Cop::FormulaAudit::MpiCheck, RuboCop::Cop::FormulaAudit::OnSystemConditionals, RuboCop::Cop::FormulaAudit::OptionDeclarations, RuboCop::Cop::FormulaAudit::Options, RuboCop::Cop::FormulaAudit::Patches, RuboCop::Cop::FormulaAudit::ProvidedByMacos, RuboCop::Cop::FormulaAudit::PyPiUrls, RuboCop::Cop::FormulaAudit::PyoxidizerCheck, RuboCop::Cop::FormulaAudit::PythonVersions, RuboCop::Cop::FormulaAudit::QuicTLSCheck, RuboCop::Cop::FormulaAudit::ResourceRequiresDependencies, RuboCop::Cop::FormulaAudit::SafePopenCommands, RuboCop::Cop::FormulaAudit::Service, RuboCop::Cop::FormulaAudit::ShellVariables, RuboCop::Cop::FormulaAudit::SingleGenerateCompletionsDSLCall, RuboCop::Cop::FormulaAudit::StdNpmArgs, RuboCop::Cop::FormulaAudit::Test, RuboCop::Cop::FormulaAudit::Text, RuboCop::Cop::FormulaAudit::Urls, RuboCop::Cop::FormulaAudit::UsesFromMacos, RuboCop::Cop::FormulaAudit::Version, RuboCop::Cop::FormulaAuditStrict::GitUrls, RuboCop::Cop::FormulaAuditStrict::MakeCheck, RuboCop::Cop::FormulaAuditStrict::Requirements, RuboCop::Cop::FormulaAuditStrict::RustCheck, RuboCop::Cop::FormulaAuditStrict::TestPresent, RuboCop::Cop::FormulaAuditStrict::Text

Defined Under Namespace

Classes: FormulaNodes

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from HelperFunctions

#block_method_called_in_block?, #block_size, #check_precedence, #class_name, #component_precedes?, #end_column, #expression_negated?, #find_all_blocks, #find_block, #find_blocks, #find_const, #find_every_func_call_by_name, #find_every_method_call_by_name, #find_instance_call, #find_instance_method_call, #find_method_calls_by_name, #find_method_def, #find_method_with_args, #find_node_method_by_name, #find_strings, #format_component, #line_number, #line_start_column, #method_called?, #method_called_ever?, #method_name, #node_equals?, #offending_node, #parameters, #parameters_passed?, #problem, #regex_match_group, #size, #source_buffer, #start_column, #string_content

Instance Attribute Details

#file_pathString?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:



18
19
20
# File 'rubocops/extend/formula_cop.rb', line 18

def file_path
  @file_path
end

Instance Method Details

#audit_comments(&_block) ⇒ void

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

This method returns an undefined value.

Yields to a block with comment text as parameter.

Parameters:

  • _block (T.proc.params(arg0: String).void)


168
169
170
171
172
173
# File 'rubocops/extend/formula_cop.rb', line 168

def audit_comments(&_block)
  processed_source.comments.each do |comment_node|
    @offensive_node = comment_node
    yield comment_node.text
  end
end

#audit_formula(formula_nodes) ⇒ void

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

This method is abstract.

This method returns an undefined value.

Parameters:



45
# File 'rubocops/extend/formula_cop.rb', line 45

def audit_formula(formula_nodes); end

#audit_urls(urls, regex, &_block) ⇒ void

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

This method returns an undefined value.

Yields to block when there is a match.

Parameters:



57
58
59
60
61
62
63
64
65
66
67
# File 'rubocops/extend/formula_cop.rb', line 57

def audit_urls(urls, regex, &_block)
  urls.each_with_index do |url_node, index|
    url_string_node = parameters(url_node).first
    url_string = string_content(url_string_node)
    match_object = regex_match_group(url_string_node, regex)
    next unless match_object

    offending_node(url_string_node.parent)
    yield match_object, url_string, index
  end
end

#caveats_stringsArray<RuboCop::AST::Node>

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Return all the caveats' string nodes in an array.



137
138
139
140
141
# File 'rubocops/extend/formula_cop.rb', line 137

def caveats_strings
  return [] if @body.nil?

  find_strings(find_method_def(@body, :caveats)).to_a
end

#dependency_name_hash_match?(node, *pattern, **kwargs, &block) ⇒ Boolean

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

Returns:

  • (Boolean)


17
# File 'sorbet/rbi/dsl/rubo_cop/cop/formula_cop.rbi', line 17

def dependency_name_hash_match?(node, *pattern, **kwargs, &block); end

#dependency_type_hash_match?(node, *pattern, **kwargs, &block) ⇒ Boolean

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

Returns:

  • (Boolean)


27
# File 'sorbet/rbi/dsl/rubo_cop/cop/formula_cop.rbi', line 27

def dependency_type_hash_match?(node, *pattern, **kwargs, &block); end

#depends_on?(dependency_name, *types) ⇒ Boolean

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns if the formula depends on dependency_name.

Parameters:

Returns:

  • (Boolean)


73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'rubocops/extend/formula_cop.rb', line 73

def depends_on?(dependency_name, *types)
  return false if @body.nil?

  types = [:any] if types.empty?
  dependency_nodes = find_every_method_call_by_name(@body, :depends_on)
  idx = dependency_nodes.index do |n|
    types.any? { |type| depends_on_name_type?(n, dependency_name, type) }
  end
  return false if idx.nil?

  @offensive_node = T.let(dependency_nodes[idx], T.nilable(RuboCop::AST::Node))

  true
end

#depends_on_name_type?(node, name = nil, type = :required) ⇒ Boolean

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

TODO:

Add case where key of hash is an array

Returns true if given dependency name and dependency type exist in given dependency method call node.

Parameters:

Returns:

  • (Boolean)


97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'rubocops/extend/formula_cop.rb', line 97

def depends_on_name_type?(node, name = nil, type = :required)
  name_match = !name # Match only by type when name is nil

  case type
  when :required
    type_match = required_dependency?(node)
    name_match ||= required_dependency_name?(node, name) if type_match
  when :build, :test, :optional, :recommended
    type_match = dependency_type_hash_match?(node, type)
    name_match ||= dependency_name_hash_match?(node, name) if type_match
  when :any
    type_match = true
    name_match ||= required_dependency_name?(node, name) || false
    name_match ||= dependency_name_hash_match?(node, name) || false
  else
    type_match = false
  end

  @offensive_node = node if type_match || name_match
  type_match && name_match
end

#formula_tapString?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns the formula tap.

Returns:



185
186
187
188
189
# File 'rubocops/extend/formula_cop.rb', line 185

def formula_tap
  return unless (match_obj = @file_path&.match(%r{/(homebrew-\w+)/}))

  match_obj[1]
end

#get_checksum_node(call) ⇒ RuboCop::AST::Node?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns the sha256 str node given a sha256 call node.

Parameters:

Returns:



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'rubocops/extend/formula_cop.rb', line 145

def get_checksum_node(call)
  return if parameters(call).empty? || parameters(call).nil?

  if parameters(call).first.str_type?
    parameters(call).first
  # sha256 is passed as a key-value pair in bottle blocks
  elsif parameters(call).first.hash_type?
    if parameters(call).first.keys.first.value == :cellar
      # sha256 :cellar :any, :tag "hexdigest"
      parameters(call).first.values.last
    elsif parameters(call).first.keys.first.is_a?(RuboCop::AST::SymbolNode)
      # sha256 :tag "hexdigest"
      parameters(call).first.values.first
    else
      # Legacy bottle block syntax
      # sha256 "hexdigest" => :tag
      parameters(call).first.keys.first
    end
  end
end

#on_class(node) ⇒ void

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

This method returns an undefined value.

This method is called by RuboCop and is the main entry point.

Parameters:

  • node (RuboCop::AST::ClassNode)


31
32
33
34
35
36
37
38
39
40
41
42
# File 'rubocops/extend/formula_cop.rb', line 31

def on_class(node)
  @file_path = T.let(processed_source.file_path, T.nilable(String))
  return unless file_path_allowed?
  return unless formula_class?(node)

  class_node, parent_class_node, body = *node
  @body = T.let(body, T.nilable(RuboCop::AST::Node))

  @formula_name = T.let(Pathname.new(@file_path).basename(".rb").to_s, T.nilable(String))
  @tap_style_exceptions = T.let(nil, T.nilable(T::Hash[Symbol, T::Array[String]]))
  audit_formula(FormulaNodes.new(node:, class_node:, parent_class_node:, body_node: T.must(@body)))
end

#required_dependency?(node, *pattern, **kwargs, &block) ⇒ Boolean

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

Returns:

  • (Boolean)


37
# File 'sorbet/rbi/dsl/rubo_cop/cop/formula_cop.rbi', line 37

def required_dependency?(node, *pattern, **kwargs, &block); end

#required_dependency_name?(node, *pattern, **kwargs, &block) ⇒ Boolean

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

Returns:

  • (Boolean)


47
# File 'sorbet/rbi/dsl/rubo_cop/cop/formula_cop.rbi', line 47

def required_dependency_name?(node, *pattern, **kwargs, &block); end

#style_exceptions_dirString?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns the style exceptions directory from the file path.

Returns:



193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'rubocops/extend/formula_cop.rb', line 193

def style_exceptions_dir
  file_directory = File.dirname(@file_path) if @file_path
  return unless file_directory

  # if we're in a sharded subdirectory, look below that.
  directory_name = File.basename(file_directory)
  formula_directory = if directory_name.length == 1 || directory_name == "lib"
    File.dirname(file_directory)
  else
    file_directory
  end

  # if we're in a Formula or HomebrewFormula subdirectory, look below that.
  formula_directory_names = ["Formula", "HomebrewFormula"].freeze
  directory_name = File.basename(formula_directory)
  tap_root_directory = if formula_directory_names.include?(directory_name)
    File.dirname(formula_directory)
  else
    formula_directory
  end

  "#{tap_root_directory}/style_exceptions"
end

#tap_style_exception?(list, formula = nil) ⇒ Boolean

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns whether the given formula exists in the given style exception list. Defaults to the current formula being checked.

Parameters:

Returns:

  • (Boolean)


220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'rubocops/extend/formula_cop.rb', line 220

def tap_style_exception?(list, formula = nil)
  if @tap_style_exceptions.nil? && !formula_tap.nil?
    @tap_style_exceptions = {}

    Pathname.glob("#{style_exceptions_dir}/*.json").each do |exception_file|
      list_name = exception_file.basename.to_s.chomp(".json").to_sym
      list_contents = begin
        JSON.parse exception_file.read
      rescue JSON::ParserError
        nil
      end
      next if list_contents.nil? || list_contents.count.zero?

      @tap_style_exceptions[list_name] = list_contents
    end
  end

  return false if @tap_style_exceptions.nil? || @tap_style_exceptions.count.zero?
  return false unless @tap_style_exceptions.key? list

  T.must(@tap_style_exceptions[list]).include?(formula || @formula_name)
end

#versioned_formula?Boolean

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns true if the formula is versioned.

Returns:

  • (Boolean)


177
178
179
180
181
# File 'rubocops/extend/formula_cop.rb', line 177

def versioned_formula?
  return false if @formula_name.nil?

  @formula_name.include?("@")
end