include_complete 0.1.0-i386-mswin32
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.
- data/CHANGELOG +20 -0
- data/README.markdown +40 -0
- data/Rakefile +59 -0
- data/ext/include_complete/compat.h +57 -0
- data/ext/include_complete/extconf.rb +6 -0
- data/ext/include_complete/include_complete.c +11 -0
- data/ext/include_complete/include_complete_one.c +151 -0
- data/ext/include_complete/patched_include.c +109 -0
- data/lib/1.8/include_complete.so +0 -0
- data/lib/1.9/include_complete.so +0 -0
- data/lib/include_complete/version.rb +3 -0
- data/lib/include_complete.rb +62 -0
- data/test/stress_test.rb +14 -0
- data/test/test.rb +262 -0
- metadata +80 -0
data/CHANGELOG
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
1/11/2010 *NAME CHANGE* TO include_complete, version reset to 0.1.0
|
2
|
+
* now called include_complete
|
3
|
+
22/10/2010 version 0.2.2
|
4
|
+
* refactored compat.h, incorporated test for 1.9
|
5
|
+
* created inline static function create_class() in compat.h
|
6
|
+
20/10/2010 version 0.2.1
|
7
|
+
* constant lookup should now work
|
8
|
+
* added real_extend and tests
|
9
|
+
15/10/2010 version 0.1.7
|
10
|
+
* should be properly working with normal Module#include now
|
11
|
+
* no more segfaults?
|
12
|
+
* added more tests
|
13
|
+
6/10/2010 version 0.1.3
|
14
|
+
* fixed native gem
|
15
|
+
* moved more version-dependant code to compat.h
|
16
|
+
5/10/2010 version 0.1.2
|
17
|
+
* added 1.8 support
|
18
|
+
* added bacon tests
|
19
|
+
4/10/10 version 0.1.0
|
20
|
+
* release! This is still beta, not 100% tested yet..but appears to work OK so far
|
data/README.markdown
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
Include Complete
|
2
|
+
----------------
|
3
|
+
|
4
|
+
(c) John Mair (banisterfiend)
|
5
|
+
MIT license
|
6
|
+
|
7
|
+
Removes the shackles from Module#include - use Module#real_include to
|
8
|
+
bring in singleton classes from modules. No more ugly ClassMethods and
|
9
|
+
included() hook hacks.
|
10
|
+
|
11
|
+
** This is BETA software and has not yet been thoroughly tested, use
|
12
|
+
at own risk **
|
13
|
+
|
14
|
+
install the gem: **for testing purposes only**
|
15
|
+
`gem install include_complete`
|
16
|
+
|
17
|
+
example:
|
18
|
+
|
19
|
+
module M
|
20
|
+
# class method
|
21
|
+
def self.hello
|
22
|
+
puts "hello!"
|
23
|
+
end
|
24
|
+
|
25
|
+
# instance method
|
26
|
+
def bye
|
27
|
+
puts "bye!"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class A
|
32
|
+
include_complete M
|
33
|
+
end
|
34
|
+
|
35
|
+
# invoke class method
|
36
|
+
A.hello #=> hello!
|
37
|
+
|
38
|
+
# invoke instance method
|
39
|
+
A.new.bye #=> bye!
|
40
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
$LOAD_PATH.unshift File.join(File.expand_path(__FILE__), '..')
|
2
|
+
|
3
|
+
direc = File.dirname(__FILE__)
|
4
|
+
dlext = Config::CONFIG['DLEXT']
|
5
|
+
|
6
|
+
require 'rake/clean'
|
7
|
+
require 'rake/gempackagetask'
|
8
|
+
require './lib/include_complete/version'
|
9
|
+
|
10
|
+
CLEAN.include("ext/**/*.#{dlext}", "ext/**/*.log", "ext/**/*.o", "ext/**/*~", "ext/**/*#*", "ext/**/*.obj", "ext/**/*.def", "ext/**/*.pdb")
|
11
|
+
CLOBBER.include("**/*.#{dlext}", "**/*~", "**/*#*", "**/*.log", "**/*.o")
|
12
|
+
|
13
|
+
def apply_spec_defaults(s)
|
14
|
+
s.name = "include_complete"
|
15
|
+
s.summary = "Fixing the limitations in traditional Module#include"
|
16
|
+
s.version = IncludeComplete::VERSION
|
17
|
+
s.date = Time.now.strftime '%Y-%m-%d'
|
18
|
+
s.author = "John Mair (banisterfiend)"
|
19
|
+
s.email = 'jrmair@gmail.com'
|
20
|
+
s.description = s.summary
|
21
|
+
s.require_path = 'lib'
|
22
|
+
s.homepage = "http://banisterfiend.wordpress.com"
|
23
|
+
s.has_rdoc = 'yard'
|
24
|
+
s.files = FileList["Rakefile", "README.markdown", "CHANGELOG",
|
25
|
+
"lib/**/*.rb", "ext/**/extconf.rb", "ext/**/*.h",
|
26
|
+
"ext/**/*.c", "test/**/*.rb"].to_a
|
27
|
+
end
|
28
|
+
|
29
|
+
task :test do
|
30
|
+
sh "bacon -k #{direc}/test/test.rb"
|
31
|
+
end
|
32
|
+
|
33
|
+
[:mingw32, :mswin32].each do |v|
|
34
|
+
namespace v do
|
35
|
+
spec = Gem::Specification.new do |s|
|
36
|
+
apply_spec_defaults(s)
|
37
|
+
s.platform = "i386-#{v}"
|
38
|
+
s.files += FileList["lib/**/*.#{dlext}"].to_a
|
39
|
+
end
|
40
|
+
|
41
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
42
|
+
pkg.need_zip = false
|
43
|
+
pkg.need_tar = false
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
namespace :ruby do
|
49
|
+
spec = Gem::Specification.new do |s|
|
50
|
+
apply_spec_defaults(s)
|
51
|
+
s.platform = Gem::Platform::RUBY
|
52
|
+
s.extensions = ["ext/include_complete/extconf.rb"]
|
53
|
+
end
|
54
|
+
|
55
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
56
|
+
pkg.need_zip = false
|
57
|
+
pkg.need_tar = false
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
/* contains basic macros to facilitate ruby 1.8 and ruby 1.9 compatibility */
|
2
|
+
|
3
|
+
#ifndef GUARD_COMPAT_H
|
4
|
+
#define GUARD_COMPAT_H
|
5
|
+
|
6
|
+
#include <ruby.h>
|
7
|
+
|
8
|
+
/* test for 1.9 */
|
9
|
+
#if !defined(RUBY_19) && defined(ROBJECT_EMBED_LEN_MAX)
|
10
|
+
# define RUBY_19
|
11
|
+
#endif
|
12
|
+
|
13
|
+
/* macros for backwards compatibility with 1.8 */
|
14
|
+
#ifndef RUBY_19
|
15
|
+
# define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl)
|
16
|
+
# define RCLASS_SUPER(c) (RCLASS(c)->super)
|
17
|
+
# define RCLASS_IV_TBL(c) (RCLASS(c)->iv_tbl)
|
18
|
+
# define OBJ_UNTRUSTED OBJ_TAINTED
|
19
|
+
# include "st.h"
|
20
|
+
#endif
|
21
|
+
|
22
|
+
#ifdef RUBY_19
|
23
|
+
inline static VALUE
|
24
|
+
class_alloc(VALUE flags, VALUE klass)
|
25
|
+
{
|
26
|
+
rb_classext_t *ext = ALLOC(rb_classext_t);
|
27
|
+
NEWOBJ(obj, struct RClass);
|
28
|
+
OBJSETUP(obj, klass, flags);
|
29
|
+
obj->ptr = ext;
|
30
|
+
RCLASS_IV_TBL(obj) = 0;
|
31
|
+
RCLASS_M_TBL(obj) = 0;
|
32
|
+
RCLASS_SUPER(obj) = 0;
|
33
|
+
RCLASS_IV_INDEX_TBL(obj) = 0;
|
34
|
+
return (VALUE)obj;
|
35
|
+
}
|
36
|
+
#endif
|
37
|
+
|
38
|
+
inline static VALUE
|
39
|
+
create_class(VALUE flags, VALUE klass)
|
40
|
+
{
|
41
|
+
#ifdef RUBY_19
|
42
|
+
VALUE new_klass = class_alloc(flags, klass);
|
43
|
+
#else
|
44
|
+
NEWOBJ(new_klass, struct RClass);
|
45
|
+
OBJSETUP(new_klass, klass, flags);
|
46
|
+
#endif
|
47
|
+
|
48
|
+
return (VALUE)new_klass;
|
49
|
+
}
|
50
|
+
|
51
|
+
# define FALSE 0
|
52
|
+
# define TRUE 1
|
53
|
+
|
54
|
+
/* a useful macro. cannot use ordinary CLASS_OF as it does not return an lvalue */
|
55
|
+
#define KLASS_OF(c) (RBASIC(c)->klass)
|
56
|
+
|
57
|
+
#endif
|
@@ -0,0 +1,151 @@
|
|
1
|
+
/* (c) 2010 John Mair (banisterfiend), MIT license */
|
2
|
+
/* */
|
3
|
+
/* include a module (and its singleton) into an inheritance chain */
|
4
|
+
/* only includes a single module, see include_complete.rb for multi-module version */
|
5
|
+
|
6
|
+
#include <ruby.h>
|
7
|
+
#include "compat.h"
|
8
|
+
|
9
|
+
static VALUE
|
10
|
+
class_to_s(VALUE self)
|
11
|
+
{
|
12
|
+
VALUE attached = rb_iv_get(self, "__attached__");
|
13
|
+
|
14
|
+
if (attached)
|
15
|
+
return rb_mod_name(rb_iv_get(attached, "__module__"));
|
16
|
+
else
|
17
|
+
return rb_mod_name(rb_iv_get(self, "__module__"));
|
18
|
+
}
|
19
|
+
|
20
|
+
/* totally hacked up version of include_class_new() from class.c; brings in singletons into inheritance chain */
|
21
|
+
static VALUE
|
22
|
+
include_class_new(VALUE module, VALUE super)
|
23
|
+
{
|
24
|
+
/* base case for recursion */
|
25
|
+
if (module == rb_singleton_class(rb_cModule))
|
26
|
+
return module;
|
27
|
+
|
28
|
+
if (TYPE(module) == T_ICLASS) {
|
29
|
+
|
30
|
+
/* include_complete */
|
31
|
+
if (!NIL_P(rb_iv_get(module, "__module__")))
|
32
|
+
module = rb_iv_get(module, "__module__");
|
33
|
+
|
34
|
+
/* ordinary Module#include */
|
35
|
+
else
|
36
|
+
module = KLASS_OF(module);
|
37
|
+
}
|
38
|
+
|
39
|
+
/* allocate iclass */
|
40
|
+
VALUE klass = create_class(T_ICLASS, rb_singleton_class(rb_cModule));
|
41
|
+
|
42
|
+
/* if the module hasn't yet got an ivtbl, create it */
|
43
|
+
if (!RCLASS_IV_TBL(module))
|
44
|
+
RCLASS_IV_TBL(module) = st_init_numtable();
|
45
|
+
|
46
|
+
/* we want to point to the original ivtbl for normal modules, so that we bring in constants */
|
47
|
+
RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module);
|
48
|
+
|
49
|
+
/* we want to point to the original module's mtbl */
|
50
|
+
RCLASS_M_TBL(klass) = RCLASS_M_TBL(module);
|
51
|
+
RCLASS_SUPER(klass) = super;
|
52
|
+
|
53
|
+
if (TYPE(module) == T_MODULE || FL_TEST(module, FL_SINGLETON))
|
54
|
+
rb_iv_set((VALUE)klass, "__module__", module);
|
55
|
+
|
56
|
+
/* create IClass for module's singleton */
|
57
|
+
/* if super is 0 then we're including into a module (not a class), so treat as special case */
|
58
|
+
VALUE meta = include_class_new(KLASS_OF(module), super ? KLASS_OF(super) : rb_cModule);
|
59
|
+
|
60
|
+
/* don't mess with (Module) */
|
61
|
+
if (meta != rb_singleton_class(rb_cModule)) {
|
62
|
+
|
63
|
+
/* set it as a singleton */
|
64
|
+
FL_SET(meta, FL_SINGLETON);
|
65
|
+
|
66
|
+
/* we want a fresh ivtbl for singleton classes (so we can redefine __attached__) */
|
67
|
+
RCLASS_IV_TBL(meta) = st_init_numtable();
|
68
|
+
|
69
|
+
/* attach singleton to module */
|
70
|
+
rb_iv_set(meta, "__attached__", (VALUE)klass);
|
71
|
+
|
72
|
+
/* attach the #to_s method to the metaclass (so #ancestors doesn't look weird) */
|
73
|
+
rb_define_singleton_method(meta, "to_s", class_to_s, 0);
|
74
|
+
}
|
75
|
+
/* assign the metaclass to module's klass */
|
76
|
+
KLASS_OF(klass) = meta;
|
77
|
+
|
78
|
+
OBJ_INFECT(klass, module);
|
79
|
+
OBJ_INFECT(klass, super);
|
80
|
+
|
81
|
+
return (VALUE)klass;
|
82
|
+
}
|
83
|
+
|
84
|
+
static VALUE
|
85
|
+
rb_include_complete_module_one(VALUE klass, VALUE module)
|
86
|
+
{
|
87
|
+
VALUE p, c;
|
88
|
+
int changed = 0;
|
89
|
+
|
90
|
+
rb_frozen_class_p(klass);
|
91
|
+
if (!OBJ_UNTRUSTED(klass)) {
|
92
|
+
rb_secure(4);
|
93
|
+
}
|
94
|
+
|
95
|
+
if (TYPE(module) != T_MODULE) {
|
96
|
+
Check_Type(module, T_MODULE);
|
97
|
+
}
|
98
|
+
|
99
|
+
OBJ_INFECT(klass, module);
|
100
|
+
c = klass;
|
101
|
+
|
102
|
+
/* ensure singleton classes exist, both for includer and includee */
|
103
|
+
rb_singleton_class(module);
|
104
|
+
rb_singleton_class(klass);
|
105
|
+
|
106
|
+
while (module) {
|
107
|
+
int superclass_seen = FALSE;
|
108
|
+
|
109
|
+
if (RCLASS_M_TBL(klass) == RCLASS_M_TBL(module))
|
110
|
+
rb_raise(rb_eArgError, "cyclic include detected");
|
111
|
+
/* ignore if the module included already in superclasses */
|
112
|
+
for (p = RCLASS_SUPER(klass); p; p = RCLASS_SUPER(p)) {
|
113
|
+
switch (BUILTIN_TYPE(p)) {
|
114
|
+
case T_ICLASS:
|
115
|
+
if (RCLASS_M_TBL(p) == RCLASS_M_TBL(module)) {
|
116
|
+
if (!superclass_seen) {
|
117
|
+
c = p; /* move insertion point */
|
118
|
+
}
|
119
|
+
goto skip;
|
120
|
+
}
|
121
|
+
break;
|
122
|
+
case T_CLASS:
|
123
|
+
superclass_seen = TRUE;
|
124
|
+
break;
|
125
|
+
}
|
126
|
+
}
|
127
|
+
|
128
|
+
/* we're including the module, so create the iclass */
|
129
|
+
VALUE imod = include_class_new(module, RCLASS_SUPER(c));
|
130
|
+
|
131
|
+
/* module gets included directly above c, so set the super */
|
132
|
+
RCLASS_SUPER(c) = imod;
|
133
|
+
|
134
|
+
/* also do the same for parallel inheritance chain (singleton classes) */
|
135
|
+
RCLASS_SUPER(KLASS_OF(c)) = KLASS_OF(imod);
|
136
|
+
c = imod;
|
137
|
+
|
138
|
+
if (RMODULE_M_TBL(module) && RMODULE_M_TBL(module)->num_entries)
|
139
|
+
changed = 1;
|
140
|
+
skip:
|
141
|
+
module = RCLASS_SUPER(module);
|
142
|
+
}
|
143
|
+
if (changed) rb_clear_cache();
|
144
|
+
|
145
|
+
return Qnil;
|
146
|
+
}
|
147
|
+
|
148
|
+
void
|
149
|
+
Init_include_complete_one() {
|
150
|
+
rb_define_method(rb_cModule, "include_complete_one", rb_include_complete_module_one, 1);
|
151
|
+
}
|
@@ -0,0 +1,109 @@
|
|
1
|
+
/* (c) 2010 John Mair (banisterfiend), MIT license */
|
2
|
+
/* patches Module#include to work correctly with real_include */
|
3
|
+
|
4
|
+
#include <ruby.h>
|
5
|
+
#include "compat.h"
|
6
|
+
|
7
|
+
/* patched to work well with real_include */
|
8
|
+
static VALUE
|
9
|
+
include_class_new(VALUE module, VALUE super)
|
10
|
+
{
|
11
|
+
VALUE klass = create_class(T_ICLASS, rb_cClass);
|
12
|
+
|
13
|
+
if (BUILTIN_TYPE(module) == T_ICLASS) {
|
14
|
+
|
15
|
+
/***************************************************************************** */
|
16
|
+
/* This is the only change required, everything else is (pretty much) copypasta from class.c */
|
17
|
+
/* correct for real_include'd modules */
|
18
|
+
if (!NIL_P(rb_iv_get(module, "__module__")))
|
19
|
+
module = rb_iv_get(module, "__module__");
|
20
|
+
else
|
21
|
+
module = RBASIC(module)->klass;
|
22
|
+
/***************************************************************************** */
|
23
|
+
|
24
|
+
}
|
25
|
+
if (!RCLASS_IV_TBL(module)) {
|
26
|
+
RCLASS_IV_TBL(module) = st_init_numtable();
|
27
|
+
}
|
28
|
+
RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module);
|
29
|
+
RCLASS_M_TBL(klass) = RCLASS_M_TBL(module);
|
30
|
+
RCLASS_SUPER(klass) = super;
|
31
|
+
if (TYPE(module) == T_ICLASS) {
|
32
|
+
RBASIC(klass)->klass = RBASIC(module)->klass;
|
33
|
+
}
|
34
|
+
else {
|
35
|
+
RBASIC(klass)->klass = module;
|
36
|
+
}
|
37
|
+
OBJ_INFECT(klass, module);
|
38
|
+
OBJ_INFECT(klass, super);
|
39
|
+
|
40
|
+
return (VALUE)klass;
|
41
|
+
}
|
42
|
+
|
43
|
+
static void
|
44
|
+
rb_patched_include_module(VALUE klass, VALUE module)
|
45
|
+
{
|
46
|
+
VALUE p, c;
|
47
|
+
int changed = 0;
|
48
|
+
|
49
|
+
rb_frozen_class_p(klass);
|
50
|
+
if (!OBJ_UNTRUSTED(klass)) {
|
51
|
+
rb_secure(4);
|
52
|
+
}
|
53
|
+
|
54
|
+
if (TYPE(module) != T_MODULE) {
|
55
|
+
Check_Type(module, T_MODULE);
|
56
|
+
}
|
57
|
+
|
58
|
+
OBJ_INFECT(klass, module);
|
59
|
+
c = klass;
|
60
|
+
while (module) {
|
61
|
+
int superclass_seen = FALSE;
|
62
|
+
|
63
|
+
if (RCLASS_M_TBL(klass) == RCLASS_M_TBL(module))
|
64
|
+
rb_raise(rb_eArgError, "cyclic include detected");
|
65
|
+
/* ignore if the module included already in superclasses */
|
66
|
+
for (p = RCLASS_SUPER(klass); p; p = RCLASS_SUPER(p)) {
|
67
|
+
switch (BUILTIN_TYPE(p)) {
|
68
|
+
case T_ICLASS:
|
69
|
+
if (RCLASS_M_TBL(p) == RCLASS_M_TBL(module)) {
|
70
|
+
if (!superclass_seen) {
|
71
|
+
c = p; /* move insertion point */
|
72
|
+
}
|
73
|
+
goto skip;
|
74
|
+
}
|
75
|
+
break;
|
76
|
+
case T_CLASS:
|
77
|
+
superclass_seen = TRUE;
|
78
|
+
break;
|
79
|
+
}
|
80
|
+
}
|
81
|
+
c = RCLASS_SUPER(c) = include_class_new(module, RCLASS_SUPER(c));
|
82
|
+
if (RMODULE_M_TBL(module) && RMODULE_M_TBL(module)->num_entries)
|
83
|
+
changed = 1;
|
84
|
+
skip:
|
85
|
+
module = RCLASS_SUPER(module);
|
86
|
+
}
|
87
|
+
if (changed) rb_clear_cache();
|
88
|
+
}
|
89
|
+
|
90
|
+
static VALUE
|
91
|
+
rb_patched_mod_append_features(VALUE module, VALUE include)
|
92
|
+
{
|
93
|
+
switch (TYPE(include)) {
|
94
|
+
case T_CLASS:
|
95
|
+
case T_MODULE:
|
96
|
+
break;
|
97
|
+
default:
|
98
|
+
Check_Type(include, T_CLASS);
|
99
|
+
break;
|
100
|
+
}
|
101
|
+
rb_patched_include_module(include, module);
|
102
|
+
|
103
|
+
return module;
|
104
|
+
}
|
105
|
+
|
106
|
+
void
|
107
|
+
Init_patched_include() {
|
108
|
+
rb_define_method(rb_cModule, "append_features", rb_patched_mod_append_features, 1);
|
109
|
+
}
|
Binary file
|
Binary file
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# (c) 2010 John Mair (banisterfiend), MIT license
|
2
|
+
|
3
|
+
direc = File.dirname(__FILE__)
|
4
|
+
|
5
|
+
begin
|
6
|
+
if RUBY_VERSION && RUBY_VERSION =~ /1.9/
|
7
|
+
require "#{direc}/1.9/include_complete"
|
8
|
+
else
|
9
|
+
require "#{direc}/1.8/include_complete"
|
10
|
+
end
|
11
|
+
rescue LoadError => e
|
12
|
+
require 'rbconfig'
|
13
|
+
dlext = Config::CONFIG['DLEXT']
|
14
|
+
require "#{direc}/include_complete.#{dlext}"
|
15
|
+
end
|
16
|
+
|
17
|
+
require "#{direc}/include_complete/version"
|
18
|
+
|
19
|
+
|
20
|
+
class Module
|
21
|
+
|
22
|
+
# include modules (and their singletons) into an
|
23
|
+
# inheritance chain
|
24
|
+
# @param [Module] mods Modules to include_complete
|
25
|
+
# @return Returns the receiver
|
26
|
+
# @example
|
27
|
+
# module M
|
28
|
+
# def self.hello
|
29
|
+
# puts "hello"
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
# class C
|
33
|
+
# include_complete M
|
34
|
+
# end
|
35
|
+
# C.hello #=> "hello"
|
36
|
+
def include_complete(*mods)
|
37
|
+
mods.each do |mod|
|
38
|
+
include_complete_one mod
|
39
|
+
end
|
40
|
+
self
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class Object
|
45
|
+
|
46
|
+
# extend modules (and their singletons) into an
|
47
|
+
# inheritance chain
|
48
|
+
# @param [Module] mods Modules to extend_complete
|
49
|
+
# @return Returns the receiver
|
50
|
+
# @example
|
51
|
+
# module M
|
52
|
+
# def self.hello
|
53
|
+
# puts "hello"
|
54
|
+
# end
|
55
|
+
# end
|
56
|
+
# o = Object.new
|
57
|
+
# o.extend_complete M
|
58
|
+
# o.singleton_class.hello #=> "hello"
|
59
|
+
def extend_complete(*mods)
|
60
|
+
class << self; self; end.send(:include_complete, *mods)
|
61
|
+
end
|
62
|
+
end
|
data/test/stress_test.rb
ADDED
data/test/test.rb
ADDED
@@ -0,0 +1,262 @@
|
|
1
|
+
direc = File.dirname(__FILE__)
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require "#{direc}/../lib/include_complete"
|
5
|
+
require 'bacon'
|
6
|
+
|
7
|
+
puts "Testing IncludeComplete version #{IncludeComplete::VERSION}..."
|
8
|
+
puts "Ruby version #{RUBY_VERSION}"
|
9
|
+
|
10
|
+
describe 'Including a module into a class using include_complete' do
|
11
|
+
before do
|
12
|
+
@m = Module.new {
|
13
|
+
def self.class_method
|
14
|
+
:class_method
|
15
|
+
end
|
16
|
+
|
17
|
+
def instance_method
|
18
|
+
:instance_method
|
19
|
+
end
|
20
|
+
}
|
21
|
+
|
22
|
+
@m::CONST = :const
|
23
|
+
|
24
|
+
@c = Class.new
|
25
|
+
|
26
|
+
@c.send(:include_complete, @m)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should make class methods accessible to class' do
|
30
|
+
@c.class_method.should.equal :class_method
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should make instance methods accessible to instances of the class' do
|
34
|
+
obj = @c.new
|
35
|
+
obj.instance_method.should.equal :instance_method
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should make constants accessible to the class' do
|
39
|
+
lambda { @c::CONST }.should.not.raise NameError
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe 'Extending a module into a class using extend_complete' do
|
44
|
+
before do
|
45
|
+
@m = Module.new {
|
46
|
+
def self.class_method
|
47
|
+
:class_method
|
48
|
+
end
|
49
|
+
|
50
|
+
def instance_method
|
51
|
+
:instance_method
|
52
|
+
end
|
53
|
+
}
|
54
|
+
|
55
|
+
@m::CONST = :const
|
56
|
+
|
57
|
+
@c = Class.new
|
58
|
+
|
59
|
+
@c.send(:extend_complete, @m)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should make instance methods from the module available as class methods on the class' do
|
63
|
+
@c.instance_method.should.equal :instance_method
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should make class methods from the module available as class methods on the singleton class' do
|
67
|
+
class << @c; self; end.class_method.should.equal :class_method
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
describe 'Including a module into a module and then into a class using include_complete' do
|
73
|
+
before do
|
74
|
+
@m1 = Module.new {
|
75
|
+
def self.class_method1
|
76
|
+
:class_method1
|
77
|
+
end
|
78
|
+
|
79
|
+
def instance_method1
|
80
|
+
:instance_method1
|
81
|
+
end
|
82
|
+
}
|
83
|
+
|
84
|
+
@m1::CONST1 = :const1
|
85
|
+
|
86
|
+
@m2 = Module.new {
|
87
|
+
def self.class_method2
|
88
|
+
:class_method2
|
89
|
+
end
|
90
|
+
|
91
|
+
def instance_method2
|
92
|
+
:instance_method2
|
93
|
+
end
|
94
|
+
}
|
95
|
+
@m2.send(:include_complete, @m1)
|
96
|
+
|
97
|
+
@m2::CONST2 = :const2
|
98
|
+
|
99
|
+
@c = Class.new
|
100
|
+
|
101
|
+
@c.send(:include_complete, @m2)
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'should make class methods on m1 accessible to m2' do
|
105
|
+
@m2.class_method1.should.equal :class_method1
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'should make constants on m1 and m2 accessible to class' do
|
109
|
+
lambda { @c::CONST1 == :const1 }.should.not.raise NameError
|
110
|
+
lambda { @m2::CONST1 == :const1 }.should.not.raise NameError
|
111
|
+
lambda { @c::CONST2 == :const2 }.should.not.raise NameError
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'should make class methods on modules m1 and m2 accessible to class' do
|
115
|
+
@c.class_method1.should.equal :class_method1
|
116
|
+
@c.class_method2.should.equal :class_method2
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'should make instance methods on modules m1 and m2 accessible to instances of class' do
|
120
|
+
obj = @c.new
|
121
|
+
|
122
|
+
obj.instance_method1.should.equal :instance_method1
|
123
|
+
obj.instance_method2.should.equal :instance_method2
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'should make ancestor chain "look" accurate' do
|
127
|
+
@m1 = Module.new {
|
128
|
+
def self.class_method1
|
129
|
+
:class_method1
|
130
|
+
end
|
131
|
+
|
132
|
+
def instance_method1
|
133
|
+
:instance_method1
|
134
|
+
end
|
135
|
+
}
|
136
|
+
|
137
|
+
Object.const_set(:M1, @m1)
|
138
|
+
|
139
|
+
@m2 = Module.new {
|
140
|
+
def self.class_method2
|
141
|
+
:class_method2
|
142
|
+
end
|
143
|
+
|
144
|
+
def instance_method2
|
145
|
+
:instance_method2
|
146
|
+
end
|
147
|
+
}
|
148
|
+
Object.const_set(:M2, @m2)
|
149
|
+
|
150
|
+
@m2.send(:include_complete, @m1)
|
151
|
+
|
152
|
+
@c = Class.new
|
153
|
+
|
154
|
+
@c.send(:include_complete, @m2)
|
155
|
+
|
156
|
+
@c.ancestors[1].to_s.should.equal M2.name
|
157
|
+
@c.class_method1.should.equal :class_method1
|
158
|
+
@c.class_method2.should.equal :class_method2
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'should work if real_including a module that has another module included using Module#include' do
|
162
|
+
@m1 = Module.new {
|
163
|
+
def self.class_method1
|
164
|
+
:class_method1
|
165
|
+
end
|
166
|
+
|
167
|
+
def instance_method1
|
168
|
+
:instance_method1
|
169
|
+
end
|
170
|
+
}
|
171
|
+
|
172
|
+
Object.const_set(:N1, @m1)
|
173
|
+
|
174
|
+
@m2 = Module.new {
|
175
|
+
def self.class_method2
|
176
|
+
:class_method2
|
177
|
+
end
|
178
|
+
|
179
|
+
def instance_method2
|
180
|
+
:instance_method2
|
181
|
+
end
|
182
|
+
}
|
183
|
+
Object.const_set(:N2, @m2)
|
184
|
+
|
185
|
+
@m2.send(:include, @m1)
|
186
|
+
|
187
|
+
@c = Class.new
|
188
|
+
|
189
|
+
@c.send(:include_complete, @m2)
|
190
|
+
|
191
|
+
@c.ancestors[1].to_s.should.equal N2.name
|
192
|
+
@c.ancestors[2].to_s.should.equal N1.name
|
193
|
+
@c.class_method1.should.equal :class_method1
|
194
|
+
@c.class_method2.should.equal :class_method2
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'should work if Module#including a module that has another module included using include_complete' do
|
198
|
+
@m1 = Module.new {
|
199
|
+
def self.class_method1
|
200
|
+
:class_method1
|
201
|
+
end
|
202
|
+
|
203
|
+
def instance_method1
|
204
|
+
:instance_method1
|
205
|
+
end
|
206
|
+
}
|
207
|
+
|
208
|
+
Object.const_set(:K1, @m1)
|
209
|
+
|
210
|
+
@m2 = Module.new {
|
211
|
+
def self.class_method2
|
212
|
+
:class_method2
|
213
|
+
end
|
214
|
+
|
215
|
+
def instance_method2
|
216
|
+
:instance_method2
|
217
|
+
end
|
218
|
+
}
|
219
|
+
Object.const_set(:K2, @m2)
|
220
|
+
|
221
|
+
@m2.send(:include_complete, @m1)
|
222
|
+
|
223
|
+
@c = Class.new
|
224
|
+
|
225
|
+
@c.send(:include, @m2)
|
226
|
+
|
227
|
+
@c.ancestors[1].should.equal K2
|
228
|
+
@c.ancestors[2].should.equal K1
|
229
|
+
@c.new.instance_method1.should.equal :instance_method1
|
230
|
+
@c.new.instance_method2.should.equal :instance_method2
|
231
|
+
end
|
232
|
+
|
233
|
+
|
234
|
+
it 'should work with multiple modules passed to include_complete' do
|
235
|
+
@m1 = Module.new {
|
236
|
+
def self.class_method1
|
237
|
+
:class_method1
|
238
|
+
end
|
239
|
+
|
240
|
+
def instance_method1
|
241
|
+
:instance_method1
|
242
|
+
end
|
243
|
+
}
|
244
|
+
|
245
|
+
@m2 = Module.new {
|
246
|
+
def self.class_method2
|
247
|
+
:class_method2
|
248
|
+
end
|
249
|
+
|
250
|
+
def instance_method2
|
251
|
+
:instance_method2
|
252
|
+
end
|
253
|
+
}
|
254
|
+
|
255
|
+
@c = Class.new
|
256
|
+
@c.send(:include_complete, @m2, @m1)
|
257
|
+
|
258
|
+
@c.class_method1.should.equal :class_method1
|
259
|
+
@c.class_method2.should.equal :class_method2
|
260
|
+
end
|
261
|
+
|
262
|
+
end
|
metadata
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: include_complete
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: i386-mswin32
|
12
|
+
authors:
|
13
|
+
- John Mair (banisterfiend)
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-11-01 00:00:00 +13:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: Fixing the limitations in traditional Module#include
|
23
|
+
email: jrmair@gmail.com
|
24
|
+
executables: []
|
25
|
+
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files: []
|
29
|
+
|
30
|
+
files:
|
31
|
+
- Rakefile
|
32
|
+
- README.markdown
|
33
|
+
- CHANGELOG
|
34
|
+
- lib/include_complete/version.rb
|
35
|
+
- lib/include_complete.rb
|
36
|
+
- ext/include_complete/extconf.rb
|
37
|
+
- ext/include_complete/compat.h
|
38
|
+
- ext/include_complete/include_complete.c
|
39
|
+
- ext/include_complete/include_complete_one.c
|
40
|
+
- ext/include_complete/patched_include.c
|
41
|
+
- test/stress_test.rb
|
42
|
+
- test/test.rb
|
43
|
+
- lib/1.8/include_complete.so
|
44
|
+
- lib/1.9/include_complete.so
|
45
|
+
has_rdoc: yard
|
46
|
+
homepage: http://banisterfiend.wordpress.com
|
47
|
+
licenses: []
|
48
|
+
|
49
|
+
post_install_message:
|
50
|
+
rdoc_options: []
|
51
|
+
|
52
|
+
require_paths:
|
53
|
+
- lib
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
hash: 3
|
60
|
+
segments:
|
61
|
+
- 0
|
62
|
+
version: "0"
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
hash: 3
|
69
|
+
segments:
|
70
|
+
- 0
|
71
|
+
version: "0"
|
72
|
+
requirements: []
|
73
|
+
|
74
|
+
rubyforge_project:
|
75
|
+
rubygems_version: 1.3.7
|
76
|
+
signing_key:
|
77
|
+
specification_version: 3
|
78
|
+
summary: Fixing the limitations in traditional Module#include
|
79
|
+
test_files: []
|
80
|
+
|