Clean up yang parser.
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / util / ParserUtils.xtend
index 80b51988d168043be20a9dbc26a8e1ee013caf62..9f03e79850f8c14c7ae5e482497eebc0e709ec2e 100644 (file)
@@ -12,11 +12,13 @@ import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.TreeMap;
 
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.ModuleImport;
 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
@@ -35,11 +37,13 @@ import org.opendaylight.yangtools.yang.parser.builder.impl.ChoiceBuilder.ChoiceN
 import org.opendaylight.yangtools.yang.parser.builder.impl.ChoiceCaseBuilder;
 import org.opendaylight.yangtools.yang.parser.builder.impl.ChoiceCaseBuilder.ChoiceCaseNodeImpl;
 import org.opendaylight.yangtools.yang.parser.builder.impl.ContainerSchemaNodeBuilder.ContainerSchemaNodeImpl;
-import org.opendaylight.yangtools.yang.parser.builder.impl.IdentityrefTypeBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.impl.IdentitySchemaNodeBuilder;
 import org.opendaylight.yangtools.yang.parser.builder.impl.ListSchemaNodeBuilder.ListSchemaNodeImpl;
 import org.opendaylight.yangtools.yang.parser.builder.impl.ModuleBuilder;
 import org.opendaylight.yangtools.yang.parser.builder.impl.NotificationBuilder.NotificationDefinitionImpl;
 import org.opendaylight.yangtools.yang.model.api.AugmentationTarget
