Example #1
0
        public override bool Read()
        {
            bool readSucceed;

            if (this.bufferedXamlNodes.Count > 0)
            {
                this.Current = this.bufferedXamlNodes.Dequeue();
                readSucceed  = this.Current != null;
            }
            else
            {
                readSucceed = this.underlyingReader.Read();
                if (readSucceed)
                {
                    this.Current = CreateCurrentNode(this.underlyingReader, this.xamlLineInfo);
                    this.PushObjectDeclarationNodeIfApplicable();
                    switch (this.Current.NodeType)
                    {
                    case XamlNodeType.StartMember:

                        // When we reach a StartMember node, the next node to come might be a Value.
                        // To correctly pass SourceLocation information, we need to rewrite this node to use ValueNodeXamlMemberInvoker.
                        // But we don't know if the next node is a Value node yet, so we are buffering here and look ahead for a single node.
                        UnitTestUtility.Assert(this.bufferedXamlNodes.Count == 0, "this.bufferedXamlNodes should be empty when we reach this code path.");
                        this.bufferedXamlNodes.Enqueue(this.Current);

                        // This directive represents the XAML node or XAML information set
                        // representation of initialization text, where a string within an
                        // object element supplies the type construction information for
                        // the surrounding object element.
                        bool isInitializationValue = this.Current.Member == XamlLanguage.Initialization;

                        bool moreNode = this.underlyingReader.Read();
                        UnitTestUtility.Assert(moreNode, "Start Member must followed by some other nodes.");

                        this.Current = this.CreateCurrentNode();

                        this.bufferedXamlNodes.Enqueue(this.Current);

                        // It is possible that the next node after StartMember is a StartObject/GetObject.
                        // We need to push the object declaration node to the Stack
                        this.PushObjectDeclarationNodeIfApplicable();

                        if (!this.SuppressingMarkupExtension() &&
                            this.Current.NodeType == XamlNodeType.Value)
                        {
                            DocumentRange    valueRange;
                            DocumentLocation currentLocation = new DocumentLocation(this.Current.LineNumber, this.Current.LinePosition);
                            bool             isInAttribute   = this.xmlReaderWithSourceLocation.AttributeValueRanges.TryGetValue(currentLocation, out valueRange);
                            bool             isInContent     = isInAttribute ? false : this.xmlReaderWithSourceLocation.ContentValueRanges.TryGetValue(currentLocation, out valueRange);

                            if (isInAttribute || (isInContent && !isInitializationValue))
                            {
                                // For Value Node with known line info, we want to route the value setting process through this Reader.
                                // Therefore we need to go back to the member node and replace the XamlMemberInvoker.
                                XamlNode          startMemberNodeForValue = this.bufferedXamlNodes.Peek();
                                XamlMember        xamlMemberForValue      = startMemberNodeForValue.Member;
                                XamlMemberInvoker newXamlMemberInvoker    = new ValueNodeXamlMemberInvoker(this, xamlMemberForValue.Invoker, valueRange);
                                startMemberNodeForValue.Member = xamlMemberForValue.ReplaceXamlMemberInvoker(this.schemaContext, newXamlMemberInvoker);
                            }
                            else if (isInContent && isInitializationValue)
                            {
                                XamlNode currentStartObject = this.objectDeclarationRecords.Peek();

                                if (!this.initializationValueRanges.ContainsKey(currentStartObject))
                                {
                                    this.initializationValueRanges.Add(currentStartObject, valueRange);
                                }
                                else
                                {
                                    UnitTestUtility.Assert(false,
                                                           "I assume it is impossible for an object  to have more than one initialization member");
                                }
                            }
                        }

                        this.StartAccessingBuffer();
                        break;

                    case XamlNodeType.EndObject:

                        this.InjectLineInfoXamlNodesToBuffer();
                        this.StartAccessingBuffer();
                        break;

                    case XamlNodeType.Value:
                        break;

                    default:
                        break;
                    }
                }
            }

            return(readSucceed);
        }
        public override bool Read()
        {
            bool readSucceed;
            if (this.bufferedXamlNodes.Count > 0)
            {
                this.Current = this.bufferedXamlNodes.Dequeue();
                readSucceed = this.Current != null;
            }
            else
            {
                readSucceed = this.underlyingReader.Read();
                if (readSucceed)
                {
                    this.Current = CreateCurrentNode(this.underlyingReader, this.xamlLineInfo);
                    this.PushObjectDeclarationNodeIfApplicable();
                    switch (this.Current.NodeType)
                    {
                        case XamlNodeType.StartMember:

                            // When we reach a StartMember node, the next node to come might be a Value.
                            // To correctly pass SourceLocation information, we need to rewrite this node to use ValueNodeXamlMemberInvoker.
                            // But we don't know if the next node is a Value node yet, so we are buffering here and look ahead for a single node.
                            UnitTestUtility.Assert(this.bufferedXamlNodes.Count == 0, "this.bufferedXamlNodes should be empty when we reach this code path.");
                            this.bufferedXamlNodes.Enqueue(this.Current);

                            // This directive represents the XAML node or XAML information set 
                            // representation of initialization text, where a string within an 
                            // object element supplies the type construction information for 
                            // the surrounding object element.
                            bool isInitializationValue = this.Current.Member == XamlLanguage.Initialization;

                            bool moreNode = this.underlyingReader.Read();
                            UnitTestUtility.Assert(moreNode, "Start Member must followed by some other nodes.");

                            this.Current = this.CreateCurrentNode();

                            this.bufferedXamlNodes.Enqueue(this.Current);

                            // It is possible that the next node after StartMember is a StartObject/GetObject.
                            // We need to push the object declaration node to the Stack
                            this.PushObjectDeclarationNodeIfApplicable();

                            if (!this.SuppressingMarkupExtension() 
                                && this.Current.NodeType == XamlNodeType.Value)
                            {
                                DocumentRange valueRange;
                                DocumentLocation currentLocation = new DocumentLocation(this.Current.LineNumber, this.Current.LinePosition);
                                bool isInAttribute = this.xmlReaderWithSourceLocation.AttributeValueRanges.TryGetValue(currentLocation, out valueRange);
                                bool isInContent = isInAttribute ? false : this.xmlReaderWithSourceLocation.ContentValueRanges.TryGetValue(currentLocation, out valueRange);

                                if (isInAttribute || (isInContent && !isInitializationValue))
                                {
                                    // For Value Node with known line info, we want to route the value setting process through this Reader.
                                    // Therefore we need to go back to the member node and replace the XamlMemberInvoker.
                                    XamlNode startMemberNodeForValue = this.bufferedXamlNodes.Peek();
                                    XamlMember xamlMemberForValue = startMemberNodeForValue.Member;
                                    XamlMemberInvoker newXamlMemberInvoker = new ValueNodeXamlMemberInvoker(this, xamlMemberForValue.Invoker, valueRange);
                                    startMemberNodeForValue.Member = xamlMemberForValue.ReplaceXamlMemberInvoker(this.schemaContext, newXamlMemberInvoker);
                                }
                                else if (isInContent && isInitializationValue)
                                {
                                    XamlNode currentStartObject = this.objectDeclarationRecords.Peek();
                                    
                                    if (!this.initializationValueRanges.ContainsKey(currentStartObject))
                                    {
                                        this.initializationValueRanges.Add(currentStartObject, valueRange);
                                    }
                                    else
                                    {
                                        UnitTestUtility.Assert(false, 
                                            "I assume it is impossible for an object  to have more than one initialization member");
                                    }
                                }
                            }

                            this.StartAccessingBuffer();
                            break;

                        case XamlNodeType.EndObject:

                            this.InjectLineInfoXamlNodesToBuffer();
                            this.StartAccessingBuffer();
                            break;

                        case XamlNodeType.Value:
                            break;

                        default:
                            break;
                    }
                }
            }

            return readSucceed;
        }