The Labs \ Source Viewer \ SSCLI \ System.CodeDom.Compiler \ CodeGenerator

  1. //------------------------------------------------------------------------------
  2. // <copyright file="CodeGenerator.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. namespace System.CodeDom.Compiler
  16. {
  17.     using System.Runtime.Remoting;
  18.     using System.Runtime.InteropServices;
  19.    
  20.     using System.Diagnostics;
  21.     using System;
  22.     using Microsoft.Win32;
  23.     using System.IO;
  24.     using System.Collections;
  25.     using System.Reflection;
  26.     using System.Globalization;
  27.     using System.CodeDom;
  28.     using System.Security.Permissions;
  29.     using System.Text;
  30.    
  31.     /// <devdoc>
  32.     /// <para>Provides a base class for code generators.</para>
  33.     /// </devdoc>
  34.     [PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
  35.     [PermissionSet(SecurityAction.InheritanceDemand, Name = "FullTrust")]
  36.     public abstract class CodeGenerator : ICodeGenerator
  37.     {
  38.         private const int ParameterMultilineThreshold = 15;
  39.         private IndentedTextWriter output;
  40.         private CodeGeneratorOptions options;
  41.        
  42.         private CodeTypeDeclaration currentClass;
  43.         private CodeTypeMember currentMember;
  44.        
  45.         private bool inNestedBinary = false;
  46.        
  47.         /// <devdoc>
  48.         /// <para>
  49.         /// Gets the current class.
  50.         /// </para>
  51.         /// </devdoc>
  52.         protected CodeTypeDeclaration CurrentClass {
  53.             get { return currentClass; }
  54.         }
  55.        
  56.         /// <devdoc>
  57.         /// <para>
  58.         /// Gets or sets the current class name.
  59.         /// </para>
  60.         /// </devdoc>
  61.         protected string CurrentTypeName {
  62.             get {
  63.                 if (currentClass != null) {
  64.                     return currentClass.Name;
  65.                 }
  66.                 return "<% unknown %>";
  67.             }
  68.         }
  69.        
  70.         /// <devdoc>
  71.         /// <para>
  72.         /// Gets or sets the current member of the class.
  73.         /// </para>
  74.         /// </devdoc>
  75.         protected CodeTypeMember CurrentMember {
  76.             get { return currentMember; }
  77.         }
  78.        
  79.         /// <devdoc>
  80.         /// <para>
  81.         /// Gets or sets the current member name.
  82.         /// </para>
  83.         /// </devdoc>
  84.         protected string CurrentMemberName {
  85.             get {
  86.                 if (currentMember != null) {
  87.                     return currentMember.Name;
  88.                 }
  89.                 return "<% unknown %>";
  90.             }
  91.         }
  92.        
  93.         /// <devdoc>
  94.         /// <para>
  95.         /// Gets or sets a value indicating whether the current object being
  96.         /// generated is an interface.
  97.         /// </para>
  98.         /// </devdoc>
  99.         protected bool IsCurrentInterface {
  100.             get {
  101.                 if (currentClass != null && !(currentClass is CodeTypeDelegate)) {
  102.                     return currentClass.IsInterface;
  103.                 }
  104.                 return false;
  105.             }
  106.         }
  107.        
  108.         /// <devdoc>
  109.         /// <para>
  110.         /// Gets or sets a value indicating whether the current object being generated
  111.         /// is a class.
  112.         /// </para>
  113.         /// </devdoc>
  114.         protected bool IsCurrentClass {
  115.             get {
  116.                 if (currentClass != null && !(currentClass is CodeTypeDelegate)) {
  117.                     return currentClass.IsClass;
  118.                 }
  119.                 return false;
  120.             }
  121.         }
  122.        
  123.         /// <devdoc>
  124.         /// <para>
  125.         /// Gets or sets a value indicating whether the current object being generated
  126.         /// is a struct.
  127.         /// </para>
  128.         /// </devdoc>
  129.         protected bool IsCurrentStruct {
  130.             get {
  131.                 if (currentClass != null && !(currentClass is CodeTypeDelegate)) {
  132.                     return currentClass.IsStruct;
  133.                 }
  134.                 return false;
  135.             }
  136.         }
  137.        
  138.         /// <devdoc>
  139.         /// <para>
  140.         /// Gets or sets a value indicating whether the current object being generated
  141.         /// is an enumeration.
  142.         /// </para>
  143.         /// </devdoc>
  144.         protected bool IsCurrentEnum {
  145.             get {
  146.                 if (currentClass != null && !(currentClass is CodeTypeDelegate)) {
  147.                     return currentClass.IsEnum;
  148.                 }
  149.                 return false;
  150.             }
  151.         }
  152.        
  153.         /// <devdoc>
  154.         /// <para>
  155.         /// Gets or sets a value indicating whether the current object being generated
  156.         /// is a delegate.
  157.         /// </para>
  158.         /// </devdoc>
  159.         protected bool IsCurrentDelegate {
  160.             get {
  161.                 if (currentClass != null && currentClass is CodeTypeDelegate) {
  162.                     return true;
  163.                 }
  164.                 return false;
  165.             }
  166.         }
  167.        
  168.         /// <devdoc>
  169.         /// <para>
  170.         /// Gets or sets the amount of spaces to indent.
  171.         /// </para>
  172.         /// </devdoc>
  173.         protected int Indent {
  174.             get { return output.Indent; }
  175.             set { output.Indent = value; }
  176.         }
  177.        
  178.         /// <devdoc>
  179.         /// <para>
  180.         /// Gets the token that represents <see langword='null'/>.
  181.         /// </para>
  182.         /// </devdoc>
  183.         protected abstract string NullToken {
  184.             get;
  185.         }
  186.        
  187.         /// <devdoc>
  188.         /// <para>
  189.         /// Gets or sets the System.IO.TextWriter
  190.         /// to use for output.
  191.         /// </para>
  192.         /// </devdoc>
  193.         protected TextWriter Output {
  194.             get { return output; }
  195.         }
  196.        
  197.         /// <devdoc>
  198.         /// <para>[To be supplied.]</para>
  199.         /// </devdoc>
  200.         protected CodeGeneratorOptions Options {
  201.             get { return options; }
  202.         }
  203.        
  204.         private void GenerateType(CodeTypeDeclaration e)
  205.         {
  206.             currentClass = e;
  207.            
  208.             if (e.StartDirectives.Count > 0) {
  209.                 GenerateDirectives(e.StartDirectives);
  210.             }
  211.            
  212.             GenerateCommentStatements(e.Comments);
  213.            
  214.             if (e.LinePragma != null)
  215.                 GenerateLinePragmaStart(e.LinePragma);
  216.            
  217.             GenerateTypeStart(e);
  218.            
  219.             if (Options.VerbatimOrder) {
  220.                 foreach (CodeTypeMember member in e.Members) {
  221.                     GenerateTypeMember(member, e);
  222.                 }
  223.             }
  224.             else {
  225.                
  226.                 GenerateFields(e);
  227.                
  228.                 GenerateSnippetMembers(e);
  229.                
  230.                 GenerateTypeConstructors(e);
  231.                
  232.                 GenerateConstructors(e);
  233.                
  234.                 GenerateProperties(e);
  235.                
  236.                 GenerateEvents(e);
  237.                
  238.                 GenerateMethods(e);
  239.                
  240.                 GenerateNestedTypes(e);
  241.             }
  242.             // Nested types clobber the current class, so reset it.
  243.             currentClass = e;
  244.            
  245.             GenerateTypeEnd(e);
  246.             if (e.LinePragma != null)
  247.                 GenerateLinePragmaEnd(e.LinePragma);
  248.            
  249.             if (e.EndDirectives.Count > 0) {
  250.                 GenerateDirectives(e.EndDirectives);
  251.             }
  252.            
  253.         }
  254.        
  255.         protected virtual void GenerateDirectives(CodeDirectiveCollection directives)
  256.         {
  257.         }
  258.        
  259.         private void GenerateTypeMember(CodeTypeMember member, CodeTypeDeclaration declaredType)
  260.         {
  261.            
  262.             if (options.BlankLinesBetweenMembers) {
  263.                 Output.WriteLine();
  264.             }
  265.            
  266.             if (member is CodeTypeDeclaration) {
  267.                 ((ICodeGenerator)this).GenerateCodeFromType((CodeTypeDeclaration)member, output.InnerWriter, options);
  268.                
  269.                 // Nested types clobber the current class, so reset it.
  270.                 currentClass = declaredType;
  271.                
  272.                 // For nested types, comments and line pragmas are handled separately, so return here
  273.                 return;
  274.             }
  275.            
  276.             if (member.StartDirectives.Count > 0) {
  277.                 GenerateDirectives(member.StartDirectives);
  278.             }
  279.            
  280.             GenerateCommentStatements(member.Comments);
  281.            
  282.             if (member.LinePragma != null) {
  283.                 GenerateLinePragmaStart(member.LinePragma);
  284.             }
  285.            
  286.             if (member is CodeMemberField) {
  287.                 GenerateField((CodeMemberField)member);
  288.             }
  289.             else if (member is CodeMemberProperty) {
  290.                 GenerateProperty((CodeMemberProperty)member, declaredType);
  291.             }
  292.             else if (member is CodeMemberMethod) {
  293.                 if (member is CodeConstructor) {
  294.                     GenerateConstructor((CodeConstructor)member, declaredType);
  295.                 }
  296.                 else if (member is CodeTypeConstructor) {
  297.                     GenerateTypeConstructor((CodeTypeConstructor)member);
  298.                 }
  299.                 else if (member is CodeEntryPointMethod) {
  300.                     GenerateEntryPointMethod((CodeEntryPointMethod)member, declaredType);
  301.                 }
  302.                 else {
  303.                     GenerateMethod((CodeMemberMethod)member, declaredType);
  304.                 }
  305.             }
  306.             else if (member is CodeMemberEvent) {
  307.                 GenerateEvent((CodeMemberEvent)member, declaredType);
  308.             }
  309.             else if (member is CodeSnippetTypeMember) {
  310.                
  311.                 // Don't indent snippets, in order to preserve the column
  312.                 // information from the original code. This improves the debugging
  313.                 // experience.
  314.                 int savedIndent = Indent;
  315.                 Indent = 0;
  316.                
  317.                 GenerateSnippetMember((CodeSnippetTypeMember)member);
  318.                
  319.                 // Restore the indent
  320.                 Indent = savedIndent;
  321.                
  322.                 // Generate an extra new line at the end of the snippet.
  323.                 // If the snippet is comment and this type only contains comments.
  324.                 // The generated code will not compile.
  325.                 Output.WriteLine();
  326.             }
  327.            
  328.             if (member.LinePragma != null) {
  329.                 GenerateLinePragmaEnd(member.LinePragma);
  330.             }
  331.            
  332.             if (member.EndDirectives.Count > 0) {
  333.                 GenerateDirectives(member.EndDirectives);
  334.             }
  335.         }
  336.        
  337.         private void GenerateTypeConstructors(CodeTypeDeclaration e)
  338.         {
  339.             IEnumerator en = e.Members.GetEnumerator();
  340.             while (en.MoveNext()) {
  341.                 if (en.Current is CodeTypeConstructor) {
  342.                     currentMember = (CodeTypeMember)en.Current;
  343.                    
  344.                     if (options.BlankLinesBetweenMembers) {
  345.                         Output.WriteLine();
  346.                     }
  347.                     if (currentMember.StartDirectives.Count > 0) {
  348.                         GenerateDirectives(currentMember.StartDirectives);
  349.                     }
  350.                     GenerateCommentStatements(currentMember.Comments);
  351.                     CodeTypeConstructor imp = (CodeTypeConstructor)en.Current;
  352.                     if (imp.LinePragma != null)
  353.                         GenerateLinePragmaStart(imp.LinePragma);
  354.                     GenerateTypeConstructor(imp);
  355.                     if (imp.LinePragma != null)
  356.                         GenerateLinePragmaEnd(imp.LinePragma);
  357.                     if (currentMember.EndDirectives.Count > 0) {
  358.                         GenerateDirectives(currentMember.EndDirectives);
  359.                     }
  360.                 }
  361.             }
  362.         }
  363.        
  364.         /// <devdoc>
  365.         /// <para> Generates code for the namepsaces in the specifield CodeDom compile unit.
  366.         /// </para>
  367.         /// </devdoc>
  368.         protected void GenerateNamespaces(CodeCompileUnit e)
  369.         {
  370.             foreach (CodeNamespace n in e.Namespaces) {
  371.                 ((ICodeGenerator)this).GenerateCodeFromNamespace(n, output.InnerWriter, options);
  372.             }
  373.         }
  374.        
  375.         /// <devdoc>
  376.         /// <para> Generates code for the specified CodeDom namespace representation and the classes it
  377.         /// contains.</para>
  378.         /// </devdoc>
  379.         protected void GenerateTypes(CodeNamespace e)
  380.         {
  381.             foreach (CodeTypeDeclaration c in e.Types) {
  382.                 if (options.BlankLinesBetweenMembers) {
  383.                     Output.WriteLine();
  384.                 }
  385.                 ((ICodeGenerator)this).GenerateCodeFromType(c, output.InnerWriter, options);
  386.             }
  387.         }
  388.        
  389.         /// <internalonly/>
  390.         bool ICodeGenerator.Supports(GeneratorSupport support)
  391.         {
  392.             return this.Supports(support);
  393.         }
  394.        
  395.         /// <internalonly/>
  396.         void ICodeGenerator.GenerateCodeFromType(CodeTypeDeclaration e, TextWriter w, CodeGeneratorOptions o)
  397.         {
  398.             bool setLocal = false;
  399.             if (output != null && w != output.InnerWriter) {
  400.                 throw new InvalidOperationException(SR.GetString(SR.CodeGenOutputWriter));
  401.             }
  402.             if (output == null) {
  403.                 setLocal = true;
  404.                 options = (o == null) ? new CodeGeneratorOptions() : o;
  405.                 output = new IndentedTextWriter(w, options.IndentString);
  406.             }
  407.            
  408.             try {
  409.                 GenerateType(e);
  410.             }
  411.             finally {
  412.                 if (setLocal) {
  413.                     output = null;
  414.                     options = null;
  415.                 }
  416.             }
  417.         }
  418.        
  419.         /// <internalonly/>
  420.         void ICodeGenerator.GenerateCodeFromExpression(CodeExpression e, TextWriter w, CodeGeneratorOptions o)
  421.         {
  422.             bool setLocal = false;
  423.             if (output != null && w != output.InnerWriter) {
  424.                 throw new InvalidOperationException(SR.GetString(SR.CodeGenOutputWriter));
  425.             }
  426.             if (output == null) {
  427.                 setLocal = true;
  428.                 options = (o == null) ? new CodeGeneratorOptions() : o;
  429.                 output = new IndentedTextWriter(w, options.IndentString);
  430.             }
  431.            
  432.             try {
  433.                 GenerateExpression(e);
  434.             }
  435.             finally {
  436.                 if (setLocal) {
  437.                     output = null;
  438.                     options = null;
  439.                 }
  440.             }
  441.         }
  442.        
  443.         /// <internalonly/>
  444.         void ICodeGenerator.GenerateCodeFromCompileUnit(CodeCompileUnit e, TextWriter w, CodeGeneratorOptions o)
  445.         {
  446.             bool setLocal = false;
  447.             if (output != null && w != output.InnerWriter) {
  448.                 throw new InvalidOperationException(SR.GetString(SR.CodeGenOutputWriter));
  449.             }
  450.             if (output == null) {
  451.                 setLocal = true;
  452.                 options = (o == null) ? new CodeGeneratorOptions() : o;
  453.                 output = new IndentedTextWriter(w, options.IndentString);
  454.             }
  455.            
  456.             try {
  457.                 if (e is CodeSnippetCompileUnit) {
  458.                     GenerateSnippetCompileUnit((CodeSnippetCompileUnit)e);
  459.                 }
  460.                 else {
  461.                     GenerateCompileUnit(e);
  462.                 }
  463.             }
  464.             finally {
  465.                 if (setLocal) {
  466.                     output = null;
  467.                     options = null;
  468.                 }
  469.             }
  470.         }
  471.        
  472.         /// <internalonly/>
  473.         void ICodeGenerator.GenerateCodeFromNamespace(CodeNamespace e, TextWriter w, CodeGeneratorOptions o)
  474.         {
  475.             bool setLocal = false;
  476.             if (output != null && w != output.InnerWriter) {
  477.                 throw new InvalidOperationException(SR.GetString(SR.CodeGenOutputWriter));
  478.             }
  479.             if (output == null) {
  480.                 setLocal = true;
  481.                 options = (o == null) ? new CodeGeneratorOptions() : o;
  482.                 output = new IndentedTextWriter(w, options.IndentString);
  483.             }
  484.            
  485.             try {
  486.                 GenerateNamespace(e);
  487.             }
  488.             finally {
  489.                 if (setLocal) {
  490.                     output = null;
  491.                     options = null;
  492.                 }
  493.             }
  494.         }
  495.        
  496.         /// <internalonly/>
  497.         void ICodeGenerator.GenerateCodeFromStatement(CodeStatement e, TextWriter w, CodeGeneratorOptions o)
  498.         {
  499.             bool setLocal = false;
  500.             if (output != null && w != output.InnerWriter) {
  501.                 throw new InvalidOperationException(SR.GetString(SR.CodeGenOutputWriter));
  502.             }
  503.             if (output == null) {
  504.                 setLocal = true;
  505.                 options = (o == null) ? new CodeGeneratorOptions() : o;
  506.                 output = new IndentedTextWriter(w, options.IndentString);
  507.             }
  508.            
  509.             try {
  510.                 GenerateStatement(e);
  511.             }
  512.             finally {
  513.                 if (setLocal) {
  514.                     output = null;
  515.                     options = null;
  516.                 }
  517.             }
  518.         }
  519.        
  520.         public virtual void GenerateCodeFromMember(CodeTypeMember member, TextWriter writer, CodeGeneratorOptions options)
  521.         {
  522.             if (this.output != null) {
  523.                 throw new InvalidOperationException(SR.GetString(SR.CodeGenReentrance));
  524.             }
  525.             this.options = (options == null) ? new CodeGeneratorOptions() : options;
  526.             this.output = new IndentedTextWriter(writer, this.options.IndentString);
  527.            
  528.             try {
  529.                 CodeTypeDeclaration dummyClass = new CodeTypeDeclaration();
  530.                 this.currentClass = dummyClass;
  531.                 GenerateTypeMember(member, dummyClass);
  532.             }
  533.             finally {
  534.                 this.currentClass = null;
  535.                 this.output = null;
  536.                 this.options = null;
  537.             }
  538.         }
  539.        
  540.        
  541.         /// <internalonly/>
  542.         bool ICodeGenerator.IsValidIdentifier(string value)
  543.         {
  544.             return this.IsValidIdentifier(value);
  545.         }
  546.         /// <internalonly/>
  547.         void ICodeGenerator.ValidateIdentifier(string value)
  548.         {
  549.             this.ValidateIdentifier(value);
  550.         }
  551.        
  552.         /// <internalonly/>
  553.         string ICodeGenerator.CreateEscapedIdentifier(string value)
  554.         {
  555.             return this.CreateEscapedIdentifier(value);
  556.         }
  557.        
  558.         /// <internalonly/>
  559.         string ICodeGenerator.CreateValidIdentifier(string value)
  560.         {
  561.             return this.CreateValidIdentifier(value);
  562.         }
  563.        
  564.         /// <internalonly/>
  565.         string ICodeGenerator.GetTypeOutput(CodeTypeReference type)
  566.         {
  567.             return this.GetTypeOutput(type);
  568.         }
  569.        
  570.         private void GenerateConstructors(CodeTypeDeclaration e)
  571.         {
  572.             IEnumerator en = e.Members.GetEnumerator();
  573.             while (en.MoveNext()) {
  574.                 if (en.Current is CodeConstructor) {
  575.                     currentMember = (CodeTypeMember)en.Current;
  576.                    
  577.                     if (options.BlankLinesBetweenMembers) {
  578.                         Output.WriteLine();
  579.                     }
  580.                     if (currentMember.StartDirectives.Count > 0) {
  581.                         GenerateDirectives(currentMember.StartDirectives);
  582.                     }
  583.                     GenerateCommentStatements(currentMember.Comments);
  584.                     CodeConstructor imp = (CodeConstructor)en.Current;
  585.                     if (imp.LinePragma != null)
  586.                         GenerateLinePragmaStart(imp.LinePragma);
  587.                     GenerateConstructor(imp, e);
  588.                     if (imp.LinePragma != null)
  589.                         GenerateLinePragmaEnd(imp.LinePragma);
  590.                     if (currentMember.EndDirectives.Count > 0) {
  591.                         GenerateDirectives(currentMember.EndDirectives);
  592.                     }
  593.                 }
  594.             }
  595.         }
  596.        
  597.         private void GenerateEvents(CodeTypeDeclaration e)
  598.         {
  599.             IEnumerator en = e.Members.GetEnumerator();
  600.             while (en.MoveNext()) {
  601.                 if (en.Current is CodeMemberEvent) {
  602.                     currentMember = (CodeTypeMember)en.Current;
  603.                    
  604.                     if (options.BlankLinesBetweenMembers) {
  605.                         Output.WriteLine();
  606.                     }
  607.                     if (currentMember.StartDirectives.Count > 0) {
  608.                         GenerateDirectives(currentMember.StartDirectives);
  609.                     }
  610.                     GenerateCommentStatements(currentMember.Comments);
  611.                     CodeMemberEvent imp = (CodeMemberEvent)en.Current;
  612.                     if (imp.LinePragma != null)
  613.                         GenerateLinePragmaStart(imp.LinePragma);
  614.                     GenerateEvent(imp, e);
  615.                     if (imp.LinePragma != null)
  616.                         GenerateLinePragmaEnd(imp.LinePragma);
  617.                     if (currentMember.EndDirectives.Count > 0) {
  618.                         GenerateDirectives(currentMember.EndDirectives);
  619.                     }
  620.                 }
  621.             }
  622.         }
  623.        
  624.         /// <devdoc>
  625.         /// <para>Generates code for the specified CodeDom code expression representation.</para>
  626.         /// </devdoc>
  627.         protected void GenerateExpression(CodeExpression e)
  628.         {
  629.             if (e is CodeArrayCreateExpression) {
  630.                 GenerateArrayCreateExpression((CodeArrayCreateExpression)e);
  631.             }
  632.             else if (e is CodeBaseReferenceExpression) {
  633.                 GenerateBaseReferenceExpression((CodeBaseReferenceExpression)e);
  634.             }
  635.             else if (e is CodeBinaryOperatorExpression) {
  636.                 GenerateBinaryOperatorExpression((CodeBinaryOperatorExpression)e);
  637.             }
  638.             else if (e is CodeCastExpression) {
  639.                 GenerateCastExpression((CodeCastExpression)e);
  640.             }
  641.             else if (e is CodeDelegateCreateExpression) {
  642.                 GenerateDelegateCreateExpression((CodeDelegateCreateExpression)e);
  643.             }
  644.             else if (e is CodeFieldReferenceExpression) {
  645.                 GenerateFieldReferenceExpression((CodeFieldReferenceExpression)e);
  646.             }
  647.             else if (e is CodeArgumentReferenceExpression) {
  648.                 GenerateArgumentReferenceExpression((CodeArgumentReferenceExpression)e);
  649.             }
  650.             else if (e is CodeVariableReferenceExpression) {
  651.                 GenerateVariableReferenceExpression((CodeVariableReferenceExpression)e);
  652.             }
  653.             else if (e is CodeIndexerExpression) {
  654.                 GenerateIndexerExpression((CodeIndexerExpression)e);
  655.             }
  656.             else if (e is CodeArrayIndexerExpression) {
  657.                 GenerateArrayIndexerExpression((CodeArrayIndexerExpression)e);
  658.             }
  659.             else if (e is CodeSnippetExpression) {
  660.                 GenerateSnippetExpression((CodeSnippetExpression)e);
  661.             }
  662.             else if (e is CodeMethodInvokeExpression) {
  663.                 GenerateMethodInvokeExpression((CodeMethodInvokeExpression)e);
  664.             }
  665.             else if (e is CodeMethodReferenceExpression) {
  666.                 GenerateMethodReferenceExpression((CodeMethodReferenceExpression)e);
  667.             }
  668.             else if (e is CodeEventReferenceExpression) {
  669.                 GenerateEventReferenceExpression((CodeEventReferenceExpression)e);
  670.             }
  671.             else if (e is CodeDelegateInvokeExpression) {
  672.                 GenerateDelegateInvokeExpression((CodeDelegateInvokeExpression)e);
  673.             }
  674.             else if (e is CodeObjectCreateExpression) {
  675.                 GenerateObjectCreateExpression((CodeObjectCreateExpression)e);
  676.             }
  677.             else if (e is CodeParameterDeclarationExpression) {
  678.                 GenerateParameterDeclarationExpression((CodeParameterDeclarationExpression)e);
  679.             }
  680.             else if (e is CodeDirectionExpression) {
  681.                 GenerateDirectionExpression((CodeDirectionExpression)e);
  682.             }
  683.             else if (e is CodePrimitiveExpression) {
  684.                 GeneratePrimitiveExpression((CodePrimitiveExpression)e);
  685.             }
  686.             else if (e is CodePropertyReferenceExpression) {
  687.                 GeneratePropertyReferenceExpression((CodePropertyReferenceExpression)e);
  688.             }
  689.             else if (e is CodePropertySetValueReferenceExpression) {
  690.                 GeneratePropertySetValueReferenceExpression((CodePropertySetValueReferenceExpression)e);
  691.             }
  692.             else if (e is CodeThisReferenceExpression) {
  693.                 GenerateThisReferenceExpression((CodeThisReferenceExpression)e);
  694.             }
  695.             else if (e is CodeTypeReferenceExpression) {
  696.                 GenerateTypeReferenceExpression((CodeTypeReferenceExpression)e);
  697.             }
  698.             else if (e is CodeTypeOfExpression) {
  699.                 GenerateTypeOfExpression((CodeTypeOfExpression)e);
  700.             }
  701.             else if (e is CodeDefaultValueExpression) {
  702.                 GenerateDefaultValueExpression((CodeDefaultValueExpression)e);
  703.             }
  704.             else {
  705.                 if (e == null) {
  706.                     throw new ArgumentNullException("e");
  707.                 }
  708.                 else {
  709.                     throw new ArgumentException(SR.GetString(SR.InvalidElementType, e.GetType().FullName), "e");
  710.                 }
  711.             }
  712.         }
  713.        
  714.         private void GenerateFields(CodeTypeDeclaration e)
  715.         {
  716.             IEnumerator en = e.Members.GetEnumerator();
  717.             while (en.MoveNext()) {
  718.                 if (en.Current is CodeMemberField) {
  719.                     currentMember = (CodeTypeMember)en.Current;
  720.                    
  721.                     if (options.BlankLinesBetweenMembers) {
  722.                         Output.WriteLine();
  723.                     }
  724.                     if (currentMember.StartDirectives.Count > 0) {
  725.                         GenerateDirectives(currentMember.StartDirectives);
  726.                     }
  727.                     GenerateCommentStatements(currentMember.Comments);
  728.                     CodeMemberField imp = (CodeMemberField)en.Current;
  729.                     if (imp.LinePragma != null)
  730.                         GenerateLinePragmaStart(imp.LinePragma);
  731.                     GenerateField(imp);
  732.                     if (imp.LinePragma != null)
  733.                         GenerateLinePragmaEnd(imp.LinePragma);
  734.                     if (currentMember.EndDirectives.Count > 0) {
  735.                         GenerateDirectives(currentMember.EndDirectives);
  736.                     }
  737.                 }
  738.             }
  739.         }
  740.        
  741.         private void GenerateSnippetMembers(CodeTypeDeclaration e)
  742.         {
  743.             IEnumerator en = e.Members.GetEnumerator();
  744.             bool hasSnippet = false;
  745.             while (en.MoveNext()) {
  746.                 if (en.Current is CodeSnippetTypeMember) {
  747.                     hasSnippet = true;
  748.                     currentMember = (CodeTypeMember)en.Current;
  749.                    
  750.                     if (options.BlankLinesBetweenMembers) {
  751.                         Output.WriteLine();
  752.                     }
  753.                     if (currentMember.StartDirectives.Count > 0) {
  754.                         GenerateDirectives(currentMember.StartDirectives);
  755.                     }
  756.                     GenerateCommentStatements(currentMember.Comments);
  757.                     CodeSnippetTypeMember imp = (CodeSnippetTypeMember)en.Current;
  758.                     if (imp.LinePragma != null)
  759.                         GenerateLinePragmaStart(imp.LinePragma);
  760.                    
  761.                     // Don't indent snippets, in order to preserve the column
  762.                     // information from the original code. This improves the debugging
  763.                     // experience.
  764.                     int savedIndent = Indent;
  765.                     Indent = 0;
  766.                    
  767.                     GenerateSnippetMember(imp);
  768.                    
  769.                     // Restore the indent
  770.                     Indent = savedIndent;
  771.                    
  772.                     if (imp.LinePragma != null)
  773.                         GenerateLinePragmaEnd(imp.LinePragma);
  774.                     if (currentMember.EndDirectives.Count > 0) {
  775.                         GenerateDirectives(currentMember.EndDirectives);
  776.                     }
  777.                    
  778.                 }
  779.             }
  780.             // Generate an extra new line at the end of the snippet.
  781.             // If the snippet is comment and this type only contains comments.
  782.             // The generated code will not compile.
  783.             if (hasSnippet) {
  784.                 Output.WriteLine();
  785.             }
  786.         }
  787.        
  788.         /// <devdoc>
  789.         /// <para> Generates code for the specified snippet code block
  790.         /// </para>
  791.         /// </devdoc>
  792.         protected virtual void GenerateSnippetCompileUnit(CodeSnippetCompileUnit e)
  793.         {
  794.            
  795.             GenerateDirectives(e.StartDirectives);
  796.            
  797.             if (e.LinePragma != null)
  798.                 GenerateLinePragmaStart(e.LinePragma);
  799.             Output.WriteLine(e.Value);
  800.             if (e.LinePragma != null)
  801.                 GenerateLinePragmaEnd(e.LinePragma);
  802.            
  803.             if (e.EndDirectives.Count > 0) {
  804.                 GenerateDirectives(e.EndDirectives);
  805.             }
  806.         }
  807.        
  808.         private void GenerateMethods(CodeTypeDeclaration e)
  809.         {
  810.             IEnumerator en = e.Members.GetEnumerator();
  811.             while (en.MoveNext()) {
  812.                 if (en.Current is CodeMemberMethod && !(en.Current is CodeTypeConstructor) && !(en.Current is CodeConstructor)) {
  813.                     currentMember = (CodeTypeMember)en.Current;
  814.                    
  815.                     if (options.BlankLinesBetweenMembers) {
  816.                         Output.WriteLine();
  817.                     }
  818.                     if (currentMember.StartDirectives.Count > 0) {
  819.                         GenerateDirectives(currentMember.StartDirectives);
  820.                     }
  821.                     GenerateCommentStatements(currentMember.Comments);
  822.                     CodeMemberMethod imp = (CodeMemberMethod)en.Current;
  823.                     if (imp.LinePragma != null)
  824.                         GenerateLinePragmaStart(imp.LinePragma);
  825.                     if (en.Current is CodeEntryPointMethod) {
  826.                         GenerateEntryPointMethod((CodeEntryPointMethod)en.Current, e);
  827.                     }
  828.                     else {
  829.                         GenerateMethod(imp, e);
  830.                     }
  831.                     if (imp.LinePragma != null)
  832.                         GenerateLinePragmaEnd(imp.LinePragma);
  833.                     if (currentMember.EndDirectives.Count > 0) {
  834.                         GenerateDirectives(currentMember.EndDirectives);
  835.                     }
  836.                 }
  837.             }
  838.         }
  839.        
  840.         private void GenerateNestedTypes(CodeTypeDeclaration e)
  841.         {
  842.             IEnumerator en = e.Members.GetEnumerator();
  843.             while (en.MoveNext()) {
  844.                 if (en.Current is CodeTypeDeclaration) {
  845.                     if (options.BlankLinesBetweenMembers) {
  846.                         Output.WriteLine();
  847.                     }
  848.                     CodeTypeDeclaration currentClass = (CodeTypeDeclaration)en.Current;
  849.                     ((ICodeGenerator)this).GenerateCodeFromType(currentClass, output.InnerWriter, options);
  850.                 }
  851.             }
  852.         }
  853.        
  854.         /// <devdoc>
  855.         /// <para> Generates code for the specified CodeDom
  856.         /// compile unit representation.</para>
  857.         /// </devdoc>
  858.         protected virtual void GenerateCompileUnit(CodeCompileUnit e)
  859.         {
  860.             GenerateCompileUnitStart(e);
  861.             GenerateNamespaces(e);
  862.             GenerateCompileUnitEnd(e);
  863.         }
  864.        
  865.         /// <devdoc>
  866.         /// <para> Generates code for the specified CodeDom
  867.         /// namespace representation.</para>
  868.         /// </devdoc>
  869.         protected virtual void GenerateNamespace(CodeNamespace e)
  870.         {
  871.             GenerateCommentStatements(e.Comments);
  872.             GenerateNamespaceStart(e);
  873.            
  874.             GenerateNamespaceImports(e);
  875.             Output.WriteLine("");
  876.            
  877.             GenerateTypes(e);
  878.             GenerateNamespaceEnd(e);
  879.         }
  880.        
  881.         /// <devdoc>
  882.         /// <para>
  883.         /// Generates code for the specified CodeDom based namespace import
  884.         /// representation.
  885.         /// </para>
  886.         /// </devdoc>
  887.         protected void GenerateNamespaceImports(CodeNamespace e)
  888.         {
  889.             IEnumerator en = e.Imports.GetEnumerator();
  890.             while (en.MoveNext()) {
  891.                 CodeNamespaceImport imp = (CodeNamespaceImport)en.Current;
  892.                 if (imp.LinePragma != null)
  893.                     GenerateLinePragmaStart(imp.LinePragma);
  894.                 GenerateNamespaceImport(imp);
  895.                 if (imp.LinePragma != null)
  896.                     GenerateLinePragmaEnd(imp.LinePragma);
  897.             }
  898.         }
  899.        
  900.         private void GenerateProperties(CodeTypeDeclaration e)
  901.         {
  902.             IEnumerator en = e.Members.GetEnumerator();
  903.             while (en.MoveNext()) {
  904.                 if (en.Current is CodeMemberProperty) {
  905.                     currentMember = (CodeTypeMember)en.Current;
  906.                    
  907.                     if (options.BlankLinesBetweenMembers) {
  908.                         Output.WriteLine();
  909.                     }
  910.                     if (currentMember.StartDirectives.Count > 0) {
  911.                         GenerateDirectives(currentMember.StartDirectives);
  912.                     }
  913.                     GenerateCommentStatements(currentMember.Comments);
  914.                     CodeMemberProperty imp = (CodeMemberProperty)en.Current;
  915.                     if (imp.LinePragma != null)
  916.                         GenerateLinePragmaStart(imp.LinePragma);
  917.                     GenerateProperty(imp, e);
  918.                     if (imp.LinePragma != null)
  919.                         GenerateLinePragmaEnd(imp.LinePragma);
  920.                     if (currentMember.EndDirectives.Count > 0) {
  921.                         GenerateDirectives(currentMember.EndDirectives);
  922.                     }
  923.                 }
  924.             }
  925.         }
  926.        
  927.         /// <devdoc>
  928.         /// <para>
  929.         /// Generates code for
  930.         /// the specified CodeDom based statement representation.
  931.         /// </para>
  932.         /// </devdoc>
  933.         protected void GenerateStatement(CodeStatement e)
  934.         {
  935.             if (e.StartDirectives.Count > 0) {
  936.                 GenerateDirectives(e.StartDirectives);
  937.             }
  938.            
  939.             if (e.LinePragma != null) {
  940.                 GenerateLinePragmaStart(e.LinePragma);
  941.             }
  942.            
  943.             if (e is CodeCommentStatement) {
  944.                 GenerateCommentStatement((CodeCommentStatement)e);
  945.             }
  946.             else if (e is CodeMethodReturnStatement) {
  947.                 GenerateMethodReturnStatement((CodeMethodReturnStatement)e);
  948.             }
  949.             else if (e is CodeConditionStatement) {
  950.                 GenerateConditionStatement((CodeConditionStatement)e);
  951.             }
  952.             else if (e is CodeTryCatchFinallyStatement) {
  953.                 GenerateTryCatchFinallyStatement((CodeTryCatchFinallyStatement)e);
  954.             }
  955.             else if (e is CodeAssignStatement) {
  956.                 GenerateAssignStatement((CodeAssignStatement)e);
  957.             }
  958.             else if (e is CodeExpressionStatement) {
  959.                 GenerateExpressionStatement((CodeExpressionStatement)e);
  960.             }
  961.             else if (e is CodeIterationStatement) {
  962.                 GenerateIterationStatement((CodeIterationStatement)e);
  963.             }
  964.             else if (e is CodeThrowExceptionStatement) {
  965.                 GenerateThrowExceptionStatement((CodeThrowExceptionStatement)e);
  966.             }
  967.             else if (e is CodeSnippetStatement) {
  968.                 // Don't indent snippet statements, in order to preserve the column
  969.                 // information from the original code. This improves the debugging
  970.                 // experience.
  971.                 int savedIndent = Indent;
  972.                 Indent = 0;
  973.                
  974.                 GenerateSnippetStatement((CodeSnippetStatement)e);
  975.                
  976.                 // Restore the indent
  977.                 Indent = savedIndent;
  978.             }
  979.             else if (e is CodeVariableDeclarationStatement) {
  980.                 GenerateVariableDeclarationStatement((CodeVariableDeclarationStatement)e);
  981.             }
  982.             else if (e is CodeAttachEventStatement) {
  983.                 GenerateAttachEventStatement((CodeAttachEventStatement)e);
  984.             }
  985.             else if (e is CodeRemoveEventStatement) {
  986.                 GenerateRemoveEventStatement((CodeRemoveEventStatement)e);
  987.             }
  988.             else if (e is CodeGotoStatement) {
  989.                 GenerateGotoStatement((CodeGotoStatement)e);
  990.             }
  991.             else if (e is CodeLabeledStatement) {
  992.                 GenerateLabeledStatement((CodeLabeledStatement)e);
  993.             }
  994.             else {
  995.                 throw new ArgumentException(SR.GetString(SR.InvalidElementType, e.GetType().FullName), "e");
  996.             }
  997.            
  998.             if (e.LinePragma != null) {
  999.                 GenerateLinePragmaEnd(e.LinePragma);
  1000.             }
  1001.             if (e.EndDirectives.Count > 0) {
  1002.                 GenerateDirectives(e.EndDirectives);
  1003.             }
  1004.         }
  1005.        
  1006.         /// <devdoc>
  1007.         /// <para>
  1008.         /// Generates code for the specified CodeDom based statement representations.
  1009.         /// </para>
  1010.         /// </devdoc>
  1011.         protected void GenerateStatements(CodeStatementCollection stms)
  1012.         {
  1013.             IEnumerator en = stms.GetEnumerator();
  1014.             while (en.MoveNext()) {
  1015.                 ((ICodeGenerator)this).GenerateCodeFromStatement((CodeStatement)en.Current, output.InnerWriter, options);
  1016.             }
  1017.         }
  1018.        
  1019.         /// <devdoc>
  1020.         /// <para>
  1021.         /// Generates code for the specified System.CodeDom.CodeAttributeBlock.
  1022.         /// </para>
  1023.         /// </devdoc>
  1024.         protected virtual void OutputAttributeDeclarations(CodeAttributeDeclarationCollection attributes)
  1025.         {
  1026.             if (attributes.Count == 0)
  1027.                 return;
  1028.             GenerateAttributeDeclarationsStart(attributes);
  1029.             bool first = true;
  1030.             IEnumerator en = attributes.GetEnumerator();
  1031.             while (en.MoveNext()) {
  1032.                 if (first) {
  1033.                     first = false;
  1034.                 }
  1035.                 else {
  1036.                     ContinueOnNewLine(", ");
  1037.                 }
  1038.                
  1039.                 CodeAttributeDeclaration current = (CodeAttributeDeclaration)en.Current;
  1040.                 Output.Write(current.Name);
  1041.                 Output.Write("(");
  1042.                
  1043.                 bool firstArg = true;
  1044.                 foreach (CodeAttributeArgument arg in current.Arguments) {
  1045.                     if (firstArg) {
  1046.                         firstArg = false;
  1047.                     }
  1048.                     else {
  1049.                         Output.Write(", ");
  1050.                     }
  1051.                    
  1052.                     OutputAttributeArgument(arg);
  1053.                 }
  1054.                
  1055.                 Output.Write(")");
  1056.                
  1057.             }
  1058.             GenerateAttributeDeclarationsEnd(attributes);
  1059.         }
  1060.        
  1061.        
  1062.         /// <devdoc>
  1063.         /// <para>
  1064.         /// Outputs an argument in a attribute block.
  1065.         /// </para>
  1066.         /// </devdoc>
  1067.         protected virtual void OutputAttributeArgument(CodeAttributeArgument arg)
  1068.         {
  1069.             if (arg.Name != null && arg.Name.Length > 0) {
  1070.                 OutputIdentifier(arg.Name);
  1071.                 Output.Write("=");
  1072.             }
  1073.             ((ICodeGenerator)this).GenerateCodeFromExpression(arg.Value, output.InnerWriter, options);
  1074.         }
  1075.        
  1076.         /// <devdoc>
  1077.         /// <para>
  1078.         /// Generates code for the specified System.CodeDom.FieldDirection.
  1079.         /// </para>
  1080.         /// </devdoc>
  1081.         protected virtual void OutputDirection(FieldDirection dir)
  1082.         {
  1083.             switch (dir) {
  1084.                 case FieldDirection.In:
  1085.                     break;
  1086.                 case FieldDirection.Out:
  1087.                     Output.Write("out ");
  1088.                     break;
  1089.                 case FieldDirection.Ref:
  1090.                     Output.Write("ref ");
  1091.                     break;
  1092.             }
  1093.         }
  1094.        
  1095.         /// <devdoc>
  1096.         /// <para>[To be supplied.]</para>
  1097.         /// </devdoc>
  1098.         protected virtual void OutputFieldScopeModifier(MemberAttributes attributes)
  1099.         {
  1100.             switch (attributes & MemberAttributes.VTableMask) {
  1101.                 case MemberAttributes.New:
  1102.                     Output.Write("new ");
  1103.                     break;
  1104.             }
  1105.            
  1106.             switch (attributes & MemberAttributes.ScopeMask) {
  1107.                 case MemberAttributes.Final:
  1108.                     break;
  1109.                 case MemberAttributes.Static:
  1110.                     Output.Write("static ");
  1111.                     break;
  1112.                 case MemberAttributes.Const:
  1113.                     Output.Write("const ");
  1114.                     break;
  1115.                 default:
  1116.                     break;
  1117.             }
  1118.         }
  1119.        
  1120.         /// <devdoc>
  1121.         /// <para>
  1122.         /// Generates code for the specified member access modifier.
  1123.         /// </para>
  1124.         /// </devdoc>
  1125.         protected virtual void OutputMemberAccessModifier(MemberAttributes attributes)
  1126.         {
  1127.             switch (attributes & MemberAttributes.AccessMask) {
  1128.                 case MemberAttributes.Assembly:
  1129.                     Output.Write("internal ");
  1130.                     break;
  1131.                 case MemberAttributes.FamilyAndAssembly:
  1132.                     Output.Write("internal ");
  1133.                     /*FamANDAssem*/break;
  1134.                 case MemberAttributes.Family:
  1135.                     Output.Write("protected ");
  1136.                     break;
  1137.                 case MemberAttributes.FamilyOrAssembly:
  1138.                     Output.Write("protected internal ");
  1139.                     break;
  1140.                 case MemberAttributes.Private:
  1141.                     Output.Write("private ");
  1142.                     break;
  1143.                 case MemberAttributes.Public:
  1144.                     Output.Write("public ");
  1145.                     break;
  1146.             }
  1147.         }
  1148.        
  1149.         /// <devdoc>
  1150.         /// <para>
  1151.         /// Generates code for the specified member scope modifier.
  1152.         /// </para>
  1153.         /// </devdoc>
  1154.         protected virtual void OutputMemberScopeModifier(MemberAttributes attributes)
  1155.         {
  1156.             switch (attributes & MemberAttributes.VTableMask) {
  1157.                 case MemberAttributes.New:
  1158.                     Output.Write("new ");
  1159.                     break;
  1160.             }
  1161.            
  1162.             switch (attributes & MemberAttributes.ScopeMask) {
  1163.                 case MemberAttributes.Abstract:
  1164.                     Output.Write("abstract ");
  1165.                     break;
  1166.                 case MemberAttributes.Final:
  1167.                     Output.Write("");
  1168.                     break;
  1169.                 case MemberAttributes.Static:
  1170.                     Output.Write("static ");
  1171.                     break;
  1172.                 case MemberAttributes.Override:
  1173.                     Output.Write("override ");
  1174.                     break;
  1175.                 default:
  1176.                     switch (attributes & MemberAttributes.AccessMask) {
  1177.                         case MemberAttributes.Family:
  1178.                         case MemberAttributes.Public:
  1179.                             Output.Write("virtual ");
  1180.                             break;
  1181.                         default:
  1182.                             // nothing;
  1183.                             break;
  1184.                     }
  1185.                     break;
  1186.             }
  1187.         }
  1188.        
  1189.         /// <devdoc>
  1190.         /// <para>
  1191.         /// Generates code for the specified type.
  1192.         /// </para>
  1193.         /// </devdoc>
  1194.         protected abstract void OutputType(CodeTypeReference typeRef);
  1195.        
  1196.         /// <devdoc>
  1197.         /// <para>
  1198.         /// Generates code for the specified type attributes.
  1199.         /// </para>
  1200.         /// </devdoc>
  1201.         protected virtual void OutputTypeAttributes(TypeAttributes attributes, bool isStruct, bool isEnum)
  1202.         {
  1203.             switch (attributes & TypeAttributes.VisibilityMask) {
  1204.                 case TypeAttributes.Public:
  1205.                 case TypeAttributes.NestedPublic:
  1206.                     Output.Write("public ");
  1207.                     break;
  1208.                 case TypeAttributes.NestedPrivate:
  1209.                     Output.Write("private ");
  1210.                     break;
  1211.             }
  1212.            
  1213.             if (isStruct) {
  1214.                 Output.Write("struct ");
  1215.             }
  1216.             else if (isEnum) {
  1217.                 Output.Write("enum ");
  1218.             }
  1219.             else {
  1220.                 switch (attributes & TypeAttributes.ClassSemanticsMask) {
  1221.                     case TypeAttributes.Class:
  1222.                         if ((attributes & TypeAttributes.Sealed) == TypeAttributes.Sealed) {
  1223.                             Output.Write("sealed ");
  1224.                         }
  1225.                         if ((attributes & TypeAttributes.Abstract) == TypeAttributes.Abstract) {
  1226.                             Output.Write("abstract ");
  1227.                         }
  1228.                         Output.Write("class ");
  1229.                         break;
  1230.                     case TypeAttributes.Interface:
  1231.                         Output.Write("interface ");
  1232.                         break;
  1233.                 }
  1234.             }
  1235.         }
  1236.        
  1237.         /// <devdoc>
  1238.         /// <para>
  1239.         /// Generates code for the specified object type and name pair.
  1240.         /// </para>
  1241.         /// </devdoc>
  1242.         protected virtual void OutputTypeNamePair(CodeTypeReference typeRef, string name)
  1243.         {
  1244.             OutputType(typeRef);
  1245.             Output.Write(" ");
  1246.             OutputIdentifier(name);
  1247.         }
  1248.        
  1249.         /// <devdoc>
  1250.         /// <para>[To be supplied.]</para>
  1251.         /// </devdoc>
  1252.         protected virtual void OutputIdentifier(string ident)
  1253.         {
  1254.             Output.Write(ident);
  1255.         }
  1256.        
  1257.         /// <devdoc>
  1258.         /// <para>
  1259.         /// Generates code for the specified expression list.
  1260.         /// </para>
  1261.         /// </devdoc>
  1262.         protected virtual void OutputExpressionList(CodeExpressionCollection expressions)
  1263.         {
  1264.                 /*newlineBetweenItems*/            OutputExpressionList(expressions, false);
  1265.         }
  1266.        
  1267.         /// <devdoc>
  1268.         /// <para>
  1269.         /// Generates code for the specified expression list.
  1270.         /// </para>
  1271.         /// </devdoc>
  1272.         protected virtual void OutputExpressionList(CodeExpressionCollection expressions, bool newlineBetweenItems)
  1273.         {
  1274.             bool first = true;
  1275.             IEnumerator en = expressions.GetEnumerator();
  1276.             Indent++;
  1277.             while (en.MoveNext()) {
  1278.                 if (first) {
  1279.                     first = false;
  1280.                 }
  1281.                 else {
  1282.                     if (newlineBetweenItems)
  1283.                         ContinueOnNewLine(",");
  1284.                     else
  1285.                         Output.Write(", ");
  1286.                 }
  1287.                 ((ICodeGenerator)this).GenerateCodeFromExpression((CodeExpression)en.Current, output.InnerWriter, options);
  1288.             }
  1289.             Indent--;
  1290.         }
  1291.        
  1292.         /// <devdoc>
  1293.         /// <para>
  1294.         /// Generates code for the specified operator.
  1295.         /// </para>
  1296.         /// </devdoc>
  1297.         protected virtual void OutputOperator(CodeBinaryOperatorType op)
  1298.         {
  1299.             switch (op) {
  1300.                 case CodeBinaryOperatorType.Add:
  1301.                     Output.Write("+");
  1302.                     break;
  1303.                 case CodeBinaryOperatorType.Subtract:
  1304.                     Output.Write("-");
  1305.                     break;
  1306.                 case CodeBinaryOperatorType.Multiply:
  1307.                     Output.Write("*");
  1308.                     break;
  1309.                 case CodeBinaryOperatorType.Divide:
  1310.                     Output.Write("/");
  1311.                     break;
  1312.                 case CodeBinaryOperatorType.Modulus:
  1313.                     Output.Write("%");
  1314.                     break;
  1315.                 case CodeBinaryOperatorType.Assign:
  1316.                     Output.Write("=");
  1317.                     break;
  1318.                 case CodeBinaryOperatorType.IdentityInequality:
  1319.                     Output.Write("!=");
  1320.                     break;
  1321.                 case CodeBinaryOperatorType.IdentityEquality:
  1322.                     Output.Write("==");
  1323.                     break;
  1324.                 case CodeBinaryOperatorType.ValueEquality:
  1325.                     Output.Write("==");
  1326.                     break;
  1327.                 case CodeBinaryOperatorType.BitwiseOr:
  1328.                     Output.Write("|");
  1329.                     break;
  1330.                 case CodeBinaryOperatorType.BitwiseAnd:
  1331.                     Output.Write("&");
  1332.                     break;
  1333.                 case CodeBinaryOperatorType.BooleanOr:
  1334.                     Output.Write("||");
  1335.                     break;
  1336.                 case CodeBinaryOperatorType.BooleanAnd:
  1337.                     Output.Write("&&");
  1338.                     break;
  1339.                 case CodeBinaryOperatorType.LessThan:
  1340.                     Output.Write("<");
  1341.                     break;
  1342.                 case CodeBinaryOperatorType.LessThanOrEqual:
  1343.                     Output.Write("<=");
  1344.                     break;
  1345.                 case CodeBinaryOperatorType.GreaterThan:
  1346.                     Output.Write(">");
  1347.                     break;
  1348.                 case CodeBinaryOperatorType.GreaterThanOrEqual:
  1349.                     Output.Write(">=");
  1350.                     break;
  1351.             }
  1352.         }
  1353.        
  1354.         /// <devdoc>
  1355.         /// <para>
  1356.         /// Generates code for the specified parameters.
  1357.         /// </para>
  1358.         /// </devdoc>
  1359.         protected virtual void OutputParameters(CodeParameterDeclarationExpressionCollection parameters)
  1360.         {
  1361.             bool first = true;
  1362.             bool multiline = parameters.Count > ParameterMultilineThreshold;
  1363.             if (multiline) {
  1364.                 Indent += 3;
  1365.             }
  1366.             IEnumerator en = parameters.GetEnumerator();
  1367.             while (en.MoveNext()) {
  1368.                 CodeParameterDeclarationExpression current = (CodeParameterDeclarationExpression)en.Current;
  1369.                 if (first) {
  1370.                     first = false;
  1371.                 }
  1372.                 else {
  1373.                     Output.Write(", ");
  1374.                 }
  1375.                 if (multiline) {
  1376.                     ContinueOnNewLine("");
  1377.                 }
  1378.                 GenerateExpression(current);
  1379.             }
  1380.             if (multiline) {
  1381.                 Indent -= 3;
  1382.             }
  1383.         }
  1384.        
  1385.         /// <devdoc>
  1386.         /// <para>
  1387.         /// Generates code for the specified CodeDom based array creation expression
  1388.         /// representation.
  1389.         /// </para>
  1390.         /// </devdoc>
  1391.         protected abstract void GenerateArrayCreateExpression(CodeArrayCreateExpression e);
  1392.         /// <devdoc>
  1393.         /// <para>
  1394.         /// Generates code for the specified CodeDom based base reference expression
  1395.         /// representation.
  1396.         /// </para>
  1397.         /// </devdoc>
  1398.         protected abstract void GenerateBaseReferenceExpression(CodeBaseReferenceExpression e);
  1399.        
  1400.         /// <devdoc>
  1401.         /// <para>
  1402.         /// Generates code for the specified CodeDom based binary operator
  1403.         /// expression representation.
  1404.         /// </para>
  1405.         /// </devdoc>
  1406.         protected virtual void GenerateBinaryOperatorExpression(CodeBinaryOperatorExpression e)
  1407.         {
  1408.             bool indentedExpression = false;
  1409.             Output.Write("(");
  1410.            
  1411.             GenerateExpression(e.Left);
  1412.             Output.Write(" ");
  1413.            
  1414.             if (e.Left is CodeBinaryOperatorExpression || e.Right is CodeBinaryOperatorExpression) {
  1415.                 // In case the line gets too long with nested binary operators, we need to output them on
  1416.                 // different lines. However we want to indent them to maintain readability, but this needs
  1417.                 // to be done only once;
  1418.                 if (!inNestedBinary) {
  1419.                     indentedExpression = true;
  1420.                     inNestedBinary = true;
  1421.                     Indent += 3;
  1422.                 }
  1423.                 ContinueOnNewLine("");
  1424.             }
  1425.            
  1426.             OutputOperator(e.Operator);
  1427.            
  1428.             Output.Write(" ");
  1429.             GenerateExpression(e.Right);
  1430.            
  1431.             Output.Write(")");
  1432.             if (indentedExpression) {
  1433.                 Indent -= 3;
  1434.                 inNestedBinary = false;
  1435.             }
  1436.         }
  1437.        
  1438.         /// <devdoc>
  1439.         /// <para>[To be supplied.]</para>
  1440.         /// </devdoc>
  1441.         protected virtual void ContinueOnNewLine(string st)
  1442.         {
  1443.             Output.WriteLine(st);
  1444.         }
  1445.        
  1446.         /// <devdoc>
  1447.         /// <para>
  1448.         /// Generates code for the specified CodeDom based cast expression
  1449.         /// representation.
  1450.         /// </para>
  1451.         /// </devdoc>
  1452.         protected abstract void GenerateCastExpression(CodeCastExpression e);
  1453.         /// <devdoc>
  1454.         /// <para>
  1455.         /// Generates code for the specified CodeDom based delegate creation expression
  1456.         /// representation.
  1457.         /// </para>
  1458.         /// </devdoc>
  1459.         protected abstract void GenerateDelegateCreateExpression(CodeDelegateCreateExpression e);
  1460.         /// <devdoc>
  1461.         /// <para>
  1462.         /// Generates code for the specified CodeDom based field reference
  1463.         /// expression representation.
  1464.         /// </para>
  1465.         /// </devdoc>
  1466.         protected abstract void GenerateFieldReferenceExpression(CodeFieldReferenceExpression e);
  1467.        
  1468.         /// <devdoc>
  1469.         /// <para>[To be supplied.]</para>
  1470.         /// </devdoc>
  1471.         protected abstract void GenerateArgumentReferenceExpression(CodeArgumentReferenceExpression e);
  1472.        
  1473.         /// <devdoc>
  1474.         /// <para>[To be supplied.]</para>
  1475.         /// </devdoc>
  1476.         protected abstract void GenerateVariableReferenceExpression(CodeVariableReferenceExpression e);
  1477.        
  1478.         /// <devdoc>
  1479.         /// <para>
  1480.         /// Generates code for the specified CodeDom based indexer expression
  1481.         /// representation.
  1482.         /// </para>
  1483.         /// </devdoc>
  1484.         protected abstract void GenerateIndexerExpression(CodeIndexerExpression e);
  1485.        
  1486.         /// <devdoc>
  1487.         /// <para>[To be supplied.]</para>
  1488.         /// </devdoc>
  1489.         protected abstract void GenerateArrayIndexerExpression(CodeArrayIndexerExpression e);
  1490.        
  1491.         /// <devdoc>
  1492.         /// <para>
  1493.         /// Generates code for the specified CodeDom based snippet
  1494.         /// expression representation.
  1495.         /// </para>
  1496.         /// </devdoc>
  1497.         protected abstract void GenerateSnippetExpression(CodeSnippetExpression e);
  1498.         /// <devdoc>
  1499.         /// <para>
  1500.         /// Generates code for the specified CodeDom based method invoke expression
  1501.         /// representation.
  1502.         /// </para>
  1503.         /// </devdoc>
  1504.         protected abstract void GenerateMethodInvokeExpression(CodeMethodInvokeExpression e);
  1505.        
  1506.         /// <devdoc>
  1507.         /// <para>[To be supplied.]</para>
  1508.         /// </devdoc>
  1509.         protected abstract void GenerateMethodReferenceExpression(CodeMethodReferenceExpression e);
  1510.        
  1511.         /// <devdoc>
  1512.         /// <para>[To be supplied.]</para>
  1513.         /// </devdoc>
  1514.         protected abstract void GenerateEventReferenceExpression(CodeEventReferenceExpression e);
  1515.        
  1516.         /// <devdoc>
  1517.         /// <para>
  1518.         /// Generates code for the specified CodeDom based delegate invoke expression
  1519.         /// representation.
  1520.         /// </para>
  1521.         /// </devdoc>
  1522.         protected abstract void GenerateDelegateInvokeExpression(CodeDelegateInvokeExpression e);
  1523.         /// <devdoc>
  1524.         /// <para>
  1525.         /// Generates code for the specified CodeDom
  1526.         /// based object creation expression representation.
  1527.         /// </para>
  1528.         /// </devdoc>
  1529.         protected abstract void GenerateObjectCreateExpression(CodeObjectCreateExpression e);
  1530.        
  1531.         /// <devdoc>
  1532.         /// <para>
  1533.         /// Generates code for the specified CodeDom
  1534.         /// based parameter declaration expression representation.
  1535.         /// </para>
  1536.         /// </devdoc>
  1537.         protected virtual void GenerateParameterDeclarationExpression(CodeParameterDeclarationExpression e)
  1538.         {
  1539.             if (e.CustomAttributes.Count > 0) {
  1540.                 OutputAttributeDeclarations(e.CustomAttributes);
  1541.                 Output.Write(" ");
  1542.             }
  1543.            
  1544.             OutputDirection(e.Direction);
  1545.             OutputTypeNamePair(e.Type, e.Name);
  1546.         }
  1547.        
  1548.         /// <devdoc>
  1549.         /// <para>[To be supplied.]</para>
  1550.         /// </devdoc>
  1551.         protected virtual void GenerateDirectionExpression(CodeDirectionExpression e)
  1552.         {
  1553.             OutputDirection(e.Direction);
  1554.             GenerateExpression(e.Expression);
  1555.         }
  1556.        
  1557.        
  1558.         /// <devdoc>
  1559.         /// <para>
  1560.         /// Generates code for the specified CodeDom based primitive expression
  1561.         /// representation.
  1562.         /// </para>
  1563.         /// </devdoc>
  1564.         protected virtual void GeneratePrimitiveExpression(CodePrimitiveExpression e)
  1565.         {
  1566.             if (e.Value == null) {
  1567.                 Output.Write(NullToken);
  1568.             }
  1569.             else if (e.Value is string) {
  1570.                 Output.Write(QuoteSnippetString((string)e.Value));
  1571.             }
  1572.             else if (e.Value is char) {
  1573.                 Output.Write("'" + e.Value.ToString() + "'");
  1574.             }
  1575.             else if (e.Value is byte) {
  1576.                 Output.Write(((byte)e.Value).ToString(CultureInfo.InvariantCulture));
  1577.             }
  1578.             else if (e.Value is Int16) {
  1579.                 Output.Write(((Int16)e.Value).ToString(CultureInfo.InvariantCulture));
  1580.             }
  1581.             else if (e.Value is Int32) {
  1582.                 Output.Write(((Int32)e.Value).ToString(CultureInfo.InvariantCulture));
  1583.             }
  1584.             else if (e.Value is Int64) {
  1585.                 Output.Write(((Int64)e.Value).ToString(CultureInfo.InvariantCulture));
  1586.             }
  1587.             else if (e.Value is float) {
  1588.                 GenerateSingleFloatValue((float)e.Value);
  1589.             }
  1590.             else if (e.Value is double) {
  1591.                 GenerateDoubleValue((double)e.Value);
  1592.             }
  1593.             else if (e.Value is decimal) {
  1594.                 GenerateDecimalValue((decimal)e.Value);
  1595.             }
  1596.             else if (e.Value is bool) {
  1597.                 if ((bool)e.Value) {
  1598.                     Output.Write("true");
  1599.                 }
  1600.                 else {
  1601.                     Output.Write("false");
  1602.                 }
  1603.             }
  1604.             else {
  1605.                 throw new ArgumentException(SR.GetString(SR.InvalidPrimitiveType, e.Value.GetType().ToString()));
  1606.             }
  1607.         }
  1608.        
  1609.         /// <devdoc>
  1610.         /// <para>[To be supplied.]</para>
  1611.         /// </devdoc>
  1612.         protected virtual void GenerateSingleFloatValue(float s)
  1613.         {
  1614.             Output.Write(s.ToString("R", CultureInfo.InvariantCulture));
  1615.         }
  1616.        
  1617.         /// <devdoc>
  1618.         /// <para>[To be supplied.]</para>
  1619.         /// </devdoc>
  1620.         protected virtual void GenerateDoubleValue(double d)
  1621.         {
  1622.             Output.Write(d.ToString("R", CultureInfo.InvariantCulture));
  1623.         }
  1624.        
  1625.         /// <devdoc>
  1626.         /// <para>[To be supplied.]</para>
  1627.         /// </devdoc>
  1628.         protected virtual void GenerateDecimalValue(decimal d)
  1629.         {
  1630.             Output.Write(d.ToString(CultureInfo.InvariantCulture));
  1631.         }
  1632.        
  1633.         protected virtual void GenerateDefaultValueExpression(CodeDefaultValueExpression e)
  1634.         {
  1635.         }
  1636.        
  1637.         /// <devdoc>
  1638.         /// <para>
  1639.         /// Generates code for the specified CodeDom based property reference
  1640.         /// expression representation.
  1641.         /// </para>
  1642.         /// </devdoc>
  1643.         protected abstract void GeneratePropertyReferenceExpression(CodePropertyReferenceExpression e);
  1644.        
  1645.         /// <devdoc>
  1646.         /// <para>[To be supplied.]</para>
  1647.         /// </devdoc>
  1648.         protected abstract void GeneratePropertySetValueReferenceExpression(CodePropertySetValueReferenceExpression e);
  1649.        
  1650.         /// <devdoc>
  1651.         /// <para>
  1652.         /// Generates code for the specified CodeDom based this reference expression
  1653.         /// representation.
  1654.         /// </para>
  1655.         /// </devdoc>
  1656.         protected abstract void GenerateThisReferenceExpression(CodeThisReferenceExpression e);
  1657.        
  1658.         /// <devdoc>
  1659.         /// <para>
  1660.         /// Generates code for the specified CodeDom based type reference expression
  1661.         /// representation.
  1662.         /// </para>
  1663.         /// </devdoc>
  1664.         protected virtual void GenerateTypeReferenceExpression(CodeTypeReferenceExpression e)
  1665.         {
  1666.             OutputType(e.Type);
  1667.         }
  1668.        
  1669.         /// <devdoc>
  1670.         /// <para>
  1671.         /// Generates code for the specified CodeDom based type of expression
  1672.         /// representation.
  1673.         /// </para>
  1674.         /// </devdoc>
  1675.         protected virtual void GenerateTypeOfExpression(CodeTypeOfExpression e)
  1676.         {
  1677.             Output.Write("typeof(");
  1678.             OutputType(e.Type);
  1679.             Output.Write(")");
  1680.         }
  1681.        
  1682.         /// <devdoc>
  1683.         /// <para>
  1684.         /// Generates code for the specified CodeDom based method
  1685.         /// invoke statement representation.
  1686.         /// </para>
  1687.         /// </devdoc>
  1688.         protected abstract void GenerateExpressionStatement(CodeExpressionStatement e);
  1689.         /// <devdoc>
  1690.         /// <para>
  1691.         /// Generates code for the specified CodeDom based for loop statement
  1692.         /// representation.
  1693.         /// </para>
  1694.         /// </devdoc>
  1695.         protected abstract void GenerateIterationStatement(CodeIterationStatement e);
  1696.         /// <devdoc>
  1697.         /// <para>
  1698.         /// Generates code for the specified CodeDom based throw exception statement
  1699.         /// representation.
  1700.         /// </para>
  1701.         /// </devdoc>
  1702.         protected abstract void GenerateThrowExceptionStatement(CodeThrowExceptionStatement e);
  1703.         /// <devdoc>
  1704.         /// <para>
  1705.         /// Generates code for the specified CodeDom based comment statement
  1706.         /// representation.
  1707.         /// </para>
  1708.         /// </devdoc>
  1709.         protected virtual void GenerateCommentStatement(CodeCommentStatement e)
  1710.         {
  1711.             GenerateComment(e.Comment);
  1712.         }
  1713.        
  1714.         /// <devdoc>
  1715.         /// <para>[To be supplied.]</para>
  1716.         /// </devdoc>
  1717.         protected virtual void GenerateCommentStatements(CodeCommentStatementCollection e)
  1718.         {
  1719.             foreach (CodeCommentStatement comment in e) {
  1720.                 GenerateCommentStatement(comment);
  1721.             }
  1722.         }
  1723.        
  1724.         /// <devdoc>
  1725.         /// <para>[To be supplied.]</para>
  1726.         /// </devdoc>
  1727.         protected abstract void GenerateComment(CodeComment e);
  1728.        
  1729.         /// <devdoc>
  1730.         /// <para>
  1731.         /// Generates code for the specified CodeDom based method return statement
  1732.         /// representation.
  1733.         /// </para>
  1734.         /// </devdoc>
  1735.         protected abstract void GenerateMethodReturnStatement(CodeMethodReturnStatement e);
  1736.         /// <devdoc>
  1737.         /// <para>
  1738.         /// Generates code for the specified CodeDom based if statement representation.
  1739.         /// </para>
  1740.         /// </devdoc>
  1741.         protected abstract void GenerateConditionStatement(CodeConditionStatement e);
  1742.         /// <devdoc>
  1743.         /// <para>
  1744.         /// Generates code for the specified CodeDom based try catch finally
  1745.         /// statement representation.
  1746.         /// </para>
  1747.         /// </devdoc>
  1748.         protected abstract void GenerateTryCatchFinallyStatement(CodeTryCatchFinallyStatement e);
  1749.         /// <devdoc>
  1750.         /// <para>
  1751.         /// Generates code for the specified CodeDom based assignment statement
  1752.         /// representation.
  1753.         /// </para>
  1754.         /// </devdoc>
  1755.         protected abstract void GenerateAssignStatement(CodeAssignStatement e);
  1756.         /// <devdoc>
  1757.         /// <para>
  1758.         /// Generates code for the specified CodeDom based attach event statement
  1759.         /// representation.
  1760.         /// </para>
  1761.         /// </devdoc>
  1762.         protected abstract void GenerateAttachEventStatement(CodeAttachEventStatement e);
  1763.         /// <devdoc>
  1764.         /// <para>
  1765.         /// Generates code for the specified CodeDom based detach event statement
  1766.         /// representation.
  1767.         /// </para>
  1768.         /// </devdoc>
  1769.         protected abstract void GenerateRemoveEventStatement(CodeRemoveEventStatement e);
  1770.        
  1771.         /// <devdoc>
  1772.         /// <para>[To be supplied.]</para>
  1773.         /// </devdoc>
  1774.         protected abstract void GenerateGotoStatement(CodeGotoStatement e);
  1775.        
  1776.         /// <devdoc>
  1777.         /// <para>[To be supplied.]</para>
  1778.         /// </devdoc>
  1779.         protected abstract void GenerateLabeledStatement(CodeLabeledStatement e);
  1780.        
  1781.         /// <devdoc>
  1782.         /// <para>
  1783.         /// Generates code for the specified CodeDom based snippet statement
  1784.         /// representation.
  1785.         /// </para>
  1786.         /// </devdoc>
  1787.         protected virtual void GenerateSnippetStatement(CodeSnippetStatement e)
  1788.         {
  1789.             Output.WriteLine(e.Value);
  1790.         }
  1791.        
  1792.         /// <devdoc>
  1793.         /// <para>
  1794.         /// Generates code for the specified CodeDom based variable declaration statement
  1795.         /// representation.
  1796.         /// </para>
  1797.         /// </devdoc>
  1798.         protected abstract void GenerateVariableDeclarationStatement(CodeVariableDeclarationStatement e);
  1799.        
  1800.         /// <devdoc>
  1801.         /// <para>
  1802.         /// Generates code for the specified CodeDom based line pragma start
  1803.         /// representation.
  1804.         /// </para>
  1805.         /// </devdoc>
  1806.         protected abstract void GenerateLinePragmaStart(CodeLinePragma e);
  1807.         /// <devdoc>
  1808.         /// <para>
  1809.         /// Generates code for the specified CodeDom based line pragma end
  1810.         /// representation.
  1811.         /// </para>
  1812.         /// </devdoc>
  1813.         protected abstract void GenerateLinePragmaEnd(CodeLinePragma e);
  1814.         /// <devdoc>
  1815.         /// <para>
  1816.         /// Generates code for the specified CodeDom based event
  1817.         /// representation.
  1818.         /// </para>
  1819.         /// </devdoc>
  1820.         protected abstract void GenerateEvent(CodeMemberEvent e, CodeTypeDeclaration c);
  1821.         /// <devdoc>
  1822.         /// <para>
  1823.         /// Generates code for the specified CodeDom based member field
  1824.         /// representation.
  1825.         /// </para>
  1826.         /// </devdoc>
  1827.         protected abstract void GenerateField(CodeMemberField e);
  1828.         /// <devdoc>
  1829.         /// <para>
  1830.         /// Generates code for the specified CodeDom based snippet class member
  1831.         /// representation.
  1832.         /// </para>
  1833.         /// </devdoc>
  1834.         protected abstract void GenerateSnippetMember(CodeSnippetTypeMember e);
  1835.        
  1836.         /// <devdoc>
  1837.         /// <para>[To be supplied.]</para>
  1838.         /// </devdoc>
  1839.         protected abstract void GenerateEntryPointMethod(CodeEntryPointMethod e, CodeTypeDeclaration c);
  1840.        
  1841.         /// <devdoc>
  1842.         /// <para>
  1843.         /// Generates code for the specified CodeDom based method
  1844.         /// representation.
  1845.         /// </para>
  1846.         /// </devdoc>
  1847.         protected abstract void GenerateMethod(CodeMemberMethod e, CodeTypeDeclaration c);
  1848.         /// <devdoc>
  1849.         /// <para>
  1850.         /// Generates code for the specified CodeDom based property
  1851.         /// representation.
  1852.         /// </para>
  1853.         /// </devdoc>
  1854.         protected abstract void GenerateProperty(CodeMemberProperty e, CodeTypeDeclaration c);
  1855.         /// <devdoc>
  1856.         /// <para>
  1857.         /// Generates code for the specified CodeDom based constructor
  1858.         /// representation.
  1859.         /// </para>
  1860.         /// </devdoc>
  1861.         protected abstract void GenerateConstructor(CodeConstructor e, CodeTypeDeclaration c);
  1862.         /// <devdoc>
  1863.         /// <para>
  1864.         /// Generates code for the specified CodeDom based class constructor
  1865.         /// representation.
  1866.         /// </para>
  1867.         /// </devdoc>
  1868.         protected abstract void GenerateTypeConstructor(CodeTypeConstructor e);
  1869.         /// <devdoc>
  1870.         /// <para>
  1871.         /// Generates code for the specified CodeDom based start class representation.
  1872.         /// </para>
  1873.         /// </devdoc>
  1874.         protected abstract void GenerateTypeStart(CodeTypeDeclaration e);
  1875.         /// <devdoc>
  1876.         /// <para>
  1877.         /// Generates code for the specified CodeDom based end class representation.
  1878.         /// </para>
  1879.         /// </devdoc>
  1880.         protected abstract void GenerateTypeEnd(CodeTypeDeclaration e);
  1881.         /// <devdoc>
  1882.         /// <para>
  1883.         /// Generates code for the specified CodeDom based compile unit start
  1884.         /// representation.
  1885.         /// </para>
  1886.         /// </devdoc>
  1887.         protected virtual void GenerateCompileUnitStart(CodeCompileUnit e)
  1888.         {
  1889.             if (e.StartDirectives.Count > 0) {
  1890.                 GenerateDirectives(e.StartDirectives);
  1891.             }
  1892.         }
  1893.         /// <devdoc>
  1894.         /// <para>
  1895.         /// Generates code for the specified CodeDom based compile unit end
  1896.         /// representation.
  1897.         /// </para>
  1898.         /// </devdoc>
  1899.         protected virtual void GenerateCompileUnitEnd(CodeCompileUnit e)
  1900.         {
  1901.             if (e.EndDirectives.Count > 0) {
  1902.                 GenerateDirectives(e.EndDirectives);
  1903.             }
  1904.         }
  1905.         /// <devdoc>
  1906.         /// <para>
  1907.         /// Generates code for the specified CodeDom based namespace start
  1908.         /// representation.
  1909.         /// </para>
  1910.         /// </devdoc>
  1911.         protected abstract void GenerateNamespaceStart(CodeNamespace e);
  1912.         /// <devdoc>
  1913.         /// <para>
  1914.         /// Generates code for the specified CodeDom based namespace end
  1915.         /// representation.
  1916.         /// </para>
  1917.         /// </devdoc>
  1918.         protected abstract void GenerateNamespaceEnd(CodeNamespace e);
  1919.         /// <devdoc>
  1920.         /// <para>
  1921.         /// Generates code for the specified CodeDom based namespace import
  1922.         /// representation.
  1923.         /// </para>
  1924.         /// </devdoc>
  1925.         protected abstract void GenerateNamespaceImport(CodeNamespaceImport e);
  1926.         /// <devdoc>
  1927.         /// <para>
  1928.         /// Generates code for the specified CodeDom based attribute block start
  1929.         /// representation.
  1930.         /// </para>
  1931.         /// </devdoc>
  1932.         protected abstract void GenerateAttributeDeclarationsStart(CodeAttributeDeclarationCollection attributes);
  1933.         /// <devdoc>
  1934.         /// <para>
  1935.         /// Generates code for the specified CodeDom based attribute block end
  1936.         /// representation.
  1937.         /// </para>
  1938.         /// </devdoc>
  1939.         protected abstract void GenerateAttributeDeclarationsEnd(CodeAttributeDeclarationCollection attributes);
  1940.        
  1941.         /// <devdoc>
  1942.         /// <para>[To be supplied.]</para>
  1943.         /// </devdoc>
  1944.         protected abstract bool Supports(GeneratorSupport support);
  1945.        
  1946.         /// <devdoc>
  1947.         /// <para>
  1948.         /// Gets or sets whether the specified value is a value identifier.
  1949.         /// </para>
  1950.         /// </devdoc>
  1951.         protected abstract bool IsValidIdentifier(string value);
  1952.         /// <devdoc>
  1953.         /// <para>
  1954.         /// Gets whether the specified identifier is valid.
  1955.         /// </para>
  1956.         /// </devdoc>
  1957.         protected virtual void ValidateIdentifier(string value)
  1958.         {
  1959.             if (!IsValidIdentifier(value)) {
  1960.                 throw new ArgumentException(SR.GetString(SR.InvalidIdentifier, value));
  1961.             }
  1962.         }
  1963.        
  1964.         /// <devdoc>
  1965.         /// <para>[To be supplied.]</para>
  1966.         /// </devdoc>
  1967.         protected abstract string CreateEscapedIdentifier(string value);
  1968.        
  1969.         /// <devdoc>
  1970.         /// <para>[To be supplied.]</para>
  1971.         /// </devdoc>
  1972.         protected abstract string CreateValidIdentifier(string value);
  1973.        
  1974.         /// <devdoc>
  1975.         /// <para>[To be supplied.]</para>
  1976.         /// </devdoc>
  1977.         protected abstract string GetTypeOutput(CodeTypeReference value);
  1978.        
  1979.         /// <devdoc>
  1980.         /// <para>
  1981.         /// Provides conversion to formatting with escape codes.
  1982.         /// </para>
  1983.         /// </devdoc>
  1984.         protected abstract string QuoteSnippetString(string value);
  1985.        
  1986.         /// <devdoc>
  1987.         /// <para>
  1988.         /// Gets a value indicating whether the specified value is a valid language
  1989.         /// independent identifier.
  1990.         /// </para>
  1991.         /// </devdoc>
  1992.         public static bool IsValidLanguageIndependentIdentifier(string value)
  1993.         {
  1994.             return IsValidTypeNameOrIdentifier(value, false);
  1995.         }
  1996.        
  1997.         static internal bool IsValidLanguageIndependentTypeName(string value)
  1998.         {
  1999.             return IsValidTypeNameOrIdentifier(value, true);
  2000.         }
  2001.        
  2002.         private static bool IsValidTypeNameOrIdentifier(string value, bool isTypeName)
  2003.         {
  2004.             bool nextMustBeStartChar = true;
  2005.            
  2006.             if (value.Length == 0)
  2007.                 return false;
  2008.            
  2009.             // each char must be Lu, Ll, Lt, Lm, Lo, Nd, Mn, Mc, Pc
  2010.             //
  2011.             for (int i = 0; i < value.Length; i++) {
  2012.                 char ch = value[i];
  2013.                 UnicodeCategory uc = Char.GetUnicodeCategory(ch);
  2014.                 switch (uc) {
  2015.                     case UnicodeCategory.UppercaseLetter:
  2016.                     case UnicodeCategory.LowercaseLetter:
  2017.                     case UnicodeCategory.TitlecaseLetter:
  2018.                     case UnicodeCategory.ModifierLetter:
  2019.                     case UnicodeCategory.LetterNumber:
  2020.                     case UnicodeCategory.OtherLetter:
  2021.                         // Lu
  2022.                         // Ll
  2023.                         // Lt
  2024.                         // Lm
  2025.                         // Lm
  2026.                         // Lo
  2027.                         nextMustBeStartChar = false;
  2028.                         break;
  2029.                     case UnicodeCategory.NonSpacingMark:
  2030.                     case UnicodeCategory.SpacingCombiningMark:
  2031.                     case UnicodeCategory.ConnectorPunctuation:
  2032.                     case UnicodeCategory.DecimalDigitNumber:
  2033.                        
  2034.                         // Mn
  2035.                         // Mc
  2036.                         // Pc
  2037.                         // Nd
  2038.                         // Underscore is a valid starting character, even though it is a ConnectorPunctuation.
  2039.                         if (nextMustBeStartChar && ch != '_')
  2040.                             return false;
  2041.                        
  2042.                         nextMustBeStartChar = false;
  2043.                         break;
  2044.                     default:
  2045.                         // We only check the special Type chars for type names.
  2046.                         if (isTypeName && IsSpecialTypeChar(ch, ref nextMustBeStartChar)) {
  2047.                             break;
  2048.                         }
  2049.                        
  2050.                         return false;
  2051.                 }
  2052.             }
  2053.            
  2054.             return true;
  2055.         }
  2056.        
  2057.         // This can be a special character like a separator that shows up in a type name
  2058.         // This is an odd set of characters. Some come from characters that are allowed by C++, like < and >.
  2059.         // Others are characters that are specified in the type and assembly name grammer.
  2060.         private static bool IsSpecialTypeChar(char ch, ref bool nextMustBeStartChar)
  2061.         {
  2062.             switch (ch) {
  2063.                 case ':':
  2064.                 case '.':
  2065.                 case '$':
  2066.                 case '+':
  2067.                 case '<':
  2068.                 case '>':
  2069.                 case '-':
  2070.                 case '[':
  2071.                 case ']':
  2072.                 case ',':
  2073.                 case '&':
  2074.                 case '*':
  2075.                     nextMustBeStartChar = true;
  2076.                     return true;
  2077.                 case '`':
  2078.                    
  2079.                     return true;
  2080.             }
  2081.             return false;
  2082.         }
  2083.        
  2084.         /// <devdoc>
  2085.         /// <para>
  2086.         /// Validates a tree to check if all the types and idenfier names follow the rules of an identifier
  2087.         /// in a langauge independent manner.
  2088.         /// </para>
  2089.         /// </devdoc>
  2090.         public static void ValidateIdentifiers(CodeObject e)
  2091.         {
  2092.             CodeValidator codeValidator = new CodeValidator();
  2093.             // This has internal state and hence is not static
  2094.             codeValidator.ValidateIdentifiers(e);
  2095.         }
  2096.        
  2097.     }
  2098. }

Developer Fusion