+import org.opendaylight.yangtools.yang.parser.builder.impl.RpcDefinitionBuilder
+import org.opendaylight.yangtools.yang.parser.builder.api.GroupingMember
 
 public final class ParserUtils {
 
@@ -202,22 +206,49 @@ public final class ParserUtils {
     public static def void fillAugmentTarget(AugmentationSchemaBuilder augment, DataNodeContainerBuilder target) {
         for (DataSchemaNodeBuilder child : augment.getChildNodeBuilders()) {
             val childCopy = CopyUtils.copy(child, target, false);
-            childCopy.setAugmenting(true);
+            if (augment.parent instanceof UsesNodeBuilder) {
+                setNodeAddedByUses(childCopy);
+            }
+            setNodeAugmenting(childCopy);
             correctNodePath(child, target.getPath());
             correctNodePath(childCopy, target.getPath());
             try {
                 target.addChildNode(childCopy);
             } catch (YangParseException e) {
-
                 // more descriptive message
                 throw new YangParseException(augment.getModuleName(), augment.getLine(),
                     "Failed to perform augmentation: " + e.getMessage());
             }
+        }
+    }
 
+    private static def void setNodeAugmenting(DataSchemaNodeBuilder child) {
+        child.setAugmenting(true);
+        if (child instanceof DataNodeContainerBuilder) {
+            val DataNodeContainerBuilder dataNodeChild = child as DataNodeContainerBuilder;
+            for (inner : dataNodeChild.getChildNodeBuilders()) {
+                setNodeAugmenting(inner);
+            }
+        } else if (child instanceof ChoiceBuilder) {
+            val ChoiceBuilder choiceChild = child as ChoiceBuilder;
+            for (inner : choiceChild.cases) {
+                setNodeAugmenting(inner);
+            }
         }
-        for (UsesNodeBuilder usesNode : augment.getUsesNodes()) {
-            val copy = CopyUtils.copyUses(usesNode, target);
-            target.addUsesNode(copy);
+    }
+
+    public static def void setNodeAddedByUses(GroupingMember child) {
+        child.setAddedByUses(true);
+        if (child instanceof DataNodeContainerBuilder) {
+            val DataNodeContainerBuilder dataNodeChild = child as DataNodeContainerBuilder;
+            for (inner : dataNodeChild.getChildNodeBuilders()) {
+                setNodeAddedByUses(inner);
+            }
+        } else if (child instanceof ChoiceBuilder) {
+            val ChoiceBuilder choiceChild = child as ChoiceBuilder;
+            for (inner : choiceChild.cases) {
+                setNodeAddedByUses(inner);
+            }
         }
     }
 
@@ -232,7 +263,10 @@ public final class ParserUtils {
     public static def void fillAugmentTarget(AugmentationSchemaBuilder augment, ChoiceBuilder target) {
         for (DataSchemaNodeBuilder builder : augment.getChildNodeBuilders()) {
             val childCopy = CopyUtils.copy(builder, target, false);
-            childCopy.setAugmenting(true);
+            if (augment.parent instanceof UsesNodeBuilder) {
+                setNodeAddedByUses(childCopy);
+            }
+            setNodeAugmenting(childCopy)
             correctNodePath(builder, target.getPath());
             correctNodePath(childCopy, target.getPath());
             target.addCase(childCopy);
@@ -240,7 +274,7 @@ public final class ParserUtils {
         for (UsesNodeBuilder usesNode : augment.getUsesNodes()) {
             if (usesNode !== null) {
                 throw new YangParseException(augment.getModuleName(), augment.getLine(),
-                    "Error in augment parsing: cannot augment uses to choice");
+                    "Error in augment parsing: cannot augment choice with nodes from grouping");
             }
         }
     }
@@ -254,7 +288,6 @@ public final class ParserUtils {
      *            schema path of node parent
      */
     static def void correctNodePath(SchemaNodeBuilder node, SchemaPath parentSchemaPath) {
-
         // set correct path
         val targetNodePath = new ArrayList<QName>(parentSchemaPath.getPath());
         targetNodePath.add(node.getQName());
@@ -278,7 +311,6 @@ public final class ParserUtils {
     }
 
 
-
     private static def Builder findNode(Builder firstNodeParent, List<QName> path, String moduleName, int line) {
         var currentName = "";
         var currentParent = firstNodeParent;
@@ -294,22 +326,27 @@ public final class ParserUtils {
                 var SchemaNodeBuilder nodeFound = dataNodeContainerParent.getDataChildByName(currentName);
                 // if not found, search in notifications
                 if (nodeFound == null && currentParent instanceof ModuleBuilder) {
-                       nodeFound = searchNotifications(currentParent as ModuleBuilder, currentName);
+                    nodeFound = searchNotifications(currentParent as ModuleBuilder, currentName);
+                }
+                // if not found, search in rpcs
+                if (nodeFound == null && currentParent instanceof ModuleBuilder) {
+                    nodeFound = searchRpcs(currentParent as ModuleBuilder, currentName);
                 }
-                // if not found, search in uses
                 if (nodeFound == null) {
-                    var found = searchUses(dataNodeContainerParent, currentName);
-                    if(found == null) {
-                        return null;
-                    } else {
-                        currentParent = found;
-                    }
+                    return null
                 } else {
-                    currentParent = nodeFound;
+                    currentParent = nodeFound
                 }
             } else if (currentParent instanceof ChoiceBuilder) {
                 val choiceParent = currentParent as ChoiceBuilder;
                 currentParent = choiceParent.getCaseNodeByName(currentName);
+            } else if (currentParent instanceof RpcDefinitionBuilder) {
+                val rpc = currentParent as RpcDefinitionBuilder;
+                if ("input".equals(currentName)) {
+                    currentParent = rpc.input;
+                } else if ("output".equals(currentName)) {
+                    currentParent = rpc.output;
+                }
             } else {
                 throw new YangParseException(moduleName, line,
                         "Error in augment parsing: failed to find node " + currentName);
@@ -333,36 +370,15 @@ public final class ParserUtils {
         return null;
     }
 
-    private static def searchUses(DataNodeContainerBuilder dataNodeContainerParent, String name) {
-        var currentName = name;
-        for (unb : dataNodeContainerParent.usesNodes) {
-            val result = findNodeInUses(currentName, unb);
-            if (result != null) {
-                var copy = CopyUtils.copy(result, unb.getParent(), true);
-                unb.getTargetChildren().add(copy);
-                return copy;
-            }
-        }
-        return null;
-    }
-    
-    public static def getRpc(ModuleBuilder module,String name) {
-        for(rpc : module.rpcs) {
-            if(name == rpc.QName.localName) {
+    private static def searchRpcs(ModuleBuilder parent, String name) {
+        for(rpc : parent.rpcs) {
+            if(rpc.getQName().localName.equals(name)) {
                 return rpc;
             }
         }
         return null;
     }
-    
-    public static def getNotification(ModuleBuilder module,String name) {
-        for(notification : module.notifications) {
-            if(name == notification.QName.localName) {
-                return notification;
-            }
-        }
-    }
-    
+
     private static def nextLevel(List<QName> path){
         return path.subList(1,path.size)
     }
@@ -377,62 +393,30 @@ public final class ParserUtils {
      *            path to augment target
      * @return true if augmentation process succeed, false otherwise
      */
-    public static def boolean processAugmentation(AugmentationSchemaBuilder augment, Builder firstNodeParent,
-        List<QName> path) {
-
-            // traverse augment target path and try to reach target node
-            val targetNode = findNode(firstNodeParent,path,augment.moduleName,augment.line);
-            if (targetNode === null) return false;
-            
-            if ((targetNode instanceof DataNodeContainerBuilder)) {
-               val targetDataNodeContainer = targetNode as DataNodeContainerBuilder;
-               augment.setTargetNodeSchemaPath(targetDataNodeContainer.getPath());
-                fillAugmentTarget(augment, targetDataNodeContainer);
-            } else if (targetNode instanceof ChoiceBuilder) {
-               val targetChoiceBuilder = targetNode as ChoiceBuilder;
-               augment.setTargetNodeSchemaPath(targetChoiceBuilder.getPath());
-                fillAugmentTarget(augment, targetChoiceBuilder);
-            } else {
-                throw new YangParseException(augment.getModuleName(), augment.getLine(),
-                    "Error in augment parsing: The target node MUST be either a container, list, choice, case, input, output, or notification node.");
-            }
-            (targetNode as AugmentationTargetBuilder).addAugmentation(augment);
-            augment.setResolved(true);
-            return true;
-        }
-
-        /**
-     * Find node with given name in uses target.
-     *
-     * @param localName
-     *            name of node to find
-     * @param uses
-     *            uses node which target grouping should be searched
-     * @return node with given name if found, null otherwise
-     */
-    private static def DataSchemaNodeBuilder findNodeInUses(String localName, UsesNodeBuilder uses) {
-        for(child : uses.targetChildren) {
-            if (child.getQName().getLocalName().equals(localName)) {
-                return child;
-            }
-        }
-
-        val target = uses.groupingBuilder;
-        for (child : target.childNodeBuilders) {
-            if (child.getQName().getLocalName().equals(localName)) {
-                return child;
-            }
-        }
-        for (usesNode : target.usesNodes) {
-            val result = findNodeInUses(localName, usesNode);
-            if (result != null) {
-                return result;
-            }
+    public static def boolean processAugmentation(AugmentationSchemaBuilder augment, Builder firstNodeParent) {
+        val path = augment.targetPath.path
+        // traverse augment target path and try to reach target node
+        val targetNode = findNode(firstNodeParent, path, augment.moduleName, augment.line);
+        if(targetNode === null) return false;
+
+        if ((targetNode instanceof DataNodeContainerBuilder)) {
+            val targetDataNodeContainer = targetNode as DataNodeContainerBuilder;
+            augment.setTargetNodeSchemaPath(targetDataNodeContainer.getPath());
+            fillAugmentTarget(augment, targetDataNodeContainer);
+        } else if (targetNode instanceof ChoiceBuilder) {
+            val targetChoiceBuilder = targetNode as ChoiceBuilder;
+            augment.setTargetNodeSchemaPath(targetChoiceBuilder.getPath());
+            fillAugmentTarget(augment, targetChoiceBuilder);
+        } else {
+            throw new YangParseException(augment.getModuleName(), augment.getLine(),
+                "Error in augment parsing: The target node MUST be either a container, list, choice, case, input, output, or notification node.");
         }
-        return null;
+        (targetNode as AugmentationTargetBuilder).addAugmentation(augment);
+        augment.setResolved(true);
+        return true;
     }
 
-        /**
+    /**
      * Find augment target node in given context and perform augmentation.
      *
      * @param augment
@@ -446,142 +430,181 @@ public final class ParserUtils {
      *            SchemaContext containing already resolved modules
      * @return true if augment process succeed, false otherwise
      */
-        public static def boolean processAugmentationOnContext(AugmentationSchemaBuilder augment, List<QName> path,
-            ModuleBuilder module, String prefix, SchemaContext context) {
-            val int line = augment.getLine();
-            val Module dependentModule = findModuleFromContext(context, module, prefix, line);
-            if (dependentModule === null) {
-                throw new YangParseException(module.getName(), line,
-                    "Error in augment parsing: failed to find module with prefix " + prefix + ".");
-            }
+    public static def boolean processAugmentationOnContext(AugmentationSchemaBuilder augment, List<QName> path,
+        ModuleBuilder module, String prefix, SchemaContext context) {
+        val int line = augment.getLine();
+        val Module dependentModule = findModuleFromContext(context, module, prefix, line);
+        if (dependentModule === null) {
+            throw new YangParseException(module.getName(), line,
+                "Error in augment parsing: failed to find module with prefix " + prefix + ".");
+        }
 
-            var currentName = path.get(0).getLocalName();
-            var SchemaNode currentParent = dependentModule.getDataChildByName(currentName);
-            if (currentParent === null) {
-                val notifications = dependentModule.getNotifications();
-                for (NotificationDefinition ntf : notifications) {
-                    if (ntf.getQName().getLocalName().equals(currentName)) {
-                        currentParent = ntf;
-                    }
+        var currentName = path.get(0).getLocalName();
+        var SchemaNode currentParent = dependentModule.getDataChildByName(currentName);
+        if (currentParent === null) {
+            val notifications = dependentModule.getNotifications();
+            for (NotificationDefinition ntf : notifications) {
+                if (ntf.getQName().getLocalName().equals(currentName)) {
+                    currentParent = ntf;
                 }
             }
+        }
+        if (currentParent === null) {
+            throw new YangParseException(module.getName(), line,
+                "Error in augment parsing: failed to find node " + currentName + ".");
+        }
+
+        for (qname : path.nextLevel) {
+            currentName = qname.getLocalName();
+            if (currentParent instanceof DataNodeContainer) {
+                currentParent = (currentParent as DataNodeContainer).getDataChildByName(currentName);
+            } else if (currentParent instanceof ChoiceNode) {
+                currentParent = (currentParent as ChoiceNode).getCaseNodeByName(currentName);
+            } else {
+                throw new YangParseException(augment.getModuleName(), line,
+                    "Error in augment parsing: failed to find node " + currentName);
+            }
+
+            // if node in path not found, return false
             if (currentParent === null) {
                 throw new YangParseException(module.getName(), line,
                     "Error in augment parsing: failed to find node " + currentName + ".");
             }
+        }
 
-            for (qname : path.nextLevel) {
-                currentName = qname.getLocalName();
-                if (currentParent instanceof DataNodeContainer) {
-                    currentParent = (currentParent as DataNodeContainer).getDataChildByName(currentName);
-                } else if (currentParent instanceof ChoiceNode) {
-                    currentParent = (currentParent as ChoiceNode).getCaseNodeByName(currentName);
-                } else {
-                    throw new YangParseException(augment.getModuleName(), line,
-                        "Error in augment parsing: failed to find node " + currentName);
-                }
+        val oldPath = currentParent.path;
 
-                // if node in path not found, return false
-                if (currentParent === null) {
-                    throw new YangParseException(module.getName(), line,
-                        "Error in augment parsing: failed to find node " + currentName + ".");
-                }
-            }
+        if (!(currentParent instanceof AugmentationTarget)) {
+            throw new YangParseException(module.getName(), line,
+                "Target of type " + currentParent.class + " cannot be augmented.");
+        }
 
-            val oldPath = currentParent.path;
+        switch (currentParent) {
+            case (currentParent instanceof ContainerSchemaNodeImpl): {
 
-            if (!(currentParent instanceof AugmentationTarget)) {
-                throw new YangParseException(module.getName(), line,
-                    "Target of type " + currentParent.class + " cannot be augmented.");
+                // includes container, input and output statement
+                val c = currentParent as ContainerSchemaNodeImpl;
+                val cb = c.toBuilder();
+                fillAugmentTarget(augment, cb);
+                (cb as AugmentationTargetBuilder ).addAugmentation(augment);
+                cb.rebuild();
+            }
+            case (currentParent instanceof ListSchemaNodeImpl): {
+                val l = currentParent as ListSchemaNodeImpl;
+                val lb = l.toBuilder();
+                fillAugmentTarget(augment, lb);
+                (lb as AugmentationTargetBuilder ).addAugmentation(augment);
+                lb.rebuild();
+                augment.setTargetNodeSchemaPath(new SchemaPath(oldPath.getPath(), oldPath.isAbsolute()));
+                augment.setResolved(true);
+            }
+            case (currentParent instanceof ChoiceNodeImpl): {
+                val ch = currentParent as ChoiceNodeImpl;
+                val chb = ch.toBuilder();
+                fillAugmentTarget(augment, chb);
+                (chb as AugmentationTargetBuilder ).addAugmentation(augment);
+                chb.rebuild();
+                augment.setTargetNodeSchemaPath(new SchemaPath(oldPath.getPath(), oldPath.isAbsolute()));
+                augment.setResolved(true);
+            }
+            case (currentParent instanceof ChoiceCaseNodeImpl): {
+                val chc = currentParent as ChoiceCaseNodeImpl;
+                val chcb = chc.toBuilder();
+                fillAugmentTarget(augment, chcb);
+                (chcb as AugmentationTargetBuilder ).addAugmentation(augment);
+                chcb.rebuild();
+                augment.setTargetNodeSchemaPath(new SchemaPath(oldPath.getPath(), oldPath.isAbsolute()));
+                augment.setResolved(true);
+            }
+            case (currentParent instanceof NotificationDefinitionImpl): {
+                val nd = currentParent as NotificationDefinitionImpl;
+                val nb = nd.toBuilder();
+                fillAugmentTarget(augment, nb);
+                (nb as AugmentationTargetBuilder ).addAugmentation(augment);
+                nb.rebuild();
+                augment.setTargetNodeSchemaPath(new SchemaPath(oldPath.getPath(), oldPath.isAbsolute()));
+                augment.setResolved(true);
+            }
+        }
+        augment.setTargetNodeSchemaPath(new SchemaPath(oldPath.getPath(), oldPath.isAbsolute()));
+        augment.setResolved(true);
+        return true;
+    }
+
+    public static def IdentitySchemaNodeBuilder findBaseIdentity(Map<String, TreeMap<Date, ModuleBuilder>> modules,
+        ModuleBuilder module, String baseString, int line) {
+        var IdentitySchemaNodeBuilder result = null;
+        if (baseString.contains(":")) {
+            val String[] splittedBase = baseString.split(":");
+            if (splittedBase.length > 2) {
+                throw new YangParseException(module.getName(), line, "Failed to parse identityref base: " +
+                    baseString);
             }
+            val prefix = splittedBase.get(0);
+            val name = splittedBase.get(1);
+            val dependentModule = findModuleFromBuilders(modules, module, prefix, line);
+            if (dependentModule !== null) {
+                result = findIdentity(dependentModule.identities, name);
+            }
+        } else {
+            result = findIdentity(module.identities, baseString);
+        }
+        return result;
+    }
 
-            switch (currentParent) {
-                case (currentParent instanceof ContainerSchemaNodeImpl): {
+    public static def IdentitySchemaNode findBaseIdentityFromContext(Map<String, TreeMap<Date, ModuleBuilder>> modules,
+            ModuleBuilder module, String baseString, int line, SchemaContext context) {
+        var IdentitySchemaNode result = null;
 
-                    // includes container, input and output statement
-                    val c = currentParent as ContainerSchemaNodeImpl;
-                    val cb = c.toBuilder();
-                    fillAugmentTarget(augment, cb);
-                    (cb as AugmentationTargetBuilder ).addAugmentation(augment);
-                    cb.rebuild();
-                }
-                case (currentParent instanceof ListSchemaNodeImpl): {
-                    val l = currentParent as ListSchemaNodeImpl;
-                    val lb = l.toBuilder();
-                    fillAugmentTarget(augment, lb);
-                    (lb as AugmentationTargetBuilder ).addAugmentation(augment);
-                    lb.rebuild();
-                    augment.setTargetNodeSchemaPath(new SchemaPath(oldPath.getPath(), oldPath.isAbsolute()));
-                    augment.setResolved(true);
-                }
-                case (currentParent instanceof ChoiceNodeImpl): {
-                    val ch = currentParent as ChoiceNodeImpl;
-                    val chb = ch.toBuilder();
-                    fillAugmentTarget(augment, chb);
-                    (chb as AugmentationTargetBuilder ).addAugmentation(augment);
-                    chb.rebuild();
-                    augment.setTargetNodeSchemaPath(new SchemaPath(oldPath.getPath(), oldPath.isAbsolute()));
-                    augment.setResolved(true);
-                }
-                case (currentParent instanceof ChoiceCaseNodeImpl): {
-                    val chc = currentParent as ChoiceCaseNodeImpl;
-                    val chcb = chc.toBuilder();
-                    fillAugmentTarget(augment, chcb);
-                    (chcb as AugmentationTargetBuilder ).addAugmentation(augment);
-                    chcb.rebuild();
-                    augment.setTargetNodeSchemaPath(new SchemaPath(oldPath.getPath(), oldPath.isAbsolute()));
-                    augment.setResolved(true);
-                }
-                case (currentParent instanceof NotificationDefinitionImpl): {
-                    val nd = currentParent as NotificationDefinitionImpl;
-                    val nb = nd.toBuilder();
-                    fillAugmentTarget(augment, nb);
-                    (nb as AugmentationTargetBuilder ).addAugmentation(augment);
-                    nb.rebuild();
-                    augment.setTargetNodeSchemaPath(new SchemaPath(oldPath.getPath(), oldPath.isAbsolute()));
-                    augment.setResolved(true);
-                }
+        val String[] splittedBase = baseString.split(":");
+        if (splittedBase.length > 2) {
+            throw new YangParseException(module.getName(), line, "Failed to parse identityref base: " + baseString);
+        }
+        val prefix = splittedBase.get(0);
+        val name = splittedBase.get(1);
+        val dependentModule = findModuleFromContext(context, module, prefix, line);
+        result = findIdentityNode(dependentModule.identities, name);
+
+        if (result == null) {
+            throw new YangParseException(module.name, line, "Failed to find base identity");
+        }
+        return result;
+    }
+
+    private static def IdentitySchemaNodeBuilder findIdentity(Set<IdentitySchemaNodeBuilder> identities, String name) {
+        for (identity : identities) {
+            if (identity.QName.localName.equals(name)) {
+                return identity;
             }
-            augment.setTargetNodeSchemaPath(new SchemaPath(oldPath.getPath(), oldPath.isAbsolute()));
-            augment.setResolved(true);
-            return true;
         }
+        return null;
+    }
 
-        public static def QName findFullQName(Map<String, TreeMap<Date, ModuleBuilder>> modules,
-            ModuleBuilder module, IdentityrefTypeBuilder idref) {
-            var QName result = null;
-            val String baseString = idref.getBaseString();
-            if (baseString.contains(":")) {
-                val String[] splittedBase = baseString.split(":");
-                if (splittedBase.length > 2) {
-                    throw new YangParseException(module.getName(), idref.getLine(),
-                        "Failed to parse identityref base: " + baseString);
-                }
-                val prefix = splittedBase.get(0);
-                val name = splittedBase.get(1);
-                val dependentModule = findModuleFromBuilders(modules, module, prefix, idref.getLine());
-                result = new QName(dependentModule.getNamespace(), dependentModule.getRevision(), prefix, name);
-            } else {
-                result = new QName(module.getNamespace(), module.getRevision(), module.getPrefix(), baseString);
+    private static def IdentitySchemaNode findIdentityNode(Set<IdentitySchemaNode> identities, String name) {
+        for (identity : identities) {
+            if (identity.QName.localName.equals(name)) {
+                return identity;
             }
-            return result;
         }
+        return null;
+    }
 
-        /**
+    /**
      * Get module in which this node is defined.
      *
      * @param node
      * @return builder of module where this node is defined
      */
-        public static def ModuleBuilder getParentModule(Builder node) {
-            if (node instanceof ModuleBuilder) {
-                return node as ModuleBuilder;
-            }
-            var parent = node.getParent();
-            while (!(parent instanceof ModuleBuilder)) {
-                parent = parent.getParent();
-            }
-            return parent as ModuleBuilder;
+    public static def ModuleBuilder getParentModule(Builder node) {
+        if (node instanceof ModuleBuilder) {
+            return node as ModuleBuilder;
         }
+        var parent = node.getParent();
+        while (!(parent instanceof ModuleBuilder)) {
+            parent = parent.getParent();
+        }
+        return parent as ModuleBuilder;
     }
-    
\ No newline at end of file
+
+}
+