contraction 0.2.4 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 220fc1b815a36a3a46425136e5b786d63b2554fc
4
- data.tar.gz: 7039c53c01ba20210aa97c7e256a4ab891c0c007
3
+ metadata.gz: d949e8e0f90ac9a867b0bc500c174af356f714e2
4
+ data.tar.gz: 7946c533f8690b04dfb4a6f41f0e50e12b8b6f89
5
5
  SHA512:
6
- metadata.gz: a025c0cd5aff6fc22d6129dbf61b7d3bfff7038b662e215f944e42379fbfa457c742f1659f73985c12e89ae0440485e1dddc657f7574ec6133225edfad79db7a
7
- data.tar.gz: dfb2ac55e0dc3784be7338a097a18889b4ba0e27d1d6f0d45ed7e2f33f51a88d16dc397a284d4ad141b8ba5586836beb0fcb8c62ea53289a75d93c0b681a862d
6
+ metadata.gz: 178ca20aa78e13a2bcb22906f40e93667fcffd29ddf0e13e362a894f38c0d2769269f5e8e203aceda27567148f08abe1c8f8d53efbbe687df2fa96e4b5dcba4f
7
+ data.tar.gz: c2fb6d2cba4457341109c9b6d96c244ceee9316f19137398a8ca645ef3f2fac218a35ef6214389dae97c4957a9beb8628e8a66ceda451a902605e17115b78d3b
data/lib/contract.rb CHANGED
@@ -4,13 +4,13 @@ module Contraction
4
4
 
5
5
  # @params [Array<TypedLine>] rules The individual lines that define the
6
6
  # contract.
7
- def initialize(rules, mod, method_name)
7
+ def initialize(rules, mod, method_name, type)
8
8
  @rules = rules
9
9
  @mod = mod
10
10
  @method_name = method_name
11
11
 
12
12
  update_rule_values
13
- get_method_definition
13
+ get_method_definition(type)
14
14
  end
15
15
 
16
16
  # Test weather the arguments to a method are of the correct type, and meet
@@ -57,8 +57,13 @@ module Contraction
57
57
  @param_rules ||= @rules.select { |r| r.is_a?(Contraction::Parser::ParamLine) }
58
58
  end
59
59
 
60
- def get_method_definition
61
- @params = mod.instance_method(method_name).parameters.map(&:last)
60
+ def get_method_definition(type)
61
+ @params = []
62
+ if type == :class
63
+ @params = mod.method(method_name.to_sym).parameters.map(&:last)
64
+ else
65
+ @params = mod.instance_method(method_name.to_sym).parameters.map(&:last)
66
+ end
62
67
  end
63
68
 
64
69
  def update_rule_values
data/lib/contraction.rb CHANGED
@@ -9,14 +9,14 @@ module Contraction
9
9
  # @param [Class] mod The module or class to update contracts for.
10
10
  def self.update_contracts(mod)
11
11
  instance = mod.allocate
12
- instance_methods = (mod.instance_methods - Object.instance_methods - Contraction.instance_methods)
13
12
 
14
- # FIXME: Deal with weather it is an instance or class method a bit nicer.
15
- instance_methods.each do |method_name|
16
- file_contents, line_no = read_file_for_method(instance, method_name)
13
+ methods_for(mod).each do |(type, methods)|
14
+ methods.each do |method_name|
15
+ file_contents, line_no = read_file_for_method(instance, method_name, type)
17
16
 
18
- contract = Contraction::Parser.parse(file_contents[0..line_no-2].reverse, mod, method_name)
19
- define_wrapped_method(mod, method_name, contract)
17
+ contract = Contraction::Parser.parse(file_contents[0..line_no-2].reverse, mod, method_name, type)
18
+ define_wrapped_method(mod, method_name, contract, type)
19
+ end
20
20
  end
21
21
  end
22
22
 
@@ -25,10 +25,44 @@ module Contraction
25
25
  update_contracts(mod)
26
26
  end
27
27
 
