2020-10-10 14:16:11 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								# typed: false
							 | 
						
					
						
							
								
									
										
										
										
											2019-04-19 15:38:03 +09:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								# frozen_string_literal: true
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-06 09:11:34 -08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								require "ast_constants"
							 | 
						
					
						
							
								
									
										
										
										
											2018-10-26 19:41:14 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								require "rubocops/extend/formula"
							 | 
						
					
						
							
								
									
										
										
										
											2017-04-08 15:10:44 +05:30
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								module RuboCop
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								  module Cop
							 | 
						
					
						
							
								
									
										
										
										
											2018-04-24 18:27:37 +10:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    module FormulaAudit
							 | 
						
					
						
							
								
									
										
										
										
											2020-11-05 17:17:03 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								      # This cop checks for correct order of components in formulae.
							 | 
						
					
						
							
								
									
										
										
										
											2017-04-08 15:10:44 +05:30
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      #
							 | 
						
					
						
							
								
									
										
										
										
											2018-10-18 21:42:43 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								      # - `component_precedence_list` has component hierarchy in a nested list
							 | 
						
					
						
							
								
									
										
										
										
											2017-04-08 15:10:44 +05:30
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      #   where each sub array contains components' details which are at same precedence level
							 | 
						
					
						
							
								
									
										
										
										
											2017-05-03 11:33:00 +05:30
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								      class ComponentsOrder < FormulaCop
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-12 16:36:06 +11:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        extend AutoCorrector
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-11-09 08:34:11 -08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        def audit_formula(_node, _class_node, _parent_class_node, body_node)
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-06 09:11:34 -08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								          @present_components, @offensive_nodes = check_order(FORMULA_COMPONENT_PRECEDENCE_LIST, body_node)
							 | 
						
					
						
							
								
									
										
										
										
											2020-04-23 11:32:23 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          component_problem @offensive_nodes[0], @offensive_nodes[1] if @offensive_nodes
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          component_precedence_list = [
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            [{ name: :depends_on, type: :method_call }],
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            [{ name: :resource, type: :block_call }],
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            [{ name: :patch, type: :method_call }, { name: :patch, type: :block_call }],
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          ]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          on_macos_blocks = find_blocks(body_node, :on_macos)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          if on_macos_blocks.length > 1
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            @offensive_node = on_macos_blocks.second
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            problem "there can only be one `on_macos` block in a formula."
							 | 
						
					
						
							
								
									
										
										
										
											2017-04-08 15:10:44 +05:30
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-04-23 11:32:23 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								          check_on_os_block_content(component_precedence_list, on_macos_blocks.first) if on_macos_blocks.any?
							 | 
						
					
						
							
								
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-04-23 11:32:23 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								          on_linux_blocks = find_blocks(body_node, :on_linux)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          if on_linux_blocks.length > 1
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            @offensive_node = on_linux_blocks.second
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            problem "there can only be one `on_linux` block in a formula."
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          check_on_os_block_content(component_precedence_list, on_linux_blocks.first) if on_linux_blocks.any?
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          resource_blocks = find_blocks(body_node, :resource)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          resource_blocks.each do |resource_block|
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            on_macos_blocks = find_blocks(resource_block.body, :on_macos)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            on_linux_blocks = find_blocks(resource_block.body, :on_linux)
							 | 
						
					
						
							
								
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-04-23 11:32:23 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            if on_macos_blocks.length.zero? && on_linux_blocks.length.zero?
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              # Found nothing. Try without .body as depending on the code,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              # on_macos or on_linux might be in .body or not ...
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              on_macos_blocks = find_blocks(resource_block, :on_macos)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              on_linux_blocks = find_blocks(resource_block, :on_linux)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              next if on_macos_blocks.length.zero? && on_linux_blocks.length.zero?
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            @offensive_node = resource_block
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-06-30 23:08:43 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            next if on_macos_blocks.length.zero? && on_linux_blocks.length.zero?
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-12-23 15:00:28 -08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            on_os_bodies = []
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            (on_macos_blocks + on_linux_blocks).each do |on_os_block|
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              on_os_body = on_os_block.body
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-13 23:18:32 -08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								              branches = on_os_body.if_type? ? on_os_body.branches : [on_os_body]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              on_os_bodies += branches.map { |branch| [on_os_block, branch] }
							 | 
						
					
						
							
								
									
										
										
										
											2020-04-23 11:32:23 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-12-23 15:00:28 -08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            message = nil
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            allowed_methods = [
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              [:url, :sha256],
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-14 17:04:40 +11:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								              [:url, :mirror, :sha256],
							 | 
						
					
						
							
								
									
										
										
										
											2020-12-23 15:00:28 -08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								              [:url, :version, :sha256],
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-14 17:04:40 +11:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								              [:url, :mirror, :version, :sha256],
							 | 
						
					
						
							
								
									
										
										
										
											2020-12-23 15:00:28 -08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            ]
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-13 23:18:32 -08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            minimum_methods = allowed_methods.first.map { |m| "`#{m}`" }.to_sentence
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            maximum_methods = allowed_methods.last.map { |m| "`#{m}`" }.to_sentence
							 | 
						
					
						
							
								
									
										
										
										
											2020-12-23 15:00:28 -08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-13 23:18:32 -08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            on_os_bodies.each do |on_os_block, on_os_body|
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              method_name = on_os_block.method_name
							 | 
						
					
						
							
								
									
										
										
										
											2020-12-23 15:00:28 -08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								              child_nodes = on_os_body.begin_type? ? on_os_body.child_nodes : [on_os_body]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              if child_nodes.all? { |n| n.send_type? || n.block_type? }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                method_names = child_nodes.map(&:method_name)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                next if allowed_methods.include? method_names
							 | 
						
					
						
							
								
									
										
										
										
											2020-06-30 23:08:43 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								              end
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-13 23:18:32 -08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								              offending_node(on_os_block)
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-14 17:04:40 +11:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								              message = "`#{method_name}` blocks within `resource` blocks must contain at least "\
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-13 23:18:32 -08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        "#{minimum_methods} and at most #{maximum_methods} (in order)."
							 | 
						
					
						
							
								
									
										
										
										
											2020-12-23 15:00:28 -08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								              break
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if message.present?
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              problem message
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              next
							 | 
						
					
						
							
								
									
										
										
										
											2020-04-23 11:32:23 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-06-30 23:08:43 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            if on_macos_blocks.length > 1
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              problem "there can only be one `on_macos` block in a resource block."
							 | 
						
					
						
							
								
									
										
										
										
											2020-04-23 11:32:23 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								              next
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-06-30 23:08:43 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            if on_linux_blocks.length > 1
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              problem "there can only be one `on_linux` block in a resource block."
							 | 
						
					
						
							
								
									
										
										
										
											2020-04-23 11:32:23 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								              next
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            end
							 | 
						
					
						
							
								
									
										
										
										
											2017-04-08 15:10:44 +05:30
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-04-23 11:32:23 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        def check_on_os_block_content(component_precedence_list, on_os_block)
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-04 18:34:03 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								          on_os_allowed_methods = %w[
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            depends_on
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            patch
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            resource
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            deprecate!
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            disable!
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            conflicts_with
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            keg_only
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            ignore_missing_libraries
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          ]
							 | 
						
					
						
							
								
									
										
										
										
											2020-04-23 11:32:23 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								          _, offensive_node = check_order(component_precedence_list, on_os_block.body)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          component_problem(*offensive_node) if offensive_node
							 | 
						
					
						
							
								
									
										
										
										
											2020-12-08 14:33:37 -08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								          child_nodes = on_os_block.body.begin_type? ? on_os_block.body.child_nodes : [on_os_block.body]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          child_nodes.each do |child|
							 | 
						
					
						
							
								
									
										
										
										
											2020-04-23 11:32:23 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            valid_node = depends_on_node?(child)
							 | 
						
					
						
							
								
									
										
										
										
											2020-12-08 14:33:37 -08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            # Check for RuboCop::AST::SendNode and RuboCop::AST::BlockNode instances
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # only, as we are checking the method_name for `patch`, `resource`, etc.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            method_type = child.send_type? || child.block_type?
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            next unless method_type
							 | 
						
					
						
							
								
									
										
										
										
											2018-04-24 18:27:37 +10:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-12-09 08:55:51 -08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            valid_node ||= on_os_allowed_methods.include? child.method_name.to_s
							 | 
						
					
						
							
								
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-12-09 08:55:51 -08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            @offensive_node = child
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            next if valid_node
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            problem "`#{on_os_block.method_name}` cannot include `#{child.method_name}`. " \
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    "Only #{on_os_allowed_methods.map { |m| "`#{m}`" }.to_sentence} are allowed."
							 | 
						
					
						
							
								
									
										
										
										
											2020-04-23 11:32:23 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								          end
							 | 
						
					
						
							
								
									
										
										
										
											2017-04-08 15:10:44 +05:30
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        end
							 | 
						
					
						
							
								
									
										
										
										
											2017-05-08 18:47:50 +05:30
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-10-18 21:42:43 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        # Reorder two nodes in the source, using the corrector instance in autocorrect method.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # Components of same type are grouped together when rewriting the source.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # Linebreaks are introduced if components are of two different methods/blocks/multilines.
							 | 
						
					
						
							
								
									
										
										
										
											2017-05-08 18:47:50 +05:30
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        def reorder_components(corrector, node1, node2)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          # order_idx : node1's index in component_precedence_list
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          # curr_p_idx: node1's index in preceding_comp_arr
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          # preceding_comp_arr: array containing components of same type
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          order_idx, curr_p_idx, preceding_comp_arr = get_state(node1)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2017-09-24 20:12:58 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								          # curr_p_idx.positive? means node1 needs to be grouped with its own kind
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          if curr_p_idx.positive?
							 | 
						
					
						
							
								
									
										
										
										
											2017-06-01 16:06:51 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            node2 = preceding_comp_arr[curr_p_idx - 1]
							 | 
						
					
						
							
								
									
										
										
										
											2017-05-08 18:47:50 +05:30
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            indentation = " " * (start_column(node2) - line_start_column(node2))
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            line_breaks = node2.multiline? ? "\n\n" : "\n"
							 | 
						
					
						
							
								
									
										
										
										
											2017-06-01 16:06:51 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            corrector.insert_after(node2.source_range, line_breaks + indentation + node1.source)
							 | 
						
					
						
							
								
									
										
										
										
											2017-05-08 18:47:50 +05:30
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								          else
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            indentation = " " * (start_column(node2) - line_start_column(node2))
							 | 
						
					
						
							
								
									
										
										
										
											2019-08-19 14:27:29 +10:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            # No line breaks up to version_scheme, order_idx == 8
							 | 
						
					
						
							
								
									
										
										
										
											2017-06-01 16:06:51 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            line_breaks = (order_idx > 8) ? "\n\n" : "\n"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            corrector.insert_before(node2.source_range, node1.source + line_breaks + indentation)
							 | 
						
					
						
							
								
									
										
										
										
											2017-05-08 18:47:50 +05:30
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								          end
							 | 
						
					
						
							
								
									
										
										
										
											2018-01-07 15:40:42 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								          corrector.remove(range_with_surrounding_space(range: node1.source_range, side: :left))
							 | 
						
					
						
							
								
									
										
										
										
											2017-05-08 18:47:50 +05:30
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-11-05 17:17:03 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        # Returns precedence index and component's index to properly reorder and group during autocorrect.
							 | 
						
					
						
							
								
									
										
										
										
											2017-05-08 18:47:50 +05:30
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        def get_state(node1)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          @present_components.each_with_index do |comp, idx|
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            return [idx, comp.index(node1), comp] if comp.member?(node1)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        end
							 | 
						
					
						
							
								
									
										
										
										
											2020-04-23 11:32:23 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        def check_order(component_precedence_list, body_node)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          present_components = component_precedence_list.map do |components|
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            components.flat_map do |component|
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              case component[:type]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              when :method_call
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                find_method_calls_by_name(body_node, component[:name]).to_a
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              when :block_call
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                find_blocks(body_node, component[:name]).to_a
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              when :method_definition
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                find_method_def(body_node, component[:name])
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            end.compact
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          # Check if each present_components is above rest of the present_components
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          offensive_nodes = nil
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          present_components.take(present_components.size - 1).each_with_index do |preceding_component, p_idx|
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            next if preceding_component.empty?
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            present_components.drop(p_idx + 1).each do |succeeding_component|
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              next if succeeding_component.empty?
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              offensive_nodes = check_precedence(preceding_component, succeeding_component)
							 | 
						
					
						
							
								
									
										
										
										
											2020-06-30 08:36:11 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								              return [present_components, offensive_nodes] if offensive_nodes
							 | 
						
					
						
							
								
									
										
										
										
											2020-04-23 11:32:23 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          end
							 | 
						
					
						
							
								
									
										
										
										
											2020-06-30 08:36:11 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								          nil
							 | 
						
					
						
							
								
									
										
										
										
											2020-04-23 11:32:23 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-12 16:36:06 +11:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        # Method to report and correct component precedence violations.
							 | 
						
					
						
							
								
									
										
										
										
											2020-04-23 11:32:23 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        def component_problem(c1, c2)
							 | 
						
					
						
							
								
									
										
										
										
											2020-11-27 12:29:38 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								          return if tap_style_exception? :components_order_exceptions
							 | 
						
					
						
							
								
									
										
										
										
											2020-04-23 11:32:23 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          problem "`#{format_component(c1)}` (line #{line_number(c1)}) " \
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-06 23:44:09 +05:30
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                  "should be put before `#{format_component(c2)}` " \
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                  "(line #{line_number(c2)})" do |corrector|
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-12 16:36:06 +11:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            reorder_components(corrector, c1, c2)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          end
							 | 
						
					
						
							
								
									
										
										
										
											2020-04-23 11:32:23 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # Node pattern method to match
							 | 
						
					
						
							
								
									
										
										
										
											2020-11-05 17:17:03 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        # `depends_on` variants.
							 | 
						
					
						
							
								
									
										
										
										
											2020-04-23 11:32:23 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        def_node_matcher :depends_on_node?, <<~EOS
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          {(if _ (send nil? :depends_on ...) nil?)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								           (send nil? :depends_on ...)}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        EOS
							 | 
						
					
						
							
								
									
										
										
										
											2017-04-08 15:10:44 +05:30
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								  end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								end
							 |