| 
									
										
										
										
											2025-02-01 23:54:35 +00:00
										 |  |  | # typed: strict | 
					
						
							| 
									
										
										
										
											2020-08-28 22:19:10 -04:00
										 |  |  | # frozen_string_literal: true | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-20 10:22:39 -08:00
										 |  |  | require "rubocops/extend/formula_cop" | 
					
						
							| 
									
										
										
										
											2020-08-28 22:19:10 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | module RuboCop | 
					
						
							|  |  |  |   module Cop | 
					
						
							|  |  |  |     module FormulaAudit | 
					
						
							| 
									
										
										
										
											2020-11-05 17:17:03 -05:00
										 |  |  |       # This cop audits `deprecate!` and `disable!` dates. | 
					
						
							| 
									
										
										
										
											2023-02-20 18:10:59 -08:00
										 |  |  |       class DeprecateDisableDate < FormulaCop | 
					
						
							| 
									
										
										
										
											2021-01-12 11:14:12 +11:00
										 |  |  |         extend AutoCorrector | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-07 15:18:29 -04:00
										 |  |  |         sig { override.params(formula_nodes: FormulaNodes).void } | 
					
						
							|  |  |  |         def audit_formula(formula_nodes) | 
					
						
							|  |  |  |           body_node = formula_nodes.body_node | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-28 22:19:10 -04:00
										 |  |  |           [:deprecate!, :disable!].each do |method| | 
					
						
							|  |  |  |             node = find_node_method_by_name(body_node, method) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             next if node.nil? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             date(node) do |date_node| | 
					
						
							|  |  |  |               Date.iso8601(string_content(date_node)) | 
					
						
							|  |  |  |             rescue ArgumentError | 
					
						
							|  |  |  |               fixed_date_string = Date.parse(string_content(date_node)).iso8601 | 
					
						
							|  |  |  |               offending_node(date_node) | 
					
						
							| 
									
										
										
										
											2021-01-12 11:14:12 +11:00
										 |  |  |               problem "Use `#{fixed_date_string}` to comply with ISO 8601" do |corrector| | 
					
						
							|  |  |  |                 corrector.replace(date_node.source_range, "\"#{fixed_date_string}\"") | 
					
						
							|  |  |  |               end | 
					
						
							| 
									
										
										
										
											2020-08-28 22:19:10 -04:00
										 |  |  |             end | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def_node_search :date, <<~EOS | 
					
						
							|  |  |  |           (pair (sym :date) $str) | 
					
						
							|  |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 17:17:03 -05:00
										 |  |  |       # This cop audits `deprecate!` and `disable!` reasons. | 
					
						
							| 
									
										
										
										
											2023-02-20 18:10:59 -08:00
										 |  |  |       class DeprecateDisableReason < FormulaCop | 
					
						
							| 
									
										
										
										
											2021-01-12 11:14:12 +11:00
										 |  |  |         extend AutoCorrector | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-11 10:29:21 +01:00
										 |  |  |         PUNCTUATION_MARKS = %w[. ! ?].freeze | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-07 15:18:29 -04:00
										 |  |  |         sig { override.params(formula_nodes: FormulaNodes).void } | 
					
						
							|  |  |  |         def audit_formula(formula_nodes) | 
					
						
							|  |  |  |           body_node = formula_nodes.body_node | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-28 22:19:10 -04:00
										 |  |  |           [:deprecate!, :disable!].each do |method| | 
					
						
							|  |  |  |             node = find_node_method_by_name(body_node, method) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             next if node.nil? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-23 18:15:48 +01:00
										 |  |  |             reason_found = T.let(false, T::Boolean) | 
					
						
							| 
									
										
										
										
											2020-08-28 22:19:10 -04:00
										 |  |  |             reason(node) do |reason_node| | 
					
						
							|  |  |  |               reason_found = true | 
					
						
							| 
									
										
										
										
											2020-08-28 22:49:26 -04:00
										 |  |  |               next if reason_node.sym_type? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-28 22:19:10 -04:00
										 |  |  |               offending_node(reason_node) | 
					
						
							|  |  |  |               reason_string = string_content(reason_node) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-12 11:14:12 +11:00
										 |  |  |               if reason_string.start_with?("it ") | 
					
						
							|  |  |  |                 problem "Do not start the reason with `it`" do |corrector| | 
					
						
							| 
									
										
										
										
											2025-02-01 23:54:35 +00:00
										 |  |  |                   corrector.replace(T.must(@offensive_node).source_range, "\"#{reason_string[3..]}\"") | 
					
						
							| 
									
										
										
										
											2021-01-12 11:14:12 +11:00
										 |  |  |                 end | 
					
						
							|  |  |  |               end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |               if PUNCTUATION_MARKS.include?(reason_string[-1]) | 
					
						
							|  |  |  |                 problem "Do not end the reason with a punctuation mark" do |corrector| | 
					
						
							| 
									
										
										
										
											2025-02-01 23:54:35 +00:00
										 |  |  |                   corrector.replace(T.must(@offensive_node).source_range, "\"#{reason_string.chop}\"") | 
					
						
							| 
									
										
										
										
											2021-01-12 11:14:12 +11:00
										 |  |  |                 end | 
					
						
							|  |  |  |               end | 
					
						
							| 
									
										
										
										
											2020-08-28 22:19:10 -04:00
										 |  |  |             end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             next if reason_found | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             case method | 
					
						
							|  |  |  |             when :deprecate! | 
					
						
							|  |  |  |               problem 'Add a reason for deprecation: `deprecate! because: "..."`' | 
					
						
							|  |  |  |             when :disable! | 
					
						
							|  |  |  |               problem 'Add a reason for disabling: `disable! because: "..."`' | 
					
						
							|  |  |  |             end | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def_node_search :reason, <<~EOS | 
					
						
							| 
									
										
										
										
											2020-08-28 22:49:26 -04:00
										 |  |  |           (pair (sym :because) ${str sym}) | 
					
						
							| 
									
										
										
										
											2020-08-28 22:19:10 -04:00
										 |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | end |