28
+ # Get all the public instance methods for a given class, that are unique to
29
+ # class (ie, not built-ins)
30
+ # @param [Class] klass The class to get the methods from
31
+ # @return [Array<Symbol>] The method names
28
32
  def self.instance_methods_for(klass)
29
33
  klass.public_instance_methods - Object.public_instance_methods - Module.public_instance_methods
30
34
  end
31
35
 
36
+ # Get all the public class methods for a given class that are unique to the
37
+ # class (ie, not built-ins). NOTE: doing something like the following _doesn't_
38
+ # make a class method private:
39
+ # class Foo
40
+ # private
41
+ # def self.foobar
42
+ # end
43
+ # end
44
+ #
45
+ # That's because defining a method on an object, even `self`, re-opens the
46
+ # object to define the method on it. It's the same as saying `def
47
+ # some_object.foobar`, only in this case `some_object` is the handy-dandy
48
+ # `self`. To make that really private, you can do:
49
+ # class Foo
50
+ # private
51
+ # def self.foobar
52
+ # end
53
+ # private_class_method :foobar
54
+ # end
55
+ #
56
+ # ... or ...
57
+ # class Foo
58
+ # private
59
+ # class << self
60
+ # def self.foobar
61
+ # end
62
+ # end
63
+ # end
64
+ # @param [Class] klass The class to get the methods from
65
+ # @return [Array<Symbol>] The method names
32
66
  def self.class_methods_for(klass)
33
67
  klass.public_methods - Object.public_methods - Module.public_methods
34
68
  end
@@ -39,21 +73,34 @@ module Contraction
39
73
 
40
74
  private
41
75
 
42
- def self.read_file_for_method(instance, method_name)
43
- file, line = instance.method(method_name).source_location
76
+ def self.read_file_for_method(instance, method_name, type)
77
+ file, line = nil, nil
78
+ if type == :class
79
+ file, line = instance.class.method(method_name).source_location
80
+ elsif type == :instance
81
+ file, line = instance.method(method_name).source_location
82
+ else
83
+ raise ArgumentError.new("Unknown method type, #{type.inspect}")
84
+ end
44
85
  filename = File.expand_path(file)
45
86
  file_contents = File.read(filename).split("\n")
46
87
  return [file_contents, line]
47
88
  end
48
89
 
49
- def self.define_wrapped_method(mod, method_name, contract)
50
- old_method = mod.instance_method(method_name)
90
+ def self.define_wrapped_method(mod, method_name, contract, type)
91
+ old_method = type == :instance ? mod.instance_method(method_name) : mod.method(method_name)
51
92
 
52
93
  arg_checks = []
53
94
  result_check = nil
54
- mod.send(:define_method, method_name) do |*method_args|
95
+ type = type == :class ? :define_singleton_method : :define_method
96
+ mod.send(type, method_name) do |*method_args|
55
97
  contract.valid_args?(*method_args)
56
- result = old_method.bind(self).call(*method_args)
98
+ result = nil
99
+ if old_method.respond_to?(:bind)
100
+ result = old_method.bind(self).call(*method_args)
101
+ else
102
+ result = old_method.call(*method_args)
103
+ end
57
104
  contract.valid_return?(*method_args, result)
58
105
  result
59
106
  end
data/lib/parser.rb CHANGED
@@ -17,7 +17,7 @@ module Contraction
17
17
  # contracts/docs apply to
18
18
  # @return [Contract] A Contract object that can be used to evaluate
19
19
  # correctness at run-time.
20
- def self.parse(text, mod, method_name)
20
+ def self.parse(text, mod, method_name, type)
21
21
  lines = text.is_a?(String) ? text.split(/$/) : text
22
22
  results = []
23
23
  lines.each do |line|
@@ -28,7 +28,7 @@ module Contraction
28
28
  end
29
29
  results.compact!
30
30
 
31
- Contract.new(results, mod, method_name)
31
+ Contract.new(results, mod, method_name, type)
32
32
  end
33
33
 
34
34
  # Parse a single line of text for @param and @return statements.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: contraction
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas Luce