Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Steep::RakeTask #995

Merged
merged 2 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,24 @@ Steep implements some of the Language Server Protocol features.

Other LSP supporting tools may work with Steep where it starts the server as `steep langserver`.

## Rake Tasks

Steep comes with a set of configurable Rake tasks.

```ruby
# Rakefile

require "steep/rake_task"
Steep::RakeTask.new do |t|
t.check.severity_level = :error
t.watch.verbose
end

task default: [:steep]
```

Use `bundle exec rake -T` to see all available tasks.

## Development

After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
Expand Down
127 changes: 127 additions & 0 deletions lib/steep/rake_task.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
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