System.Xml.Xsl.Qil.QilXmlReader.EndElement C# (CSharp) Method

EndElement() private method

private EndElement ( ) : void
return void
        private void EndElement()
        {
            MethodInfo facMethod = null;
            object[] facArgs;
            QilList list;
            QilNode nd;
            ReaderAnnotation ann;

            list = _stk.Pop();
            ann = (ReaderAnnotation)list.Annotation;

            // Special case certain element names
            string s = _r.LocalName;
            switch (_r.LocalName)
            {
                case "QilExpression":
                    {
                        Debug.Assert(list.Count > 0, "QilExpression node requires a Root expression");
                        QilExpression qil = _f.QilExpression(list[list.Count - 1]);

                        // Be flexible on order and presence of QilExpression children
                        for (int i = 0; i < list.Count - 1; i++)
                        {
                            switch (list[i].NodeType)
                            {
                                case QilNodeType.True:
                                case QilNodeType.False:
                                    qil.IsDebug = list[i].NodeType == QilNodeType.True;
                                    break;

                                case QilNodeType.FunctionList:
                                    qil.FunctionList = (QilList)list[i];
                                    break;

                                case QilNodeType.GlobalVariableList:
                                    qil.GlobalVariableList = (QilList)list[i];
                                    break;

                                case QilNodeType.GlobalParameterList:
                                    qil.GlobalParameterList = (QilList)list[i];
                                    break;
                            }
                        }
                        nd = qil;
                        break;
                    }

                case "ForwardDecls":
                    _inFwdDecls = false;
                    return;

                case "Parameter":
                case "Let":
                case "For":
                case "Function":
                    {
                        string id = ann.Id;
                        QilName name = ann.Name;
                        Debug.Assert(id != null, _r.LocalName + " must have an id attribute");
                        Debug.Assert(!_inFwdDecls || ann.XmlType != null, "Forward decl for " + _r.LocalName + " '" + id + "' must have an xmlType attribute");

                        // Create node (may be discarded later if it was already declared in forward declarations section)
                        switch (_r.LocalName)
                        {
                            case "Parameter":
                                Debug.Assert(list.Count <= (_inFwdDecls ? 0 : 1), "Parameter '" + id + "' must have 0 or 1 arguments");
                                Debug.Assert(ann.XmlType != null, "Parameter '" + id + "' must have an xmlType attribute");
                                if (_inFwdDecls || list.Count == 0)
                                    nd = _f.Parameter(null, name, ann.XmlType);
                                else
                                    nd = _f.Parameter(list[0], name, ann.XmlType);
                                break;

                            case "Let":
                                Debug.Assert(list.Count == (_inFwdDecls ? 0 : 1), "Let '" + id + "' must have 0 or 1 arguments");
                                if (_inFwdDecls)
                                    nd = _f.Let(_f.Unknown(ann.XmlType));
                                else
                                    nd = _f.Let(list[0]);
                                break;

                            case "For":
                                Debug.Assert(list.Count == 1, "For '" + id + "' must have 1 argument");
                                nd = _f.For(list[0]);
                                break;

                            default:
                                Debug.Assert(list.Count == (_inFwdDecls ? 2 : 3), "Function '" + id + "' must have 2 or 3 arguments");
                                if (_inFwdDecls)
                                    nd = _f.Function(list[0], list[1], ann.XmlType);
                                else
                                    nd = _f.Function(list[0], list[1], list[2], ann.XmlType != null ? ann.XmlType : list[1].XmlType);
                                break;
                        }

                        // Set DebugName
                        if (name != null)
                            ((QilReference)nd).DebugName = name.ToString();

                        if (_inFwdDecls)
                        {
                            Debug.Assert(!_scope.ContainsKey(id), "Multiple nodes have id '" + id + "'");
                            _fwdDecls[id] = nd;
                            _scope[id] = nd;
                        }
                        else
                        {
                            if (_fwdDecls.ContainsKey(id))
                            {
                                // Replace forward declaration
                                Debug.Assert(_r.LocalName == Enum.GetName(typeof(QilNodeType), nd.NodeType), "Id '" + id + "' is not not bound to a " + _r.LocalName + " forward decl");
                                nd = _fwdDecls[id];
                                _fwdDecls.Remove(id);

                                if (list.Count > 0) nd[0] = list[0];
                                if (list.Count > 1) nd[1] = list[1];
                            }
                            else
                            {
                                // Put reference in scope
                                Debug.Assert(!_scope.ContainsKey(id), "Id '" + id + "' is already in scope");
                                _scope[id] = nd;
                            }
                        }
                        nd.Annotation = ann;
                        break;
                    }

                case "RefTo":
                    {
                        // Lookup reference
                        string id = ann.Id;
                        Debug.Assert(id != null, _r.LocalName + " must have an id attribute");

                        Debug.Assert(_scope.ContainsKey(id), "Id '" + id + "' is not in scope");
                        _stk.Peek().Add(_scope[id]);
                        return;
                    }

                case "Sequence":
                    nd = _f.Sequence(list);
                    break;

                case "FunctionList":
                    nd = _f.FunctionList(list);
                    break;

                case "GlobalVariableList":
                    nd = _f.GlobalVariableList(list);
                    break;

                case "GlobalParameterList":
                    nd = _f.GlobalParameterList(list);
                    break;

                case "ActualParameterList":
                    nd = _f.ActualParameterList(list);
                    break;

                case "FormalParameterList":
                    nd = _f.FormalParameterList(list);
                    break;

                case "SortKeyList":
                    nd = _f.SortKeyList(list);
                    break;

                case "BranchList":
                    nd = _f.BranchList(list);
                    break;

                case "XsltInvokeEarlyBound":
                    {
                        Debug.Assert(ann.ClrNamespace != null, "XsltInvokeEarlyBound must have a clrNamespace attribute");
                        Debug.Assert(list.Count == 2, "XsltInvokeEarlyBound must have exactly 2 arguments");
                        Debug.Assert(list.XmlType != null, "XsltInvokeEarlyBound must have an xmlType attribute");
                        MethodInfo mi = null;
                        QilName name = (QilName)list[0];

                        foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
                        {
                            Type t = asm.GetType(ann.ClrNamespace);
                            if (t != null)
                            {
                                mi = t.GetMethod(name.LocalName);
                                break;
                            }
                        }

                        Debug.Assert(mi != null, "Cannot find method " + ann.ClrNamespace + "." + name.ToString());

                        nd = _f.XsltInvokeEarlyBound(name, _f.LiteralObject(mi), list[1], ann.XmlType);
                        break;
                    }

                default:
                    {
                        // Find factory method which will be used to construct the Qil node
                        Debug.Assert(s_nameToFactoryMethod.ContainsKey(_r.LocalName), "Method " + _r.LocalName + " could not be found on QilFactory");
                        facMethod = s_nameToFactoryMethod[_r.LocalName];
                        Debug.Assert(facMethod.GetParameters().Length == list.Count, "NodeType " + _r.LocalName + " does not allow " + list.Count + " parameters");

                        // Create factory method arguments
                        facArgs = new object[list.Count];
                        for (int i = 0; i < facArgs.Length; i++)
                            facArgs[i] = list[i];

                        // Create node and set its properties
                        nd = (QilNode)facMethod.Invoke(_f, facArgs);
                        break;
                    }
            }

            nd.SourceLine = list.SourceLine;

            // Add node to its parent's list
            _stk.Peek().Add(nd);
        }