delorean_lang 0.5.4 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: afc7142d7683c1fe4d606a86dd7c46eff3ae672b1eb58db13cb587c18b9ea741
4
- data.tar.gz: a522e77939cbcaa4b8592980ced9281179a07e171fe3e34b69adba13661a8215
3
+ metadata.gz: 2c6e040929f0803bd19bee9c0cd459a1a1bdcbdc20e99da3998a2e8c7f0ef1d3
4
+ data.tar.gz: 175ad860916a349b6a7bfe493e17a4e6c18a7eaaf3ce5625e7a71117f49581fa
5
5
  SHA512:
6
- metadata.gz: 03b53dcf912b0311f12151e6fa189e797f767205cd36d6aac6547d58ab6fad6cfbe6905766caae199c15d4898360829a2249379d61634fec98062fc33753b8ae
7
- data.tar.gz: d21c189ed7f03b98cc5c21525a1c031b4a6d43477291744a7016e75f411ca9aad5cafe4c2b87451059036438d5c60d6c14fc9a94fd703be7f902b802dfbe2fe2
6
+ metadata.gz: 51d8f5e885171313517eab09ea2536bfb807aae2fde1e450ccce5ffabf4b3250dfebd84384f32a67856d6eaa00fc8b8c56cd15ec2c9d7b07f7a48e84495e994d
7
+ data.tar.gz: 9896fef50b9852c7347048e5db5d4bb4412a78beb218d46117b0c805e8a9eccc3cb63aada6b9a04abf042d0357ea2e05977b9ab25e8f46acd662ef283c24b44e
data/.rubocop.yml CHANGED
@@ -17,8 +17,7 @@ Style/StringLiterals:
17
17
  Metrics/LineLength:
18
18
  Max: 80
19
19
  Exclude:
20
- - 'spec/func_spec.rb'
21
- - 'spec/parse_spec.rb'
20
+ - 'spec/**/*'
22
21
 
23
22
  Metrics/ModuleLength:
24
23
  Max: 100
@@ -78,3 +77,7 @@ Naming/HeredocDelimiterCase:
78
77
 
79
78
  Naming/RescuedExceptionsVariableName:
80
79
  Enabled: false
80
+
81
+ Metrics/ParameterLists:
82
+ Exclude:
83
+ - 'spec/spec_helper.rb'
data/Gemfile CHANGED
@@ -4,8 +4,3 @@ source 'https://rubygems.org'
4
4
 
5
5
  # Specify your gem's dependencies in delorean.gemspec
6
6
  gemspec
7
-
8
- group :development, :test do
9
- gem 'pry'
10
- gem 'rspec-instafail', require: false
11
- end
data/README.md CHANGED
@@ -172,6 +172,10 @@ There are two ways of calling ruby code from delorean. First one is to whitelist
172
172
  method.called_on Enumerable, with: [Integer]
173
173
  end
174
174
 
