The Labs \ Source Viewer \ SSCLI \ System.Xml.Xsl.Qil \ QilReplaceVisitor

  1. //------------------------------------------------------------------------------
  2. // <copyright file="QilReplaceVisitor.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. using System;
  16. using System.Collections;
  17. using System.Collections.Generic;
  18. using System.Diagnostics;
  19. using System.Xml.Xsl;
  20. namespace System.Xml.Xsl.Qil
  21. {
  22.    
  23.     /// <summary>
  24.     /// Base internal class for visitors that replace the graph as they visit it.
  25.     /// </summary>
  26.     internal abstract class QilReplaceVisitor : QilVisitor
  27.     {
  28.         protected QilFactory f;
  29.        
  30.         public QilReplaceVisitor(QilFactory f)
  31.         {
  32.             this.f = f;
  33.         }
  34.        
  35.        
  36.         //-----------------------------------------------
  37.         // QilVisitor overrides
  38.         //-----------------------------------------------
  39.        
  40.         /// <summary>
  41.         /// Visit all children of "parent", replacing each child with a copy of each child.
  42.         /// </summary>
  43.         protected override QilNode VisitChildren(QilNode parent)
  44.         {
  45.             XmlQueryType oldParentType = parent.XmlType;
  46.             bool recalcType = false;
  47.            
  48.             // Visit children
  49.             for (int i = 0; i < parent.Count; i++) {
  50.                 QilNode oldChild = parent[i];
  51.                 QilNode newChild;
  52.                 XmlQueryType oldChildType = oldChild != null ? oldChild.XmlType : null;
  53.                
  54.                 // Visit child
  55.                 if (IsReference(parent, i))
  56.                     newChild = VisitReference(oldChild);
  57.                 else
  58.                     newChild = Visit(oldChild);
  59.                
  60.                 // Only replace child and recalculate type if oldChild != newChild or oldChild.XmlType != newChild.XmlType
  61.                 if (!Ref.Equals(oldChild, newChild) || (newChild != null && !Ref.Equals(oldChildType, newChild.XmlType))) {
  62.                     recalcType = true;
  63.                     parent[i] = newChild;
  64.                 }
  65.             }
  66.            
  67.             if (recalcType)
  68.                 RecalculateType(parent, oldParentType);
  69.            
  70.             return parent;
  71.         }
  72.        
  73.        
  74.         //-----------------------------------------------
  75.         // QilReplaceVisitor methods
  76.         //-----------------------------------------------
  77.        
  78.         /// <summary>
  79.         /// Once children have been replaced, the Xml type is recalculated.
  80.         /// </summary>
  81.         protected virtual void RecalculateType(QilNode node, XmlQueryType oldType)
  82.         {
  83.             XmlQueryType newType;
  84.            
  85.             newType = f.TypeChecker.Check(node);
  86.            
  87.             // Note the use of AtMost to account for cases when folding of Error nodes in the graph cause
  88.             // cardinality to be recalculated.
  89.             // For example, (Sequence (TextCtor (Error "error")) (Int32 1)) => (Sequence (Error "error") (Int32 1))
  90.             // In this case, cardinality has gone from More to One
  91.             Debug.Assert(newType.IsSubtypeOf(XmlQueryTypeFactory.AtMost(oldType, oldType.Cardinality)), "Replace shouldn't relax original type");
  92.            
  93.             node.XmlType = newType;
  94.         }
  95.     }
  96. }

Developer Fusion