class Tapioca::Cli
def __print_version
def __print_version puts "Tapioca v#{Tapioca::VERSION}" end
def addon_mode!
def addon_mode! @addon_mode = true end
def annotations
def annotations if !options[:netrc] && options[:netrc_file] raise Thor::Error, set_color("Options `--no-netrc` and `--netrc-file` can't be used together", :bold, :red) end command = Commands::Annotations.new( central_repo_root_uris: options[:sources], auth: options[:auth], netrc_file: netrc_file(options), typed_overrides: options[:typed_overrides], ) command.run end
def check_shims
def check_shims command = Commands::CheckShims.new( gem_rbi_dir: options[:gem_rbi_dir], dsl_rbi_dir: options[:dsl_rbi_dir], shim_rbi_dir: options[:shim_rbi_dir], annotations_rbi_dir: options[:annotations_rbi_dir], todo_rbi_file: options[:todo_rbi_file], payload: options[:payload], number_of_workers: options[:workers], ) command.run end
def configure
def configure command = Commands::Configure.new( sorbet_config: SORBET_CONFIG_FILE, tapioca_config: options[:config], default_postrequire: options[:postrequire], ) command.run end
def dsl(*constant_or_paths)
def dsl(*constant_or_paths) set_environment(options) # Assume anything starting with a capital letter or colon is a class, otherwise a path constants, paths = constant_or_paths.partition { |c| c =~ /\A[A-Z:]/ } command_args = { requested_constants: constants, requested_paths: paths.map { |p| Pathname.new(p) }, outpath: Pathname.new(options[:outdir]), only: options[:only], exclude: options[:exclude], file_header: options[:file_header], tapioca_path: TAPIOCA_DIR, skip_constant: options[:skip_constant], quiet: options[:quiet], verbose: options[:verbose], number_of_workers: options[:workers], rbi_formatter: rbi_formatter(options), app_root: options[:app_root], halt_upon_load_error: options[:halt_upon_load_error], compiler_options: options[:compiler_options], lsp_addon: self.class.addon_mode, } command = if options[:verify] Commands::DslVerify.new(**command_args) elsif options[:list_compilers] Commands::DslCompilerList.new(**command_args) else Commands::DslGenerate.new(**command_args) end command.run end
def exit_on_failure?
def exit_on_failure? !@addon_mode end
def gem(*gems)
def gem(*gems) set_environment(options) all = options[:all] verify = options[:verify] include_dependencies = options[:include_dependencies] raise MalformattedArgumentError, "Options '--all' and '--verify' are mutually exclusive" if all && verify if gems.empty? raise MalformattedArgumentError, "Option '--include-dependencies' must be provided with gems" if include_dependencies else raise MalformattedArgumentError, "Option '--all' must be provided without any other arguments" if all raise MalformattedArgumentError, "Option '--verify' must be provided without any other arguments" if verify end command_args = { gem_names: all ? [] : gems, exclude: options[:exclude], include_dependencies: options[:include_dependencies], prerequire: options[:prerequire], postrequire: options[:postrequire], typed_overrides: options[:typed_overrides], outpath: Pathname.new(options[:outdir]), file_header: options[:file_header], include_doc: options[:doc], include_loc: options[:loc], include_exported_rbis: options[:exported_gem_rbis], number_of_workers: options[:workers], auto_strictness: options[:auto_strictness], dsl_dir: options[:dsl_dir], rbi_formatter: rbi_formatter(options), halt_upon_load_error: options[:halt_upon_load_error], lsp_addon: options[:lsp_addon], } command = if verify Commands::GemVerify.new(**command_args) elsif !gems.empty? || all Commands::GemGenerate.new(**command_args) else Commands::GemSync.new(**command_args) end command.run end
def init
def init # We need to make sure that trackers stay enabled until the `gem` command is invoked Runtime::Trackers.with_trackers_enabled do invoke(:configure) invoke(:annotations) invoke(:gem) end # call the command directly to skip deprecation warning Commands::Todo.new( todo_file: DEFAULT_TODO_FILE, file_header: true, ).run print_init_next_steps end
def print_init_next_steps
def print_init_next_steps say(<<~OUTPUT) #{set_color("This project is now set up for use with Sorbet and Tapioca", :bold)} The sorbet/ folder should exist and look something like this: ├── config # Default options to be passed to Sorbet on every run └── rbi/ ├── annotations/ # Type definitions pulled from the rbi-central repository ├── gems/ # Autogenerated type definitions for your gems └── todo.rbi # Constants which were still missing after RBI generation └── tapioca/ ├── config.yml # Default options to be passed to Tapioca └── require.rb # A file where you can make requires from gems that might be needed for gem RBI generation Please check this folder into version control. #{set_color("🤔 What's next", :bold)} 1. Many Ruby applications use metaprogramming DSLs to dynamically generate constants and methods. To generate type definitions for any DSLs in your application, run: #{set_color("bin/tapioca dsl", :cyan)} 2. Check whether the constants in the #{set_color("sorbet/rbi/todo.rbi", :cyan)} file actually exist in your project. It is possible that some of these constants are typos, and leaving them in #{set_color("todo.rbi", :cyan)} will hide errors in your application. Ideally, you should be able to remove all definitions from this file and delete it. 3. Typecheck your project: #{set_color("bundle exec srb tc", :cyan)} There should not be any typechecking errors. 4. Upgrade a file marked "#{set_color("# typed: false", :cyan)}" to "#{set_color("# typed: true", :cyan)}". Then, run: #{set_color("bundle exec srb tc", :cyan)} and try to fix any errors. You can use Spoom to bump files for you: #{set_color("spoom bump --from false --to true", :cyan)} To learn more about Spoom, visit: #{set_color("https://github.com/Shopify/spoom", :cyan)} 5. Add signatures to your methods with #{set_color("sig", :cyan)}. To learn how, read: #{set_color("https://sorbet.org/docs/sigs", :cyan)} #{set_color("Documentation", :bold)} We recommend skimming these docs to get a feel for how to use Sorbet: - Gradual Type Checking: #{set_color("https://sorbet.org/docs/gradual", :cyan)} - Enabling Static Checks: #{set_color("https://sorbet.org/docs/static", :cyan)} - RBI Files: #{set_color("https://sorbet.org/docs/rbi", :cyan)} OUTPUT end
def require
def require command = Commands::Require.new( requires_path: options[:postrequire], sorbet_config_path: SORBET_CONFIG_FILE, ) command.run end
def todo
def todo command = Commands::Todo.new( todo_file: options[:todo_file], file_header: options[:file_header], ) command.run_with_deprecation end