diff options
| author | Dan Allen <dan.j.allen@gmail.com> | 2018-03-24 01:28:47 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-03-24 01:28:47 -0600 |
| commit | c5122e926f185645ffb153a40fcc0900166704da (patch) | |
| tree | 04d3122d3106b9caa642e1f6ca9400d417725e54 | |
| parent | bd1c5288dcb6ed2bea61ddbdd3142e470b77fec6 (diff) | |
resolves #2622 raise clearer exception when extension class cannot be resolved (PR #2623)
- split impl of class_for_name by Ruby version
- add tests to verify correct error message is thrown when passed an illegal constant name
- add tests to verify top-level class is not resolved when namespaced class is requested
| -rw-r--r-- | lib/asciidoctor/extensions.rb | 35 | ||||
| -rw-r--r-- | test/extensions_test.rb | 42 |
2 files changed, 68 insertions, 9 deletions
diff --git a/lib/asciidoctor/extensions.rb b/lib/asciidoctor/extensions.rb index 4e9b34d8..acb8988e 100644 --- a/lib/asciidoctor/extensions.rb +++ b/lib/asciidoctor/extensions.rb @@ -1481,17 +1481,36 @@ module Extensions # Public: Resolves the Class object for the qualified name. # # Returns Class - def class_for_name qualified_name - resolved = ::Object - (qualified_name.split '::').each do |name| - unless name.empty? || ((resolved.const_defined? name) && ::Module === (resolved = resolved.const_get name)) - raise ::NameError, %(Could not resolve class for name: #{qualified_name}) + if RUBY_MIN_VERSION_2 + def class_for_name qualified_name + resolved = ::Object.const_get qualified_name, false + raise unless ::Class === resolved + resolved + rescue + raise ::NameError, %(Could not resolve class for name: #{qualified_name}) + end + elsif RUBY_MIN_VERSION_1_9 + def class_for_name qualified_name + resolved = (qualified_name.split '::').reduce ::Object do |current, name| + name.empty? ? current : (current.const_get name, false) + end + raise unless ::Class === resolved + resolved + rescue + raise ::NameError, %(Could not resolve class for name: #{qualified_name}) + end + else + def class_for_name qualified_name + resolved = (qualified_name.split '::').reduce ::Object do |current, name| + # NOTE on Ruby 1.8, const_defined? only checks for constant in current scope + name.empty? ? current : ((current.const_defined? name) ? (current.const_get name) : raise) end + raise unless ::Class === resolved + resolved + rescue + raise ::NameError, %(Could not resolve class for name: #{qualified_name}) end - raise ::NameError, %(Could not resolve class for name: #{qualified_name}) unless ::Class === resolved - resolved end end - end end diff --git a/test/extensions_test.rb b/test/extensions_test.rb index b4f3d51e..c2d3ea6a 100644 --- a/test/extensions_test.rb +++ b/test/extensions_test.rb @@ -340,6 +340,24 @@ context 'Extensions' do end end + test 'should raise exception if constant name is invalid' do + begin + Asciidoctor::Extensions.class_for_name 'foobar' + flunk 'Expecting RuntimeError to be raised' + rescue NameError => e + assert_equal 'Could not resolve class for name: foobar', e.message + end + end + + test 'should raise exception if class not found in scope' do + begin + Asciidoctor::Extensions.class_for_name 'Asciidoctor::Extensions::String' + flunk 'Expecting RuntimeError to be raised' + rescue NameError => e + assert_equal 'Could not resolve class for name: Asciidoctor::Extensions::String', e.message + end + end + test 'should raise exception if name resolves to module' do begin Asciidoctor::Extensions.class_for_name 'Asciidoctor::Extensions' @@ -361,6 +379,29 @@ context 'Extensions' do assert_equal Asciidoctor::Document, clazz end + test 'should not resolve class if not in scope' do + begin + Asciidoctor::Extensions.resolve_class 'Asciidoctor::Extensions::String' + flunk 'Expecting RuntimeError to be raised' + rescue NameError => e + assert_equal 'Could not resolve class for name: Asciidoctor::Extensions::String', e.message + end + end + + test 'should raise NameError if extension class cannot be resolved from string' do + begin + Asciidoctor::Extensions.register do + block 'foobar' + end + doc = empty_document + flunk 'Expecting RuntimeError to be raised' + rescue NameError => e + assert_equal 'Could not resolve class for name: foobar', e.message + ensure + Asciidoctor::Extensions.unregister_all + end + end + test 'should allow standalone registry to be created but not registered' do registry = Asciidoctor::Extensions.create 'sample' do block do @@ -1197,7 +1238,6 @@ sample content end end - test 'should add multiple docinfo to document' do input = <<-EOS = Document Title |
