Skip to content

Instantly share code, notes, and snippets.

@JoshCheek
Created October 26, 2017 18:22
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JoshCheek/4d603504b99392a856e7f1726f7bd195 to your computer and use it in GitHub Desktop.
Save JoshCheek/4d603504b99392a856e7f1726f7bd195 to your computer and use it in GitHub Desktop.
Trey Typing
module TreyTyping
def method_added(name)
m = instance_method(name)
file, line = m.source_location
types = RubyVM::InstructionSequence.disasm(m).lines.slice_before { |l| l['checkkeyword'] }.to_a.drop(1).map { |lines| Object.const_get lines[3].split.last[1..-1] }
return if file == __FILE__ && line == 1+__LINE__
define_method name do |*args, **kws|
kws.zip(types).each do |(name, value), type|
next if type === value
raise TypeError, "#{name} should be a #{type}"
end
m.bind(self).call(*args, **kws)
end
end
end
require 'rspec/autorun'
RSpec.describe 'Trey Typing' do
extend TreyTyping
def omg(a: Integer, b: String)
[a, b]
end
it 'can invoke the method with the correct types' do
expect(omg a: 1, b: 'abc').to eq [1, 'abc']
end
it 'explodes if the wrong type is passed' do
expect { omg a: '1', b: 'abc' }.to raise_error TypeError
end
end
# >> ..
# >>
# >> Finished in 0.00471 seconds (files took 0.09411 seconds to load)
# >> 2 examples, 0 failures
# >>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment