Repository: asciidoctor/asciidoctorj
Issue: (RuntimeError) can't modify frozen NilClass on getParent()

When `getParent()` is called on the root `ContentNode` (where `null` is expected), a ruby `RuntimeError` is thrown.

Code to reproduce it:

    public static void main(String[] args) {
        String s = "== A small Example\\n" +
                "\\n" +
                "Lorem ipsum dolor sit amet:\\n";

        org.asciidoctor.Asciidoctor asciidoctor = org.asciidoctor.Asciidoctor.Factory.create();
        org.asciidoctor.ast.Document document = asciidoctor.load(s, new java.util.HashMap<String, Object>());
        org.asciidoctor.ast.ContentNode parent = document.getParent(); // Runtime error here!
        System.out.println(parent);
    }

Using `org.asciidoctor: asciidoctorj:1.6.0-alpha.6` as dependency.

Error is:
> Exception in thread "main" org.jruby.exceptions.RaiseException: (RuntimeError) can't modify frozen NilClass

---

The code works with `org.asciidoctor:asciidoctorj:1.5.6` (the code needs to be modified, because the API changed):

    public static void main(String[] args) {
        String s = "== A small Example\\n" +
                "\\n" +
                "Lorem ipsum dolor sit amet:\\n";

        org.asciidoctor.Asciidoctor asciidoctor = org.asciidoctor.Asciidoctor.Factory.create();
        org.asciidoctor.ast.Document document = asciidoctor.load(s, new java.util.HashMap<String, Object>());
        org.asciidoctor.ast.AbstractNode parent = document.getParent();
        System.out.println(parent);
    }

This works: `parent` is `null` as expected.


Changed files:
asciidoctorj-core/src/main/java/org/asciidoctor/ast/NodeConverter.java
asciidoctorj-core/src/test/java/org/asciidoctor/WhenAsciiDocIsRenderedToDocument.java

diff --git a/asciidoctorj-core/src/main/java/org/asciidoctor/ast/NodeConverter.java b/asciidoctorj-core/src/main/java/org/asciidoctor/ast/NodeConverter.java
index 9dbb8ed0..bdd04a6a 100644
--- a/asciidoctorj-core/src/main/java/org/asciidoctor/ast/NodeConverter.java
+++ b/asciidoctorj-core/src/main/java/org/asciidoctor/ast/NodeConverter.java
@@ -126,15 +126,16 @@ public final class NodeConverter {
 
         if (object instanceof IRubyObject || object instanceof RubyObjectHolderProxy) {
             IRubyObject rubyObject = asRubyObject(object);
+            if (rubyObject.isNil()) {
+                return null;
+            }
             NodeCache nodeCache = NodeCache.get(rubyObject);
             ContentNode cachedNode = nodeCache.getASTNode();
             if (cachedNode != null) {
                 return cachedNode;
             }
 
-            Ruby runtime = rubyObject.getRuntime();
-
-            ContentNode ret = null;
+            ContentNode ret;
 
             switch (NodeType.getNodeType(rubyObject)) {
                 case BLOCK_CLASS:
diff --git a/asciidoctorj-core/src/test/java/org/asciidoctor/WhenAsciiDocIsRenderedToDocument.java b/asciidoctorj-core/src/test/java/org/asciidoctor/WhenAsciiDocIsRenderedToDocument.java
index 1ac0b756..4f848e38 100644
--- a/asciidoctorj-core/src/test/java/org/asciidoctor/WhenAsciiDocIsRenderedToDocument.java
+++ b/asciidoctorj-core/src/test/java/org/asciidoctor/WhenAsciiDocIsRenderedToDocument.java
@@ -1,25 +1,9 @@
 package org.asciidoctor;
 
-import static org.hamcrest.Matchers.either;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.greaterThan;
-import static org.hamcrest.Matchers.nullValue;
-import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
-import static org.hamcrest.collection.IsMapContaining.hasKey;
-import static org.hamcrest.collection.IsIterableContainingInOrder.contains;
-import static org.junit.Assert.assertThat;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 import org.asciidoctor.arquillian.api.Unshared;
-import org.asciidoctor.ast.StructuralNode;
 import org.asciidoctor.ast.Document;
 import org.asciidoctor.ast.Section;
+import org.asciidoctor.ast.StructuralNode;
 import org.asciidoctor.internal.IOUtils;
 import org.asciidoctor.util.ClasspathResources;
 import org.jboss.arquillian.junit.Arquillian;
@@ -27,6 +11,22 @@ import org.jboss.arquillian.test.api.ArquillianResource;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.hamcrest.Matchers.either;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
+import static org.hamcrest.collection.IsIterableContainingInOrder.contains;
+import static org.hamcrest.collection.IsMapContaining.hasKey;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+
 @RunWith(Arquillian.class)
 public class WhenAsciiDocIsRenderedToDocument {
 
@@ -341,4 +341,15 @@ public class WhenAsciiDocIsRenderedToDocument {
         assertThat(section.getContentModel(), is("compound"));
         assertThat(section.getBlocks().get(0).getContentModel(), is("simple"));
     }
+
+    @Test
+    public void should_be_able_to_get_parent_from_document() {
+        String s = "== A small Example\\n" +
+            "\\n" +
+            "Lorem ipsum dolor sit amet:\\n";
+
+        Document document = asciidoctor.load(s, new HashMap<String, Object>());
+        assertNull(document.getParent());
+    }
+
 }