| 
									
										
										
										
											2020-10-10 14:16:11 +02:00
										 |  |  | # typed: true | 
					
						
							| 
									
										
										
										
											2019-04-19 15:38:03 +09:00
										 |  |  | # frozen_string_literal: true | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-26 19:49:21 +01:00
										 |  |  | require "forwardable" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module RuboCop | 
					
						
							|  |  |  |   module Cask | 
					
						
							|  |  |  |     module AST | 
					
						
							| 
									
										
										
										
											2023-05-07 08:23:19 +02:00
										 |  |  |       class StanzaBlock | 
					
						
							|  |  |  |         extend T::Helpers | 
					
						
							| 
									
										
										
										
											2018-10-26 19:49:21 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-07 08:23:19 +02:00
										 |  |  |         sig { returns(RuboCop::AST::BlockNode) } | 
					
						
							|  |  |  |         attr_reader :block_node | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         sig { returns(T::Array[Parser::Source::Comment]) } | 
					
						
							|  |  |  |         attr_reader :comments | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         sig { params(block_node: RuboCop::AST::BlockNode, comments: T::Array[Parser::Source::Comment]).void } | 
					
						
							| 
									
										
										
										
											2018-10-26 19:49:21 +01:00
										 |  |  |         def initialize(block_node, comments) | 
					
						
							|  |  |  |           @block_node = block_node | 
					
						
							|  |  |  |           @comments = comments | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-07 08:23:19 +02:00
										 |  |  |         sig { returns(T::Array[Stanza]) } | 
					
						
							|  |  |  |         def stanzas | 
					
						
							|  |  |  |           return [] unless (block_body = block_node.block_body) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           # If a block only contains one stanza, it is that stanza's direct parent, otherwise | 
					
						
							|  |  |  |           # stanzas are grouped in a nested block and the block is that nested block's parent. | 
					
						
							|  |  |  |           is_stanza = if block_body.begin_block? | 
					
						
							|  |  |  |             ->(node) { node.parent.parent == block_node } | 
					
						
							|  |  |  |           else | 
					
						
							|  |  |  |             ->(node) { node.parent == block_node } | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           @stanzas ||= block_body.each_node | 
					
						
							|  |  |  |                                  .select(&:stanza?) | 
					
						
							|  |  |  |                                  .select(&is_stanza) | 
					
						
							|  |  |  |                                  .map { |node| Stanza.new(node, comments) } | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       # This class wraps the AST block node that represents the entire cask | 
					
						
							|  |  |  |       # definition. It includes various helper methods to aid cops in their | 
					
						
							|  |  |  |       # analysis. | 
					
						
							|  |  |  |       class CaskBlock < StanzaBlock | 
					
						
							|  |  |  |         extend Forwardable | 
					
						
							| 
									
										
										
										
											2018-10-26 19:49:21 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-07 08:23:19 +02:00
										 |  |  |         def cask_node | 
					
						
							|  |  |  |           block_node | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2018-10-26 19:49:21 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         def_delegator :cask_node, :block_body, :cask_body | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def header | 
					
						
							| 
									
										
										
										
											2023-05-07 08:23:19 +02:00
										 |  |  |           @header ||= CaskHeader.new(block_node.method_node) | 
					
						
							| 
									
										
										
										
											2018-10-26 19:49:21 +01:00
										 |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-07 08:23:19 +02:00
										 |  |  |         # TODO: Use `StanzaBlock#stanzas` for all cops, where possible. | 
					
						
							| 
									
										
										
										
											2018-10-26 19:49:21 +01:00
										 |  |  |         def stanzas | 
					
						
							|  |  |  |           return [] unless cask_body | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           @stanzas ||= cask_body.each_node | 
					
						
							|  |  |  |                                 .select(&:stanza?) | 
					
						
							| 
									
										
										
										
											2023-04-12 23:14:43 +01:00
										 |  |  |                                 .map { |node| Stanza.new(node, comments) } | 
					
						
							| 
									
										
										
										
											2018-10-26 19:49:21 +01:00
										 |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def toplevel_stanzas | 
					
						
							| 
									
										
										
										
											2023-03-21 14:43:39 +01:00
										 |  |  |           # If a `cask` block only contains one stanza, it is that stanza's direct parent, | 
					
						
							|  |  |  |           # otherwise stanzas are grouped in a block and `cask` is that block's parent. | 
					
						
							|  |  |  |           is_toplevel_stanza = if cask_body.begin_block? | 
					
						
							|  |  |  |             ->(stanza) { stanza.parent_node.parent.cask_block? } | 
					
						
							|  |  |  |           else | 
					
						
							|  |  |  |             ->(stanza) { stanza.parent_node.cask_block? } | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           @toplevel_stanzas ||= stanzas.select(&is_toplevel_stanza) | 
					
						
							| 
									
										
										
										
											2018-10-26 19:49:21 +01:00
										 |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | end |