contraction 0.2.4 → 0.2.5

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
  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