175
+ ::Delorean::Ruby.whitelist.add_class_method :last do |method|
176
+ method.called_on ActiveRecord::Base, with: [Integer]
177
+ end
178
+
175
179
  ```
176
180
 
177
181
  By default Delorean has some methods whitelisted, such as `length`, `min`, `max`, etc. Those can be found in `/lib/delorean/ruby/whitelists/default`. If you don't want to use defaults, you can override whitelist with and empty one.
data/delorean.gemspec CHANGED
@@ -21,6 +21,7 @@ Gem::Specification.new do |gem|
21
21
  gem.add_dependency 'treetop', '~> 1.5'
22
22
  gem.add_development_dependency 'pry'
23
23
  gem.add_development_dependency 'rspec', '~> 2.1'
24
+ gem.add_development_dependency 'rspec-instafail'
24
25
  gem.add_development_dependency 'rubocop'
25
26
  gem.add_development_dependency 'rubocop-performance'
26
27
  gem.add_development_dependency 'sqlite3', '~> 1.3.10'
data/lib/delorean/base.rb CHANGED
@@ -160,15 +160,16 @@ module Delorean
160
160
  raise "bad method #{method}"
161
161
  end
162
162
 
163
- # FIXME: this is pretty hacky -- should probably merge
164
- # whitelist and SIG mechanisms.
165
163
  if obj.is_a?(Class) || obj.is_a?(Module)
166
- _e[:_engine].parse_check_call_fn(method, args.count, obj)
167
- return obj.send(msg, *args)
164
+ matcher = ::Delorean::Ruby.whitelist.class_method_matcher(
165
+ method_name: msg
166
+ )
167
+ klass = obj
168
+ else
169
+ matcher = ::Delorean::Ruby.whitelist.matcher(method_name: msg)
170
+ klass = obj.class
168
171
  end
169
172
 
170
- matcher = ::Delorean::Ruby.whitelist.matcher(method_name: msg)
171
-
172
173
  raise "no such method #{method}" unless matcher
173
174
 
174
175
  if matcher.match_to?
@@ -177,7 +178,7 @@ module Delorean
177
178
  )
178
179
  end
179
180
 
180
- matcher.match!(klass: obj.class, args: args)
181
+ matcher.match!(klass: klass, args: args)
181
182
 
182
183
  obj.send(msg, *args)
183
184
  end
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Delorean
4
- SIG = '_SIG'.freeze
5
- MOD = 'DELOREAN__'.freeze
6
- POST = '__D'.freeze
4
+ MOD = 'DELOREAN__'
5
+ POST = '__D'
7
6
  end
@@ -202,7 +202,7 @@ module Delorean
202
202
  raise exc.new(msg, @module_name, curr_line)
203
203
  end
204
204
 
205
- def parse_check_call_fn(fn, argcount, class_name = nil)
205
+ def parse_check_call_fn(fn, _argcount, class_name = nil)
206
206
  klass = case class_name
207
207
  when nil
208
208
  @m::BaseClass
@@ -214,20 +214,6 @@ module Delorean
214
214
 
215
215
  err(UndefinedFunctionError, "Function #{fn} not found") unless
216
216
  klass.methods.member? fn.to_sym
217
-
218
- # signature methods must be named FUNCTION_NAME_SIG
219
- sig = "#{fn}#{SIG}".upcase.to_sym
220
-
221
- err(UndefinedFunctionError, "Signature #{sig} not found") unless
222
- klass.constants.member? sig
223
-
224
- min, max = klass.const_get(sig)
225
-
226
- err(BadCallError, "Too many args to #{fn} (#{argcount} > #{max})") if
227
- argcount > max
228
-
229
- err(BadCallError, "Too few args to #{fn} (#{argcount} < #{min})") if
230
- argcount < min
231
217
  end
232
218
 
233
219
  def parser
@@ -2,19 +2,14 @@
2
2
 
3
3
  module Delorean
4
4
  module Functions
5
- def delorean_fn(name, options = {})
6
- define_singleton_method(name) do |*args|
7
- yield(*args)
8
- end
9
-
10
- sig = options[:sig]
5
+ def delorean_fn(name, _options = {}, &block)
6
+ any_args = Delorean::Ruby::Whitelists::Matchers::Arguments::ANYTHING
11
7
 
12
- raise 'no signature' unless sig
8
+ define_singleton_method(name, block)
13
9
 
14
- sig = [sig, sig] if sig.is_a? Integer
15
- raise 'Bad signature' unless sig.is_a?(Array) && (sig.length == 2)
16
-
17
- const_set(name.to_s.upcase + Delorean::SIG, sig)
10
+ ::Delorean::Ruby.whitelist.add_class_method name do |method|
11
+ method.called_on self, with: any_args
12
+ end
18
13
  end
19
14
 
20
15
  # FIXME: IDEA: we just make :cache an argument to delorean_fn.
@@ -400,13 +400,13 @@ eos
400
400
  end
401
401
 
402
402
  if vcode.is_a?(ClassText)
403
+ # FIXME: Do we really need this check here?
403
404
  # ruby class call
404
405
  class_name = vcode.text
405
406
  context.parse_check_call_fn(i.text_value, arg_count, class_name)
406
- "#{class_name}.#{i.text_value}(#{args_str})"
407
- else
408
- "_instance_call(#{vcode}, '#{i.text_value}', [#{args_str}], _e)"
409
407
  end
408
+
409
+ "_instance_call(#{vcode}, '#{i.text_value}', [#{args_str}], _e)"
410
410
  end
411
411
  end
412
412
 
@@ -8,6 +8,7 @@ module Delorean
8
8
  module Whitelists
9
9
  class Base
10
10
  attr_reader :matchers
11
+ attr_reader :class_method_matchers
11
12
 
12
13
  def add_method(method_name, match_to: nil, &block)
13
14
  return method_name_error unless method_name.is_a?(Symbol)
@@ -19,19 +20,48 @@ module Delorean
19
20
  )
20
21
  end
21
22
 
23
+ matcher = matchers[method_name.to_sym]
24
+
25
+ return matcher.extend_matcher(&block) if matcher
26
+
22
27
  matchers[method_name.to_sym] = method_matcher_class.new(
23
28
  method_name: method_name, &block
24
29
  )
25
30
  end
26
31
 
32
+ def add_class_method(method_name, match_to: nil, &block)
33
+ return method_name_error unless method_name.is_a?(Symbol)
34
+ return block_and_match_error if !match_to.nil? && block_given?
35
+
36
+ unless match_to.nil?
37
+ return add_class_matched_method(
38
+ method_name: method_name, match_to: match_to
39
+ )
40
+ end
41
+
42
+ matcher = class_method_matchers[method_name.to_sym]
43
+
44
+ return matcher.extend_matcher(&block) if matcher
45
+
46
+ class_method_matchers[method_name.to_sym] = method_matcher_class.new(
47
+ method_name: method_name, &block
48
+ )
49
+ end
50
+
27
51
  def matcher(method_name:)
28
52
  matchers[method_name.to_sym]
29
53
  end
30
54
 
55
+ def class_method_matcher(method_name:)
56
+ class_method_matchers[method_name.to_sym]
57
+ end
58
+
31
59
  private
32
60
 
33
61
  def initialize
34
62
  @matchers = {}
63
+ @class_method_matchers = {}
64
+
35
65
  initialize_hook
36
66
  end
37
67
 
@@ -39,13 +69,24 @@ module Delorean
39
69
  correct_match_to = match_to.is_a?(String) || match_to.is_a?(Symbol)
40
70
  return wrong_match_to_error unless correct_match_to
41
71
 
42
- matcher = ::Delorean::Ruby::Whitelists::Matchers::Method.new(
72
+ matcher = method_matcher_class.new(
43
73
  method_name: method_name, match_to: match_to.to_sym
44
74
  )
45
75
 
46
76
  matchers[method_name.to_sym] = matcher
47
77
  end
48
78
 
79
+ def add_class_matched_method(method_name:, match_to:)
80
+ correct_match_to = match_to.is_a?(String) || match_to.is_a?(Symbol)
81
+ return wrong_match_to_error unless correct_match_to
82
+
83
+ matcher = method_matcher_class.new(
84
+ method_name: method_name, match_to: match_to.to_sym
85
+ )
86
+
87
+ class_method_matchers[method_name.to_sym] = matcher
88
+ end
89
+
49
90
  def block_and_match_error
50
91
  raise(
51
92
  ::Delorean::Ruby::Whitelists::WhitelistError,
@@ -5,6 +5,8 @@ module Delorean
5
5
  module Whitelists
6
6
  module Matchers
7
7
  class Arguments
8
+ ANYTHING = :_delorean_anything
9
+
8
10
  attr_reader :called_on, :method_name, :with
9
11
 
10
12
  def initialize(called_on:, method_name:, with: [])
@@ -14,6 +16,8 @@ module Delorean
14
16
  end
15
17
 
16
18
  def match!(args:)
19
+ return if with == ANYTHING
20
+
17
21
  raise "too many args to #{method_name}" if args.size > with.size
18
22
 
19
23
  with.each_with_index do |s, i|
@@ -23,6 +23,12 @@ module Delorean
23
23
  )
24
24
 
25
25
  arguments_matchers << matcher
26
+
27
+ # Sort matchers by reversed ancestors chain length, so
28
+ # matcher method would find the closest ancestor in hierarchy
29
+ arguments_matchers.sort_by! do |obj|
30
+ -obj.called_on.ancestors.size
31
+ end
26
32
  end
27
33
 
28
34
  def matcher(klass:)
@@ -42,6 +48,10 @@ module Delorean
42
48
  def match_to?
43
49
  !match_to.nil?
44
50
  end
51
+
52
+ def extend_matcher
53
+ yield self if block_given?
54
+ end
45
55
  end
46
56
  end
47
57
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Delorean
4
- VERSION = '0.5.4'.freeze
4
+ VERSION = '0.6.0'
5
5
  end
data/spec/eval_spec.rb CHANGED
@@ -371,6 +371,83 @@ eoc
371
371
  r.should == 867 + 5309
372
372
  end
373
373
 
374
+ it 'should be able call method defined in a parent or matched to' do
375
+ engine.parse defn(
376
+ 'A:',
377
+ ' b = DeloreanFunctionsChildClass.test_fn',
378
+ ' c = DeloreanFunctionsChildClass.test_fn2',
379
+ ' d = DifferentClassSameMethod.test_fn2',
380
+ ' e = DifferentClassSameMethod.match_to_test_fn2',
381
+ )
382
+
383
+ r = engine.evaluate('A', 'b')
384
+ r.should == :test_fn_result
385
+
386
+ r = engine.evaluate('A', 'c')
387
+ r.should == :test_fn2_result
388
+
389
+ r = engine.evaluate('A', 'd')
390
+ r.should == :test_fn2_result_different
391
+
392
+ r = engine.evaluate('A', 'e')
393
+ r.should == :test_fn2_result_different
394
+ end
395
+
396
+ it 'should raise exception if method is not whitelisted' do
397
+ engine.parse defn(
398
+ 'A:',
399
+ ' a = DeloreanFunctionsChildClass.test_fn4',
400
+ ' b = DeloreanFunctionsChildClass.test_fn4()',
401
+ ' c = Dummy.this_is_crazy()',
402
+ )
403
+
404
+ lambda {
405
+ engine.evaluate('A', 'a')
406
+ }.should raise_error(
407
+ Delorean::InvalidGetAttribute,
408
+ "attr lookup failed: 'test_fn4' on <Class> DeloreanFunctionsChildClass - no such method test_fn4"
409
+ )
410
+
411
+ lambda {
412
+ engine.evaluate('A', 'b')
413
+ }.should raise_error(RuntimeError, 'no such method test_fn4')
414
+
415
+ lambda {
416
+ engine.evaluate('A', 'c')
417
+ }.should raise_error(RuntimeError, 'no such method this_is_crazy')
418
+ end
419
+
420
+ it 'should raise exception if required arguments are missing' do
421
+ engine.parse defn(
422
+ 'A:',
423
+ ' a = DifferentClassSameMethod.test_fn3(1, 2, 3, 4, 5,
424
+ 6, 7, 8, 9, 10)',
425
+ ' b = DifferentClassSameMethod.test_fn3(1, 2, 3, 4) ',
426
+ ' c = DifferentClassSameMethod.test_fn3(1, 2) ',
427
+ ' d = DifferentClassSameMethod.test_fn3() ',
428
+ )
429
+
430
+ r = engine.evaluate('A', 'a')
431
+ r.should == { a: 1, b: 2, c: 3, d: 4, e: 5, rest: [6, 7, 8, 9, 10] }
432
+
433
+ r = engine.evaluate('A', 'b')
434
+ r.should == { a: 1, b: 2, c: 3, d: 4, e: nil, rest: [] }
435
+
436
+ lambda {
437
+ r = engine.evaluate('A', 'c')
438
+ }.should raise_error(
439
+ ArgumentError,
440
+ 'wrong number of arguments (given 2, expected 3+)'
441
+ )
442
+
443
+ lambda {
444
+ r = engine.evaluate('A', 'd')
445
+ }.should raise_error(
446
+ ArgumentError,
447
+ 'wrong number of arguments (given 0, expected 3+)'
448
+ )
449
+ end
450
+
374
451
  it 'should ignore undeclared params sent to eval which match attr names' do
375
452
  engine.parse defn('A:',
376
453
  ' d = 12',
data/spec/parse_spec.rb CHANGED
@@ -393,21 +393,21 @@ describe 'Delorean' do
393
393
  )
394
394
  end
395
395
 
396
- it 'should get exception on arg count to class method call' do
397
- lambda {
398
- engine.parse defn('A:',
399
- ' b = Dummy.i_just_met_you(1, 2, 3)',
400
- )
401
- }.should raise_error(Delorean::BadCallError)
402
- end
403
-
404
- it "shouldn't be able to call ActiveRecord methods without signature" do
405
- lambda {
406
- engine.parse defn('A:',
407
- ' b = Dummy.this_is_crazy()',
408
- )
409
- }.should raise_error(Delorean::UndefinedFunctionError)
410
- end
396
+ # it 'should get exception on arg count to class method call' do
397
+ # lambda {
398
+ # engine.parse defn('A:',
399
+ # ' b = Dummy.i_just_met_you(1, 2, 3)',
400
+ # )
401
+ # }.should raise_error(Delorean::BadCallError)
402
+ # end
403
+ #
404
+ # it "shouldn't be able to call ActiveRecord methods without signature" do
405
+ # lambda {
406
+ # engine.parse defn('A:',
407
+ # ' b = Dummy.this_is_crazy()',
408
+ # )
409
+ # }.should raise_error(Delorean::UndefinedFunctionError)
410
+ # end
411
411
 
412
412
  it 'should be able to call class methods on ActiveRecord classes in modules' do
413
413
  engine.parse defn('A:',
@@ -5,11 +5,14 @@ require 'delorean/ruby/whitelists/empty'
5
5
 
6
6
  describe 'Delorean Ruby whitelisting' do
7
7
  it 'allows to override whitelist with an empty one' do
8
+ old_whitelist = ::Delorean::Ruby.whitelist
8
9
  ::Delorean::Ruby.whitelist = whitelist
9
10
  expect(whitelist.matchers).to be_empty
10
11
 
11
12
  ::Delorean::Ruby.whitelist = ::Delorean::Ruby::Whitelists::Default.new
12
13
  expect(::Delorean::Ruby.whitelist.matchers).to_not be_empty
14
+
15
+ ::Delorean::Ruby.whitelist = old_whitelist
13
16
  end
14
17
 
15
18
  let(:whitelist) { ::Delorean::Ruby::Whitelists::Empty.new }
@@ -76,4 +79,108 @@ describe 'Delorean Ruby whitelisting' do
76
79
  expect(matcher.match_to?).to be true
77
80
  end
78
81
  end
82
+
83
+ describe 'class_methods' do
84
+ let(:method_matcher) do
85
+ Delorean::Ruby.whitelist.class_method_matcher(method_name: :test_method)
86
+ end
87
+
88
+ let(:engine) do
89
+ engine = Delorean::Engine.new 'XXX'
90
+
91
+ engine.parse defn(
92
+ 'A:',
93
+ ' a = RootClass.test_method(1)',
94
+ ' b = RootClass.test_method(true)',
95
+ ' c = RootClassChild.test_method("test")',
96
+ ' d = RootClassChild.test_method(1)',
97
+ ' e = RootClassChildsChild.test_method(true)',
98
+ ' f = RootClassChildsChild.test_method(1)',
99
+ ' g = RootClassChildsChildsChild.test_method(true)',
100
+ ' h = RootClassChildsChildsChild.test_method(1)',
101
+ ' i = RootClassChildsChildsChild.test_method()',
102
+ ' j = RootClassChildsChildsChild.test_method',
103
+ ' k = RootClassChildsChildsChild.test_method(true, true)',
104
+ ' l = RootClassChildsChildsChild.test_method2(true)'
105
+ )
106
+
107
+ engine
108
+ end
109
+
110
+ it 'fetches the closest method matcher in class hierarchy' do
111
+ arg_matcher = method_matcher.matcher(klass: RootClass)
112
+ expect(arg_matcher.with).to eq [Integer]
113
+
114
+ arg_matcher = method_matcher.matcher(klass: RootClassChild)
115
+ expect(arg_matcher.with).to eq [String]
116
+
117
+ arg_matcher = method_matcher.matcher(klass: RootClassChildsChild)
118
+ expect(arg_matcher.with).to eq [TrueClass]
119
+
120
+ arg_matcher = method_matcher.matcher(klass: RootClassChildsChildsChild)
121
+ expect(arg_matcher.with).to eq [TrueClass]
122
+ end
123
+
124
+ it 'allows to call methods correctly' do
125
+ r = engine.evaluate('A', 'a')
126
+ expect(r).to eq :test_method_with_int_arg
127
+
128
+ r = engine.evaluate('A', 'c')
129
+ expect(r).to eq :test_method_with_str_arg
130
+
131
+ r = engine.evaluate('A', 'e')
132
+ expect(r).to eq :test_method_with_true_arg
133
+
134
+ r = engine.evaluate('A', 'g')
135
+ expect(r).to eq :test_method_with_true_arg
136
+ end
137
+
138
+ it 'raises exception if argument type mismatched' do
139
+ expect { engine.evaluate('A', 'b') }.to raise_error(
140
+ RuntimeError,
141
+ 'bad arg 0, method test_method: true/TrueClass [Integer]'
142
+ )
143
+
144
+ expect { engine.evaluate('A', 'd') }.to raise_error(
145
+ RuntimeError,
146
+ 'bad arg 0, method test_method: 1/Integer [String]'
147
+ )
148
+
149
+ expect { engine.evaluate('A', 'f') }.to raise_error(
150
+ RuntimeError,
151
+ 'bad arg 0, method test_method: 1/Integer [TrueClass]'
152
+ )
153
+
154
+ expect { engine.evaluate('A', 'h') }.to raise_error(
155
+ RuntimeError,
156
+ 'bad arg 0, method test_method: 1/Integer [TrueClass]'
157
+ )
158
+ end
159
+
160
+ it 'raises exception if argument is not present' do
161
+ expect { engine.evaluate('A', 'i') }.to raise_error(
162
+ RuntimeError,
163
+ 'bad arg 0, method test_method: /NilClass [TrueClass]'
164
+ )
165
+
166
+ expect { engine.evaluate('A', 'j') }.to raise_error(
167
+ Delorean::InvalidGetAttribute,
168
+ "attr lookup failed: 'test_method' on <Class> RootClassChildsChildsChild - bad arg 0, method test_method: /NilClass [TrueClass]"
169
+ )
170
+ end
171
+
172
+ it 'raises exception if too many arguments' do
173
+ expect { engine.evaluate('A', 'k') }.to raise_error(
174
+ RuntimeError,
175
+ 'too many args to test_method'
176
+ )
177
+ end
178
+
179
+ it 'raises exception method is not whitelisted' do
180
+ expect { engine.evaluate('A', 'l') }.to raise_error(
181
+ RuntimeError,
182
+ 'no such method test_method2'
183
+ )
184
+ end
185
+ end
79
186
  end
data/spec/spec_helper.rb CHANGED
@@ -3,10 +3,10 @@
3
3
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
4
  $LOAD_PATH.unshift(File.dirname(__FILE__))
5
5
 
6
+ require 'pry'
6
7
  require 'rspec'
7
8
  require 'delorean_lang'
8
9
  require 'active_record'
9
- require 'pry'
10
10
 
11
11
  # Requires supporting files with custom matchers and macros, etc,
12
12
  # in ./support/ and its subdirectories.
@@ -36,18 +36,14 @@ class Dummy < ActiveRecord::Base
36
36
 
37
37
  belongs_to :dummy
38
38
 
39
- def self.i_just_met_you(name, number)
39
+ delorean_fn :i_just_met_you do |name, number|
40
40
  Dummy.new(name: name, number: number)
41
41
  end
42
42
 
43
- I_JUST_MET_YOU_SIG = [1, 2].freeze
44
-
45
- def self.call_me_maybe(*a)
43
+ delorean_fn :call_me_maybe do |*a|
46
44
  a.inject(0, :+)
47
45
  end
48
46
 
49
- CALL_ME_MAYBE_SIG = [0, Float::INFINITY].freeze
50
-
51
47
  def self.this_is_crazy; end
52
48
 
53
49
  def self.miss_you_so_bad
@@ -55,18 +51,14 @@ class Dummy < ActiveRecord::Base
55
51
  Dummy.new(name: 'jello', number: 456, dummy: d)
56
52
  end
57
53
 
58
- MISS_YOU_SO_BAD_SIG = [0, 0].freeze
59
-
60
54
  delorean_fn :all_of_me, sig: 0 do
61
55
  [{ 'name' => 'hello', 'foo' => 'bar' }]
62
56
  end
63
57
 
64
- def self.i_threw_a_hash_in_the_well
58
+ delorean_fn :i_threw_a_hash_in_the_well do
65
59
  { a: 123, 'a' => 456, b: 789 }
66
60
  end
67
61
 
68
- I_THREW_A_HASH_IN_THE_WELL_SIG = [0, 0].freeze
69
-
70
62
  def name2
71
63
  "#{name}-#{number.round(4)}"
72
64
  end
@@ -96,7 +88,6 @@ class DummyChild < Dummy
96
88
  def self.hello
97
89
  DummyChild.new(name: 'child', number: 99_999)
98
90
  end
99
- HELLO_SIG = [0, 0].freeze
100
91
  end
101
92
 
102
93
  module M
@@ -106,10 +97,10 @@ module M
106
97
  delorean_fn(:heres_my_number, sig: [0, Float::INFINITY]) do |*a|
107
98
  a.inject(0, :+)
108
99
  end
100
+
109
101
  def self.sup
110
102
  LittleDummy.new
111
103
  end
112
- SUP_SIG = [0, 0].freeze
113
104
  end
114
105
 
115
106
  module N
@@ -134,6 +125,80 @@ module M
134
125
  DummyModule = ::DummyModule
135
126
  end
136
127
 
128
+ class DeloreanFunctionsClass
129
+ extend Delorean::Functions
130
+
131
+ delorean_fn :test_fn, sig: 0 do
132
+ :test_fn_result
133
+ end
134
+ end
135
+
136
+ class DeloreanFunctionsChildClass < DeloreanFunctionsClass
137
+ delorean_fn :test_fn2, sig: 0 do
138
+ :test_fn2_result
139
+ end
140
+
141
+ def self.test_fn4; end
142
+ end
143
+
144
+ class DifferentClassSameMethod
145
+ extend Delorean::Functions
146
+
147
+ delorean_fn :test_fn2, sig: 0 do
148
+ :test_fn2_result_different
149
+ end
150
+
151
+ delorean_fn :test_fn3, sig: 0 do |a, b, c, d = :default, e = nil, *args|
152
+ {
153
+ a: a,
154
+ b: b,
155
+ c: c,
156
+ d: d,
157
+ e: e,
158
+ rest: args
159
+ }
160
+ end
161
+ end
162
+
163
+ class RootClass
164
+ def self.test_method(_int_arg)
165
+ :test_method_with_int_arg
166
+ end
167
+ end
168
+
169
+ Delorean::Ruby.whitelist.add_class_method :test_method do |method|
170
+ method.called_on RootClass, with: [Integer]
171
+ end
172
+
173
+ class RootClassChild < RootClass
174
+ def self.test_method(_str_arg)
175
+ :test_method_with_str_arg
176
+ end
177
+ end
178
+
179
+ Delorean::Ruby.whitelist.add_class_method :test_method do |method|
180
+ method.called_on RootClassChild, with: [String]
181
+ end
182
+
183
+ class RootClassChildsChild < RootClassChild
184
+ def self.test_method(_true_arg)
185
+ :test_method_with_true_arg
186
+ end
187
+ end
188
+
189
+ Delorean::Ruby.whitelist.add_class_method :test_method do |method|
190
+ method.called_on RootClassChildsChild, with: [TrueClass]
191
+ end
192
+
193
+ class RootClassChildsChildsChild < RootClassChildsChild
194
+ def self.test_method2(bool_arg); end
195
+ end
196
+
197
+ Delorean::Ruby.whitelist.add_class_method(
198
+ :match_to_test_fn2,
199
+ match_to: :test_fn2
200
+ )
201
+
137
202
  ######################################################################
138
203
 
139
204
  class TestContainer < Delorean::AbstractContainer
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: delorean_lang
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.4
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Arman Bostani
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-05-08 00:00:00.000000000 Z
11
+ date: 2019-05-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '2.1'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec-instafail
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rubocop
71
85
  requirement: !ruby/object:Gem::Requirement