Skip to content

Commit

Permalink
Support anonymous classes in Module#name
Browse files Browse the repository at this point in the history
  • Loading branch information
adambeynon committed Oct 20, 2013
1 parent e5103ad commit 1207c2c
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 10 deletions.
30 changes: 28 additions & 2 deletions corelib/module.rb
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,33 @@ def module_function(*methods)
end

def name
`#{self}._name`
%x{
if (self._full_name) {
return self._full_name;
}
var result = [], base = self;
while (base) {
if (base._name === nil) {
return result.length === 0 ? nil : result.join('::');
}
result.unshift(base._name);
base = base._base_module;
if (base === $opal.Object) {
break;
}
}
if (result.length === 0) {
return nil;
}
return self._full_name = result.join('::');
}
end

def public(*)
Expand Down Expand Up @@ -429,7 +455,7 @@ def remove_const(name)
end

def to_s
`#{self}._name`
name.to_s
end

def undef_method(symbol)
Expand Down
16 changes: 8 additions & 8 deletions corelib/runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
var const_scope = const_alloc.prototype = new base.constructor();
klass._scope = const_scope;
const_scope.base = klass;
klass._base_module = base.base;
const_scope.constructor = const_alloc;
const_scope.constants = [];

Expand Down Expand Up @@ -143,7 +144,7 @@
klass = boot_class(superklass, constructor);

// name class using base (e.g. Foo or Foo::Baz)
klass._name = (base === RubyObject ? id : base._name + '::' + id);
klass._name = id;

// every class gets its own constant scope, inherited from current scope
create_scope(base._scope, klass, id);
Expand Down Expand Up @@ -216,7 +217,7 @@
}
else {
module = boot_module()
module._name = (base === RubyObject ? id : base._name + '::' + id);
module._name = id;

create_scope(base._scope, module, id);

Expand Down Expand Up @@ -339,12 +340,11 @@
var scope = base_module._scope;

if (value._isClass && value._name === nil) {
if (base_module === RubyObject) {
value._name = name;
}
else {
value._name = base_module._name + '::' + name;
}
value._name = name;
}

if (value._isClass) {
value._base_module = base_module;
}

scope.constants.push(name);
Expand Down
52 changes: 52 additions & 0 deletions spec/opal/module/name_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
require 'spec_helper'

module ModuleNameSpec
module A
class B
end
end
end

describe "Module#name" do
it "should return the class name for boot types" do
BasicObject.name.should == "BasicObject"
Object.name.should == "Object"
Class.name.should == "Class"
Module.name.should == "Module"
end

it "should return class name for bridged classes" do
Array.name.should == "Array"
end

it "should return name for modules and classes" do
Enumerator.name.should == "Enumerator"
Enumerable.name.should == "Enumerable"
end

it "should return nil for anonymous class" do
Class.new.name.should == nil
end

it "should join nested classes using '::'" do
ModuleNameSpec::A.name.should == "ModuleNameSpec::A"
ModuleNameSpec::A::B.name.should == "ModuleNameSpec::A::B"
end

it "uses just child name when class set inside anonymous parent" do
a = Class.new
b = Class.new
a.const_set :Child, b
b.name.should == "Child"
end

it "uses parent name once parent anonymous class gets name" do
a = Class.new
b = Class.new
a.const_set :Child, b
b.name.should == "Child"

ModuleNameSpec.const_set :Parent, a
b.name.should == "ModuleNameSpec::Parent::Child"
end
end

0 comments on commit 1207c2c

Please sign in to comment.