| 
									
										
										
										
											2024-08-12 10:30:59 +01:00
										 |  |  | # typed: true # rubocop:todo Sorbet/StrictSigil | 
					
						
							| 
									
										
										
										
											2019-04-19 15:38:03 +09:00
										 |  |  | # frozen_string_literal: true | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-30 16:29:12 +01:00
										 |  |  | require "rubocops/shared/helper_functions" | 
					
						
							| 
									
										
										
										
											2017-05-30 01:22:47 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-02 20:26:29 +05:30
										 |  |  | module RuboCop | 
					
						
							|  |  |  |   module Cop | 
					
						
							| 
									
										
										
										
											2023-02-20 18:10:59 -08:00
										 |  |  |     # Abstract base class for all formula cops. | 
					
						
							| 
									
										
										
										
											2023-02-21 09:52:20 -08:00
										 |  |  |     class FormulaCop < Base | 
					
						
							| 
									
										
										
										
											2023-02-20 18:10:59 -08:00
										 |  |  |       extend T::Helpers | 
					
						
							| 
									
										
										
										
											2018-03-07 16:14:55 +00:00
										 |  |  |       include RangeHelp | 
					
						
							| 
									
										
										
										
											2020-07-30 16:29:12 +01:00
										 |  |  |       include HelperFunctions | 
					
						
							| 
									
										
										
										
											2018-03-07 16:14:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-20 18:10:59 -08:00
										 |  |  |       abstract! | 
					
						
							|  |  |  |       exclude_from_registry | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-04 01:18:00 +05:30
										 |  |  |       attr_accessor :file_path | 
					
						
							| 
									
										
										
										
											2020-05-12 08:32:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-10 13:05:31 -07:00
										 |  |  |       @registry = Registry.global | 
					
						
							| 
									
										
										
										
											2017-04-23 04:09:13 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-07 15:18:29 -04:00
										 |  |  |       class FormulaNodes < T::Struct | 
					
						
							|  |  |  |         prop :node, RuboCop::AST::ClassNode | 
					
						
							|  |  |  |         prop :class_node, RuboCop::AST::ConstNode | 
					
						
							|  |  |  |         prop :parent_class_node, RuboCop::AST::ConstNode | 
					
						
							|  |  |  |         prop :body_node, RuboCop::AST::Node | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 17:17:03 -05:00
										 |  |  |       # This method is called by RuboCop and is the main entry point. | 
					
						
							| 
									
										
										
										
											2017-04-23 04:09:13 +05:30
										 |  |  |       def on_class(node) | 
					
						
							| 
									
										
										
										
											2024-04-30 12:06:16 +01:00
										 |  |  |         @file_path = processed_source.file_path | 
					
						
							| 
									
										
										
										
											2017-08-04 01:18:00 +05:30
										 |  |  |         return unless file_path_allowed? | 
					
						
							| 
									
										
										
										
											2017-05-24 00:07:06 +05:30
										 |  |  |         return unless formula_class?(node) | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-30 01:22:47 +05:30
										 |  |  |         class_node, parent_class_node, @body = *node | 
					
						
							| 
									
										
										
										
											2017-08-30 15:48:41 +05:30
										 |  |  |         @formula_name = Pathname.new(@file_path).basename(".rb").to_s | 
					
						
							| 
									
										
										
										
											2020-11-27 01:23:07 -05:00
										 |  |  |         @tap_style_exceptions = nil | 
					
						
							| 
									
										
										
										
											2024-07-07 15:18:29 -04:00
										 |  |  |         audit_formula(FormulaNodes.new(node:, class_node:, parent_class_node:, body_node: @body)) | 
					
						
							| 
									
										
										
										
											2017-04-23 04:09:13 +05:30
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2017-03-02 20:26:29 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-07 15:18:29 -04:00
										 |  |  |       sig { abstract.params(formula_nodes: FormulaNodes).void } | 
					
						
							|  |  |  |       def audit_formula(formula_nodes); end | 
					
						
							| 
									
										
										
										
											2023-02-14 19:19:37 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-18 21:42:43 -04:00
										 |  |  |       # Yields to block when there is a match. | 
					
						
							| 
									
										
										
										
											2020-11-05 17:17:03 -05:00
										 |  |  |       # | 
					
						
							| 
									
										
										
										
											2018-10-18 21:42:43 -04:00
										 |  |  |       # @param urls [Array] url/mirror method call nodes | 
					
						
							| 
									
										
										
										
											2020-11-05 17:17:03 -05:00
										 |  |  |       # @param regex [Regexp] pattern to match URLs | 
					
						
							| 
									
										
										
										
											2017-07-30 12:57:57 +05:30
										 |  |  |       def audit_urls(urls, regex) | 
					
						
							| 
									
										
										
										
											2021-10-01 13:42:05 +01:00
										 |  |  |         urls.each_with_index do |url_node, index| | 
					
						
							| 
									
										
										
										
											2017-07-30 12:57:57 +05:30
										 |  |  |           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 | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-30 12:57:57 +05:30
										 |  |  |           offending_node(url_string_node.parent) | 
					
						
							| 
									
										
										
										
											2021-10-01 13:42:05 +01:00
										 |  |  |           yield match_object, url_string, index | 
					
						
							| 
									
										
										
										
											2017-07-30 12:57:57 +05:30
										 |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-14 02:52:30 +00:00
										 |  |  |       # Returns if the formula depends on dependency_name. | 
					
						
							| 
									
										
										
										
											2020-11-05 17:17:03 -05:00
										 |  |  |       # | 
					
						
							| 
									
										
										
										
											2018-10-18 21:42:43 -04:00
										 |  |  |       # @param dependency_name dependency's name | 
					
						
							| 
									
										
										
										
											2017-05-24 21:07:50 +05:30
										 |  |  |       def depends_on?(dependency_name, *types) | 
					
						
							| 
									
										
										
										
											2023-12-14 02:52:30 +00:00
										 |  |  |         return false if @body.nil? | 
					
						
							| 
									
										
										
										
											2022-11-05 04:17:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-07 14:08:58 +00:00
										 |  |  |         types = [:any] if types.empty? | 
					
						
							| 
									
										
										
										
											2017-05-30 01:22:47 +05:30
										 |  |  |         dependency_nodes = find_every_method_call_by_name(@body, :depends_on) | 
					
						
							| 
									
										
										
										
											2017-05-24 00:07:06 +05:30
										 |  |  |         idx = dependency_nodes.index do |n| | 
					
						
							| 
									
										
										
										
											2017-05-24 21:07:50 +05:30
										 |  |  |           types.any? { |type| depends_on_name_type?(n, dependency_name, type) } | 
					
						
							| 
									
										
										
										
											2017-05-24 00:07:06 +05:30
										 |  |  |         end | 
					
						
							| 
									
										
										
										
											2023-12-14 02:52:30 +00:00
										 |  |  |         return false if idx.nil? | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-24 00:07:06 +05:30
										 |  |  |         @offensive_node = dependency_nodes[idx] | 
					
						
							| 
									
										
										
										
											2023-12-14 02:52:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         true | 
					
						
							| 
									
										
										
										
											2017-05-24 00:07:06 +05:30
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-18 21:42:43 -04:00
										 |  |  |       # Returns true if given dependency name and dependency type exist in given dependency method call node. | 
					
						
							| 
									
										
										
										
											2017-05-30 01:22:47 +05:30
										 |  |  |       # TODO: Add case where key of hash is an array | 
					
						
							|  |  |  |       def depends_on_name_type?(node, name = nil, type = :required) | 
					
						
							| 
									
										
										
										
											2023-02-20 10:22:39 -08:00
										 |  |  |         name_match = !name # Match only by type when name is nil | 
					
						
							| 
									
										
										
										
											2017-05-30 01:22:47 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  |         case type | 
					
						
							| 
									
										
										
										
											2017-05-24 00:07:06 +05:30
										 |  |  |         when :required | 
					
						
							| 
									
										
										
										
											2017-08-06 14:48:39 +05:30
										 |  |  |           type_match = required_dependency?(node) | 
					
						
							| 
									
										
										
										
											2018-01-07 14:08:58 +00:00
										 |  |  |           name_match ||= required_dependency_name?(node, name) if type_match | 
					
						
							| 
									
										
										
										
											2018-03-19 10:11:08 +00:00
										 |  |  |         when :build, :test, :optional, :recommended | 
					
						
							| 
									
										
										
										
											2017-08-06 14:48:39 +05:30
										 |  |  |           type_match = dependency_type_hash_match?(node, type) | 
					
						
							| 
									
										
										
										
											2018-01-07 14:08:58 +00:00
										 |  |  |           name_match ||= dependency_name_hash_match?(node, name) if type_match | 
					
						
							|  |  |  |         when :any | 
					
						
							|  |  |  |           type_match = true | 
					
						
							|  |  |  |           name_match ||= required_dependency_name?(node, name) | 
					
						
							|  |  |  |           name_match ||= dependency_name_hash_match?(node, name) | 
					
						
							| 
									
										
										
										
											2017-05-24 21:07:50 +05:30
										 |  |  |         else | 
					
						
							|  |  |  |           type_match = false | 
					
						
							| 
									
										
										
										
											2017-05-24 00:07:06 +05:30
										 |  |  |         end | 
					
						
							| 
									
										
										
										
											2017-05-30 01:22:47 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-12 02:19:31 +11:00
										 |  |  |         @offensive_node = node if type_match || name_match | 
					
						
							| 
									
										
										
										
											2017-05-30 01:22:47 +05:30
										 |  |  |         type_match && name_match | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-15 02:28:32 +02:00
										 |  |  |       def_node_search :required_dependency?, <<~EOS | 
					
						
							| 
									
										
										
										
											2017-10-21 03:12:50 +02:00
										 |  |  |         (send nil? :depends_on ({str sym} _)) | 
					
						
							| 
									
										
										
										
											2017-08-06 14:48:39 +05:30
										 |  |  |       EOS | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-15 02:28:32 +02:00
										 |  |  |       def_node_search :required_dependency_name?, <<~EOS | 
					
						
							| 
									
										
										
										
											2017-10-21 03:12:50 +02:00
										 |  |  |         (send nil? :depends_on ({str sym} %1)) | 
					
						
							| 
									
										
										
										
											2017-08-06 14:48:39 +05:30
										 |  |  |       EOS | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-15 02:28:32 +02:00
										 |  |  |       def_node_search :dependency_type_hash_match?, <<~EOS | 
					
						
							| 
									
										
										
										
											2017-08-06 14:48:39 +05:30
										 |  |  |         (hash (pair ({str sym} _) ({str sym} %1))) | 
					
						
							|  |  |  |       EOS | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-15 02:28:32 +02:00
										 |  |  |       def_node_search :dependency_name_hash_match?, <<~EOS | 
					
						
							| 
									
										
										
										
											2018-01-09 20:08:22 +00:00
										 |  |  |         (hash (pair ({str sym} %1) (...))) | 
					
						
							| 
									
										
										
										
											2017-08-06 14:48:39 +05:30
										 |  |  |       EOS | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 17:17:03 -05:00
										 |  |  |       # Return all the caveats' string nodes in an array. | 
					
						
							| 
									
										
										
										
											2017-05-22 13:09:49 +05:30
										 |  |  |       def caveats_strings | 
					
						
							| 
									
										
										
										
											2022-11-05 04:17:50 +00:00
										 |  |  |         return [] if @body.nil? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-22 13:09:49 +05:30
										 |  |  |         find_strings(find_method_def(@body, :caveats)) | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 17:17:03 -05:00
										 |  |  |       # Returns the sha256 str node given a sha256 call node. | 
					
						
							| 
									
										
										
										
											2017-06-16 19:44:14 +05:30
										 |  |  |       def get_checksum_node(call) | 
					
						
							|  |  |  |         return if parameters(call).empty? || parameters(call).nil? | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-16 19:44:14 +05:30
										 |  |  |         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? | 
					
						
							| 
									
										
										
										
											2021-01-28 19:32:23 +01:00
										 |  |  |           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 | 
					
						
							| 
									
										
										
										
											2017-06-16 19:44:14 +05:30
										 |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 17:17:03 -05:00
										 |  |  |       # Yields to a block with comment text as parameter. | 
					
						
							| 
									
										
										
										
											2017-07-30 20:14:59 +05:30
										 |  |  |       def audit_comments | 
					
						
							| 
									
										
										
										
											2021-01-12 02:19:31 +11:00
										 |  |  |         processed_source.comments.each do |comment_node| | 
					
						
							| 
									
										
										
										
											2017-07-30 20:14:59 +05:30
										 |  |  |           @offensive_node = comment_node | 
					
						
							|  |  |  |           yield comment_node.text | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 17:17:03 -05:00
										 |  |  |       # Returns true if the formula is versioned. | 
					
						
							| 
									
										
										
										
											2017-05-24 13:04:55 +05:30
										 |  |  |       def versioned_formula? | 
					
						
							| 
									
										
										
										
											2017-08-30 15:48:41 +05:30
										 |  |  |         @formula_name.include?("@") | 
					
						
							| 
									
										
										
										
											2017-05-24 13:04:55 +05:30
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 17:17:03 -05:00
										 |  |  |       # Returns the formula tap. | 
					
						
							| 
									
										
										
										
											2017-08-04 01:18:00 +05:30
										 |  |  |       def formula_tap | 
					
						
							| 
									
										
										
										
											2021-02-12 18:33:37 +05:30
										 |  |  |         return unless (match_obj = @file_path.match(%r{/(homebrew-\w+)/})) | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-04 01:18:00 +05:30
										 |  |  |         match_obj[1] | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-09 14:20:28 +01:00
										 |  |  |       # Returns the style exceptions directory from the file path. | 
					
						
							|  |  |  |       def style_exceptions_dir | 
					
						
							|  |  |  |         file_directory = File.dirname(@file_path) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # 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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-27 13:13:09 -05:00
										 |  |  |       # Returns whether the given formula exists in the given style exception list. | 
					
						
							|  |  |  |       # Defaults to the current formula being checked. | 
					
						
							|  |  |  |       def tap_style_exception?(list, formula = nil) | 
					
						
							| 
									
										
										
										
											2020-11-29 15:17:11 -05:00
										 |  |  |         if @tap_style_exceptions.nil? && !formula_tap.nil? | 
					
						
							| 
									
										
										
										
											2020-11-27 01:23:07 -05:00
										 |  |  |           @tap_style_exceptions = {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-09 14:20:28 +01:00
										 |  |  |           Pathname.glob("#{style_exceptions_dir}/*.json").each do |exception_file| | 
					
						
							| 
									
										
										
										
											2020-11-27 01:23:07 -05:00
										 |  |  |             list_name = exception_file.basename.to_s.chomp(".json").to_sym | 
					
						
							|  |  |  |             list_contents = begin | 
					
						
							|  |  |  |               JSON.parse exception_file.read | 
					
						
							|  |  |  |             rescue JSON::ParserError | 
					
						
							|  |  |  |               nil | 
					
						
							|  |  |  |             end | 
					
						
							| 
									
										
										
										
											2020-11-29 15:17:11 -05:00
										 |  |  |             next if list_contents.nil? || list_contents.count.zero? | 
					
						
							| 
									
										
										
										
											2020-11-27 01:23:07 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |             @tap_style_exceptions[list_name] = list_contents | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-29 15:17:11 -05:00
										 |  |  |         return false if @tap_style_exceptions.nil? || @tap_style_exceptions.count.zero? | 
					
						
							| 
									
										
										
										
											2020-11-27 01:23:07 -05:00
										 |  |  |         return false unless @tap_style_exceptions.key? list | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-27 13:13:09 -05:00
										 |  |  |         @tap_style_exceptions[list].include?(formula || @formula_name) | 
					
						
							| 
									
										
										
										
											2020-11-27 01:23:07 -05:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-23 04:09:13 +05:30
										 |  |  |       private | 
					
						
							| 
									
										
										
										
											2017-03-02 20:26:29 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-24 00:07:06 +05:30
										 |  |  |       def formula_class?(node) | 
					
						
							|  |  |  |         _, class_node, = *node | 
					
						
							| 
									
										
										
										
											2017-09-04 13:47:05 +05:30
										 |  |  |         class_names = %w[
 | 
					
						
							|  |  |  |           Formula | 
					
						
							|  |  |  |           GithubGistFormula | 
					
						
							|  |  |  |           ScriptFileFormula | 
					
						
							|  |  |  |           AmazonWebServicesFormula | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         class_node && class_names.include?(string_content(class_node)) | 
					
						
							| 
									
										
										
										
											2017-04-23 04:09:13 +05:30
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2017-03-16 23:49:43 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-04 01:18:00 +05:30
										 |  |  |       def file_path_allowed? | 
					
						
							| 
									
										
										
										
											2019-04-08 12:47:15 -04:00
										 |  |  |         return true if @file_path.nil? # file_path is nil when source is directly passed to the cop, e.g. in specs | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-30 12:06:16 +01:00
										 |  |  |         !@file_path.include?("/Library/Homebrew/test/") | 
					
						
							| 
									
										
										
										
											2017-03-02 20:26:29 +05:30
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2022-08-02 21:56:45 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       def on_system_methods | 
					
						
							| 
									
										
										
										
											2023-05-09 02:15:28 +02:00
										 |  |  |         @on_system_methods ||= [:intel, :arm, :macos, :linux, :system, *MacOSVersion::SYMBOLS.keys].map do |m| | 
					
						
							| 
									
										
										
										
											2022-08-02 21:56:45 -07:00
										 |  |  |           :"on_#{m}" | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2017-03-02 20:26:29 +05:30
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | end |