Skip to content

Commit

Permalink
Fix multiple issues with const access using :: forms.
Browse files Browse the repository at this point in the history
* Symbols with :: should raise errors.
* Leading :: starts from Object (fixes #1487).
* const_defined? supports :: too (fixes #2319).
  • Loading branch information
headius committed Jan 14, 2015
1 parent a2ef35f commit 5868779
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 7 deletions.
39 changes: 35 additions & 4 deletions core/src/main/java/org/jruby/RubyModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -2792,11 +2792,33 @@ public RubyBoolean const_defined_p(ThreadContext context, IRubyObject symbol) {

@JRubyMethod(name = "const_defined?", required = 1, optional = 1)
public RubyBoolean const_defined_p19(ThreadContext context, IRubyObject[] args) {
IRubyObject symbol = args[0];
Ruby runtime = context.runtime;
String fullName = args[0].asJavaString();
String symbol = fullName;
boolean inherit = args.length == 1 || (!args[1].isNil() && args[1].isTrue());

// Note: includes part of fix for JRUBY-1339
return context.runtime.newBoolean(fastIsConstantDefined19(validateConstant(symbol).intern(), inherit));
// symbol form does not allow ::
if (args[0] instanceof RubySymbol && symbol.indexOf("::") != -1) {
throw runtime.newNameError("wrong constant name", symbol);
}

RubyModule mod = this;

if (symbol.startsWith("::")) mod = runtime.getObject();

int sep;
while((sep = symbol.indexOf("::")) != -1) {
String segment = symbol.substring(0, sep);
symbol = symbol.substring(sep + 2);
IRubyObject obj = mod.getConstantNoConstMissing(validateConstant(segment, args[0]), inherit, inherit);
if(obj instanceof RubyModule) {
mod = (RubyModule)obj;
} else {
throw runtime.newTypeError(segment + " does not refer to class/module");
}
}

return runtime.newBoolean(mod.getConstantNoConstMissing(validateConstant(symbol, args[0]), inherit, inherit) != null);
}

/** rb_mod_const_get
Expand All @@ -2812,11 +2834,20 @@ public IRubyObject const_get_1_9(ThreadContext context, IRubyObject[] args) {

@JRubyMethod(name = "const_get", required = 1, optional = 1)
public IRubyObject const_get_2_0(ThreadContext context, IRubyObject[] args) {
Ruby runtime = context.runtime;
String fullName = args[0].asJavaString();
String symbol = fullName;
boolean inherit = args.length == 1 || (!args[1].isNil() && args[1].isTrue());

// symbol form does not allow ::
if (args[0] instanceof RubySymbol && symbol.indexOf("::") != -1) {
throw context.runtime.newNameError("wrong constant name", symbol);
}

RubyModule mod = this;

if (symbol.startsWith("::")) mod = runtime.getObject();

int sep;
while((sep = symbol.indexOf("::")) != -1) {
String segment = symbol.substring(0, sep);
Expand All @@ -2825,7 +2856,7 @@ public IRubyObject const_get_2_0(ThreadContext context, IRubyObject[] args) {
if(obj instanceof RubyModule) {
mod = (RubyModule)obj;
} else {
throw context.runtime.newTypeError(segment + " does not refer to class/module");
throw runtime.newTypeError(segment + " does not refer to class/module");
}
}

Expand Down
3 changes: 0 additions & 3 deletions test/mri/excludes/TestModule.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@
exclude :test_leading_colons, "needs investigation"
exclude :test_method_added, "needs investigation"
exclude :test_method_redefinition, "needs investigation"
exclude :test_nested_defined, "needs investigation"
exclude :test_nested_defined_bad_class, "needs investigation"
exclude :test_nested_get_symbol, "needs investigation"
exclude :test_private_constant_reopen, "needs investigation"
exclude :test_private_constant_with_no_args, "needs investigation"
exclude :test_private_top_methods, "needs investigation"
Expand Down

0 comments on commit 5868779

Please sign in to comment.