jinterface 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,38 @@
1
+ module JInterface
2
+ class ArgRange
3
+ attr :min, :max
4
+ def initialize(meth)
5
+ reset(meth)
6
+ end
7
+ def +(range)
8
+ if range.is_a? self.class
9
+ @min = range.min if range.min < @min
10
+ @max = range.max if range.max > @max
11
+ end
12
+ return self
13
+ end
14
+ def cover?(range)
15
+ return range.is_a?(self.class) &&
16
+ @min <= range.min && @max >= range.max
17
+ end
18
+ def reset(meth)
19
+ @min, @max = getMethodRange(meth)
20
+ end
21
+ def to_s()
22
+ "(#{@min}, #{@max}#{@max == Float::INFINITY ? ']' : ')'}"
23
+ end
24
+ private
25
+ def getMethodRange(meth)
26
+ return 0, 0 unless meth.is_a?(UnboundMethod) or meth.is_a?(Method)
27
+ #Get min and max number of args for method
28
+ min = 0
29
+ params = meth.parameters
30
+ max = params.length
31
+ params.each do |type, |
32
+ ++min if type == :req
33
+ max = Float::INFINITY if type == :rest
34
+ end
35
+ return min, max
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,111 @@
1
+ require 'jinterface/interface_class_methods'
2
+ require 'jinterface/arg_range.rb'
3
+ module JInterface
4
+ module InterfaceClassMethods
5
+ def include(*args)
6
+ #For each inclusion
7
+ args.each do |mod|
8
+ #Make sure it is an interface
9
+ raise TypeError.new(
10
+ "Cannot include non-interface module"\
11
+ " '#{mod.name}' in interface '#{self.name}'."
12
+ ) unless JInterface.interface? mod
13
+ #Add the method arrays together
14
+ arg_ranges = mod.instance_variable_get(:@arg_ranges)
15
+ arg_ranges.each do |method_name, range|
16
+ @arg_ranges[method_name] = range + @arg_ranges[method_name]
17
+ end
18
+ #Include it
19
+ super mod
20
+ end
21
+ end
22
+ def included(obj)
23
+ #Ignore if included in an interface,
24
+ #include method will take care of checks
25
+ return if JInterface.interface?(obj)
26
+ #Cache public obj method names
27
+ obj_methods = Hash[obj.public_instance_methods.map.with_index.to_a]
28
+ #Check interface methods are implemented in obj
29
+ act_range = JInterface::ArgRange.new(nil)
30
+ self.public_instance_methods.each do |method_name|
31
+ #If method does not exist
32
+ if not obj_methods.key? method_name
33
+ #Raise error if under a different scope
34
+ [:private, :protected].each do |scope|
35
+ raise NameError.new(
36
+ "Method '#{method_name}' in class '#{obj.name}'"\
37
+ " must be declared as public, not #{scope},"\
38
+ " as declared in interface '#{self.name}'."
39
+ ) if obj.send("#{scope}_method_defined?", method_name)
40
+ end
41
+ #If here, method does not exist. This is possible
42
+ #if the method was removed or made undefined
43
+ raise NotImplementedError.new(
44
+ "Method '#{method_name}' must be implemented in class"\
45
+ " '#{obj.name}' as declared in interface '#{self.name}'."
46
+ )
47
+ end
48
+ #Make sure method was overriden (implemented)
49
+ meth = obj.public_instance_method method_name
50
+ raise NotImplementedError.new(
51
+ "Method '#{method_name}' must be implemented in class"\
52
+ " '#{obj.name}' as declared in interface '#{meth.owner.name}'."
53
+ ) if JInterface.interface? meth.owner
54
+ #Make sure method can handle number of args defined
55
+ act_range.reset(meth)
56
+ exp_range = @arg_ranges[method_name]
57
+ raise ArgumentError.new(
58
+ "Method '#{method_name}' in class '#{obj.name}'"\
59
+ " must handle #{exp_range} arguments, not #{act_range},"\
60
+ " as declared in included interface(s)."
61
+ ) unless act_range.cover? exp_range
62
+ end
63
+ end
64
+ def method_added(method_name)
65
+ meth = self.public_instance_method(method_name)
66
+ @arg_ranges[method_name] = JInterface::ArgRange.new(meth) + @arg_ranges[method_name]
67
+ end
68
+ def private(*args)
69
+ raise SyntaxError.new(
70
+ "Interface '#{self.name}' cannot declare"\
71
+ " private methods, only public methods."
72
+ )
73
+ end
74
+ def protected(*args)
75
+ raise SyntaxError.new(
76
+ "Interface '#{self.name}' cannot declare"\
77
+ " protected methods, only public methods."
78
+ )
79
+ end
80
+ def singleton_method_added(*args)
81
+ raise SyntaxError.new(
82
+ "Interface '#{self.name}' cannot declare"\
83
+ " class methods, only instance methods."
84
+ )
85
+ end
86
+ def extend(*args)
87
+ raise SyntaxError.new(
88
+ "Interface '#{self.name}' cannot extend,"\
89
+ " only include other interfaces."
90
+ )
91
+ end
92
+ def extended(obj)
93
+ raise SyntaxError.new(
94
+ "Interface '#{self.name}' cannot be "\
95
+ " extended, only included, in '#{obj.name}'."
96
+ )
97
+ end
98
+ def prepend(*args)
99
+ raise SyntaxError.new(
100
+ "Interface '#{self.name}' cannot prepend,"\
101
+ " only include other interfaces."
102
+ )
103
+ end
104
+ def prepended(obj)
105
+ raise SyntaxError.new(
106
+ "Interface '#{self.name}' cannot be "\
107
+ " prepended, only included, in '#{obj.name}'."
108
+ )
109
+ end
110
+ end
111
+ end
data/lib/jinterface.rb ADDED
@@ -0,0 +1,82 @@
1
+ require 'jinterface/interface_class_methods'
2
+ module JInterface
3
+ class << self
4
+ def included(mod)
5
+ #Do not do anything if in production
6
+ return if production?
7
+ #Make sure JInterface used with module
8
+ raise TypeError.new(
9
+ "JInterface cannot be used with class"\
10
+ " '#{mod.name}', only with modules."
11
+ ) if mod.instance_of? Class
12
+ #Extend module
13
+ mod.class_eval do
14
+ extend JInterface::InterfaceClassMethods
15
+ @arg_ranges = {
16
+ #method_name => ArgRange
17
+ }
18
+ #In case JInterface inclusion was
19
+ #not first thing in class declaration:
20
+ #Raise error if private method defined
21
+ private_instance_methods.each do |method_name|
22
+ private method_name
23
+ end
24
+ #Raise error if protected method defined
25
+ protected_instance_methods.each do |method_name|
26
+ protected method_name
27
+ end
28
+ #Raise error if class method defined
29
+ methods(false).each do |method_name|
30
+ singleton_method_added method_name
31
+ end
32
+ #Raise error if non-interface included
33
+ included_modules.each do |mod|
34
+ include mod unless JInterface.interface? mod
35
+ end
36
+ #Raise error if module prepended
37
+ prepended_modules.each do |mod|
38
+ prepend mod
39
+ end if defined? prepended_modules
40
+ #Raise error if module extended
41
+ (
42
+ (class << mod; self; end).included_modules -
43
+ Module.included_modules -
44
+ [JInterface::InterfaceClassMethods]
45
+ ).each do |mod|
46
+ extend mod
47
+ end
48
+ #Send each method through method_added method
49
+ public_instance_methods(false).each do |method_name|
50
+ method_added(method_name)
51
+ end
52
+ end
53
+ end
54
+ def extended(obj)
55
+ raise SyntaxError.new(
56
+ "Interface '#{self.name}' cannot be "\
57
+ " extended, only included, in '#{obj.name}'."
58
+ )
59
+ end
60
+ def prepended(obj)
61
+ raise SyntaxError.new(
62
+ "Interface '#{self.name}' cannot be "\
63
+ " prepended, only included, in '#{obj.name}'."
64
+ )
65
+ end
66
+ def interface?(obj)
67
+ ( obj == JInterface or
68
+ ( obj.instance_of?(Module) and
69
+ (class << obj; self end) < JInterface::InterfaceClassMethods
70
+ )
71
+ ) ? true : false
72
+ end
73
+ def production=(flag)
74
+ @enabled = flag == true
75
+ end
76
+ def production?()
77
+ return @enabled ||= false
78
+ end
79
+ end
80
+ end
81
+ #Turn JInterface checking on or off
82
+ JInterface.production = defined?(Rails) and Rails.is_a?(Class) ? Rails.env.production? : false
data.tar.gz.sig ADDED
Binary file
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jinterface
3
+ version: !ruby/object:Gem::Version
4
+ hash: 31
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 0
10
+ version: 0.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Michael Rojas
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain:
17
+ - |
18
+ -----BEGIN CERTIFICATE-----
19
+ MIIDRDCCAiygAwIBAgIBADANBgkqhkiG9w0BAQUFADBIMRowGAYDVQQDDBFkZXYu
20
+ bWljaGFlbC5yb2phczEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPy
21
+ LGQBGRYDY29tMB4XDTE0MDQxMTIyMzM1M1oXDTE1MDQxMTIyMzM1M1owSDEaMBgG
22
+ A1UEAwwRZGV2Lm1pY2hhZWwucm9qYXMxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDET
23
+ MBEGCgmSJomT8ixkARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
24
+ ggEBAKqba7uCWi7wkNCeUFLDa+Ql5fG75E8kGruxP5BBAWhOUwjWpKfUv/8Paqlk
25
+ 7P3rtNMLnofentNQciXLgSlK0jwyO9Kuevi3nIPbFuVcQR5D58z9SLezYQSl1hPu
26
+ RaO2IFLfnakj2QjyH3RVdzBDq3+merqkI0qmDvWCs6aJljHsAOBjk5DftY5elCDP
27
+ ooks39ZVpsdwpoAewmtq9uvMivCRz+Vf1yJYVoRuVUSczoOPgN4PW/MJfLQhih5b
28
+ FrsDqGQdNgSjgL7rTZMd0/tiUdo9GaGYG/Rl3TtzlyxB9pJTTc1rDmi/1A2G6Weo
29
+ UX97pHPgP+0WEl3e41jbYkClSfMCAwEAAaM5MDcwHQYDVR0OBBYEFDWsnI/cwObC
30
+ XU3Yf8T0vyKp9Wb+MAsGA1UdDwQEAwIEsDAJBgNVHRMEAjAAMA0GCSqGSIb3DQEB
31
+ BQUAA4IBAQAcCK9Sfoae8T+Sw7xY5ZMUAt55IO8Ldq61J+V8+Q49vgXb7/m379DC
32
+ FZhia4pj4n1g//M0nHm2/yQblXK7qwkYpGB3uEK5yedaY5fCGZlRe67rcPJ4No1x
33
+ tHpBaYknGBP3ITEt1Btw5HhPpccirBk8cBIP9vEN/k9yNn9jpVRRBLXiXaKusDRy
34
+ NccuJexQuG86gK8tnQh1kN2t+MA5UkDeHWsysJrEsT1/p6UChw60MhlQ2gFTrIvu
35
+ EBm0ICzl7th3TQgzeiWbMUiUx7k5B+Oi/btCNjCIGkpWyWC+nL1SweWtOFGQGuGm
36
+ UX363H4LFf3sXXUY2b+Nf5+zMlVQADoL
37
+ -----END CERTIFICATE-----
38
+
39
+ date: 2014-04-09 00:00:00 Z
40
+ dependencies: []
41
+
42
+ description: Simulate java interfaces in ruby to enforce public class implementation
43
+ email: dev.michael.rojas@gmail.com
44
+ executables: []
45
+
46
+ extensions: []
47
+
48
+ extra_rdoc_files: []
49
+
50
+ files:
51
+ - lib/jinterface.rb
52
+ - lib/jinterface/arg_range.rb
53
+ - lib/jinterface/interface_class_methods.rb
54
+ homepage: https://github.com/havelessbemore/JInterface
55
+ licenses:
56
+ - MIT
57
+ post_install_message:
58
+ rdoc_options: []
59
+
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ hash: 3
68
+ segments:
69
+ - 0
70
+ version: "0"
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ hash: 3
77
+ segments:
78
+ - 0
79
+ version: "0"
80
+ requirements: []
81
+
82
+ rubyforge_project:
83
+ rubygems_version: 1.8.24
84
+ signing_key:
85
+ specification_version: 3
86
+ summary: JInterface
87
+ test_files: []
88
+
metadata.gz.sig ADDED
Binary file