private static void WriteVisitMember(CodeWriter codeWriter, DataModel model, DataModelMember member)
        {
            DataModelType memberType = model.GetTypeForMember(member);

            switch (memberType.Kind)
            {
            case DataModelTypeKind.BuiltInNumber:
            case DataModelTypeKind.BuiltInString:
            case DataModelTypeKind.BuiltInDictionary:
            case DataModelTypeKind.BuiltInBoolean:
            case DataModelTypeKind.BuiltInUri:
            case DataModelTypeKind.Enum:
            case DataModelTypeKind.BuiltInVersion:
                // Don't visit builtins; overrides would inspect those directly.
                return;

            case DataModelTypeKind.Leaf:
            case DataModelTypeKind.Base:
                // Visit this member
                break;

            case DataModelTypeKind.Default:
            default:
                Debug.Fail("Unexpected DataModelTypeKind");
                return;
            }

            string sourceVariable = "node." + member.CSharpName;

            if (member.Rank == 0)
            {
                codeWriter.WriteLine("{0} = this.VisitNullChecked({0});", sourceVariable);
                return;
            }

            var indexNamer = new LocalVariableNamer("index");
            var valueNamer = new LocalVariableNamer("value");

            string indexName = null;

            for (int idx = 1; idx < member.Rank; ++idx)
            {
                string valueName = valueNamer.MakeName();
                indexName = indexNamer.MakeName();
                codeWriter.OpenBrace("if ({0} != null)", sourceVariable);
                codeWriter.OpenBrace("for (int {0} = 0; {0} < {1}.Count; ++{0})", indexName, sourceVariable);
                codeWriter.WriteLine("var {0} = {1}[{2}];", valueName, sourceVariable, indexName);
                sourceVariable = valueName;
            }

            indexName = indexNamer.MakeName();
            codeWriter.OpenBrace("if ({0} != null)", sourceVariable);
            codeWriter.OpenBrace("for (int {0} = 0; {0} < {1}.Count; ++{0})", indexName, sourceVariable);
            codeWriter.WriteLine("{0}[{1}] = this.VisitNullChecked({0}[{1}]);", sourceVariable, indexName);

            for (int idx = 0; idx < member.Rank; ++idx)
            {
                codeWriter.CloseBrace(); // if (source != null)
                codeWriter.CloseBrace(); // for
            }

            codeWriter.WriteLine();
        }
        /// <summary>Generates a rewriting visitor class for the supplied model.</summary>
        /// <exception cref="ArgumentNullException">
        /// Thrown when one or more required arguments are null.
        /// </exception>
        /// <param name="codeWriter">The code writer into which the rewriting visitor shall be written.</param>
        /// <param name="model">The model for which a rewriting visitor shall be generated.</param>
        public static void Generate(CodeWriter codeWriter, DataModel model)
        {
            codeWriter.WriteLine("/// <summary>Rewriting visitor for a {0} tree.</summary>", model.Name);
            codeWriter.OpenBrace("public abstract class {0}RewritingVisitor", model.Name);

            codeWriter.WriteLine("/// <summary>Starts a rewriting visit of a {0} tree.</summary>", model.Name);
            codeWriter.WriteLine("/// <param name=\"node\">The node to rewrite.</param>");
            codeWriter.OpenBrace("public virtual object Visit({0} node)", CodeGenerator.CommonInterfaceName);
            codeWriter.WriteLine("return this.VisitActual(node);");
            codeWriter.CloseBrace();
            codeWriter.WriteLine();

            codeWriter.WriteLine("/// <summary>Executes a visit of a {0} tree.</summary>", model.Name);
            codeWriter.WriteLine("/// <param name=\"node\">The node to visit.</param>");
            codeWriter.OpenBrace("public virtual object VisitActual({0} node)", CodeGenerator.CommonInterfaceName);
            codeWriter.OpenBrace("if (node == null)");
            codeWriter.WriteLine("throw new ArgumentNullException(\"node\");");
            codeWriter.CloseBrace(); // if node == null
            codeWriter.WriteLine();

            codeWriter.OpenBrace("switch (node.SyntaxKind)");

            foreach (DataModelType type in model.Types)
            {
                if (type.Kind == DataModelTypeKind.Leaf)
                {
                    string csName = type.CSharpName;
                    codeWriter.DecrementIndentLevel();
                    codeWriter.WriteLine("case {0}Kind.{1}:", model.Name, csName);
                    codeWriter.IncrementIndentLevel();
                    codeWriter.WriteLine("return this.Visit{0}(({0})node);", csName);
                }
            }

            codeWriter.DecrementIndentLevel();
            codeWriter.WriteLine("default:");
            codeWriter.IncrementIndentLevel();
            codeWriter.WriteLine("return node;");
            codeWriter.CloseBrace(); // switch
            codeWriter.CloseBrace(); // VisitActual

            codeWriter.WriteLine();
            codeWriter.WriteLine("private T VisitNullChecked<T>(T node)", CodeGenerator.CommonInterfaceName);
            codeWriter.IncrementIndentLevel();
            codeWriter.WriteLine("where T : class, " + CodeGenerator.CommonInterfaceName);
            codeWriter.DecrementIndentLevel();
            codeWriter.OpenBrace();
            codeWriter.OpenBrace("if (node == null)");
            codeWriter.WriteLine("return null;");
            codeWriter.CloseBrace(); // node == null
            codeWriter.WriteLine();
            codeWriter.WriteLine("return (T)this.Visit(node);");
            codeWriter.CloseBrace(); // VisitNullChecked

            foreach (DataModelType type in model.Types)
            {
                if (type.Kind == DataModelTypeKind.Leaf)
                {
                    string csName = type.CSharpName;
                    codeWriter.WriteLine();
                    codeWriter.WriteLine("/// <summary>Rewrites a {0} node in a {1} tree.</summary>", csName, model.Name);
                    codeWriter.WriteLine("/// <param name=\"node\">A {0} node to visit.</param>", csName);
                    codeWriter.OpenBrace("public virtual {0} Visit{0}({0} node)", csName);
                    codeWriter.OpenBrace("if (node != null)");
                    foreach (DataModelMember member in type.Members)
                    {
                        WriteVisitMember(codeWriter, model, member);
                    }

                    codeWriter.CloseBrace();
                    codeWriter.WriteLine();
                    codeWriter.WriteLine("return node;");
                    codeWriter.CloseBrace(); // Visit{TNode}
                }
            }

            codeWriter.CloseBrace(); // class
        }