Permalink
Browse files

Merge pull request #4639 from MSNexploder/module_order

Fix Module inclusion order
  • Loading branch information...
headius committed Jun 6, 2017
2 parents 6e79faf + 5b036d9 commit d47687ac2de03e1ae6f40dbbbc01b7f63c1a50df
Showing with 22 additions and 27 deletions.
  1. +20 −26 core/src/main/java/org/jruby/RubyModule.java
  2. +1 −0 test/jruby.index
  3. +1 −1 test/{ → jruby}/test_include_order.rb
@@ -2936,14 +2936,17 @@ private void doIncludeModule(RubyModule baseModule) {
// nextClass.isIncluded() && nextClass.getNonIncludedClass() == nextModule.getNonIncludedClass();
// scan class hierarchy for module
for (RubyClass nextClass = methodLocation.getSuperClass(); nextClass != null; nextClass = nextClass.getSuperClass()) {
if (doesTheClassWrapTheModule(nextClass, nextModule)) {
// next in hierarchy is an included version of the module we're attempting,
// so we skip including it
if (nextClass.isIncluded()) {
// does the class equal the module
if (nextClass.getDelegate() == nextModule.getDelegate()) {
// next in hierarchy is an included version of the module we're attempting,
// so we skip including it
// if we haven't encountered a real superclass, use the found module as the new inclusion point
if (!superclassSeen) currentInclusionPoint = nextClass;
// if we haven't encountered a real superclass, use the found module as the new inclusion point
if (!superclassSeen) currentInclusionPoint = nextClass;
continue ModuleLoop;
continue ModuleLoop;
}
} else {
superclassSeen = true;
}
@@ -2992,36 +2995,27 @@ private void doPrependModule(RubyModule baseModule) {
boolean superclassSeen = false;
// scan class hierarchy for module
for (RubyClass nextClass = this.getSuperClass(); nextClass != null; nextClass = nextClass.getSuperClass()) {
if (doesTheClassWrapTheModule(nextClass, nextModule)) {
// next in hierarchy is an included version of the module we're attempting,
// so we skip including it
for (RubyClass nextClass = methodLocation.getSuperClass(); nextClass != null; nextClass = nextClass.getSuperClass()) {
if (nextClass.isIncluded()) {
// does the class equal the module
if (nextClass.getDelegate() == nextModule.getDelegate()) {
// next in hierarchy is an included version of the module we're attempting,
// so we skip including it
// if we haven't encountered a real superclass, use the found module as the new inclusion point
if (!superclassSeen) currentInclusionPoint = nextClass;
// if we haven't encountered a real superclass, use the found module as the new inclusion point
if (!superclassSeen) currentInclusionPoint = nextClass;
continue ModuleLoop;
continue ModuleLoop;
}
} else {
superclassSeen = true;
}
}
currentInclusionPoint = proceedWithPrepend(currentInclusionPoint, nextModule);
currentInclusionPoint = proceedWithPrepend(currentInclusionPoint, nextModule.getDelegate());
}
}
/**
* Is the given class a wrapper for the specified module?
*
* @param theClass The class to inspect
* @param theModule The module we're looking for
* @return true if the class is a wrapper for the module, false otherwise
*/
private boolean doesTheClassWrapTheModule(RubyClass theClass, RubyModule theModule) {
return theClass.isIncluded() &&
theClass.getDelegate() == theModule.getDelegate();
}
/**
* Gather all modules that would be included by including the given module.
* The resulting list contains the given module and its (zero or more)
View
@@ -34,6 +34,7 @@ jruby/test_frame_self
jruby/test_hash
jruby/test_higher_javasupport
jruby/test_ifaddr
jruby/test_include_order
jruby/test_included_in_object_space
jruby/test_integer_overflows
jruby/test_ivar_table_integrity
@@ -44,4 +44,4 @@ class Y
def test_include_order
assert_equal Y.new.foo, [:Z, :A, :Q]
end
end
end

0 comments on commit d47687a

Please sign in to comment.