Skip to content

Instantly share code, notes, and snippets.

@Rallymen007
Created February 23, 2016 09:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Rallymen007/3b144dafccd1e23a9c4e to your computer and use it in GitHub Desktop.
Save Rallymen007/3b144dafccd1e23a9c4e to your computer and use it in GitHub Desktop.
//
// Mono.CSharp CSharpCodeProvider Class implementation
//
// Author:
// Daniel Stodden (stodden@in.tum.de)
// Marek Safar (marek.safar@seznam.cz)
// Ilker Cetinkaya (mail@ilker.de)
//
// (C) 2002 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.
//
namespace Modified.Mono.CSharp {
using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Collections;
using System.Text;
using System.Collections.Generic;
internal class CSharpCodeGenerator
: CodeGenerator {
IDictionary<string, string> providerOptions;
// It is used for beautiful "for" syntax
bool dont_write_semicolon;
//
// Constructors
//
public CSharpCodeGenerator() {
dont_write_semicolon = false;
}
public CSharpCodeGenerator(IDictionary<string, string> providerOptions) {
this.providerOptions = providerOptions;
}
protected IDictionary<string, string> ProviderOptions
{
get { return providerOptions; }
}
//
// Properties
//
protected override string NullToken
{
get
{
return "null";
}
}
//
// Methods
//
protected override void GenerateArrayCreateExpression(CodeArrayCreateExpression expression) {
//
// This tries to replicate MS behavior as good as
// possible.
//
// The Code-Array stuff in ms.net seems to be broken
// anyways, or I'm too stupid to understand it.
//
// I'm sick of it. If you try to develop array
// creations, test them on windows. If it works there
// but not in mono, drop me a note. I'd be especially
// interested in jagged-multidimensional combinations
// with proper initialization :}
//
TextWriter output = Output;
output.Write("new ");
CodeExpressionCollection initializers = expression.Initializers;
CodeTypeReference createType = expression.CreateType;
if (initializers.Count > 0) {
OutputType(createType);
if (expression.CreateType.ArrayRank == 0) {
output.Write("[]");
}
OutputStartBrace();
++Indent;
OutputExpressionList(initializers, true);
--Indent;
output.Write("}");
} else {
CodeTypeReference arrayType = createType.ArrayElementType;
while (arrayType != null) {
createType = arrayType;
arrayType = arrayType.ArrayElementType;
}
OutputType(createType);
output.Write('[');
CodeExpression size = expression.SizeExpression;
if (size != null)
GenerateExpression(size);
else
output.Write(expression.Size);
output.Write(']');
}
}
protected override void GenerateBaseReferenceExpression(CodeBaseReferenceExpression expression) {
Output.Write("base");
}
protected override void GenerateCastExpression(CodeCastExpression expression) {
TextWriter output = Output;
output.Write("((");
OutputType(expression.TargetType);
output.Write(")(");
GenerateExpression(expression.Expression);
output.Write("))");
}
protected override void GenerateCompileUnitStart(CodeCompileUnit compileUnit) {
GenerateComment(new CodeComment("------------------------------------------------------------------------------"));
GenerateComment(new CodeComment(" <autogenerated>"));
GenerateComment(new CodeComment(" This code was generated by a tool."));
GenerateComment(new CodeComment(" Mono Runtime Version: " + System.Environment.Version));
GenerateComment(new CodeComment(""));
GenerateComment(new CodeComment(" Changes to this file may cause incorrect behavior and will be lost if "));
GenerateComment(new CodeComment(" the code is regenerated."));
GenerateComment(new CodeComment(" </autogenerated>"));
GenerateComment(new CodeComment("------------------------------------------------------------------------------"));
Output.WriteLine();
base.GenerateCompileUnitStart(compileUnit);
}
protected override void GenerateCompileUnit(CodeCompileUnit compileUnit) {
GenerateCompileUnitStart(compileUnit);
List<CodeNamespaceImport> imports = null;
foreach (CodeNamespace codeNamespace in compileUnit.Namespaces) {
if (!string.IsNullOrEmpty(codeNamespace.Name))
continue;
if (codeNamespace.Imports.Count == 0)
continue;
if (imports == null)
imports = new List<CodeNamespaceImport>();
foreach (CodeNamespaceImport i in codeNamespace.Imports)
imports.Add(i);
}
if (imports != null) {
imports.Sort((a, b) => a.Namespace.CompareTo(b.Namespace));
foreach (var import in imports)
GenerateNamespaceImport(import);
Output.WriteLine();
}
if (compileUnit.AssemblyCustomAttributes.Count > 0) {
OutputAttributes(compileUnit.AssemblyCustomAttributes,
"assembly: ", false);
Output.WriteLine("");
}
CodeNamespaceImportCollection global_imports = null;
foreach (CodeNamespace codeNamespace in compileUnit.Namespaces) {
if (string.IsNullOrEmpty(codeNamespace.Name)) {
global_imports = codeNamespace.Imports;
codeNamespace.Imports.Clear();
}
GenerateNamespace(codeNamespace);
if (global_imports != null) {
codeNamespace.Imports.Clear();
foreach (CodeNamespaceImport ns in global_imports)
codeNamespace.Imports.Add(ns);
global_imports = null;
}
}
GenerateCompileUnitEnd(compileUnit);
}
protected override void GenerateDefaultValueExpression(CodeDefaultValueExpression e) {
Output.Write("default(");
OutputType(e.Type);
Output.Write(')');
}
protected override void GenerateDelegateCreateExpression(CodeDelegateCreateExpression expression) {
TextWriter output = Output;
output.Write("new ");
OutputType(expression.DelegateType);
output.Write('(');
CodeExpression targetObject = expression.TargetObject;
if (targetObject != null) {
GenerateExpression(targetObject);
Output.Write('.');
}
output.Write(GetSafeName(expression.MethodName));
output.Write(')');
}
protected override void GenerateFieldReferenceExpression(CodeFieldReferenceExpression expression) {
CodeExpression targetObject = expression.TargetObject;
if (targetObject != null) {
GenerateExpression(targetObject);
Output.Write('.');
}
Output.Write(GetSafeName(expression.FieldName));
}
protected override void GenerateArgumentReferenceExpression(CodeArgumentReferenceExpression expression) {
Output.Write(GetSafeName(expression.ParameterName));
}
protected override void GenerateVariableReferenceExpression(CodeVariableReferenceExpression expression) {
Output.Write(GetSafeName(expression.VariableName));
}
protected override void GenerateIndexerExpression(CodeIndexerExpression expression) {
TextWriter output = Output;
GenerateExpression(expression.TargetObject);
output.Write('[');
OutputExpressionList(expression.Indices);
output.Write(']');
}
protected override void GenerateArrayIndexerExpression(CodeArrayIndexerExpression expression) {
TextWriter output = Output;
GenerateExpression(expression.TargetObject);
output.Write('[');
OutputExpressionList(expression.Indices);
output.Write(']');
}
protected override void GenerateSnippetExpression(CodeSnippetExpression expression) {
Output.Write(expression.Value);
}
protected override void GenerateMethodInvokeExpression(CodeMethodInvokeExpression expression) {
TextWriter output = Output;
GenerateMethodReferenceExpression(expression.Method);
output.Write('(');
OutputExpressionList(expression.Parameters);
output.Write(')');
}
protected override void GenerateMethodReferenceExpression(CodeMethodReferenceExpression expression) {
if (expression.TargetObject != null) {
GenerateExpression(expression.TargetObject);
Output.Write('.');
};
Output.Write(GetSafeName(expression.MethodName));
if (expression.TypeArguments.Count > 0)
Output.Write(GetTypeArguments(expression.TypeArguments));
}
protected override void GenerateEventReferenceExpression(CodeEventReferenceExpression expression) {
if (expression.TargetObject != null) {
GenerateExpression(expression.TargetObject);
Output.Write('.');
}
Output.Write(GetSafeName(expression.EventName));
}
protected override void GenerateDelegateInvokeExpression(CodeDelegateInvokeExpression expression) {
if (expression.TargetObject != null)
GenerateExpression(expression.TargetObject);
Output.Write('(');
OutputExpressionList(expression.Parameters);
Output.Write(')');
}
protected override void GenerateObjectCreateExpression(CodeObjectCreateExpression expression) {
Output.Write("new ");
OutputType(expression.CreateType);
Output.Write('(');
OutputExpressionList(expression.Parameters);
Output.Write(')');
}
protected override void GeneratePropertyReferenceExpression(CodePropertyReferenceExpression expression) {
CodeExpression targetObject = expression.TargetObject;
if (targetObject != null) {
GenerateExpression(targetObject);
Output.Write('.');
}
Output.Write(GetSafeName(expression.PropertyName));
}
protected override void GeneratePropertySetValueReferenceExpression(CodePropertySetValueReferenceExpression expression) {
Output.Write("value");
}
protected override void GenerateThisReferenceExpression(CodeThisReferenceExpression expression) {
Output.Write("this");
}
protected override void GenerateExpressionStatement(CodeExpressionStatement statement) {
GenerateExpression(statement.Expression);
if (dont_write_semicolon)
return;
Output.WriteLine(';');
}
protected override void GenerateIterationStatement(CodeIterationStatement statement) {
TextWriter output = Output;
dont_write_semicolon = true;
output.Write("for (");
GenerateStatement(statement.InitStatement);
output.Write("; ");
GenerateExpression(statement.TestExpression);
output.Write("; ");
GenerateStatement(statement.IncrementStatement);
output.Write(")");
dont_write_semicolon = false;
OutputStartBrace();
++Indent;
GenerateStatements(statement.Statements);
--Indent;
output.WriteLine('}');
}
protected override void GenerateThrowExceptionStatement(CodeThrowExceptionStatement statement) {
Output.Write("throw");
if (statement.ToThrow != null) {
Output.Write(' ');
GenerateExpression(statement.ToThrow);
}
Output.WriteLine(";");
}
protected override void GenerateComment(CodeComment comment) {
TextWriter output = Output;
string commentChars = null;
if (comment.DocComment) {
commentChars = "///";
} else {
commentChars = "//";
}
output.Write(commentChars);
output.Write(' ');
string text = comment.Text;
for (int i = 0; i < text.Length; i++) {
output.Write(text[i]);
if (text[i] == '\r') {
if (i < (text.Length - 1) && text[i + 1] == '\n') {
continue;
}
output.Write(commentChars);
} else if (text[i] == '\n') {
output.Write(commentChars);
}
}
output.WriteLine();
}
protected override void GenerateMethodReturnStatement(CodeMethodReturnStatement statement) {
TextWriter output = Output;
if (statement.Expression != null) {
output.Write("return ");
GenerateExpression(statement.Expression);
output.WriteLine(";");
} else {
output.WriteLine("return;");
}
}
protected override void GenerateConditionStatement(CodeConditionStatement statement) {
TextWriter output = Output;
output.Write("if (");
GenerateExpression(statement.Condition);
output.Write(")");
OutputStartBrace();
++Indent;
GenerateStatements(statement.TrueStatements);
--Indent;
CodeStatementCollection falses = statement.FalseStatements;
if (falses.Count > 0) {
output.Write('}');
if (Options.ElseOnClosing)
output.Write(' ');
else
output.WriteLine();
output.Write("else");
OutputStartBrace();
++Indent;
GenerateStatements(falses);
--Indent;
}
output.WriteLine('}');
}
protected override void GenerateTryCatchFinallyStatement(CodeTryCatchFinallyStatement statement) {
TextWriter output = Output;
CodeGeneratorOptions options = Options;
output.Write("try");
OutputStartBrace();
++Indent;
GenerateStatements(statement.TryStatements);
--Indent;
foreach (CodeCatchClause clause in statement.CatchClauses) {
output.Write('}');
if (options.ElseOnClosing)
output.Write(' ');
else
output.WriteLine();
output.Write("catch (");
OutputTypeNamePair(clause.CatchExceptionType, GetSafeName(clause.LocalName));
output.Write(")");
OutputStartBrace();
++Indent;
GenerateStatements(clause.Statements);
--Indent;
}
CodeStatementCollection finallies = statement.FinallyStatements;
if (finallies.Count > 0) {
output.Write('}');
if (options.ElseOnClosing)
output.Write(' ');
else
output.WriteLine();
output.Write("finally");
OutputStartBrace();
++Indent;
GenerateStatements(finallies);
--Indent;
}
output.WriteLine('}');
}
protected override void GenerateAssignStatement(CodeAssignStatement statement) {
TextWriter output = Output;
GenerateExpression(statement.Left);
output.Write(" = ");
GenerateExpression(statement.Right);
if (dont_write_semicolon)
return;
output.WriteLine(';');
}
protected override void GenerateAttachEventStatement(CodeAttachEventStatement statement) {
TextWriter output = Output;
GenerateEventReferenceExpression(statement.Event);
output.Write(" += ");
GenerateExpression(statement.Listener);
output.WriteLine(';');
}
protected override void GenerateRemoveEventStatement(CodeRemoveEventStatement statement) {
TextWriter output = Output;
GenerateEventReferenceExpression(statement.Event);
output.Write(" -= ");
GenerateExpression(statement.Listener);
output.WriteLine(';');
}
protected override void GenerateGotoStatement(CodeGotoStatement statement) {
TextWriter output = Output;
output.Write("goto ");
output.Write(GetSafeName(statement.Label));
output.WriteLine(";");
}
protected override void GenerateLabeledStatement(CodeLabeledStatement statement) {
Indent--;
Output.Write(statement.Label);
Output.WriteLine(":");
Indent++;
if (statement.Statement != null) {
GenerateStatement(statement.Statement);
}
}
protected override void GenerateVariableDeclarationStatement(CodeVariableDeclarationStatement statement) {
TextWriter output = Output;
OutputTypeNamePair(statement.Type, GetSafeName(statement.Name));
CodeExpression initExpression = statement.InitExpression;
if (initExpression != null) {
output.Write(" = ");
GenerateExpression(initExpression);
}
if (!dont_write_semicolon) {
output.WriteLine(';');
}
}
protected override void GenerateLinePragmaStart(CodeLinePragma linePragma) {
Output.WriteLine();
Output.Write("#line ");
Output.Write(linePragma.LineNumber);
Output.Write(" \"");
Output.Write(linePragma.FileName);
Output.Write("\"");
Output.WriteLine();
}
protected override void GenerateLinePragmaEnd(CodeLinePragma linePragma) {
Output.WriteLine();
Output.WriteLine("#line default");
Output.WriteLine("#line hidden");
}
protected override void GenerateEvent(CodeMemberEvent eventRef, CodeTypeDeclaration declaration) {
if (IsCurrentDelegate || IsCurrentEnum) {
return;
}
OutputAttributes(eventRef.CustomAttributes, null, false);
if (eventRef.PrivateImplementationType == null) {
OutputMemberAccessModifier(eventRef.Attributes);
}
Output.Write("event ");
if (eventRef.PrivateImplementationType != null) {
OutputTypeNamePair(eventRef.Type,
eventRef.PrivateImplementationType.BaseType + "." +
eventRef.Name);
} else {
OutputTypeNamePair(eventRef.Type, GetSafeName(eventRef.Name));
}
Output.WriteLine(';');
}
protected override void GenerateField(CodeMemberField field) {
if (IsCurrentDelegate || IsCurrentInterface) {
return;
}
TextWriter output = Output;
OutputAttributes(field.CustomAttributes, null, false);
if (IsCurrentEnum) {
Output.Write(GetSafeName(field.Name));
} else {
MemberAttributes attributes = field.Attributes;
OutputMemberAccessModifier(attributes);
OutputVTableModifier(attributes);
OutputFieldScopeModifier(attributes);
OutputTypeNamePair(field.Type, GetSafeName(field.Name));
}
CodeExpression initExpression = field.InitExpression;
if (initExpression != null) {
output.Write(" = ");
GenerateExpression(initExpression);
}
if (IsCurrentEnum)
output.WriteLine(',');
else
output.WriteLine(';');
}
protected override void GenerateSnippetMember(CodeSnippetTypeMember member) {
Output.Write(member.Text);
}
protected override void GenerateEntryPointMethod(CodeEntryPointMethod method,
CodeTypeDeclaration declaration) {
OutputAttributes(method.CustomAttributes, null, false);
Output.Write("public static ");
OutputType(method.ReturnType);
Output.Write(" Main()");
OutputStartBrace();
Indent++;
GenerateStatements(method.Statements);
Indent--;
Output.WriteLine("}");
}
protected override void GenerateMethod(CodeMemberMethod method,
CodeTypeDeclaration declaration) {
if (IsCurrentDelegate || IsCurrentEnum) {
return;
}
TextWriter output = Output;
OutputAttributes(method.CustomAttributes, null, false);
OutputAttributes(method.ReturnTypeCustomAttributes,
"return: ", false);
MemberAttributes attributes = method.Attributes;
if (!IsCurrentInterface) {
if (method.PrivateImplementationType == null) {
OutputMemberAccessModifier(attributes);
OutputVTableModifier(attributes);
OutputMemberScopeModifier(attributes);
}
} else {
OutputVTableModifier(attributes);
}
OutputType(method.ReturnType);
output.Write(' ');
CodeTypeReference privateType = method.PrivateImplementationType;
if (privateType != null) {
output.Write(privateType.BaseType);
output.Write('.');
}
output.Write(GetSafeName(method.Name));
GenerateGenericsParameters(method.TypeParameters);
output.Write('(');
OutputParameters(method.Parameters);
output.Write(')');
GenerateGenericsConstraints(method.TypeParameters);
if (IsAbstract(attributes) || declaration.IsInterface)
output.WriteLine(';');
else {
OutputStartBrace();
++Indent;
GenerateStatements(method.Statements);
--Indent;
output.WriteLine('}');
}
}
static bool IsAbstract(MemberAttributes attributes) {
return (attributes & MemberAttributes.ScopeMask) == MemberAttributes.Abstract;
}
protected override void GenerateProperty(CodeMemberProperty property,
CodeTypeDeclaration declaration) {
if (IsCurrentDelegate || IsCurrentEnum) {
return;
}
TextWriter output = Output;
OutputAttributes(property.CustomAttributes, null, false);
MemberAttributes attributes = property.Attributes;
if (!IsCurrentInterface) {
if (property.PrivateImplementationType == null) {
OutputMemberAccessModifier(attributes);
OutputVTableModifier(attributes);
OutputMemberScopeModifier(attributes);
}
} else {
OutputVTableModifier(attributes);
}
OutputType(property.Type);
output.Write(' ');
if (!IsCurrentInterface && property.PrivateImplementationType != null) {
output.Write(property.PrivateImplementationType.BaseType);
output.Write('.');
}
// only consider property indexer if name is Item (case-insensitive
// comparison) AND property has parameters
if (string.Compare(property.Name, "Item", true, CultureInfo.InvariantCulture) == 0 && property.Parameters.Count > 0) {
output.Write("this[");
OutputParameters(property.Parameters);
output.Write(']');
} else {
output.Write(GetSafeName(property.Name));
}
OutputStartBrace();
++Indent;
if (declaration.IsInterface || IsAbstract(property.Attributes)) {
if (property.HasGet) output.WriteLine("get;");
if (property.HasSet) output.WriteLine("set;");
} else {
if (property.HasGet) {
output.Write("get");
OutputStartBrace();
++Indent;
GenerateStatements(property.GetStatements);
--Indent;
output.WriteLine('}');
}
if (property.HasSet) {
output.Write("set");
OutputStartBrace();
++Indent;
GenerateStatements(property.SetStatements);
--Indent;
output.WriteLine('}');
}
}
--Indent;
output.WriteLine('}');
}
protected override void GenerateConstructor(CodeConstructor constructor, CodeTypeDeclaration declaration) {
if (IsCurrentDelegate || IsCurrentEnum || IsCurrentInterface) {
return;
}
OutputAttributes(constructor.CustomAttributes, null, false);
OutputMemberAccessModifier(constructor.Attributes);
Output.Write(GetSafeName(CurrentTypeName) + "(");
OutputParameters(constructor.Parameters);
Output.Write(")");
if (constructor.BaseConstructorArgs.Count > 0) {
Output.WriteLine(" : ");
Indent += 2;
Output.Write("base(");
OutputExpressionList(constructor.BaseConstructorArgs);
Output.Write(')');
Indent -= 2;
}
if (constructor.ChainedConstructorArgs.Count > 0) {
Output.WriteLine(" : ");
Indent += 2;
Output.Write("this(");
OutputExpressionList(constructor.ChainedConstructorArgs);
Output.Write(')');
Indent -= 2;
}
OutputStartBrace();
Indent++;
GenerateStatements(constructor.Statements);
Indent--;
Output.WriteLine('}');
}
protected override void GenerateTypeConstructor(CodeTypeConstructor constructor) {
if (IsCurrentDelegate || IsCurrentEnum || IsCurrentInterface) {
return;
}
OutputAttributes(constructor.CustomAttributes, null, false);
Output.Write("static " + GetSafeName(CurrentTypeName) + "()");
OutputStartBrace();
Indent++;
GenerateStatements(constructor.Statements);
Indent--;
Output.WriteLine('}');
}
protected override void GenerateTypeStart(CodeTypeDeclaration declaration) {
TextWriter output = Output;
OutputAttributes(declaration.CustomAttributes, null, false);
if (!IsCurrentDelegate) {
OutputTypeAttributes(declaration);
output.Write(GetSafeName(declaration.Name));
GenerateGenericsParameters(declaration.TypeParameters);
IEnumerator enumerator = declaration.BaseTypes.GetEnumerator();
if (enumerator.MoveNext()) {
CodeTypeReference type = (CodeTypeReference)enumerator.Current;
output.Write(" : ");
OutputType(type);
while (enumerator.MoveNext()) {
type = (CodeTypeReference)enumerator.Current;
output.Write(", ");
OutputType(type);
}
}
GenerateGenericsConstraints(declaration.TypeParameters);
OutputStartBrace();
++Indent;
} else {
if ((declaration.TypeAttributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public) {
output.Write("public ");
}
CodeTypeDelegate delegateDecl = (CodeTypeDelegate)declaration;
output.Write("delegate ");
OutputType(delegateDecl.ReturnType);
output.Write(" ");
output.Write(GetSafeName(declaration.Name));
output.Write("(");
OutputParameters(delegateDecl.Parameters);
output.WriteLine(");");
}
}
protected override void GenerateTypeEnd(CodeTypeDeclaration declaration) {
if (!IsCurrentDelegate) {
--Indent;
Output.WriteLine("}");
}
}
protected override void GenerateNamespaceStart(CodeNamespace ns) {
TextWriter output = Output;
string name = ns.Name;
if (name != null && name.Length != 0) {
output.Write("namespace ");
output.Write(GetSafeName(name));
OutputStartBrace();
++Indent;
}
}
protected override void GenerateNamespaceEnd(CodeNamespace ns) {
string name = ns.Name;
if (name != null && name.Length != 0) {
--Indent;
Output.WriteLine("}");
}
}
protected override void GenerateNamespaceImport(CodeNamespaceImport import) {
TextWriter output = Output;
output.Write("using ");
output.Write(GetSafeName(import.Namespace));
output.WriteLine(';');
}
protected override void GenerateAttributeDeclarationsStart(CodeAttributeDeclarationCollection attributes) {
Output.Write('[');
}
protected override void GenerateAttributeDeclarationsEnd(CodeAttributeDeclarationCollection attributes) {
Output.Write(']');
}
private void OutputStartBrace() {
if (Options.BracingStyle == "C") {
Output.WriteLine("");
Output.WriteLine("{");
} else {
Output.WriteLine(" {");
}
}
private void OutputAttributes(CodeAttributeDeclarationCollection attributes, string prefix, bool inline) {
bool params_set = false;
foreach (CodeAttributeDeclaration att in attributes) {
if (att.Name == "System.ParamArrayAttribute") {
params_set = true;
continue;
}
GenerateAttributeDeclarationsStart(attributes);
if (prefix != null) {
Output.Write(prefix);
}
OutputAttributeDeclaration(att);
GenerateAttributeDeclarationsEnd(attributes);
if (inline) {
Output.Write(" ");
} else {
Output.WriteLine();
}
}
if (params_set) {
if (prefix != null)
Output.Write(prefix);
Output.Write("params");
if (inline)
Output.Write(" ");
else
Output.WriteLine();
}
}
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 override void OutputType(CodeTypeReference type) {
Output.Write(GetTypeOutput(type));
}
private void OutputVTableModifier(MemberAttributes attributes) {
if ((attributes & MemberAttributes.VTableMask) == MemberAttributes.New) {
Output.Write("new ");
}
}
protected override void OutputFieldScopeModifier(MemberAttributes attributes) {
switch (attributes & MemberAttributes.ScopeMask) {
case MemberAttributes.Static:
Output.Write("static ");
break;
case MemberAttributes.Const:
Output.Write("const ");
break;
}
}
// Note: this method should in fact be private as in .NET 2.0, the
// CSharpCodeGenerator no longer derives from CodeGenerator but we
// still need to make this change.
protected override void OutputMemberAccessModifier(MemberAttributes attributes) {
switch (attributes & MemberAttributes.AccessMask) {
case MemberAttributes.Assembly:
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;
}
}
// Note: this method should in fact be private as in .NET 2.0, the
// CSharpCodeGenerator no longer derives from CodeGenerator but we
// still need to make this change.
protected override void OutputMemberScopeModifier(MemberAttributes attributes) {
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:
MemberAttributes access = attributes & MemberAttributes.AccessMask;
if (access == MemberAttributes.Assembly || access == MemberAttributes.Family || access == MemberAttributes.Public) {
Output.Write("virtual ");
}
break;
}
}
private void OutputTypeAttributes(CodeTypeDeclaration declaration) {
TextWriter output = Output;
TypeAttributes attributes = declaration.TypeAttributes;
switch (attributes & TypeAttributes.VisibilityMask) {
case TypeAttributes.Public:
case TypeAttributes.NestedPublic:
output.Write("public ");
break;
case TypeAttributes.NestedPrivate:
output.Write("private ");
break;
case TypeAttributes.NotPublic:
case TypeAttributes.NestedFamANDAssem:
case TypeAttributes.NestedAssembly:
output.Write("internal ");
break;
case TypeAttributes.NestedFamily:
output.Write("protected ");
break;
case TypeAttributes.NestedFamORAssem:
output.Write("protected internal ");
break;
}
if ((declaration.Attributes & MemberAttributes.New) != 0)
output.Write("new ");
if (declaration.IsStruct) {
if (declaration.IsPartial) {
output.Write("partial ");
}
output.Write("struct ");
} else if (declaration.IsEnum) {
output.Write("enum ");
} else {
if ((attributes & TypeAttributes.Interface) != 0) {
if (declaration.IsPartial) {
output.Write("partial ");
}
output.Write("interface ");
} else {
if ((attributes & TypeAttributes.Sealed) != 0)
output.Write("sealed ");
if ((attributes & TypeAttributes.Abstract) != 0)
output.Write("abstract ");
if (declaration.IsPartial) {
output.Write("partial ");
}
output.Write("class ");
}
}
}
protected override string QuoteSnippetString(string value) {
// FIXME: this is weird, but works.
string output = value.Replace("\\", "\\\\");
output = output.Replace("\"", "\\\"");
output = output.Replace("\t", "\\t");
output = output.Replace("\r", "\\r");
output = output.Replace("\n", "\\n");
return "\"" + output + "\"";
}
protected override void GeneratePrimitiveExpression(CodePrimitiveExpression e) {
if (e.Value is char) {
this.GenerateCharValue((char)e.Value);
} else if (e.Value is ushort) {
ushort uc = (ushort)e.Value;
Output.Write(uc.ToString(CultureInfo.InvariantCulture));
} else if (e.Value is uint) {
uint ui = (uint)e.Value;
Output.Write(ui.ToString(CultureInfo.InvariantCulture));
Output.Write("u");
} else if (e.Value is ulong) {
ulong ul = (ulong)e.Value;
Output.Write(ul.ToString(CultureInfo.InvariantCulture));
Output.Write("ul");
} else if (e.Value is sbyte) {
sbyte sb = (sbyte)e.Value;
Output.Write(sb.ToString(CultureInfo.InvariantCulture));
} else {
base.GeneratePrimitiveExpression(e);
}
}
private void GenerateCharValue(char c) {
Output.Write('\'');
switch (c) {
case '\0':
Output.Write("\\0");
break;
case '\t':
Output.Write("\\t");
break;
case '\n':
Output.Write("\\n");
break;
case '\r':
Output.Write("\\r");
break;
case '"':
Output.Write("\\\"");
break;
case '\'':
Output.Write("\\'");
break;
case '\\':
Output.Write("\\\\");
break;
case '\u2028':
Output.Write("\\u");
Output.Write(((int)c).ToString("X4", CultureInfo.InvariantCulture));
break;
case '\u2029':
Output.Write("\\u");
Output.Write(((int)c).ToString("X4", CultureInfo.InvariantCulture));
break;
default:
Output.Write(c);
break;
}
Output.Write('\'');
}
protected override void GenerateSingleFloatValue(float f) {
base.GenerateSingleFloatValue(f);
base.Output.Write('F');
}
protected override void GenerateDecimalValue(decimal d) {
base.GenerateDecimalValue(d);
base.Output.Write('m');
}
protected override void GenerateParameterDeclarationExpression(CodeParameterDeclarationExpression e) {
OutputAttributes(e.CustomAttributes, null, true);
OutputDirection(e.Direction);
OutputType(e.Type);
Output.Write(' ');
Output.Write(GetSafeName(e.Name));
}
protected override void GenerateTypeOfExpression(CodeTypeOfExpression e) {
Output.Write("typeof(");
OutputType(e.Type);
Output.Write(")");
}
/*
* ICodeGenerator
*/
protected override string CreateEscapedIdentifier(string value) {
if (value == null)
throw new NullReferenceException("Argument identifier is null.");
return GetSafeName(value);
}
protected override string CreateValidIdentifier(string value) {
if (value == null)
throw new NullReferenceException();
if (keywordsTable == null)
FillKeywordTable();
if (keywordsTable.Contains(value))
return "_" + value;
else
return value;
}
protected override string GetTypeOutput(CodeTypeReference type) {
if ((type.Options & CodeTypeReferenceOptions.GenericTypeParameter) != 0)
return type.BaseType;
string typeOutput = null;
if (type.ArrayElementType != null) {
typeOutput = GetTypeOutput(type.ArrayElementType);
} else {
typeOutput = DetermineTypeOutput(type);
}
int rank = type.ArrayRank;
if (rank > 0) {
typeOutput += '[';
for (--rank; rank > 0; --rank) {
typeOutput += ',';
}
typeOutput += ']';
}
return typeOutput;
}
private string DetermineTypeOutput(CodeTypeReference type) {
string typeOutput = null;
string baseType = type.BaseType;
switch (baseType.ToLower(System.Globalization.CultureInfo.InvariantCulture)) {
case "system.int32":
typeOutput = "int";
break;
case "system.int64":
typeOutput = "long";
break;
case "system.int16":
typeOutput = "short";
break;
case "system.boolean":
typeOutput = "bool";
break;
case "system.char":
typeOutput = "char";
break;
case "system.string":
typeOutput = "string";
break;
case "system.object":
typeOutput = "object";
break;
case "system.void":
typeOutput = "void";
break;
case "system.byte":
typeOutput = "byte";
break;
case "system.sbyte":
typeOutput = "sbyte";
break;
case "system.decimal":
typeOutput = "decimal";
break;
case "system.double":
typeOutput = "double";
break;
case "system.single":
typeOutput = "float";
break;
case "system.uint16":
typeOutput = "ushort";
break;
case "system.uint32":
typeOutput = "uint";
break;
case "system.uint64":
typeOutput = "ulong";
break;
default:
StringBuilder sb = new StringBuilder(baseType.Length);
if ((type.Options & CodeTypeReferenceOptions.GlobalReference) != 0) {
sb.Append("global::");
}
int lastProcessedChar = 0;
for (int i = 0; i < baseType.Length; i++) {
char currentChar = baseType[i];
if (currentChar != '+' && currentChar != '.') {
if (currentChar == '`') {
sb.Append(CreateEscapedIdentifier(baseType.Substring(
lastProcessedChar, i - lastProcessedChar)));
// skip ` character
i++;
// determine number of type arguments to output
int end = i;
while (end < baseType.Length && Char.IsDigit(baseType[end]))
end++;
int typeArgCount = Int32.Parse(baseType.Substring(i, end - i));
// output type arguments
OutputTypeArguments(type.TypeArguments, sb, typeArgCount);
// skip type argument indicator
i = end;
// if next character is . or +, then append .
if ((i < baseType.Length) && ((baseType[i] == '+') || (baseType[i] == '.'))) {
sb.Append('.');
// skip character that we just processed
i++;
}
// save postion of last processed character
lastProcessedChar = i;
}
} else {
sb.Append(CreateEscapedIdentifier(baseType.Substring(
lastProcessedChar, i - lastProcessedChar)));
sb.Append('.');
// skip separator
i++;
// save postion of last processed character
lastProcessedChar = i;
}
}
// add characters that have not yet been processed
if (lastProcessedChar < baseType.Length) {
sb.Append(CreateEscapedIdentifier(baseType.Substring(lastProcessedChar)));
}
typeOutput = sb.ToString();
break;
}
return typeOutput;
}
static bool is_identifier_start_character(char c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || c == '@' || Char.IsLetter(c);
}
static bool is_identifier_part_character(char c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || (c >= '0' && c <= '9') || Char.IsLetter(c);
}
protected override bool IsValidIdentifier(string identifier) {
if (identifier == null || identifier.Length == 0)
return false;
if (keywordsTable == null)
FillKeywordTable();
if (keywordsTable.Contains(identifier))
return false;
if (!is_identifier_start_character(identifier[0]))
return false;
for (int i = 1; i < identifier.Length; i++)
if (!is_identifier_part_character(identifier[i]))
return false;
return true;
}
protected override bool Supports(GeneratorSupport supports) {
return true;
}
protected override void GenerateDirectives(CodeDirectiveCollection directives) {
foreach (CodeDirective d in directives) {
if (d is CodeChecksumPragma) {
GenerateCodeChecksumPragma((CodeChecksumPragma)d);
continue;
}
if (d is CodeRegionDirective) {
GenerateCodeRegionDirective((CodeRegionDirective)d);
continue;
}
throw new NotImplementedException("Unknown CodeDirective");
}
}
void GenerateCodeChecksumPragma(CodeChecksumPragma pragma) {
Output.Write("#pragma checksum ");
Output.Write(QuoteSnippetString(pragma.FileName));
Output.Write(" \"");
Output.Write(pragma.ChecksumAlgorithmId.ToString("B"));
Output.Write("\" \"");
if (pragma.ChecksumData != null) {
foreach (byte b in pragma.ChecksumData) {
Output.Write(b.ToString("X2"));
}
}
Output.WriteLine("\"");
}
void GenerateCodeRegionDirective(CodeRegionDirective region) {
switch (region.RegionMode) {
case CodeRegionMode.Start:
Output.Write("#region ");
Output.WriteLine(region.RegionText);
return;
case CodeRegionMode.End:
Output.WriteLine("#endregion");
return;
}
}
void GenerateGenericsParameters(CodeTypeParameterCollection parameters) {
int count = parameters.Count;
if (count == 0)
return;
Output.Write('<');
for (int i = 0; i < count - 1; ++i) {
Output.Write(parameters[i].Name);
Output.Write(", ");
}
Output.Write(parameters[count - 1].Name);
Output.Write('>');
}
void GenerateGenericsConstraints(CodeTypeParameterCollection parameters) {
int count = parameters.Count;
if (count == 0)
return;
bool indented = false;
for (int i = 0; i < count; i++) {
CodeTypeParameter p = parameters[i];
bool hasConstraints = (p.Constraints.Count != 0);
Output.WriteLine();
if (!hasConstraints && !p.HasConstructorConstraint)
continue;
if (!indented) {
++Indent;
indented = true;
}
Output.Write("where ");
Output.Write(p.Name);
Output.Write(" : ");
for (int j = 0; j < p.Constraints.Count; j++) {
if (j > 0)
Output.Write(", ");
OutputType(p.Constraints[j]);
}
if (p.HasConstructorConstraint) {
if (hasConstraints)
Output.Write(", ");
Output.Write("new");
if (hasConstraints)
Output.Write(" ");
Output.Write("()");
}
}
if (indented)
--Indent;
}
string GetTypeArguments(CodeTypeReferenceCollection collection) {
StringBuilder sb = new StringBuilder(" <");
foreach (CodeTypeReference r in collection) {
sb.Append(GetTypeOutput(r));
sb.Append(", ");
}
sb.Length--;
sb[sb.Length - 1] = '>';
return sb.ToString();
}
private void OutputTypeArguments(CodeTypeReferenceCollection typeArguments, StringBuilder sb, int count) {
if (count == 0) {
return;
} else if (typeArguments.Count == 0) {
// generic type definition
sb.Append("<>");
return;
}
sb.Append('<');
// write first type argument
sb.Append(GetTypeOutput(typeArguments[0]));
// subsequent type argument are prefixed by ', ' separator
for (int i = 1; i < count; i++) {
sb.Append(", ");
sb.Append(GetTypeOutput(typeArguments[i]));
}
sb.Append('>');
}
#if false
//[MonoTODO]
public override void ValidateIdentifier (string identifier)
{
}
#endif
private string GetSafeName(string id) {
if (keywordsTable == null) {
FillKeywordTable();
}
if (keywordsTable.Contains(id)) {
return "@" + id;
} else {
return id;
}
}
static void FillKeywordTable() {
lock (keywords) {
if (keywordsTable == null) {
keywordsTable = new Hashtable();
foreach (string keyword in keywords) {
keywordsTable.Add(keyword, keyword);
}
}
}
}
private static Hashtable keywordsTable;
private static string[] keywords = new string[] {
"abstract","event","new","struct","as","explicit","null","switch","base","extern",
"this","false","operator","throw","break","finally","out","true",
"fixed","override","try","case","params","typeof","catch","for",
"private","foreach","protected","checked","goto","public",
"unchecked","class","if","readonly","unsafe","const","implicit","ref",
"continue","in","return","using","virtual","default",
"interface","sealed","volatile","delegate","internal","do","is",
"sizeof","while","lock","stackalloc","else","static","enum",
"namespace",
"object","bool","byte","float","uint","char","ulong","ushort",
"decimal","int","sbyte","short","double","long","string","void",
"partial", "yield", "where"
};
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment