# typed: strict # frozen_string_literal: true module Tapioca module Commands class Todo < CommandWithoutTracker include SorbetHelper DEPRECATION_MESSAGE = T.let(<<~DEPRECATION, String) The `todo` command is deprecated and will be removed in a future release. If your project is still missing type definitions for constants, try the following: 1. Regenerate gem RBIs by running `bin/tapioca gem --all` and `bin/tapioca annotations` 2. Generate RBIs for DSLs by running `bin/tapioca dsl` 3. If the missing constants are defined in files that a gem does not load by default, manually require those files in `sorbet/tapioca/require.rb` and regenerate gem RBIs 4. Manually create an RBI shim defining the missing constants DEPRECATION sig do params( todo_file: String, file_header: T::Boolean, ).void end def initialize(todo_file:, file_header:) @todo_file = todo_file @file_header = file_header super() end sig { void } def run_with_deprecation say(DEPRECATION_MESSAGE, :red) say("") run end private sig { override.void } def execute say("Finding all unresolved constants, this may take a few seconds... ") # Clean all existing unresolved constants before regenerating the list # so Sorbet won't grab them as already resolved. File.delete(@todo_file) if File.exist?(@todo_file) constants = unresolved_constants if constants.empty? say("Nothing to do", :green) return end say("Done", :green) contents = rbi(constants, command: default_command(:todo)) create_file(@todo_file, contents.string, verbose: false) name = set_color(@todo_file, :yellow, :bold) say("\nAll unresolved constants have been written to #{name}.", [:green, :bold]) say("Please review changes and commit them.", [:green, :bold]) end sig { params(constants: T::Array[String], command: String).returns(RBI::File) } def rbi(constants, command:) file = RBI::File.new if @file_header file.comments << RBI::Comment.new("DO NOT EDIT MANUALLY") file.comments << RBI::Comment.new("This is an autogenerated file for unresolved constants.") file.comments << RBI::Comment.new("Please instead update this file by running `#{command}`.") file.comments << RBI::BlankLine.new end file.comments << RBI::Comment.new("typed: false") constants.each do |name| file << RBI::Module.new(name) end file end sig { returns(T::Array[String]) } def unresolved_constants # Taken from https://github.com/sorbet/sorbet/blob/master/gems/sorbet/lib/todo-rbi.rb sorbet("--print=missing-constants", "--quiet", "--stdout-hup-hack", "--no-error-count") .out .strip .each_line .filter_map do |line| next if line.include?("<") line.strip .gsub(/T\.class_of\(([:\w]+)\)/, '\1') # Turn T.class_of(Foo)::Bar into Foo::Bar end .sort end end end end