From 05b716613b89e376e032ad66d5118b37fb93fcc7 Mon Sep 17 00:00:00 2001 From: Issy Long Date: Sun, 3 Mar 2024 22:21:29 +0000 Subject: [PATCH 1/5] Convert the `utils/tty` RBI generator to a Tapioca compiler - The preferred way of doing RBI generation is via Tapioca. So I am trying to stop being intimidated by it, by learning how it works. - This is very WIP still, currently failing with the following message because the `module` name is missing in the generated RBI file. ``` There are parse errors in the generated RBI files. Errors: sorbet/rbi/dsl/tty.rbi:8: unexpected token tNL (2001) sorbet/rbi/dsl/tty.rbi:64: unexpected token "end" (2001) ``` --- Library/Homebrew/dev-cmd/typecheck.rb | 1 - .../Homebrew/sorbet/custom_generators/tty.rb | 31 --------- Library/Homebrew/sorbet/rbi/dsl/tty.rbi | 64 +++++++++++++++++++ .../Homebrew/sorbet/tapioca/compilers/tty.rb | 31 +++++++++ Library/Homebrew/utils/tty.rbi | 60 ----------------- 5 files changed, 95 insertions(+), 92 deletions(-) delete mode 100644 Library/Homebrew/sorbet/custom_generators/tty.rb create mode 100644 Library/Homebrew/sorbet/rbi/dsl/tty.rbi create mode 100644 Library/Homebrew/sorbet/tapioca/compilers/tty.rb delete mode 100644 Library/Homebrew/utils/tty.rbi diff --git a/Library/Homebrew/dev-cmd/typecheck.rb b/Library/Homebrew/dev-cmd/typecheck.rb index 4789caa7df101..0072ddf8c4f0f 100644 --- a/Library/Homebrew/dev-cmd/typecheck.rb +++ b/Library/Homebrew/dev-cmd/typecheck.rb @@ -51,7 +51,6 @@ def run tapioca_args = args.update_all? ? ["--all"] : [] ohai "Updating homegrown RBI files..." - safe_system "bundle", "exec", "ruby", "sorbet/custom_generators/tty.rb" safe_system "bundle", "exec", "ruby", "sorbet/custom_generators/env_config.rb" ohai "Updating Tapioca RBI files..." diff --git a/Library/Homebrew/sorbet/custom_generators/tty.rb b/Library/Homebrew/sorbet/custom_generators/tty.rb deleted file mode 100644 index 3cab79d2d2311..0000000000000 --- a/Library/Homebrew/sorbet/custom_generators/tty.rb +++ /dev/null @@ -1,31 +0,0 @@ -# typed: true -# frozen_string_literal: true - -require_relative "../../global" -require_relative "../../env_config" -require_relative "../../utils/tty" - -File.open("#{File.dirname(__FILE__)}/../../utils/tty.rbi", "w") do |file| - file.write(<<~RUBY) - # typed: strict - - module Tty - RUBY - - dynamic_methods = Tty::COLOR_CODES.keys + Tty::STYLE_CODES.keys + Tty::SPECIAL_CODES.keys - methods = Tty.methods(false).sort.select { |method| dynamic_methods.include?(method) } - - methods.each do |method| - return_type = (method.to_s.end_with?("?") ? T::Boolean : String) - signature = "sig { returns(#{return_type}) }" - - file.write(<<-RUBY) - #{signature} - def self.#{method}; end - RUBY - - file.write("\n") if methods.last != method - end - - file.write("end\n") -end diff --git a/Library/Homebrew/sorbet/rbi/dsl/tty.rbi b/Library/Homebrew/sorbet/rbi/dsl/tty.rbi new file mode 100644 index 0000000000000..84b763a6d5569 --- /dev/null +++ b/Library/Homebrew/sorbet/rbi/dsl/tty.rbi @@ -0,0 +1,64 @@ +# typed: true + +# DO NOT EDIT MANUALLY +# This is an autogenerated file for dynamic methods in `Tty`. +# Please instead update this file by running `bin/tapioca dsl Tty`. + +module + sig { returns(String) } + def blue; end + + sig { returns(String) } + def bold; end + + sig { returns(String) } + def cyan; end + + sig { returns(String) } + def default; end + + sig { returns(String) } + def down; end + + sig { returns(String) } + def erase_char; end + + sig { returns(String) } + def erase_line; end + + sig { returns(String) } + def green; end + + sig { returns(String) } + def italic; end + + sig { returns(String) } + def left; end + + sig { returns(String) } + def magenta; end + + sig { returns(String) } + def no_underline; end + + sig { returns(String) } + def red; end + + sig { returns(String) } + def reset; end + + sig { returns(String) } + def right; end + + sig { returns(String) } + def strikethrough; end + + sig { returns(String) } + def underline; end + + sig { returns(String) } + def up; end + + sig { returns(String) } + def yellow; end +end diff --git a/Library/Homebrew/sorbet/tapioca/compilers/tty.rb b/Library/Homebrew/sorbet/tapioca/compilers/tty.rb new file mode 100644 index 0000000000000..73239a5b055db --- /dev/null +++ b/Library/Homebrew/sorbet/tapioca/compilers/tty.rb @@ -0,0 +1,31 @@ +# typed: strict +# frozen_string_literal: true + +require_relative "../../../global" +require_relative "../../../utils/tty" + +module Tapioca + module Compilers + class Tty < Tapioca::Dsl::Compiler + ConstantType = type_member { { fixed: Module } } + + sig { override.returns(T::Enumerable[Module]) } + def self.gather_constants + [::Tty] + end + + sig { override.void } + def decorate + root.create_path(constant) do |klass| + dynamic_methods = ::Tty::COLOR_CODES.keys + ::Tty::STYLE_CODES.keys + ::Tty::SPECIAL_CODES.keys + methods = ::Tty.methods(false).sort.select { |method| dynamic_methods.include?(method) } + + methods.each do |method| + return_type = (method.to_s.end_with?("?") ? "T::Boolean" : "String") + klass.create_method(method.to_s, return_type:) + end + end + end + end + end +end diff --git a/Library/Homebrew/utils/tty.rbi b/Library/Homebrew/utils/tty.rbi deleted file mode 100644 index b92c259d6db26..0000000000000 --- a/Library/Homebrew/utils/tty.rbi +++ /dev/null @@ -1,60 +0,0 @@ -# typed: strict - -module Tty - sig { returns(String) } - def self.blue; end - - sig { returns(String) } - def self.bold; end - - sig { returns(String) } - def self.cyan; end - - sig { returns(String) } - def self.default; end - - sig { returns(String) } - def self.down; end - - sig { returns(String) } - def self.erase_char; end - - sig { returns(String) } - def self.erase_line; end - - sig { returns(String) } - def self.green; end - - sig { returns(String) } - def self.italic; end - - sig { returns(String) } - def self.left; end - - sig { returns(String) } - def self.magenta; end - - sig { returns(String) } - def self.no_underline; end - - sig { returns(String) } - def self.red; end - - sig { returns(String) } - def self.reset; end - - sig { returns(String) } - def self.right; end - - sig { returns(String) } - def self.strikethrough; end - - sig { returns(String) } - def self.underline; end - - sig { returns(String) } - def self.up; end - - sig { returns(String) } - def self.yellow; end -end From 769547e7e39acd0b1919f131a4302fd343c6a38f Mon Sep 17 00:00:00 2001 From: Douglas Eichelberger Date: Fri, 15 Mar 2024 21:10:08 -0700 Subject: [PATCH 2/5] Use create_module instead --- Library/Homebrew/sorbet/rbi/dsl/tty.rbi | 2 +- Library/Homebrew/sorbet/tapioca/compilers/tty.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Library/Homebrew/sorbet/rbi/dsl/tty.rbi b/Library/Homebrew/sorbet/rbi/dsl/tty.rbi index 84b763a6d5569..f57d3260c1d1c 100644 --- a/Library/Homebrew/sorbet/rbi/dsl/tty.rbi +++ b/Library/Homebrew/sorbet/rbi/dsl/tty.rbi @@ -4,7 +4,7 @@ # This is an autogenerated file for dynamic methods in `Tty`. # Please instead update this file by running `bin/tapioca dsl Tty`. -module +module Tty sig { returns(String) } def blue; end diff --git a/Library/Homebrew/sorbet/tapioca/compilers/tty.rb b/Library/Homebrew/sorbet/tapioca/compilers/tty.rb index 73239a5b055db..7ad90277d035a 100644 --- a/Library/Homebrew/sorbet/tapioca/compilers/tty.rb +++ b/Library/Homebrew/sorbet/tapioca/compilers/tty.rb @@ -16,13 +16,13 @@ def self.gather_constants sig { override.void } def decorate - root.create_path(constant) do |klass| + root.create_module(constant.name) do |mod| dynamic_methods = ::Tty::COLOR_CODES.keys + ::Tty::STYLE_CODES.keys + ::Tty::SPECIAL_CODES.keys methods = ::Tty.methods(false).sort.select { |method| dynamic_methods.include?(method) } methods.each do |method| return_type = (method.to_s.end_with?("?") ? "T::Boolean" : "String") - klass.create_method(method.to_s, return_type:) + mod.create_method(method.to_s, return_type:) end end end From bbf5825d5455640e54f077fbef604e2dc2b80206 Mon Sep 17 00:00:00 2001 From: Issy Long Date: Sun, 17 Mar 2024 20:28:54 +0000 Subject: [PATCH 3/5] Appease RuboCop --- Library/Homebrew/sorbet/tapioca/compilers/tty.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Library/Homebrew/sorbet/tapioca/compilers/tty.rb b/Library/Homebrew/sorbet/tapioca/compilers/tty.rb index 7ad90277d035a..04aaa15b33bd2 100644 --- a/Library/Homebrew/sorbet/tapioca/compilers/tty.rb +++ b/Library/Homebrew/sorbet/tapioca/compilers/tty.rb @@ -7,11 +7,16 @@ module Tapioca module Compilers class Tty < Tapioca::Dsl::Compiler + # FIXME: Enable cop again when https://github.com/sorbet/sorbet/issues/3532 is fixed. + # rubocop:disable Style/MutableConstant + # This should be a module whose singleton class contains RuboCop::AST::NodePattern::Macros, + # but I don't know how to express that in Sorbet. ConstantType = type_member { { fixed: Module } } + # rubocop:enable Style/MutableConstant sig { override.returns(T::Enumerable[Module]) } def self.gather_constants - [::Tty] + [::Tty] end sig { override.void } From e4a1f3319ca6ab08d32717b1c06d91203db66133 Mon Sep 17 00:00:00 2001 From: Issy Long Date: Fri, 29 Mar 2024 00:37:49 +0000 Subject: [PATCH 4/5] Tty methods are class methods --- Library/Homebrew/sorbet/rbi/dsl/tty.rbi | 78 ++++++++++--------- .../Homebrew/sorbet/tapioca/compilers/tty.rb | 2 +- 2 files changed, 41 insertions(+), 39 deletions(-) diff --git a/Library/Homebrew/sorbet/rbi/dsl/tty.rbi b/Library/Homebrew/sorbet/rbi/dsl/tty.rbi index f57d3260c1d1c..c8b83d867a431 100644 --- a/Library/Homebrew/sorbet/rbi/dsl/tty.rbi +++ b/Library/Homebrew/sorbet/rbi/dsl/tty.rbi @@ -5,60 +5,62 @@ # Please instead update this file by running `bin/tapioca dsl Tty`. module Tty - sig { returns(String) } - def blue; end + class << self + sig { returns(String) } + def blue; end - sig { returns(String) } - def bold; end + sig { returns(String) } + def bold; end - sig { returns(String) } - def cyan; end + sig { returns(String) } + def cyan; end - sig { returns(String) } - def default; end + sig { returns(String) } + def default; end - sig { returns(String) } - def down; end + sig { returns(String) } + def down; end - sig { returns(String) } - def erase_char; end + sig { returns(String) } + def erase_char; end - sig { returns(String) } - def erase_line; end + sig { returns(String) } + def erase_line; end - sig { returns(String) } - def green; end + sig { returns(String) } + def green; end - sig { returns(String) } - def italic; end + sig { returns(String) } + def italic; end - sig { returns(String) } - def left; end + sig { returns(String) } + def left; end - sig { returns(String) } - def magenta; end + sig { returns(String) } + def magenta; end - sig { returns(String) } - def no_underline; end + sig { returns(String) } + def no_underline; end - sig { returns(String) } - def red; end + sig { returns(String) } + def red; end - sig { returns(String) } - def reset; end + sig { returns(String) } + def reset; end - sig { returns(String) } - def right; end + sig { returns(String) } + def right; end - sig { returns(String) } - def strikethrough; end + sig { returns(String) } + def strikethrough; end - sig { returns(String) } - def underline; end + sig { returns(String) } + def underline; end - sig { returns(String) } - def up; end + sig { returns(String) } + def up; end - sig { returns(String) } - def yellow; end + sig { returns(String) } + def yellow; end + end end diff --git a/Library/Homebrew/sorbet/tapioca/compilers/tty.rb b/Library/Homebrew/sorbet/tapioca/compilers/tty.rb index 04aaa15b33bd2..1f59873d115e1 100644 --- a/Library/Homebrew/sorbet/tapioca/compilers/tty.rb +++ b/Library/Homebrew/sorbet/tapioca/compilers/tty.rb @@ -27,7 +27,7 @@ def decorate methods.each do |method| return_type = (method.to_s.end_with?("?") ? "T::Boolean" : "String") - mod.create_method(method.to_s, return_type:) + mod.create_method(method.to_s, return_type:, class_method: true) end end end From db39e939b015c722a66e99a714b62a5f9fc2f864 Mon Sep 17 00:00:00 2001 From: Issy Long Date: Sat, 30 Mar 2024 13:07:16 +0000 Subject: [PATCH 5/5] Apply suggestions from code review --- Library/Homebrew/sorbet/tapioca/compilers/tty.rb | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/Library/Homebrew/sorbet/tapioca/compilers/tty.rb b/Library/Homebrew/sorbet/tapioca/compilers/tty.rb index 1f59873d115e1..c24e60e386750 100644 --- a/Library/Homebrew/sorbet/tapioca/compilers/tty.rb +++ b/Library/Homebrew/sorbet/tapioca/compilers/tty.rb @@ -2,32 +2,26 @@ # frozen_string_literal: true require_relative "../../../global" -require_relative "../../../utils/tty" +require "utils/tty" module Tapioca module Compilers class Tty < Tapioca::Dsl::Compiler # FIXME: Enable cop again when https://github.com/sorbet/sorbet/issues/3532 is fixed. # rubocop:disable Style/MutableConstant - # This should be a module whose singleton class contains RuboCop::AST::NodePattern::Macros, - # but I don't know how to express that in Sorbet. ConstantType = type_member { { fixed: Module } } # rubocop:enable Style/MutableConstant sig { override.returns(T::Enumerable[Module]) } - def self.gather_constants - [::Tty] - end + def self.gather_constants = [::Tty] sig { override.void } def decorate - root.create_module(constant.name) do |mod| + root.create_module(T.must(constant.name)) do |mod| dynamic_methods = ::Tty::COLOR_CODES.keys + ::Tty::STYLE_CODES.keys + ::Tty::SPECIAL_CODES.keys - methods = ::Tty.methods(false).sort.select { |method| dynamic_methods.include?(method) } - methods.each do |method| - return_type = (method.to_s.end_with?("?") ? "T::Boolean" : "String") - mod.create_method(method.to_s, return_type:, class_method: true) + dynamic_methods.each do |method| + mod.create_method(method.to_s, return_type: "String", class_method: true) end end end