This commit is contained in:
Douglas Eichelberger 2024-01-30 22:48:36 -08:00
parent 352f57d753
commit b2dc842238
31 changed files with 465 additions and 21 deletions

View File

@ -60,6 +60,7 @@ group :tests, optional: true do
gem "simplecov-cobertura", require: false
end
group :typecheck, optional: true do
gem "method_source", require: false
gem "parlour", require: false
gem "sorbet-static-and-runtime", require: false
gem "spoom", require: false

View File

@ -176,6 +176,7 @@ DEPENDENCIES
bootsnap
byebug
json_schemer
method_source
minitest
parallel_tests
parlour

View File

@ -45,6 +45,7 @@ module Homebrew
HOMEBREW_LIBRARY_PATH.cd do
if update
safe_system "bundle", "exec", "tapioca", "dsl"
excluded_gems = [
"json", # RBI file is already provided by Sorbet
]

View File

@ -2,4 +2,5 @@
module RuboCop::Cop::Cask::CaskHelp
requires_ancestor { RuboCop::Cop::Base }
# requires_ancestor { RuboCop::Cop::CommentsHelp }
end

View File

@ -0,0 +1 @@
**/*.rbi linguist-generated=true

View File

@ -0,0 +1,10 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `RuboCop::Cop::Cask::Variables`.
# Please instead update this file by running `bin/tapioca dsl RuboCop::Cop::Cask::Variables`.
class RuboCop::Cop::Cask::Variables
sig { params(node: T.untyped, block: T.untyped).returns(T.untyped) }
def variable_assignment(*node, &block); end
end

View File

@ -0,0 +1,10 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `RuboCop::Cop::FormulaAudit::ComponentsOrder`.
# Please instead update this file by running `bin/tapioca dsl RuboCop::Cop::FormulaAudit::ComponentsOrder`.
class RuboCop::Cop::FormulaAudit::ComponentsOrder
sig { params(node: RuboCop::AST::Node, kwargs: T.untyped, block: T.untyped).returns(T.untyped) }
def depends_on_node?(*node, **kwargs, &block); end
end

View File

@ -0,0 +1,34 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `RuboCop::Cop::FormulaAudit::DependencyOrder`.
# Please instead update this file by running `bin/tapioca dsl RuboCop::Cop::FormulaAudit::DependencyOrder`.
class RuboCop::Cop::FormulaAudit::DependencyOrder
sig { params(node: T.untyped, block: T.untyped).returns(T.untyped) }
def build_with_dependency_node(*node, &block); end
sig { params(node: T.untyped, block: T.untyped).returns(T::Boolean) }
def buildtime_dependency?(*node, &block); end
sig { params(node: T.untyped, block: T.untyped).returns(T.untyped) }
def dependency_name_node(*node, &block); end
sig { params(node: RuboCop::AST::Node, kwargs: T.untyped, block: T.untyped).returns(T.untyped) }
def depends_on_node?(*node, **kwargs, &block); end
sig { params(node: T.untyped, block: T.untyped).returns(T::Boolean) }
def negate_normal_dependency?(*node, &block); end
sig { params(node: T.untyped, block: T.untyped).returns(T::Boolean) }
def optional_dependency?(*node, &block); end
sig { params(node: T.untyped, block: T.untyped).returns(T::Boolean) }
def recommended_dependency?(*node, &block); end
sig { params(node: T.untyped, block: T.untyped).returns(T::Boolean) }
def test_dependency?(*node, &block); end
sig { params(node: RuboCop::AST::Node, kwargs: T.untyped, block: T.untyped).returns(T.untyped) }
def uses_from_macos_node?(*node, **kwargs, &block); end
end

View File

@ -0,0 +1,10 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `RuboCop::Cop::FormulaAudit::DeprecateDisableDate`.
# Please instead update this file by running `bin/tapioca dsl RuboCop::Cop::FormulaAudit::DeprecateDisableDate`.
class RuboCop::Cop::FormulaAudit::DeprecateDisableDate
sig { params(node: T.untyped, block: T.untyped).returns(T.untyped) }
def date(*node, &block); end
end

View File

@ -0,0 +1,10 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `RuboCop::Cop::FormulaAudit::DeprecateDisableReason`.
# Please instead update this file by running `bin/tapioca dsl RuboCop::Cop::FormulaAudit::DeprecateDisableReason`.
class RuboCop::Cop::FormulaAudit::DeprecateDisableReason
sig { params(node: T.untyped, block: T.untyped).returns(T.untyped) }
def reason(*node, &block); end
end

View File

@ -0,0 +1,13 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `RuboCop::Cop::FormulaAudit::GenerateCompletionsDSL`.
# Please instead update this file by running `bin/tapioca dsl RuboCop::Cop::FormulaAudit::GenerateCompletionsDSL`.
class RuboCop::Cop::FormulaAudit::GenerateCompletionsDSL
sig { params(node: T.untyped, block: T.untyped).returns(T.untyped) }
def correctable_shell_completion_node(*node, &block); end
sig { params(node: T.untyped, block: T.untyped).returns(T.untyped) }
def shell_completion_node(*node, &block); end
end

View File

@ -0,0 +1,10 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `RuboCop::Cop::FormulaAudit::GitUrls`.
# Please instead update this file by running `bin/tapioca dsl RuboCop::Cop::FormulaAudit::GitUrls`.
class RuboCop::Cop::FormulaAudit::GitUrls
sig { params(node: RuboCop::AST::Node, kwargs: T.untyped, block: T.untyped).returns(T.untyped) }
def url_has_revision?(*node, **kwargs, &block); end
end

View File

@ -0,0 +1,10 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `RuboCop::Cop::FormulaAudit::Licenses`.
# Please instead update this file by running `bin/tapioca dsl RuboCop::Cop::FormulaAudit::Licenses`.
class RuboCop::Cop::FormulaAudit::Licenses
sig { params(node: RuboCop::AST::Node, kwargs: T.untyped, block: T.untyped).returns(T.untyped) }
def license_exception?(*node, **kwargs, &block); end
end

View File

@ -0,0 +1,22 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `RuboCop::Cop::FormulaAudit::Miscellaneous`.
# Please instead update this file by running `bin/tapioca dsl RuboCop::Cop::FormulaAudit::Miscellaneous`.
class RuboCop::Cop::FormulaAudit::Miscellaneous
sig { params(node: T.untyped, block: T.untyped).returns(T.untyped) }
def conditional_dependencies(*node, &block); end
sig { params(node: RuboCop::AST::Node, kwargs: T.untyped, block: T.untyped).returns(T.untyped) }
def destructure_hash(*node, **kwargs, &block); end
sig { params(node: T.untyped, block: T.untyped).returns(T.untyped) }
def formula_path_strings(*node, &block); end
sig { params(node: RuboCop::AST::Node, kwargs: T.untyped, block: T.untyped).returns(T.untyped) }
def hash_dep(*node, **kwargs, &block); end
sig { params(node: T.untyped, block: T.untyped).returns(T::Boolean) }
def languageNodeModule?(*node, &block); end
end

View File

@ -0,0 +1,10 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `RuboCop::Cop::FormulaAudit::OptionDeclarations`.
# Please instead update this file by running `bin/tapioca dsl RuboCop::Cop::FormulaAudit::OptionDeclarations`.
class RuboCop::Cop::FormulaAudit::OptionDeclarations
sig { params(node: T.untyped, block: T.untyped).returns(T.untyped) }
def depends_on_build_with(*node, &block); end
end

View File

@ -0,0 +1,10 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `RuboCop::Cop::FormulaAudit::Patches`.
# Please instead update this file by running `bin/tapioca dsl RuboCop::Cop::FormulaAudit::Patches`.
class RuboCop::Cop::FormulaAudit::Patches
sig { params(node: T.untyped, block: T.untyped).returns(T::Boolean) }
def patch_data?(*node, &block); end
end

View File

@ -0,0 +1,10 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `RuboCop::Cop::FormulaAudit::Test`.
# Please instead update this file by running `bin/tapioca dsl RuboCop::Cop::FormulaAudit::Test`.
class RuboCop::Cop::FormulaAudit::Test
sig { params(node: T.untyped, block: T.untyped).returns(T.untyped) }
def test_calls(*node, &block); end
end

View File

@ -0,0 +1,10 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `RuboCop::Cop::FormulaAudit::Text`.
# Please instead update this file by running `bin/tapioca dsl RuboCop::Cop::FormulaAudit::Text`.
class RuboCop::Cop::FormulaAudit::Text
sig { params(node: T.untyped, block: T.untyped).returns(T.untyped) }
def prefix_path(*node, &block); end
end

View File

@ -0,0 +1,10 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `RuboCop::Cop::FormulaAuditStrict::GitUrls`.
# Please instead update this file by running `bin/tapioca dsl RuboCop::Cop::FormulaAuditStrict::GitUrls`.
class RuboCop::Cop::FormulaAuditStrict::GitUrls
sig { params(node: RuboCop::AST::Node, kwargs: T.untyped, block: T.untyped).returns(T.untyped) }
def url_has_tag?(*node, **kwargs, &block); end
end

View File

@ -0,0 +1,13 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `RuboCop::Cop::FormulaAuditStrict::Text`.
# Please instead update this file by running `bin/tapioca dsl RuboCop::Cop::FormulaAuditStrict::Text`.
class RuboCop::Cop::FormulaAuditStrict::Text
sig { params(node: T.untyped, block: T.untyped).returns(T.untyped) }
def interpolated_share_path_starts_with(*node, &block); end
sig { params(node: T.untyped, block: T.untyped).returns(T.untyped) }
def share_path_starts_with(*node, &block); end
end

View File

@ -0,0 +1,19 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `RuboCop::Cop::FormulaCop`.
# Please instead update this file by running `bin/tapioca dsl RuboCop::Cop::FormulaCop`.
class RuboCop::Cop::FormulaCop
sig { params(node: T.untyped, block: T.untyped).returns(T::Boolean) }
def dependency_name_hash_match?(*node, &block); end
sig { params(node: T.untyped, block: T.untyped).returns(T::Boolean) }
def dependency_type_hash_match?(*node, &block); end
sig { params(node: T.untyped, block: T.untyped).returns(T::Boolean) }
def required_dependency?(*node, &block); end
sig { params(node: T.untyped, block: T.untyped).returns(T::Boolean) }
def required_dependency_name?(*node, &block); end
end

View File

@ -0,0 +1,10 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `RuboCop::Cop::Homebrew::Blank`.
# Please instead update this file by running `bin/tapioca dsl RuboCop::Cop::Homebrew::Blank`.
class RuboCop::Cop::Homebrew::Blank
sig { params(node: RuboCop::AST::Node, kwargs: T.untyped, block: T.untyped).returns(T.untyped) }
def nil_or_empty?(*node, **kwargs, &block); end
end

View File

@ -0,0 +1,13 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `RuboCop::Cop::Homebrew::CompactBlank`.
# Please instead update this file by running `bin/tapioca dsl RuboCop::Cop::Homebrew::CompactBlank`.
class RuboCop::Cop::Homebrew::CompactBlank
sig { params(node: RuboCop::AST::Node, kwargs: T.untyped, block: T.untyped).returns(T.untyped) }
def reject_with_block?(*node, **kwargs, &block); end
sig { params(node: RuboCop::AST::Node, kwargs: T.untyped, block: T.untyped).returns(T.untyped) }
def reject_with_block_pass?(*node, **kwargs, &block); end
end

View File

@ -0,0 +1,10 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `RuboCop::Cop::Homebrew::MoveToExtendOS`.
# Please instead update this file by running `bin/tapioca dsl RuboCop::Cop::Homebrew::MoveToExtendOS`.
class RuboCop::Cop::Homebrew::MoveToExtendOS
sig { params(node: RuboCop::AST::Node, kwargs: T.untyped, block: T.untyped).returns(T.untyped) }
def os_check?(*node, **kwargs, &block); end
end

View File

@ -0,0 +1,10 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `RuboCop::Cop::Homebrew::NegateInclude`.
# Please instead update this file by running `bin/tapioca dsl RuboCop::Cop::Homebrew::NegateInclude`.
class RuboCop::Cop::Homebrew::NegateInclude
sig { params(node: RuboCop::AST::Node, kwargs: T.untyped, block: T.untyped).returns(T.untyped) }
def negate_include_call?(*node, **kwargs, &block); end
end

View File

@ -0,0 +1,13 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `RuboCop::Cop::Homebrew::Presence`.
# Please instead update this file by running `bin/tapioca dsl RuboCop::Cop::Homebrew::Presence`.
class RuboCop::Cop::Homebrew::Presence
sig { params(node: RuboCop::AST::Node, kwargs: T.untyped, block: T.untyped).returns(T.untyped) }
def redundant_negative_receiver_and_other(*node, **kwargs, &block); end
sig { params(node: RuboCop::AST::Node, kwargs: T.untyped, block: T.untyped).returns(T.untyped) }
def redundant_receiver_and_other(*node, **kwargs, &block); end
end

View File

@ -0,0 +1,10 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `RuboCop::Cop::Homebrew::Present`.
# Please instead update this file by running `bin/tapioca dsl RuboCop::Cop::Homebrew::Present`.
class RuboCop::Cop::Homebrew::Present
sig { params(node: RuboCop::AST::Node, kwargs: T.untyped, block: T.untyped).returns(T.untyped) }
def exists_and_not_empty?(*node, **kwargs, &block); end
end

View File

@ -0,0 +1,10 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `RuboCop::Cop::Homebrew::SafeNavigationWithBlank`.
# Please instead update this file by running `bin/tapioca dsl RuboCop::Cop::Homebrew::SafeNavigationWithBlank`.
class RuboCop::Cop::Homebrew::SafeNavigationWithBlank
sig { params(node: RuboCop::AST::Node, kwargs: T.untyped, block: T.untyped).returns(T.untyped) }
def safe_navigation_blank_in_conditional?(*node, **kwargs, &block); end
end

View File

@ -0,0 +1,28 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `RuboCop::Cop::OnSystemConditionalsHelper`.
# Please instead update this file by running `bin/tapioca dsl RuboCop::Cop::OnSystemConditionalsHelper`.
module RuboCop::Cop::OnSystemConditionalsHelper
sig { params(node: T.untyped, block: T.untyped).returns(T.untyped) }
def hardware_cpu_search(*node, &block); end
sig { params(node: T.untyped, block: T.untyped).returns(T.untyped) }
def if_arch_node_search(*node, &block); end
sig { params(node: T.untyped, block: T.untyped).returns(T.untyped) }
def if_base_os_node_search(*node, &block); end
sig { params(node: T.untyped, block: T.untyped).returns(T.untyped) }
def if_macos_version_node_search(*node, &block); end
sig { params(node: T.untyped, block: T.untyped).returns(T.untyped) }
def macos_version_comparison_search(*node, &block); end
sig { params(node: RuboCop::AST::Node, kwargs: T.untyped, block: T.untyped).returns(T.untyped) }
def on_macos_version_method_call(*node, **kwargs, &block); end
sig { params(node: RuboCop::AST::Node, kwargs: T.untyped, block: T.untyped).returns(T.untyped) }
def on_system_method_call(*node, **kwargs, &block); end
end

View File

@ -5035,6 +5035,14 @@ end
module Homebrew
extend ::T::Private::Methods::MethodHooks
extend ::T::Private::Methods::SingletonMethodHooks
extend ::FileUtils::StreamUtils_
end
module HostEnvironmentSimulatorHelper
def in_its_own_process_with(*files); end
end
module HostEnvironmentSimulatorHelper
end
class IO
@ -8431,26 +8439,6 @@ module RuboCop::AST::CollectionNode
def to_sentence(*args, **arg, &block); end
end
class RuboCop::AST::Node
def arch_variable?(param0=T.unsafe(nil)); end
def begin_block?(param0=T.unsafe(nil)); end
def block_args(param0=T.unsafe(nil)); end
def block_body(param0=T.unsafe(nil)); end
def cask_block?(param0=T.unsafe(nil)); end
def key_node(param0=T.unsafe(nil)); end
def method_node(param0=T.unsafe(nil)); end
def on_system_block?(param0=T.unsafe(nil)); end
def val_node(param0=T.unsafe(nil)); end
end
module RuboCop::AST::NodePattern::Sets
SET_ARM_INTEL = ::T.let(nil, ::T.untyped)
SET_BASH_COMPLETION_ZSH_COMPLETION_FISH_COMPLETION = ::T.let(nil, ::T.untyped)
@ -8637,7 +8625,12 @@ end
class RuboCop::Cop::Cask::Variables
include ::RuboCop::Cop::CommentsHelp
def variable_assignment(param0); end
end
class RuboCop::Cop::Cop
def highlights(); end
def messages(); end
end
class RuboCop::Cop::FormulaAudit::ComponentsOrder
@ -8791,6 +8784,56 @@ module RuboCop::Cop::OnSystemConditionalsHelper
def on_system_method_call(param0=T.unsafe(nil)); end
end
module RuboCop::RSpec::ExpectOffense
def expect_correction(correction, loop: T.unsafe(nil), source: T.unsafe(nil)); end
def expect_no_corrections(); end
def expect_no_offenses(source, file=T.unsafe(nil)); end
def expect_offense(source, file=T.unsafe(nil), severity: T.unsafe(nil), chomp: T.unsafe(nil), **replacements); end
def format_offense(source, **replacements); end
def parse_annotations(source, raise_error: T.unsafe(nil), **replacements); end
def parse_processed_source(source, file=T.unsafe(nil)); end
def set_formatter_options(); end
end
class RuboCop::RSpec::ExpectOffense::AnnotatedSource
def ==(other); end
def annotations(); end
def initialize(lines, annotations); end
def lines(); end
def match_annotations?(other); end
def plain_source(); end
def with_offense_annotations(offenses); end
ABBREV = ::T.let(nil, ::T.untyped)
ANNOTATION_PATTERN = ::T.let(nil, ::T.untyped)
end
class RuboCop::RSpec::ExpectOffense::AnnotatedSource
def self.parse(annotated_source); end
end
module RuboCop::RSpec::ExpectOffense
end
class RuboCop::RSpec::ParallelFormatter
def dump_pending(*arg); end
end
class RuboCop::RSpec::ParallelFormatter
end
class RubyLex
def check_code_block(code, tokens=T.unsafe(nil)); end

View File

@ -0,0 +1,81 @@
# typed: strict
# frozen_string_literal: true
require "method_source"
require "rubocop"
require_relative "../../../rubocops"
module Tapioca
module Compilers
class Rubocop < Tapioca::Dsl::Compiler
# FIXME: Enable cop again when https://github.com/sorbet/sorbet/issues/3532 is fixed.
# rubocop:disable Style/MutableConstant
ConstantType = type_member { { fixed: T::Class[T.anything] } }
# rubocop:enable Style/MutableConstant
sig { override.returns(T::Enumerable[Module]) }
def self.gather_constants
[
RuboCop::Cop::Cask::Variables,
RuboCop::Cop::Homebrew::Blank,
RuboCop::Cop::Homebrew::CompactBlank,
RuboCop::Cop::Homebrew::MoveToExtendOS,
RuboCop::Cop::Homebrew::NegateInclude,
RuboCop::Cop::Homebrew::Presence,
RuboCop::Cop::Homebrew::Present,
RuboCop::Cop::Homebrew::SafeNavigationWithBlank,
RuboCop::Cop::FormulaAudit::ComponentsOrder,
RuboCop::Cop::FormulaAudit::DependencyOrder,
RuboCop::Cop::FormulaAudit::DeprecateDisableDate,
RuboCop::Cop::FormulaAudit::DeprecateDisableReason,
RuboCop::Cop::FormulaAudit::Licenses,
RuboCop::Cop::FormulaAudit::OptionDeclarations,
RuboCop::Cop::FormulaAudit::GenerateCompletionsDSL,
RuboCop::Cop::FormulaAudit::GitUrls,
RuboCop::Cop::FormulaAudit::Miscellaneous,
RuboCop::Cop::FormulaAudit::Patches,
RuboCop::Cop::FormulaAudit::Test,
RuboCop::Cop::FormulaAudit::Text,
RuboCop::Cop::FormulaAuditStrict::GitUrls,
RuboCop::Cop::FormulaAuditStrict::Text,
RuboCop::Cop::FormulaCop,
RuboCop::Cop::OnSystemConditionalsHelper,
]
end
sig { override.void }
def decorate
root.create_path(constant) do |klass|
# For each encrypted attribute we find in the class
constant.instance_methods(false).each do |method_name|
source = constant.instance_method(method_name).source.lstrip
# https://www.rubydoc.info/gems/rubocop-ast/RuboCop/AST/NodePattern/Macros
# https://github.com/rubocop/rubocop-ast/blob/master/lib/rubocop/ast/node_pattern.rb
# https://github.com/rubocop/rubocop-ast/blob/master/lib/rubocop/ast/node_pattern/method_definer.rb
if source.start_with?("def_node_matcher")
# https://github.com/Shopify/tapioca/blob/3341a9b/lib/tapioca/rbi_ext/model.rb#L89
klass.create_method(
method_name.to_s,
parameters: [
create_rest_param("node", type: "RuboCop::AST::Node"),
create_kw_rest_param("kwargs", type: "T.untyped"),
create_block_param("block", type: "T.untyped"),
],
return_type: "T.untyped",
)
elsif source.start_with?("def_node_search")
klass.create_method(
method_name.to_s,
parameters: [
create_rest_param("node", type: "T.untyped"),
create_block_param("block", type: "T.untyped"),
],
return_type: method_name.to_s.end_with?("?") ? "T::Boolean" : "T.untyped",
)
end
end
end
end
end
end
end