public void EnteringNode(object sender, XmlTraverseEventArgs e)
        {
            var node = e.Node;

            switch (node.LocalName)
            {
            // Nodes
            case AstConstants.Nodes.Stmt_Interface:
                currentInterface = new Interface(node)
                {
                    StartLine = AstNode.GetStartLine(node),
                    EndLine   = AstNode.GetEndLine(node)
                };
                break;

            case AstConstants.Nodes.Stmt_Class:
                currentClass = new Class(node)
                {
                    StartLine = AstNode.GetStartLine(node),
                    EndLine   = AstNode.GetEndLine(node)
                };
                break;

            case AstConstants.Nodes.Stmt_ClassMethod:
                ClassMethodEnter(node);
                break;

            case AstConstants.Nodes.Stmt_Property:
                inPropertyDeclarations = true;
                break;

            case AstConstants.Nodes.Stmt_PropertyProperty:
                currentProperty = new Property(node)
                {
                    StartLine           = AstNode.GetStartLine(node),
                    EndLine             = AstNode.GetEndLine(node),
                    VisibilityModifiers = propertyModifiers,
                };
                break;

            case AstConstants.Nodes.Stmt_Function:
                currentFunctions.Push(new Function(node)
                {
                    StartLine = AstNode.GetStartLine(node),
                    EndLine   = AstNode.GetEndLine(node)
                });
                functionClosureOrder.Push(FunctionClosure.Function);
                break;

            case AstConstants.Nodes.Expr_Closure:
                currentClosures.Push(new ExtractorClosureInfo()
                {
                    Closure = new Closure(node)
                    {
                        StartLine = AstNode.GetStartLine(node),
                        EndLine   = AstNode.GetEndLine(node)
                    }
                });
                functionClosureOrder.Push(FunctionClosure.Closure);
                break;

            case AstConstants.Nodes.Param:
                currentParameter = new Parameter(node);
                break;

            case AstConstants.Nodes.Expr_ClosureUse:
                currentClosureUse = new ClosureUse(node);
                break;

            // Subnodes
            case AstConstants.Subnodes.Name:
                Name(node);
                break;

            case AstConstants.Subnodes.Params:
                inParamDeclarations = true;
                break;

            case AstConstants.Subnodes.ByRef:
                Subnode_ByRef_Enter(node);
                break;

            case AstConstants.Subnodes.Variadic:
                if (inParamDeclarations && !parameteVariadicIsSet)
                {
                    currentParameter.IsVariadic = Convert.ToBoolean(node.FirstChild.LocalName);
                    parameteVariadicIsSet       = true;
                }
                break;

            case AstConstants.Subnodes.Default:
                if (inParamDeclarations && !parameterDefaultIsSet)
                {
                    currentParameter.IsOptional = node.FirstChild.Prefix != AstConstants.Scalar;
                    parameterDefaultIsSet       = true;
                }
                break;

            case AstConstants.Subnodes.Uses:
                if (currentClosures.Any() && currentClosures.Peek().ClosureUses == null && !currentClosures.Peek().ClosureUsagesIsSet)
                {
                    currentClosures.Peek().ClosureUses = new Queue <ClosureUse>();
                }
                break;

            case AstConstants.Subnodes.Var:
                if (currentClosureUse != null)
                {
                    currentClosureUse.Name = node.InnerText;
                }
                break;

            case AstConstants.Subnodes.Type:
                if (inPropertyDeclarations && currentProperty == null)
                {
                    var visibilityModifiers = (AstConstants.VisibilityModifiers)Enum.Parse(typeof(AstConstants.VisibilityModifiers), node.InnerText);
                    // No modifier in source code = 0, if no modifier is present the default visibility is public
                    propertyModifiers = visibilityModifiers == 0 ? AstConstants.VisibilityModifiers.Public : visibilityModifiers;
                }
                break;
            }
        }
        public void LeavingNode(object sender, XmlTraverseEventArgs e)
        {
            var node = e.Node;

            switch (node.LocalName)
            {
            // Nodes
            case AstConstants.Nodes.Stmt_Interface:
                _interfaces.Add(currentInterface);
                currentInterface = null;
                break;

            case AstConstants.Nodes.Stmt_Class:
                _classes.Add(currentClass);
                currentClass = null;
                break;

            case AstConstants.Nodes.Stmt_ClassMethod:
                ClassMethodExit();
                break;

            case AstConstants.Nodes.Stmt_Property:
                inPropertyDeclarations = false;
                propertyModifiers      = 0;
                break;

            case AstConstants.Nodes.Stmt_PropertyProperty:
                currentClass.Properties.Add(currentProperty);
                currentProperty = null;
                break;

            case AstConstants.Nodes.Stmt_Function:
                _functions.Add(currentFunctions.Pop());
                functionClosureOrder.Pop();
                break;

            case AstConstants.Nodes.Expr_ClosureUse:
                currentClosures.Peek().ClosureUses.Enqueue(currentClosureUse);
                currentClosureUse = null;
                break;

            case AstConstants.Nodes.Expr_Closure:
                _closures.Add(currentClosures.Pop().Closure);
                functionClosureOrder.Pop();
                break;

            case AstConstants.Nodes.Param:
                parameters.Enqueue(currentParameter);
                currentParameter      = null;
                parameteVariadicIsSet = false;
                parameterByRefIsSet   = false;
                parameterDefaultIsSet = false;
                break;

            // Subnodes
            case AstConstants.Subnodes.Params:
                ParamsExit();
                break;

            case AstConstants.Subnodes.Uses:
                if (currentClosures.Any())
                {
                    ExtractorClosureInfo closureInfo = currentClosures.Peek();
                    if (!closureInfo.ClosureUsagesIsSet && closureInfo.ClosureUses != null)
                    {
                        closureInfo.Closure.UseParameters = closureInfo.ClosureUses.ToArray();
                        closureInfo.ClosureUsagesIsSet    = true;
                    }
                }
                break;
            }
        }