mirror of
https://github.com/Homebrew/brew.git
synced 2025-07-14 16:09:03 +08:00
Migrate from Sorbet DSL plugins to Parlour
This commit is contained in:
parent
0d8caf722b
commit
07239d267c
10
Library/Homebrew/.parlour
Normal file
10
Library/Homebrew/.parlour
Normal file
@ -0,0 +1,10 @@
|
||||
parser: false
|
||||
|
||||
output_file:
|
||||
rbi: sorbet/rbi/parlour.rbi
|
||||
|
||||
relative_requires:
|
||||
- sorbet/parlour.rb
|
||||
|
||||
plugins:
|
||||
Attr: {}
|
@ -24,6 +24,7 @@ gem "simplecov-cobertura", require: false
|
||||
gem "warning", require: false
|
||||
|
||||
group :sorbet, optional: true do
|
||||
gem "parlour", require: false
|
||||
gem "rspec-sorbet", require: false
|
||||
gem "sorbet", require: false
|
||||
gem "sorbet-runtime", require: false
|
||||
|
@ -188,6 +188,7 @@ DEPENDENCIES
|
||||
mechanize
|
||||
minitest
|
||||
parallel_tests
|
||||
parlour
|
||||
patchelf
|
||||
plist
|
||||
ronn
|
||||
|
@ -61,6 +61,7 @@ module Homebrew
|
||||
|
||||
ohai "Updating Tapioca RBI files..."
|
||||
system "bundle", "exec", "tapioca", "sync", "--exclude", *excluded_gems
|
||||
system "bundle", "exec", "parlour"
|
||||
system "bundle", "exec", "srb", "rbi", "hidden-definitions"
|
||||
system "bundle", "exec", "srb", "rbi", "todo"
|
||||
|
||||
|
6
Library/Homebrew/extend/hash_validator.rbi
Normal file
6
Library/Homebrew/extend/hash_validator.rbi
Normal file
@ -0,0 +1,6 @@
|
||||
# typed: strict
|
||||
|
||||
class Hash
|
||||
sig { params(valid_keys: T.untyped).void }
|
||||
def assert_valid_keys!(*valid_keys); end
|
||||
end
|
9
Library/Homebrew/extend/time.rbi
Normal file
9
Library/Homebrew/extend/time.rbi
Normal file
@ -0,0 +1,9 @@
|
||||
# typed: strict
|
||||
|
||||
class Time
|
||||
sig { returns(T.any(Integer, Float)) }
|
||||
def remaining; end
|
||||
|
||||
sig { returns(T.any(Integer, Float)) }
|
||||
def remaining!; end
|
||||
end
|
@ -6,6 +6,3 @@
|
||||
|
||||
--ignore
|
||||
/test/.gem
|
||||
|
||||
--dsl-plugins
|
||||
sorbet/triggers.yml
|
||||
|
42
Library/Homebrew/sorbet/parlour.rb
Normal file
42
Library/Homebrew/sorbet/parlour.rb
Normal file
@ -0,0 +1,42 @@
|
||||
# frozen_string_literal: true
|
||||
# typed: true
|
||||
|
||||
require_relative "../warnings"
|
||||
Warnings.ignore :parser_syntax do
|
||||
require "parser/current"
|
||||
end
|
||||
|
||||
module Homebrew
|
||||
module Parlour
|
||||
extend T::Sig
|
||||
|
||||
ROOT_DIR = T.let(Pathname(__dir__).parent.realpath.freeze, Pathname)
|
||||
|
||||
sig { returns(T::Array[Parser::AST::Node]) }
|
||||
def self.ast_list
|
||||
@@ast_list ||= begin
|
||||
ast_list = []
|
||||
parser = Parser::CurrentRuby.new
|
||||
|
||||
ROOT_DIR.find do |path|
|
||||
Find.prune if path.directory? && %w[sorbet shims test vendor].any? { |subdir| path == ROOT_DIR/subdir }
|
||||
|
||||
Find.prune if path.file? && path.extname != ".rb"
|
||||
|
||||
next unless path.file?
|
||||
|
||||
buffer = Parser::Source::Buffer.new(path, source: path.read)
|
||||
|
||||
parser.reset
|
||||
ast = parser.parse(buffer)
|
||||
ast_list << ast if ast
|
||||
end
|
||||
|
||||
ast_list
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require "parlour"
|
||||
require_relative "parlour/attr"
|
110
Library/Homebrew/sorbet/parlour/attr.rb
Normal file
110
Library/Homebrew/sorbet/parlour/attr.rb
Normal file
@ -0,0 +1,110 @@
|
||||
# frozen_string_literal: true
|
||||
# typed: strict
|
||||
|
||||
class Attr < Parlour::Plugin
|
||||
sig { override.params(root: Parlour::RbiGenerator::Namespace).void }
|
||||
def generate(root)
|
||||
tree = T.let([], T::Array[T.untyped])
|
||||
Homebrew::Parlour.ast_list.each do |node|
|
||||
tree += find_custom_attr(node)
|
||||
end
|
||||
process_custom_attr(tree, root)
|
||||
end
|
||||
|
||||
sig { override.returns(T.nilable(String)) }
|
||||
def strictness
|
||||
return "strict"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
sig { params(node: Parser::AST::Node, list: T::Array[String]).returns(T::Array[String]) }
|
||||
def traverse_module_name(node, list = [])
|
||||
parent, name = node.children
|
||||
list = traverse_module_name(parent, list) if parent
|
||||
list << name.to_s
|
||||
list
|
||||
end
|
||||
|
||||
sig { params(node: T.nilable(Parser::AST::Node)).returns(T.nilable(String)) }
|
||||
def extract_module_name(node)
|
||||
return if node.nil?
|
||||
|
||||
traverse_module_name(node).join("::")
|
||||
end
|
||||
|
||||
sig { params(node: Parser::AST::Node).returns(T::Array[T.untyped]) }
|
||||
def find_custom_attr(node)
|
||||
tree = T.let([], T::Array[T.untyped])
|
||||
children = node.children.dup
|
||||
|
||||
if node.type == :begin
|
||||
children.each do |child|
|
||||
subtree = find_custom_attr(child)
|
||||
tree += subtree unless subtree.empty?
|
||||
end
|
||||
elsif node.type == :sclass
|
||||
subtree = find_custom_attr(node.children[1])
|
||||
return tree if subtree.empty?
|
||||
|
||||
tree << [:sclass, subtree]
|
||||
elsif node.type == :class || node.type == :module
|
||||
element = []
|
||||
if node.type == :class
|
||||
element << :class
|
||||
element << extract_module_name(children.shift)
|
||||
element << extract_module_name(children.shift)
|
||||
elsif node.type == :module
|
||||
element << :module
|
||||
element << extract_module_name(children.shift)
|
||||
end
|
||||
|
||||
body = children.shift
|
||||
return tree if body.nil?
|
||||
|
||||
subtree = find_custom_attr(body)
|
||||
return tree if subtree.empty?
|
||||
|
||||
element << subtree
|
||||
tree << element
|
||||
elsif node.type == :send && children.shift.nil?
|
||||
method_name = children.shift
|
||||
if method_name == :attr_rw || method_name == :attr_predicate
|
||||
children.each do |name_node|
|
||||
tree << [method_name, name_node.children.first.to_s]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
tree
|
||||
end
|
||||
|
||||
sig { params(tree: T::Array[T.untyped], namespace: Parlour::RbiGenerator::Namespace, sclass: T::Boolean).void }
|
||||
def process_custom_attr(tree, namespace, sclass: false)
|
||||
tree.each do |node|
|
||||
type = node.shift
|
||||
case type
|
||||
when :sclass
|
||||
process_custom_attr(node.shift, namespace, sclass: true)
|
||||
when :class
|
||||
class_namespace = namespace.create_class(node.shift, superclass: node.shift)
|
||||
process_custom_attr(node.shift, class_namespace)
|
||||
when :module
|
||||
module_namespace = namespace.create_module(node.shift)
|
||||
process_custom_attr(node.shift, module_namespace)
|
||||
when :attr_rw
|
||||
name = node.shift
|
||||
name = "self.#{name}" if sclass
|
||||
namespace.create_method(name, parameters: [
|
||||
Parlour::RbiGenerator::Parameter.new("arg", type: "T.untyped", default: "T.unsafe(nil)")
|
||||
], return_type: "T.untyped")
|
||||
when :attr_predicate
|
||||
name = node.shift
|
||||
name = "self.#{name}" if sclass
|
||||
namespace.create_method(name, return_type: "T::Boolean")
|
||||
else
|
||||
raise "Malformed tree."
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -1,13 +0,0 @@
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
source = ARGV[5]
|
||||
|
||||
source.scan(/:([^?]+\?)/).flatten.each do |method|
|
||||
puts <<~RUBY
|
||||
# typed: strict
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def #{method}; end
|
||||
RUBY
|
||||
end
|
@ -1,13 +0,0 @@
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
source = ARGV[5]
|
||||
|
||||
source.scan(/:([^\s,]+)/).flatten.each do |method|
|
||||
puts <<~RUBY
|
||||
# typed: strict
|
||||
|
||||
sig { params(arg: T.untyped).returns(T.untyped) }
|
||||
def #{method}(arg = T.unsafe(nil)); end
|
||||
RUBY
|
||||
end
|
@ -1,17 +0,0 @@
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
source = ARGV[5]
|
||||
|
||||
match = source.match(/\s*def_delegator\s+.*:(?<method>[^:]+)\s*\Z/m)
|
||||
|
||||
raise if match.nil?
|
||||
|
||||
method = match[:method]
|
||||
|
||||
puts <<~RUBY
|
||||
# typed: strict
|
||||
|
||||
sig {params(arg0: T.untyped, blk: T.untyped).returns(T.untyped)}
|
||||
def #{method}(*arg0, &blk); end
|
||||
RUBY
|
@ -1,17 +0,0 @@
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
source = ARGV[5]
|
||||
|
||||
symbols = source.scan(/:[^\s,]+/)
|
||||
|
||||
_, *methods = symbols.map { |s| s.delete_prefix(":") }
|
||||
|
||||
methods.each do |method|
|
||||
puts <<~RUBY
|
||||
# typed: strict
|
||||
|
||||
sig {params(arg0: T.untyped, blk: T.untyped).returns(T.untyped)}
|
||||
def #{method}(*arg0, &blk); end
|
||||
RUBY
|
||||
end
|
@ -1,21 +0,0 @@
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
source = ARGV[5]
|
||||
|
||||
methods = if (single = source[/delegate\s+([^:]+):\s+/, 1])
|
||||
[single]
|
||||
else
|
||||
multiple = source[/delegate\s+\[(.*?)\]\s+=>\s+/m, 1]
|
||||
non_comments = multiple.gsub(/\#.*$/, "")
|
||||
non_comments.scan(/:([^:,\s]+)/).flatten
|
||||
end
|
||||
|
||||
methods.each do |method|
|
||||
puts <<~RUBY
|
||||
# typed: strict
|
||||
|
||||
sig {params(arg0: T.untyped, blk: T.untyped).returns(T.untyped)}
|
||||
def #{method}(*arg0, &blk); end
|
||||
RUBY
|
||||
end
|
@ -1,43 +0,0 @@
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
source = ARGV[5]
|
||||
|
||||
case source[/\Ausing\s+(.*)\Z/, 1]
|
||||
when "Magic"
|
||||
puts <<-RUBY
|
||||
# typed: strict
|
||||
|
||||
class ::Pathname
|
||||
sig { returns(String) }
|
||||
def magic_number; end
|
||||
|
||||
sig { returns(String) }
|
||||
def file_type; end
|
||||
|
||||
sig { returns(T::Array[String]) }
|
||||
def zipinfo; end
|
||||
end
|
||||
RUBY
|
||||
when "HashValidator"
|
||||
puts <<-RUBY
|
||||
# typed: strict
|
||||
|
||||
class ::Hash
|
||||
sig { params(valid_keys: T.untyped).void }
|
||||
def assert_valid_keys!(*valid_keys); end
|
||||
end
|
||||
RUBY
|
||||
when "TimeRemaining"
|
||||
puts <<-RUBY
|
||||
# typed: strict
|
||||
|
||||
class ::Time
|
||||
sig { returns(T.any(Integer, Float)) }
|
||||
def remaining; end
|
||||
|
||||
sig { returns(T.any(Integer, Float)) }
|
||||
def remaining!; end
|
||||
end
|
||||
RUBY
|
||||
end
|
164
Library/Homebrew/sorbet/rbi/parlour.rbi
Normal file
164
Library/Homebrew/sorbet/rbi/parlour.rbi
Normal file
@ -0,0 +1,164 @@
|
||||
# typed: strict
|
||||
module Homebrew
|
||||
class Cleanup
|
||||
sig { returns(T::Boolean) }
|
||||
def dry_run?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def scrub?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def prune?; end
|
||||
end
|
||||
end
|
||||
|
||||
module Debrew
|
||||
sig { returns(T::Boolean) }
|
||||
def self.active?; end
|
||||
end
|
||||
|
||||
class Formula
|
||||
sig { params(arg: T.untyped).returns(T.untyped) }
|
||||
def self.desc(arg = T.unsafe(nil)); end
|
||||
|
||||
sig { params(arg: T.untyped).returns(T.untyped) }
|
||||
def self.homepage(arg = T.unsafe(nil)); end
|
||||
|
||||
sig { params(arg: T.untyped).returns(T.untyped) }
|
||||
def self.revision(arg = T.unsafe(nil)); end
|
||||
|
||||
sig { params(arg: T.untyped).returns(T.untyped) }
|
||||
def self.version_scheme(arg = T.unsafe(nil)); end
|
||||
end
|
||||
|
||||
class FormulaInstaller
|
||||
sig { returns(T::Boolean) }
|
||||
def installed_as_dependency?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def installed_on_request?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def show_summary_heading?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def show_header?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def force_bottle?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def ignore_deps?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def only_deps?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def interactive?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def git?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def force?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def keep_tmp?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def verbose?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def debug?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def quiet?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def hold_locks?; end
|
||||
end
|
||||
|
||||
class Requirement
|
||||
sig { params(arg: T.untyped).returns(T.untyped) }
|
||||
def self.fatal(arg = T.unsafe(nil)); end
|
||||
|
||||
sig { params(arg: T.untyped).returns(T.untyped) }
|
||||
def self.cask(arg = T.unsafe(nil)); end
|
||||
|
||||
sig { params(arg: T.untyped).returns(T.untyped) }
|
||||
def self.download(arg = T.unsafe(nil)); end
|
||||
end
|
||||
|
||||
class BottleSpecification
|
||||
sig { params(arg: T.untyped).returns(T.untyped) }
|
||||
def rebuild(arg = T.unsafe(nil)); end
|
||||
end
|
||||
|
||||
class SystemCommand
|
||||
sig { returns(T::Boolean) }
|
||||
def sudo?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def print_stdout?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def print_stderr?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def must_succeed?; end
|
||||
end
|
||||
|
||||
module Cask
|
||||
class Audit
|
||||
sig { returns(T::Boolean) }
|
||||
def appcast?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def new_cask?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def strict?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def online?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def token_conflicts?; end
|
||||
end
|
||||
|
||||
class DSL
|
||||
class Caveats < Base
|
||||
sig { returns(T::Boolean) }
|
||||
def discontinued?; end
|
||||
end
|
||||
end
|
||||
|
||||
class Installer
|
||||
sig { returns(T::Boolean) }
|
||||
def binaries?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def force?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def skip_cask_deps?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def require_sha?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def reinstall?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def upgrade?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def verbose?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def installed_as_dependency?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def quarantine?; end
|
||||
end
|
||||
end
|
@ -1,10 +0,0 @@
|
||||
ruby_extra_args:
|
||||
- --disable-gems
|
||||
|
||||
triggers:
|
||||
using: sorbet/plugins/using.rb
|
||||
attr_predicate: sorbet/plugins/attr_predicate.rb
|
||||
attr_rw: sorbet/plugins/attr_rw.rb
|
||||
def_delegator: sorbet/plugins/def_delegator.rb
|
||||
def_delegators: sorbet/plugins/def_delegators.rb
|
||||
delegate: sorbet/plugins/delegate.rb
|
@ -3,3 +3,14 @@
|
||||
module UnpackStrategy
|
||||
include Kernel
|
||||
end
|
||||
|
||||
class Pathname
|
||||
sig { returns(String) }
|
||||
def magic_number; end
|
||||
|
||||
sig { returns(String) }
|
||||
def file_type; end
|
||||
|
||||
sig { returns(T::Array[String]) }
|
||||
def zipinfo; end
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user