Write() 공개 정적인 메소드

Create and initialize XmlILConstructInfo annotation for the specified node.
public static Write ( QilNode nd ) : XmlILConstructInfo
nd QilNode
리턴 XmlILConstructInfo
예제 #1
0
        /// <summary>
        /// Analyze the content argument of the ElementCtor.  Try to eliminate as many runtime checks as possible,
        /// both for the ElementCtor and for content constructors.
        /// </summary>
        public override QilNode Analyze(QilNode ndElem, QilNode ndContent)
        {
            Debug.Assert(ndElem.NodeType == QilNodeType.ElementCtor);
            this.parentInfo = XmlILConstructInfo.Write(ndElem);

            // Start by assuming that these properties are false (they default to true, but analyzer might be able to
            // prove they are really false).
            this.parentInfo.MightHaveNamespacesAfterAttributes = false;
            this.parentInfo.MightHaveAttributes          = false;
            this.parentInfo.MightHaveDuplicateAttributes = false;

            // The element's namespace might need to be declared
            this.parentInfo.MightHaveNamespaces = !this.parentInfo.IsNamespaceInScope;

            // Clear list of duplicate attributes
            _dupAttrs.Clear();

            return(base.Analyze(ndElem, ndContent));
        }
예제 #2
0
        /// <summary>
        /// Perform analysis on the specified constructor and its content.  Return the ndContent that was passed in,
        /// or a replacement.
        /// </summary>
        public virtual QilNode Analyze(QilNode ndConstr, QilNode ndContent)
        {
            if (ndConstr == null)
            {
                // Root expression is analyzed
                this.parentInfo = null;
                this.xstates    = PossibleXmlStates.WithinSequence;
                this.withinElem = false;

                Debug.Assert(ndContent != null);
                ndContent = AnalyzeContent(ndContent);
            }
            else
            {
                this.parentInfo = XmlILConstructInfo.Write(ndConstr);

                if (ndConstr.NodeType == QilNodeType.Function)
                {
                    // Results of function should be pushed to writer
                    this.parentInfo.ConstructMethod = XmlILConstructMethod.Writer;

                    // Start with PossibleXmlStates.None and then add additional possible starting states
                    PossibleXmlStates xstates = PossibleXmlStates.None;
                    foreach (XmlILConstructInfo infoCaller in this.parentInfo.CallersInfo)
                    {
                        if (xstates == PossibleXmlStates.None)
                        {
                            xstates = infoCaller.InitialStates;
                        }
                        else if (xstates != infoCaller.InitialStates)
                        {
                            xstates = PossibleXmlStates.Any;
                        }

                        // Function's results are pushed to Writer, so make sure that Invoke nodes' construct methods match
                        infoCaller.PushToWriterFirst = true;
                    }
                    this.parentInfo.InitialStates = xstates;
                }
                else
                {
                    // Build a standalone tree, with this constructor as its root
                    if (ndConstr.NodeType != QilNodeType.Choice)
                    {
                        this.parentInfo.InitialStates = this.parentInfo.FinalStates = PossibleXmlStates.WithinSequence;
                    }

                    // Don't stream Rtf; fully cache the Rtf and copy it into any containing tree in order to simplify XmlILVisitor.VisitRtfCtor
                    if (ndConstr.NodeType != QilNodeType.RtfCtor)
                    {
                        this.parentInfo.ConstructMethod = XmlILConstructMethod.WriterThenIterator;
                    }
                }

                // Set withinElem = true if analyzing element content
                this.withinElem = (ndConstr.NodeType == QilNodeType.ElementCtor);

                switch (ndConstr.NodeType)
                {
                case QilNodeType.DocumentCtor: this.xstates = PossibleXmlStates.WithinContent; break;

                case QilNodeType.ElementCtor: this.xstates = PossibleXmlStates.EnumAttrs; break;

                case QilNodeType.AttributeCtor: this.xstates = PossibleXmlStates.WithinAttr; break;

                case QilNodeType.NamespaceDecl: Debug.Assert(ndContent == null); break;

                case QilNodeType.TextCtor: Debug.Assert(ndContent == null); break;

                case QilNodeType.RawTextCtor: Debug.Assert(ndContent == null); break;

                case QilNodeType.CommentCtor: this.xstates = PossibleXmlStates.WithinComment; break;

                case QilNodeType.PICtor: this.xstates = PossibleXmlStates.WithinPI; break;

                case QilNodeType.XsltCopy: this.xstates = PossibleXmlStates.Any; break;

                case QilNodeType.XsltCopyOf: Debug.Assert(ndContent == null); break;

                case QilNodeType.Function: this.xstates = this.parentInfo.InitialStates; break;

                case QilNodeType.RtfCtor: this.xstates = PossibleXmlStates.WithinContent; break;

                case QilNodeType.Choice: this.xstates = PossibleXmlStates.Any; break;

                default: Debug.Assert(false, ndConstr.NodeType + " is not handled by XmlILStateAnalyzer."); break;
                }

                if (ndContent != null)
                {
                    ndContent = AnalyzeContent(ndContent);
                }

                if (ndConstr.NodeType == QilNodeType.Choice)
                {
                    AnalyzeChoice(ndConstr as QilChoice, this.parentInfo);
                }

                // Since Function will never be another node's content, set its final states here
                if (ndConstr.NodeType == QilNodeType.Function)
                {
                    this.parentInfo.FinalStates = this.xstates;
                }
            }

            return(ndContent);
        }
