Jo Shields a575963da9 Imported Upstream version 3.6.0
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
2014-08-13 10:39:27 +01:00

1317 lines
35 KiB
C#

//
// System.CodeDom.Compiler.CodeGenerator.cs
//
// Authors:
// Miguel de Icaza (miguel@ximian.com)
// Daniel Stodden (stodden@in.tum.de)
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
// Marek Safar (marek.safar@seznam.cz)
//
// (C) 2001-2003 Ximian, Inc.
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Globalization;
using System.CodeDom;
using System.Reflection;
using System.IO;
using System.Collections;
namespace System.CodeDom.Compiler {
public abstract class CodeGenerator : ICodeGenerator
{
private IndentedTextWriter output;
private CodeGeneratorOptions options;
private CodeTypeMember currentMember;
private CodeTypeDeclaration currentType;
private Visitor visitor;
//
// Constructors
//
protected CodeGenerator()
{
visitor = new Visitor (this);
}
//
// Properties
//
protected
CodeTypeDeclaration CurrentClass {
get {
return currentType;
}
}
protected CodeTypeMember CurrentMember {
get {
return currentMember;
}
}
protected string CurrentMemberName {
get {
if (currentMember == null)
return "<% unknown %>";
return currentMember.Name;
}
}
protected string CurrentTypeName {
get {
if (currentType == null)
return "<% unknown %>";
return currentType.Name;
}
}
protected int Indent {
get {
return output.Indent;
}
set {
output.Indent = value;
}
}
protected bool IsCurrentClass {
get {
if (currentType == null)
return false;
return currentType.IsClass && !(currentType is CodeTypeDelegate);
}
}
protected bool IsCurrentDelegate {
get {
return currentType is CodeTypeDelegate;
}
}
protected bool IsCurrentEnum {
get {
if (currentType == null)
return false;
return currentType.IsEnum;
}
}
protected bool IsCurrentInterface {
get {
if (currentType == null)
return false;
return currentType.IsInterface;
}
}
protected bool IsCurrentStruct {
get {
if (currentType == null)
return false;
return currentType.IsStruct;
}
}
protected abstract string NullToken {
get;
}
protected CodeGeneratorOptions Options {
get {
return options;
}
}
protected TextWriter Output {
get {
return output;
}
}
//
// Methods
//
protected virtual void ContinueOnNewLine (string st)
{
output.WriteLine (st);
}
/*
* Code Generation methods
*/
protected abstract void GenerateArgumentReferenceExpression (CodeArgumentReferenceExpression e);
protected abstract void GenerateArrayCreateExpression (CodeArrayCreateExpression e);
protected abstract void GenerateArrayIndexerExpression (CodeArrayIndexerExpression e);
protected abstract void GenerateAssignStatement (CodeAssignStatement s);
protected abstract void GenerateAttachEventStatement (CodeAttachEventStatement s);
protected abstract void GenerateAttributeDeclarationsStart (CodeAttributeDeclarationCollection attributes);
protected abstract void GenerateAttributeDeclarationsEnd (CodeAttributeDeclarationCollection attributes);
protected abstract void GenerateBaseReferenceExpression (CodeBaseReferenceExpression e);
protected virtual void GenerateBinaryOperatorExpression (CodeBinaryOperatorExpression e)
{
output.Write ('(');
GenerateExpression (e.Left);
output.Write (' ');
OutputOperator (e.Operator);
output.Write (' ');
GenerateExpression (e.Right);
output.Write (')');
}
protected abstract void GenerateCastExpression (CodeCastExpression e);
[MonoTODO]
public virtual void GenerateCodeFromMember (CodeTypeMember member, TextWriter writer, CodeGeneratorOptions options)
{
throw new NotImplementedException ();
}
protected abstract void GenerateComment (CodeComment comment);
protected virtual void GenerateCommentStatement (CodeCommentStatement statement)
{
GenerateComment (statement.Comment);
}
protected virtual void GenerateCommentStatements (CodeCommentStatementCollection statements)
{
foreach (CodeCommentStatement comment in statements)
GenerateCommentStatement (comment);
}
protected virtual void GenerateCompileUnit (CodeCompileUnit compileUnit)
{
GenerateCompileUnitStart (compileUnit);
foreach (CodeNamespace ns in compileUnit.Namespaces)
if (string.IsNullOrEmpty(ns.Name))
GenerateNamespace (ns);
CodeAttributeDeclarationCollection attributes = compileUnit.AssemblyCustomAttributes;
if (attributes.Count != 0) {
foreach (CodeAttributeDeclaration att in attributes) {
GenerateAttributeDeclarationsStart (attributes);
output.Write ("assembly: ");
OutputAttributeDeclaration (att);
GenerateAttributeDeclarationsEnd (attributes);
}
output.WriteLine ();
}
foreach (CodeNamespace ns in compileUnit.Namespaces)
if (!string.IsNullOrEmpty(ns.Name))
GenerateNamespace (ns);
GenerateCompileUnitEnd (compileUnit);
}
protected virtual void GenerateCompileUnitEnd (CodeCompileUnit compileUnit)
{
if (compileUnit.EndDirectives.Count > 0)
GenerateDirectives (compileUnit.EndDirectives);
}
protected virtual void GenerateCompileUnitStart (CodeCompileUnit compileUnit)
{
if (compileUnit.StartDirectives.Count > 0) {
GenerateDirectives (compileUnit.StartDirectives);
Output.WriteLine ();
}
}
protected abstract void GenerateConditionStatement (CodeConditionStatement s);
protected abstract void GenerateConstructor (CodeConstructor x, CodeTypeDeclaration d);
protected virtual void GenerateDecimalValue (Decimal d)
{
Output.Write (d.ToString (CultureInfo.InvariantCulture));
}
[MonoTODO]
protected virtual void GenerateDefaultValueExpression (CodeDefaultValueExpression e)
{
throw new NotImplementedException ();
}
protected abstract void GenerateDelegateCreateExpression (CodeDelegateCreateExpression e);
protected abstract void GenerateDelegateInvokeExpression (CodeDelegateInvokeExpression e);
protected virtual void GenerateDirectionExpression (CodeDirectionExpression e)
{
OutputDirection (e.Direction);
output.Write (' ');
GenerateExpression (e.Expression);
}
protected virtual void GenerateDoubleValue (Double d)
{
Output.Write (d.ToString (CultureInfo.InvariantCulture));
}
protected abstract void GenerateEntryPointMethod (CodeEntryPointMethod m, CodeTypeDeclaration d);
protected abstract void GenerateEvent (CodeMemberEvent ev, CodeTypeDeclaration d);
protected abstract void GenerateEventReferenceExpression (CodeEventReferenceExpression e);
protected void GenerateExpression (CodeExpression e)
{
if (e == null)
throw new ArgumentNullException ("e");
try {
e.Accept (visitor);
} catch (NotImplementedException) {
throw new ArgumentException ("Element type " + e.GetType () + " is not supported.", "e");
}
}
protected abstract void GenerateExpressionStatement (CodeExpressionStatement statement);
protected abstract void GenerateField (CodeMemberField f);
protected abstract void GenerateFieldReferenceExpression (CodeFieldReferenceExpression e);
protected abstract void GenerateGotoStatement (CodeGotoStatement statement);
protected abstract void GenerateIndexerExpression (CodeIndexerExpression e);
protected abstract void GenerateIterationStatement (CodeIterationStatement s);
protected abstract void GenerateLabeledStatement (CodeLabeledStatement statement);
protected abstract void GenerateLinePragmaStart (CodeLinePragma p);
protected abstract void GenerateLinePragmaEnd (CodeLinePragma p);
protected abstract void GenerateMethod (CodeMemberMethod m, CodeTypeDeclaration d);
protected abstract void GenerateMethodInvokeExpression (CodeMethodInvokeExpression e);
protected abstract void GenerateMethodReferenceExpression (CodeMethodReferenceExpression e);
protected abstract void GenerateMethodReturnStatement (CodeMethodReturnStatement e);
protected virtual void GenerateNamespace (CodeNamespace ns)
{
foreach (CodeCommentStatement statement in ns.Comments)
GenerateCommentStatement (statement);
GenerateNamespaceStart (ns);
foreach (CodeNamespaceImport import in ns.Imports) {
if (import.LinePragma != null)
GenerateLinePragmaStart (import.LinePragma);
GenerateNamespaceImport (import);
if (import.LinePragma != null)
GenerateLinePragmaEnd (import.LinePragma);
}
output.WriteLine();
GenerateTypes (ns);
GenerateNamespaceEnd (ns);
}
protected abstract void GenerateNamespaceStart (CodeNamespace ns);
protected abstract void GenerateNamespaceEnd (CodeNamespace ns);
protected abstract void GenerateNamespaceImport (CodeNamespaceImport i);
protected void GenerateNamespaceImports (CodeNamespace e)
{
foreach (CodeNamespaceImport import in e.Imports) {
if (import.LinePragma != null)
GenerateLinePragmaStart (import.LinePragma);
GenerateNamespaceImport (import);
if (import.LinePragma != null)
GenerateLinePragmaEnd (import.LinePragma);
}
}
protected void GenerateNamespaces (CodeCompileUnit e)
{
foreach (CodeNamespace ns in e.Namespaces)
GenerateNamespace (ns);
}
protected abstract void GenerateObjectCreateExpression (CodeObjectCreateExpression e);
protected virtual void GenerateParameterDeclarationExpression (CodeParameterDeclarationExpression e)
{
if (e.CustomAttributes != null && e.CustomAttributes.Count > 0)
OutputAttributeDeclarations (e.CustomAttributes);
OutputDirection (e.Direction);
OutputType (e.Type);
output.Write (' ');
output.Write (e.Name);
}
protected virtual void GeneratePrimitiveExpression (CodePrimitiveExpression e)
{
object value = e.Value;
if (value == null) {
output.Write (NullToken);
return;
}
Type type = value.GetType ();
TypeCode typeCode = Type.GetTypeCode (type);
switch (typeCode) {
case TypeCode.Boolean:
output.Write (value.ToString ().ToLower (CultureInfo.InvariantCulture));
break;
case TypeCode.Char:
output.Write ("'" + value.ToString () + "'");
break;
case TypeCode.String:
output.Write (QuoteSnippetString ((string) value));
break;
case TypeCode.Single:
GenerateSingleFloatValue ((float) value);
break;
case TypeCode.Double:
GenerateDoubleValue ((double) value);
break;
case TypeCode.Decimal:
GenerateDecimalValue ((decimal) value);
break;
case TypeCode.Byte:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
output.Write (((IFormattable)value).ToString (null, CultureInfo.InvariantCulture));
break;
default:
throw new ArgumentException (string.Format(CultureInfo.InvariantCulture,
"Invalid Primitive Type: {0}. Only CLS compliant primitive " +
"types can be used. Consider using CodeObjectCreateExpression.",
type.FullName));
}
}
protected abstract void GenerateProperty (CodeMemberProperty p, CodeTypeDeclaration d);
protected abstract void GeneratePropertyReferenceExpression (CodePropertyReferenceExpression e);
protected abstract void GeneratePropertySetValueReferenceExpression (CodePropertySetValueReferenceExpression e);
protected abstract void GenerateRemoveEventStatement (CodeRemoveEventStatement statement);
protected virtual void GenerateSingleFloatValue (Single s)
{
output.Write (s.ToString(CultureInfo.InvariantCulture));
}
protected virtual void GenerateSnippetCompileUnit (CodeSnippetCompileUnit e)
{
if (e.LinePragma != null)
GenerateLinePragmaStart (e.LinePragma);
output.WriteLine (e.Value);
if (e.LinePragma != null)
GenerateLinePragmaEnd (e.LinePragma);
}
protected abstract void GenerateSnippetExpression (CodeSnippetExpression e);
protected abstract void GenerateSnippetMember (CodeSnippetTypeMember m);
protected virtual void GenerateSnippetStatement (CodeSnippetStatement s)
{
output.WriteLine (s.Value);
}
protected void GenerateStatement (CodeStatement s)
{
if (s.StartDirectives.Count > 0)
GenerateDirectives (s.StartDirectives);
if (s.LinePragma != null)
GenerateLinePragmaStart (s.LinePragma);
CodeSnippetStatement snippet = s as CodeSnippetStatement;
if (snippet != null) {
int indent = Indent;
try {
Indent = 0;
GenerateSnippetStatement (snippet);
} finally {
Indent = indent;
}
} else {
try {
s.Accept (visitor);
} catch (NotImplementedException) {
throw new ArgumentException ("Element type " + s.GetType () + " is not supported.", "s");
}
}
if (s.LinePragma != null)
GenerateLinePragmaEnd (s.LinePragma);
if (s.EndDirectives.Count > 0)
GenerateDirectives (s.EndDirectives);
}
protected void GenerateStatements (CodeStatementCollection c)
{
foreach (CodeStatement statement in c)
GenerateStatement (statement);
}
protected abstract void GenerateThisReferenceExpression (CodeThisReferenceExpression e);
protected abstract void GenerateThrowExceptionStatement (CodeThrowExceptionStatement s);
protected abstract void GenerateTryCatchFinallyStatement (CodeTryCatchFinallyStatement s);
protected abstract void GenerateTypeEnd (CodeTypeDeclaration declaration);
protected abstract void GenerateTypeConstructor (CodeTypeConstructor constructor);
protected virtual void GenerateTypeOfExpression (CodeTypeOfExpression e)
{
output.Write ("typeof(");
OutputType (e.Type);
output.Write (")");
}
protected virtual void GenerateTypeReferenceExpression (CodeTypeReferenceExpression e)
{
OutputType (e.Type);
}
protected void GenerateTypes (CodeNamespace e)
{
foreach (CodeTypeDeclaration type in e.Types) {
if (options.BlankLinesBetweenMembers)
output.WriteLine ();
GenerateType (type);
}
}
protected abstract void GenerateTypeStart (CodeTypeDeclaration declaration);
protected abstract void GenerateVariableDeclarationStatement (CodeVariableDeclarationStatement e);
protected abstract void GenerateVariableReferenceExpression (CodeVariableReferenceExpression e);
//
// Other members
//
/*
* Output Methods
*/
protected virtual void OutputAttributeArgument (CodeAttributeArgument argument)
{
string name = argument.Name;
if ((name != null) && (name.Length > 0)) {
output.Write (name);
output.Write ('=');
}
GenerateExpression (argument.Value);
}
private void OutputAttributeDeclaration (CodeAttributeDeclaration attribute)
{
output.Write (attribute.Name.Replace ('+', '.'));
output.Write ('(');
IEnumerator enumerator = attribute.Arguments.GetEnumerator();
if (enumerator.MoveNext()) {
CodeAttributeArgument argument = (CodeAttributeArgument)enumerator.Current;
OutputAttributeArgument (argument);
while (enumerator.MoveNext()) {
output.Write (',');
argument = (CodeAttributeArgument)enumerator.Current;
OutputAttributeArgument (argument);
}
}
output.Write (')');
}
protected virtual void OutputAttributeDeclarations (CodeAttributeDeclarationCollection attributes)
{
GenerateAttributeDeclarationsStart (attributes);
IEnumerator enumerator = attributes.GetEnumerator();
if (enumerator.MoveNext()) {
CodeAttributeDeclaration attribute = (CodeAttributeDeclaration)enumerator.Current;
OutputAttributeDeclaration (attribute);
while (enumerator.MoveNext()) {
attribute = (CodeAttributeDeclaration)enumerator.Current;
output.WriteLine (',');
OutputAttributeDeclaration (attribute);
}
}
GenerateAttributeDeclarationsEnd (attributes);
}
protected virtual void OutputDirection (FieldDirection direction)
{
switch (direction) {
case FieldDirection.In:
//output.Write ("in ");
break;
case FieldDirection.Out:
output.Write ("out ");
break;
case FieldDirection.Ref:
output.Write ("ref ");
break;
}
}
protected virtual void OutputExpressionList (CodeExpressionCollection expressions)
{
OutputExpressionList (expressions, false);
}
protected virtual void OutputExpressionList (CodeExpressionCollection expressions,
bool newLineBetweenItems)
{
++Indent;
IEnumerator enumerator = expressions.GetEnumerator();
if (enumerator.MoveNext()) {
CodeExpression expression = (CodeExpression)enumerator.Current;
GenerateExpression (expression);
while (enumerator.MoveNext()) {
expression = (CodeExpression)enumerator.Current;
output.Write (',');
if (newLineBetweenItems)
output.WriteLine ();
else
output.Write (' ');
GenerateExpression (expression);
}
}
--Indent;
}
protected virtual void OutputFieldScopeModifier (MemberAttributes attributes)
{
if ((attributes & MemberAttributes.VTableMask) == MemberAttributes.New)
output.Write ("new ");
switch (attributes & MemberAttributes.ScopeMask) {
case MemberAttributes.Static:
output.Write ("static ");
break;
case MemberAttributes.Const:
output.Write ("const ");
break;
}
}
protected virtual void OutputIdentifier (string ident)
{
output.Write (ident);
}
protected virtual void OutputMemberAccessModifier (MemberAttributes attributes)
{
switch (attributes & MemberAttributes.AccessMask) {
case MemberAttributes.Assembly:
output.Write ("internal ");
break;
case MemberAttributes.FamilyAndAssembly:
output.Write ("internal ");
break;
case MemberAttributes.Family:
output.Write ("protected ");
break;
case MemberAttributes.FamilyOrAssembly:
output.Write ("protected internal ");
break;
case MemberAttributes.Private:
output.Write ("private ");
break;
case MemberAttributes.Public:
output.Write ("public ");
break;
}
}
protected virtual void OutputMemberScopeModifier (MemberAttributes attributes)
{
if ((attributes & MemberAttributes.VTableMask) == MemberAttributes.New)
output.Write( "new " );
switch (attributes & MemberAttributes.ScopeMask) {
case MemberAttributes.Abstract:
output.Write ("abstract ");
break;
case MemberAttributes.Final:
// Do nothing
break;
case MemberAttributes.Static:
output.Write ("static ");
break;
case MemberAttributes.Override:
output.Write ("override ");
break;
default:
//
// FUNNY! if the scope value is
// rubbish (0 or >Const), and access
// is public or protected, make it
// "virtual".
//
// i'm not sure whether this is 100%
// correct, but it seems to be MS
// behavior.
//
// On .NET 2.0, internal members
// are also marked "virtual".
//
MemberAttributes access = attributes & MemberAttributes.AccessMask;
if (access == MemberAttributes.Public || access == MemberAttributes.Family)
output.Write ("virtual ");
break;
}
}
protected virtual void OutputOperator (CodeBinaryOperatorType op)
{
switch (op) {
case CodeBinaryOperatorType.Add:
output.Write ("+");
break;
case CodeBinaryOperatorType.Subtract:
output.Write ("-");
break;
case CodeBinaryOperatorType.Multiply:
output.Write ("*");
break;
case CodeBinaryOperatorType.Divide:
output.Write ("/");
break;
case CodeBinaryOperatorType.Modulus:
output.Write ("%");
break;
case CodeBinaryOperatorType.Assign:
output.Write ("=");
break;
case CodeBinaryOperatorType.IdentityInequality:
output.Write ("!=");
break;
case CodeBinaryOperatorType.IdentityEquality:
output.Write ("==");
break;
case CodeBinaryOperatorType.ValueEquality:
output.Write ("==");
break;
case CodeBinaryOperatorType.BitwiseOr:
output.Write ("|");
break;
case CodeBinaryOperatorType.BitwiseAnd:
output.Write ("&");
break;
case CodeBinaryOperatorType.BooleanOr:
output.Write ("||");
break;
case CodeBinaryOperatorType.BooleanAnd:
output.Write ("&&");
break;
case CodeBinaryOperatorType.LessThan:
output.Write ("<");
break;
case CodeBinaryOperatorType.LessThanOrEqual:
output.Write ("<=");
break;
case CodeBinaryOperatorType.GreaterThan:
output.Write (">");
break;
case CodeBinaryOperatorType.GreaterThanOrEqual:
output.Write (">=");
break;
}
}
protected virtual void OutputParameters (CodeParameterDeclarationExpressionCollection parameters)
{
bool first = true;
foreach (CodeParameterDeclarationExpression expr in parameters) {
if (first)
first = false;
else
output.Write (", ");
GenerateExpression (expr);
}
}
protected abstract void OutputType (CodeTypeReference t);
protected virtual void OutputTypeAttributes (TypeAttributes attributes,
bool isStruct,
bool isEnum)
{
switch (attributes & TypeAttributes.VisibilityMask) {
case TypeAttributes.NotPublic:
// private by default
break;
case TypeAttributes.Public:
case TypeAttributes.NestedPublic:
output.Write ("public ");
break;
case TypeAttributes.NestedPrivate:
output.Write ("private ");
break;
}
if (isStruct)
output.Write ("struct ");
else if (isEnum)
output.Write ("enum ");
else {
if ((attributes & TypeAttributes.Interface) != 0)
output.Write ("interface ");
else if (currentType is CodeTypeDelegate)
output.Write ("delegate ");
else {
if ((attributes & TypeAttributes.Sealed) != 0)
output.Write ("sealed ");
if ((attributes & TypeAttributes.Abstract) != 0)
output.Write ("abstract ");
output.Write ("class ");
}
}
}
protected virtual void OutputTypeNamePair (CodeTypeReference type,
string name)
{
OutputType (type);
output.Write (' ');
output.Write (name);
}
protected abstract string QuoteSnippetString (string value);
/*
* ICodeGenerator
*/
protected abstract string CreateEscapedIdentifier (string value);
string ICodeGenerator.CreateEscapedIdentifier (string value)
{
return CreateEscapedIdentifier (value);
}
protected abstract string CreateValidIdentifier (string value);
string ICodeGenerator.CreateValidIdentifier (string value)
{
return CreateValidIdentifier (value);
}
private void InitOutput (TextWriter output, CodeGeneratorOptions options)
{
if (options == null)
options = new CodeGeneratorOptions ();
this.output = new IndentedTextWriter (output, options.IndentString);
this.options = options;
}
void ICodeGenerator.GenerateCodeFromCompileUnit (CodeCompileUnit compileUnit,
TextWriter output,
CodeGeneratorOptions options)
{
InitOutput (output, options);
if (compileUnit is CodeSnippetCompileUnit) {
GenerateSnippetCompileUnit ((CodeSnippetCompileUnit) compileUnit);
} else {
GenerateCompileUnit (compileUnit);
}
}
void ICodeGenerator.GenerateCodeFromExpression (CodeExpression expression,
TextWriter output,
CodeGeneratorOptions options)
{
InitOutput (output, options);
GenerateExpression (expression);
}
void ICodeGenerator.GenerateCodeFromNamespace (CodeNamespace ns,
TextWriter output,
CodeGeneratorOptions options)
{
InitOutput (output, options);
GenerateNamespace (ns);
}
void ICodeGenerator.GenerateCodeFromStatement (CodeStatement statement,
TextWriter output,
CodeGeneratorOptions options)
{
InitOutput (output, options);
GenerateStatement (statement);
}
void ICodeGenerator.GenerateCodeFromType (CodeTypeDeclaration type,
TextWriter output,
CodeGeneratorOptions options)
{
InitOutput (output, options);
GenerateType (type);
}
private void GenerateType (CodeTypeDeclaration type)
{
this.currentType = type;
this.currentMember = null;
if (type.StartDirectives.Count > 0)
GenerateDirectives (type.StartDirectives);
foreach (CodeCommentStatement statement in type.Comments)
GenerateCommentStatement (statement);
if (type.LinePragma != null)
GenerateLinePragmaStart (type.LinePragma);
GenerateTypeStart (type);
CodeTypeMember[] members = new CodeTypeMember[type.Members.Count];
type.Members.CopyTo (members, 0);
if (!Options.VerbatimOrder)
{
int[] order = new int[members.Length];
for (int n = 0; n < members.Length; n++)
order[n] = Array.IndexOf (memberTypes, members[n].GetType ()) * members.Length + n;
Array.Sort (order, members);
}
// WARNING: if anything is missing in the foreach loop and you add it, add the type in
// its corresponding place in CodeTypeMemberComparer class (below)
CodeTypeDeclaration subtype = null;
foreach (CodeTypeMember member in members) {
CodeTypeMember prevMember = this.currentMember;
this.currentMember = member;
if (prevMember != null && subtype == null) {
if (prevMember.LinePragma != null)
GenerateLinePragmaEnd (prevMember.LinePragma);
if (prevMember.EndDirectives.Count > 0)
GenerateDirectives (prevMember.EndDirectives);
if (!Options.VerbatimOrder && prevMember is CodeSnippetTypeMember && !(member is CodeSnippetTypeMember))
output.WriteLine ();
}
if (options.BlankLinesBetweenMembers)
output.WriteLine ();
subtype = member as CodeTypeDeclaration;
if (subtype != null) {
GenerateType (subtype);
this.currentType = type;
continue;
}
if (currentMember.StartDirectives.Count > 0)
GenerateDirectives (currentMember.StartDirectives);
foreach (CodeCommentStatement statement in member.Comments)
GenerateCommentStatement (statement);
if (member.LinePragma != null)
GenerateLinePragmaStart (member.LinePragma);
try {
member.Accept (visitor);
} catch (NotImplementedException) {
throw new ArgumentException ("Element type " + member.GetType () + " is not supported.");
}
}
// Hack because of previous continue usage
if (currentMember != null && !(currentMember is CodeTypeDeclaration)) {
if (currentMember.LinePragma != null)
GenerateLinePragmaEnd (currentMember.LinePragma);
if (currentMember.EndDirectives.Count > 0)
GenerateDirectives (currentMember.EndDirectives);
if (!Options.VerbatimOrder && currentMember is CodeSnippetTypeMember)
output.WriteLine ();
}
this.currentType = type;
GenerateTypeEnd (type);
if (type.LinePragma != null)
GenerateLinePragmaEnd (type.LinePragma);
if (type.EndDirectives.Count > 0)
GenerateDirectives (type.EndDirectives);
}
protected abstract string GetTypeOutput (CodeTypeReference type);
string ICodeGenerator.GetTypeOutput (CodeTypeReference type)
{
return GetTypeOutput (type);
}
protected abstract bool IsValidIdentifier (string value);
bool ICodeGenerator.IsValidIdentifier (string value)
{
return IsValidIdentifier (value);
}
public static bool IsValidLanguageIndependentIdentifier (string value)
{
if (value == null)
return false;
if (value.Equals (string.Empty))
return false;
switch (char.GetUnicodeCategory (value[0])) {
case UnicodeCategory.LetterNumber:
case UnicodeCategory.LowercaseLetter:
case UnicodeCategory.TitlecaseLetter:
case UnicodeCategory.UppercaseLetter:
case UnicodeCategory.OtherLetter:
case UnicodeCategory.ModifierLetter:
case UnicodeCategory.ConnectorPunctuation:
break;
default:
return false;
}
for (int x = 1; x < value.Length; ++x) {
switch (char.GetUnicodeCategory (value[x])) {
case UnicodeCategory.LetterNumber:
case UnicodeCategory.LowercaseLetter:
case UnicodeCategory.TitlecaseLetter:
case UnicodeCategory.UppercaseLetter:
case UnicodeCategory.OtherLetter:
case UnicodeCategory.ModifierLetter:
case UnicodeCategory.ConnectorPunctuation:
case UnicodeCategory.DecimalDigitNumber:
case UnicodeCategory.NonSpacingMark:
case UnicodeCategory.SpacingCombiningMark:
case UnicodeCategory.Format:
break;
default:
return false;
}
}
return true;
}
protected abstract bool Supports (GeneratorSupport supports);
bool ICodeGenerator.Supports (GeneratorSupport value)
{
return Supports (value);
}
protected virtual void ValidateIdentifier (string value)
{
if (!(IsValidIdentifier (value)))
throw new ArgumentException ("Identifier is invalid", "value");
}
[MonoTODO]
public static void ValidateIdentifiers (CodeObject e)
{
throw new NotImplementedException();
}
void ICodeGenerator.ValidateIdentifier (string value)
{
ValidateIdentifier (value);
}
// The position in the array determines the order in which those
// kind of CodeTypeMembers are generated. Less is more ;-)
static readonly Type [] memberTypes = { typeof (CodeMemberField),
typeof (CodeSnippetTypeMember),
typeof (CodeTypeConstructor),
typeof (CodeConstructor),
typeof (CodeMemberProperty),
typeof (CodeMemberEvent),
typeof (CodeMemberMethod),
typeof (CodeTypeDeclaration),
typeof (CodeEntryPointMethod)
};
protected virtual void GenerateDirectives (CodeDirectiveCollection directives)
{
}
internal class Visitor : ICodeDomVisitor {
CodeGenerator g;
public Visitor (CodeGenerator generator)
{
this.g = generator;
}
// CodeExpression
public void Visit (CodeArgumentReferenceExpression o)
{
g.GenerateArgumentReferenceExpression (o);
}
public void Visit (CodeArrayCreateExpression o)
{
g.GenerateArrayCreateExpression (o);
}
public void Visit (CodeArrayIndexerExpression o)
{
g.GenerateArrayIndexerExpression (o);
}
public void Visit (CodeBaseReferenceExpression o)
{
g.GenerateBaseReferenceExpression (o);
}
public void Visit (CodeBinaryOperatorExpression o)
{
g.GenerateBinaryOperatorExpression (o);
}
public void Visit (CodeCastExpression o)
{
g.GenerateCastExpression (o);
}
public void Visit (CodeDefaultValueExpression o)
{
g.GenerateDefaultValueExpression (o);
}
public void Visit (CodeDelegateCreateExpression o)
{
g.GenerateDelegateCreateExpression (o);
}
public void Visit (CodeDelegateInvokeExpression o)
{
g.GenerateDelegateInvokeExpression (o);
}
public void Visit (CodeDirectionExpression o)
{
g.GenerateDirectionExpression (o);
}
public void Visit (CodeEventReferenceExpression o)
{
g.GenerateEventReferenceExpression (o);
}
public void Visit (CodeFieldReferenceExpression o)
{
g.GenerateFieldReferenceExpression (o);
}
public void Visit (CodeIndexerExpression o)
{
g.GenerateIndexerExpression (o);
}
public void Visit (CodeMethodInvokeExpression o)
{
g.GenerateMethodInvokeExpression (o);
}
public void Visit (CodeMethodReferenceExpression o)
{
g.GenerateMethodReferenceExpression (o);
}
public void Visit (CodeObjectCreateExpression o)
{
g.GenerateObjectCreateExpression (o);
}
public void Visit (CodeParameterDeclarationExpression o)
{
g.GenerateParameterDeclarationExpression (o);
}
public void Visit (CodePrimitiveExpression o)
{
g.GeneratePrimitiveExpression (o);
}
public void Visit (CodePropertyReferenceExpression o)
{
g.GeneratePropertyReferenceExpression (o);
}
public void Visit (CodePropertySetValueReferenceExpression o)
{
g.GeneratePropertySetValueReferenceExpression (o);
}
public void Visit (CodeSnippetExpression o)
{
g.GenerateSnippetExpression (o);
}
public void Visit (CodeThisReferenceExpression o)
{
g.GenerateThisReferenceExpression (o);
}
public void Visit (CodeTypeOfExpression o)
{
g.GenerateTypeOfExpression (o);
}
public void Visit (CodeTypeReferenceExpression o)
{
g.GenerateTypeReferenceExpression (o);
}
public void Visit (CodeVariableReferenceExpression o)
{
g.GenerateVariableReferenceExpression (o);
}
// CodeStatement
public void Visit (CodeAssignStatement o)
{
g.GenerateAssignStatement (o);
}
public void Visit (CodeAttachEventStatement o)
{
g.GenerateAttachEventStatement (o);
}
public void Visit (CodeCommentStatement o)
{
g.GenerateCommentStatement (o);
}
public void Visit (CodeConditionStatement o)
{
g.GenerateConditionStatement (o);
}
public void Visit (CodeExpressionStatement o)
{
g.GenerateExpressionStatement (o);
}
public void Visit (CodeGotoStatement o)
{
g.GenerateGotoStatement (o);
}
public void Visit (CodeIterationStatement o)
{
g.GenerateIterationStatement (o);
}
public void Visit (CodeLabeledStatement o)
{
g.GenerateLabeledStatement (o);
}
public void Visit (CodeMethodReturnStatement o)
{
g.GenerateMethodReturnStatement (o);
}
public void Visit (CodeRemoveEventStatement o)
{
g.GenerateRemoveEventStatement (o);
}
public void Visit (CodeThrowExceptionStatement o)
{
g.GenerateThrowExceptionStatement (o);
}
public void Visit (CodeTryCatchFinallyStatement o)
{
g.GenerateTryCatchFinallyStatement (o);
}
public void Visit (CodeVariableDeclarationStatement o)
{
g.GenerateVariableDeclarationStatement (o);
}
// CodeTypeMember
public void Visit (CodeConstructor o)
{
g.GenerateConstructor (o, g.CurrentClass);
}
public void Visit (CodeEntryPointMethod o)
{
g.GenerateEntryPointMethod (o, g.CurrentClass);
}
public void Visit (CodeMemberEvent o)
{
g.GenerateEvent (o, g.CurrentClass);
}
public void Visit (CodeMemberField o)
{
g.GenerateField (o);
}
public void Visit (CodeMemberMethod o)
{
g.GenerateMethod (o, g.CurrentClass);
}
public void Visit (CodeMemberProperty o)
{
g.GenerateProperty (o, g.CurrentClass);
}
public void Visit (CodeSnippetTypeMember o)
{
var indent = g.Indent;
g.Indent = 0;
g.GenerateSnippetMember (o);
if (g.Options.VerbatimOrder)
g.Output.WriteLine ();
g.Indent = indent;
}
public void Visit (CodeTypeConstructor o)
{
g.GenerateTypeConstructor (o);
}
}
}
}