| 
									
										
										
										
											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 Cop | 
					
						
							|  |  |  |     module Cask | 
					
						
							| 
									
										
										
										
											2023-04-15 22:55:12 +01:00
										 |  |  |       # This cop checks that a cask's stanzas are grouped correctly, including nested within `on_*` blocks. | 
					
						
							| 
									
										
										
										
											2021-06-23 13:23:18 -07:00
										 |  |  |       # @see https://docs.brew.sh/Cask-Cookbook#stanza-order | 
					
						
							| 
									
										
										
										
											2021-01-12 18:25:05 +11:00
										 |  |  |       class StanzaGrouping < Base | 
					
						
							| 
									
										
										
										
											2018-10-26 19:49:21 +01:00
										 |  |  |         extend Forwardable | 
					
						
							| 
									
										
										
										
											2021-01-12 18:25:05 +11:00
										 |  |  |         extend AutoCorrector | 
					
						
							| 
									
										
										
										
											2018-10-26 19:49:21 +01:00
										 |  |  |         include CaskHelp | 
					
						
							|  |  |  |         include RangeHelp | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-12 17:34:03 +01:00
										 |  |  |         MISSING_LINE_MSG = "stanza groups should be separated by a single empty line" | 
					
						
							|  |  |  |         EXTRA_LINE_MSG = "stanzas within the same group should have no lines between them" | 
					
						
							| 
									
										
										
										
											2018-10-26 19:49:21 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         def on_cask(cask_block) | 
					
						
							|  |  |  |           @cask_block = cask_block | 
					
						
							|  |  |  |           @line_ops = {} | 
					
						
							| 
									
										
										
										
											2023-04-12 17:34:03 +01:00
										 |  |  |           cask_stanzas = cask_block.toplevel_stanzas | 
					
						
							|  |  |  |           add_offenses(cask_stanzas) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-07 08:34:13 +02:00
										 |  |  |           return if (on_blocks = on_system_methods(cask_stanzas)).none? | 
					
						
							| 
									
										
										
										
											2023-04-12 17:34:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-15 22:55:12 +01:00
										 |  |  |           on_blocks.map(&:method_node).select(&:block_type?).each do |on_block| | 
					
						
							|  |  |  |             stanzas = inner_stanzas(on_block, processed_source.comments) | 
					
						
							|  |  |  |             add_offenses(stanzas) | 
					
						
							| 
									
										
										
										
											2023-04-12 17:34:03 +01:00
										 |  |  |           end | 
					
						
							| 
									
										
										
										
											2018-10-26 19:49:21 +01:00
										 |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         private | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         attr_reader :cask_block, :line_ops | 
					
						
							| 
									
										
										
										
											2020-05-12 08:32:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-12 19:12:51 +01:00
										 |  |  |         def_delegators :cask_block, :cask_node, :toplevel_stanzas | 
					
						
							| 
									
										
										
										
											2018-10-26 19:49:21 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-12 17:34:03 +01:00
										 |  |  |         def add_offenses(stanzas) | 
					
						
							|  |  |  |           stanzas.each_cons(2) do |stanza, next_stanza| | 
					
						
							| 
									
										
										
										
											2018-10-26 19:49:21 +01:00
										 |  |  |             next unless next_stanza | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if missing_line_after?(stanza, next_stanza) | 
					
						
							|  |  |  |               add_offense_missing_line(stanza) | 
					
						
							|  |  |  |             elsif extra_line_after?(stanza, next_stanza) | 
					
						
							|  |  |  |               add_offense_extra_line(stanza) | 
					
						
							|  |  |  |             end | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def missing_line_after?(stanza, next_stanza) | 
					
						
							|  |  |  |           !(stanza.same_group?(next_stanza) || | 
					
						
							|  |  |  |             empty_line_after?(stanza)) | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def extra_line_after?(stanza, next_stanza) | 
					
						
							|  |  |  |           stanza.same_group?(next_stanza) && | 
					
						
							|  |  |  |             empty_line_after?(stanza) | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def empty_line_after?(stanza) | 
					
						
							|  |  |  |           source_line_after(stanza).empty? | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def source_line_after(stanza) | 
					
						
							|  |  |  |           processed_source[index_of_line_after(stanza)] | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def index_of_line_after(stanza) | 
					
						
							|  |  |  |           stanza.source_range.last_line | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def add_offense_missing_line(stanza) | 
					
						
							|  |  |  |           line_index = index_of_line_after(stanza) | 
					
						
							|  |  |  |           line_ops[line_index] = :insert | 
					
						
							| 
									
										
										
										
											2021-01-12 18:25:05 +11:00
										 |  |  |           add_offense(line_index, message: MISSING_LINE_MSG) do |corrector| | 
					
						
							|  |  |  |             corrector.insert_before(@range, "\n") | 
					
						
							|  |  |  |           end | 
					
						
							| 
									
										
										
										
											2018-10-26 19:49:21 +01:00
										 |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def add_offense_extra_line(stanza) | 
					
						
							|  |  |  |           line_index = index_of_line_after(stanza) | 
					
						
							|  |  |  |           line_ops[line_index] = :remove | 
					
						
							| 
									
										
										
										
											2021-01-12 18:25:05 +11:00
										 |  |  |           add_offense(line_index, message: EXTRA_LINE_MSG) do |corrector| | 
					
						
							|  |  |  |             corrector.remove(@range) | 
					
						
							|  |  |  |           end | 
					
						
							| 
									
										
										
										
											2018-10-26 19:49:21 +01:00
										 |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def add_offense(line_index, message:) | 
					
						
							|  |  |  |           line_length = [processed_source[line_index].size, 1].max | 
					
						
							| 
									
										
										
										
											2021-01-12 18:25:05 +11:00
										 |  |  |           @range = source_range(processed_source.buffer, line_index + 1, 0, | 
					
						
							|  |  |  |                                 line_length) | 
					
						
							| 
									
										
										
										
											2024-03-07 16:20:20 +00:00
										 |  |  |           super(@range, message:) | 
					
						
							| 
									
										
										
										
											2018-10-26 19:49:21 +01:00
										 |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | end |