Skip to content

Commit

Permalink
Add Steep::RakeTask to run Steep CLI commands
Browse files Browse the repository at this point in the history
  • Loading branch information
Aesthetikx committed Feb 3, 2024
1 parent fecbd20 commit b74545a
Show file tree
Hide file tree
Showing 2 changed files with 214 additions and 0 deletions.
128 changes: 128 additions & 0 deletions lib/steep/rake_task.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
require "rake"
require "rake/tasklib"

module Steep
# Provides Rake tasks for running Steep commands.
#
# require "steep/rake_task"
# Steep::RakeTask.new do |t|
# t.check.severity_level = :error
# t.watch.verbose
# end
class RakeTask < Rake::TaskLib
attr_accessor :name

def self.available_commands
require "steep/cli"

skipped_commands = %i[langserver checkfile]

Steep::CLI.available_commands - skipped_commands
end

def initialize(name = :steep, cli_runner = default_cli_runner)
super()

@name = name

configuration = TaskConfiguration.new

yield configuration if block_given?

define_tasks(configuration, cli_runner)
end

private

# :nodoc:
class TaskConfiguration
def initialize
@commands = {}
end

def method_missing(command)
if respond_to?(command)
@commands[command] ||= CommandConfiguration.new
else
super
end
end

def respond_to_missing?(name, include_private = false)
RakeTask.available_commands.include?(name) || super
end

def options(command)
@commands[command]&.to_a || []
end
end

# :nodoc:
class CommandConfiguration
def initialize
@options = []
end

def method_missing(name, value = nil)
@options << "--#{name.to_s.gsub(/_/, '-').gsub(/=/, '')}"
@options << value.to_s unless value.nil?
end

def respond_to_missing?(_name)
true
end

def to_a
@options
end
end

def default_cli_runner
lambda do |arguments|
require "steep"

cli = Steep::CLI.new(
stdout: $stdout,
stdin: $stdin,
stderr: $stderr,
argv: arguments
)

cli.run
end
end

def define_tasks(configuration, cli_runner)
namespace name do
RakeTask.available_commands.each do |command|
desc "Run steep #{command}"

task command do |_, args|
configured_options = configuration.options(command)

argv = [
command.to_s,
*configured_options,
*args.extras
]

result = cli_runner[argv]

raise "Steep failed" if result.nonzero?
end
end

desc "Run steep help"
task "help" do
arguments = ["--help"]

cli_runner[arguments]
end
end

# Default steep task to steep:check
desc "Run steep check" unless ::Rake.application.last_description
task name => ["#{name}:check"]
end
end
end
86 changes: 86 additions & 0 deletions test/rake_task_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
require_relative "test_helper"

require_relative "../lib/steep/rake_task"

require "minitest/mock"

class RakeTaskTest < Minitest::Test
def test_task_configuration
configuration = Steep::RakeTask::TaskConfiguration.new

configuration.check.severity_level = :error
configuration.watch.verbose

assert_raises(NoMethodError) do
configuration.missing_command.verbose
end

assert_equal ["--severity-level", "error"], configuration.options(:check)
assert_equal ["--verbose"], configuration.options(:watch)
assert_equal [], configuration.options(:stats)
end

def test_define_task_with_options
cli = mock_cli(expecting: %w[check --severity-level error])

setup_rake_tasks!(cli) do |task|
task.check.severity_level = :error
end

Rake::Task["steep:check"].invoke
end

def test_rake_arguments
cli = mock_cli(expecting: %w[check --severity-level error])

setup_rake_tasks!(cli)

Rake::Task["steep:check"].invoke("--severity-level", "error")
end

def test_help_task
cli = mock_cli(expecting: %w[--help])

setup_rake_tasks!(cli)

Rake::Task["steep:help"].invoke
end

def test_default_task
cli = mock_cli(expecting: %w[check --verbose])

setup_rake_tasks!(cli) do |task|
task.check.verbose
end

Rake::Task["steep"].invoke
end

def test_skipped_commands
setup_rake_tasks!

assert Rake::Task.task_defined?("steep:help")

refute Rake::Task.task_defined?("steep:langserver")
end

private

def setup_rake_tasks!(cli_runner = nil, &block)
Rake::Task.clear

Steep::RakeTask.new(:steep, cli_runner, &block)
end

def mock_cli(expecting:)
cli = Minitest::Mock.new

cli.expect(:run, nil, [expecting])

lambda do |arguments|
cli.run(arguments)

0
end
end
end

0 comments on commit b74545a

Please sign in to comment.