예제 #3
0
        /// <summary>
        /// Recursively analyze content.  Return "nd" or a replacement for it.
        /// </summary>
        protected virtual QilNode AnalyzeContent(QilNode nd)
        {
            XmlILConstructInfo info;
            QilNode            ndChild;

            // Handle special node-types that are replaced
            switch (nd.NodeType)
            {
            case QilNodeType.For:
            case QilNodeType.Let:
            case QilNodeType.Parameter:
                // Iterator references are shared and cannot be annotated directly with ConstructInfo,
                // so wrap them with Nop node.
                nd = this.fac.Nop(nd);
                break;
            }

            // Get node's ConstructInfo annotation
            info = XmlILConstructInfo.Write(nd);

            // Set node's guaranteed parent constructor
            info.ParentInfo = this.parentInfo;

            // Construct all content using the Writer
            info.PushToWriterLast = true;

            // Set states that are possible before expression is constructed
            info.InitialStates = this.xstates;

            switch (nd.NodeType)
            {
            case QilNodeType.Loop: AnalyzeLoop(nd as QilLoop, info); break;

            case QilNodeType.Sequence: AnalyzeSequence(nd as QilList, info); break;

            case QilNodeType.Conditional: AnalyzeConditional(nd as QilTernary, info); break;

            case QilNodeType.Choice: AnalyzeChoice(nd as QilChoice, info); break;

            case QilNodeType.Error:
            case QilNodeType.Warning:
                // Ensure that construct method is Writer
                info.ConstructMethod = XmlILConstructMethod.Writer;
                break;

            case QilNodeType.Nop:
                ndChild = (nd as QilUnary).Child;
                switch (ndChild.NodeType)
                {
                case QilNodeType.For:
                case QilNodeType.Let:
                case QilNodeType.Parameter:
                    // Copy iterator items as content
                    AnalyzeCopy(nd, info);
                    break;

                default:
                    // Ensure that construct method is Writer and recursively analyze content
                    info.ConstructMethod = XmlILConstructMethod.Writer;
                    AnalyzeContent(ndChild);
                    break;
                }
                break;

            default:
                AnalyzeCopy(nd, info);
                break;
            }

            // Set states that are possible after expression is constructed
            info.FinalStates = this.xstates;

            return(nd);
        }
예제 #4
0
        /// <summary>
        /// Determine whether an ElementCtor, AttributeCtor, or NamespaceDecl's namespace is already declared.  If it is,
        /// set the IsNamespaceInScope property to True.  Otherwise, add the namespace to the set of in-scope namespaces if
        /// addInScopeNmsp is True.  Return false if the name is computed or is invalid.
        /// </summary>
        private bool CheckNamespaceInScope(QilBinary nd)
        {
            QilName       ndName;
            string        prefix, ns, prefixExisting, nsExisting;
            XPathNodeType nodeType;

            switch (nd.NodeType)
            {
            case QilNodeType.ElementCtor:
            case QilNodeType.AttributeCtor:
                ndName = nd.Left as QilName;
                if (ndName != null)
                {
                    prefix   = ndName.Prefix;
                    ns       = ndName.NamespaceUri;
                    nodeType = (nd.NodeType == QilNodeType.ElementCtor) ? XPathNodeType.Element : XPathNodeType.Attribute;
                    break;
                }

                // Not a literal name, so return false
                return(false);

            default:
                Debug.Assert(nd.NodeType == QilNodeType.NamespaceDecl);
                prefix   = (string)(QilLiteral)nd.Left;
                ns       = (string)(QilLiteral)nd.Right;
                nodeType = XPathNodeType.Namespace;
                break;
            }

            // Attribute with null namespace and xmlns:xml are always in-scope
            if (nd.NodeType == QilNodeType.AttributeCtor && ns.Length == 0 ||
                prefix == "xml" && ns == XmlReservedNs.NsXml)
            {
                XmlILConstructInfo.Write(nd).IsNamespaceInScope = true;
                return(true);
            }

            // Don't process names that are invalid
            if (!ValidateNames.ValidateName(prefix, string.Empty, ns, nodeType, ValidateNames.Flags.CheckPrefixMapping))
            {
                return(false);
            }

            // Atomize names
            prefix = _nsmgr.NameTable.Add(prefix);
            ns     = _nsmgr.NameTable.Add(ns);

            // Determine whether namespace is already in-scope
            for (int iNmsp = 0; iNmsp < _cntNmsp; iNmsp++)
            {
                _nsmgr.GetNamespaceDeclaration(iNmsp, out prefixExisting, out nsExisting);

                // If prefix is already declared,
                if ((object)prefix == (object)prefixExisting)
                {
                    // Then if the namespace is the same, this namespace is redundant
                    if ((object)ns == (object)nsExisting)
                    {
                        XmlILConstructInfo.Write(nd).IsNamespaceInScope = true;
                    }

                    // Else quit searching, because any further matching prefixes will be hidden (not in-scope)
                    Debug.Assert(nd.NodeType != QilNodeType.NamespaceDecl || !_nsmgr.HasNamespace(prefix) || _nsmgr.LookupNamespace(prefix) == ns,
                                 "Compilers must ensure that namespace declarations do not conflict with the namespace used by the element constructor.");
                    break;
                }
            }

            // If not in-scope, then add if it's allowed
            if (_addInScopeNmsp)
            {
                _nsmgr.AddNamespace(prefix, ns);
                _cntNmsp++;
            }

            return(true);
        }