Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / ndp / fx / src / CompMod / Microsoft / CSharp / CSharpCodeProvider.cs / 5 / CSharpCodeProvider.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace Microsoft.CSharp { using System.Diagnostics; using System; using System.IO; using System.Collections; using System.Collections.Specialized; using System.ComponentModel; using System.Reflection; using System.CodeDom; using System.CodeDom.Compiler; using System.Text; using System.Text.RegularExpressions; using System.Globalization; using System.Security.Permissions; using System.Security.Principal; using System.Collections.Generic; ////// [PermissionSet(SecurityAction.LinkDemand, Name="FullTrust")] [PermissionSet(SecurityAction.InheritanceDemand, Name="FullTrust")] public class CSharpCodeProvider: CodeDomProvider { private CSharpCodeGenerator generator; public CSharpCodeProvider() { generator = new CSharpCodeGenerator(); } public CSharpCodeProvider(IDictionary[To be supplied.] ///providerOptions) { if (providerOptions == null) { throw new ArgumentNullException("providerOptions"); } generator = new CSharpCodeGenerator(providerOptions); } /// /// public override string FileExtension { get { return "cs"; } } [Obsolete("Callers should not use the ICodeGenerator interface and should instead use the methods directly on the CodeDomProvider class.")] public override ICodeGenerator CreateGenerator() { return (ICodeGenerator)generator; } [Obsolete("Callers should not use the ICodeCompiler interface and should instead use the methods directly on the CodeDomProvider class.")] public override ICodeCompiler CreateCompiler() { return (ICodeCompiler)generator; } ///Retrieves the default extension to use when saving files using this code dom provider. ////// This method allows a code dom provider implementation to provide a different type converter /// for a given data type. At design time, a designer may pass data types through this /// method to see if the code dom provider wants to provide an additional converter. /// A typical way this would be used is if the language this code dom provider implements /// does not support all of the values of the MemberAttributes enumeration, or if the language /// uses different names (Protected instead of Family, for example). The default /// implementation just calls TypeDescriptor.GetConverter for the given type. /// public override TypeConverter GetConverter(Type type) { if (type == typeof(MemberAttributes)) { return CSharpMemberAttributeConverter.Default; } else if (type == typeof(TypeAttributes)) { return CSharpTypeAttributeConverter.Default; } return base.GetConverter(type); } public override void GenerateCodeFromMember(CodeTypeMember member, TextWriter writer, CodeGeneratorOptions options) { generator.GenerateCodeFromMember(member, writer, options); } } ////// internal class CSharpCodeGenerator : ICodeCompiler, ICodeGenerator{ private IndentedTextWriter output; private CodeGeneratorOptions options; private CodeTypeDeclaration currentClass; private CodeTypeMember currentMember; private bool inNestedBinary = false; private IDictionary/// C# (C Sharp) Code Generator. /// ///provOptions; private const int ParameterMultilineThreshold = 15; private const int MaxLineLength = 80; private const GeneratorSupport LanguageSupport = GeneratorSupport.ArraysOfArrays | GeneratorSupport.EntryPointMethod | GeneratorSupport.GotoStatements | GeneratorSupport.MultidimensionalArrays | GeneratorSupport.StaticConstructors | GeneratorSupport.TryCatchStatements | GeneratorSupport.ReturnTypeAttributes | GeneratorSupport.AssemblyAttributes | GeneratorSupport.DeclareValueTypes | GeneratorSupport.DeclareEnums | GeneratorSupport.DeclareEvents | GeneratorSupport.DeclareDelegates | GeneratorSupport.DeclareInterfaces | GeneratorSupport.ParameterAttributes | GeneratorSupport.ReferenceParameters | GeneratorSupport.ChainedConstructorArguments | GeneratorSupport.NestedTypes | GeneratorSupport.MultipleInterfaceMembers | GeneratorSupport.PublicStaticMembers | GeneratorSupport.ComplexExpressions | #if !FEATURE_PAL GeneratorSupport.Win32Resources | #endif // !FEATURE_PAL GeneratorSupport.Resources| GeneratorSupport.PartialTypes | GeneratorSupport.GenericTypeReference | GeneratorSupport.GenericTypeDeclaration | GeneratorSupport.DeclareIndexerProperties; private static Regex outputReg; private static readonly string[][] keywords = new string[][] { null, // 1 character new string[] { // 2 characters "as", "do", "if", "in", "is", }, new string[] { // 3 characters "for", "int", "new", "out", "ref", "try", }, new string[] { // 4 characters "base", "bool", "byte", "case", "char", "else", "enum", "goto", "lock", "long", "null", "this", "true", "uint", "void", }, new string[] { // 5 characters "break", "catch", "class", "const", "event", "false", "fixed", "float", "sbyte", "short", "throw", "ulong", "using", "where", "while", "yield", }, new string[] { // 6 characters "double", "extern", "object", "params", "public", "return", "sealed", "sizeof", "static", "string", "struct", "switch", "typeof", "unsafe", "ushort", }, new string[] { // 7 characters "checked", "decimal", "default", "finally", "foreach", "partial", "private", "virtual", }, new string[] { // 8 characters "abstract", "continue", "delegate", "explicit", "implicit", "internal", "operator", "override", "readonly", "volatile", }, new string[] { // 9 characters "__arglist", "__makeref", "__reftype", "interface", "namespace", "protected", "unchecked", }, new string[] { // 10 characters "__refvalue", "stackalloc", }, }; internal CSharpCodeGenerator() { } internal CSharpCodeGenerator(IDictionary providerOptions) { provOptions = providerOptions; } #if DEBUG static CSharpCodeGenerator() { FixedStringLookup.VerifyLookupTable(keywords, false); // Sanity check: try some values; Debug.Assert(IsKeyword("for")); Debug.Assert(!IsKeyword("foR")); Debug.Assert(IsKeyword("operator")); Debug.Assert(!IsKeyword("blah")); } #endif private bool generatingForLoop = false; /// /// private string FileExtension { get { return ".cs"; } } ////// Gets /// or sets the file extension to use for source files. /// ////// #if !PLATFORM_UNIX private string CompilerName { get { return "csc.exe"; } } #else // !PLATFORM_UNIX private string CompilerName { get { return "csc"; } } #endif // !PLATFORM_UNIX ////// Gets or /// sets the name of the compiler executable. /// ////// private string CurrentTypeName { get { if (currentClass != null) { return currentClass.Name; } return "<% unknown %>"; } } private int Indent { get { return output.Indent; } set { output.Indent = value; } } ////// Gets or sets the current class name. /// ////// private bool IsCurrentInterface { get { if (currentClass != null && !(currentClass is CodeTypeDelegate)) { return currentClass.IsInterface; } return false; } } ////// Gets or sets a value indicating whether the current object being /// generated is an interface. /// ////// private bool IsCurrentClass { get { if (currentClass != null && !(currentClass is CodeTypeDelegate)) { return currentClass.IsClass; } return false; } } ////// Gets or sets a value indicating whether the current object being generated /// is a class. /// ////// private bool IsCurrentStruct { get { if (currentClass != null && !(currentClass is CodeTypeDelegate)) { return currentClass.IsStruct; } return false; } } ////// Gets or sets a value indicating whether the current object being generated /// is a struct. /// ////// private bool IsCurrentEnum { get { if (currentClass != null && !(currentClass is CodeTypeDelegate)) { return currentClass.IsEnum; } return false; } } ////// Gets or sets a value indicating whether the current object being generated /// is an enumeration. /// ////// private bool IsCurrentDelegate { get { if (currentClass != null && currentClass is CodeTypeDelegate) { return true; } return false; } } ////// Gets or sets a value indicating whether the current object being generated /// is a delegate. /// ////// private string NullToken { get { return "null"; } } ////// Gets the token used to represent ///. /// /// private CodeGeneratorOptions Options { get { return options; } } private TextWriter Output { get { return output; } } ///[To be supplied.] ////// private string QuoteSnippetStringCStyle(string value) { StringBuilder b = new StringBuilder(value.Length+5); Indentation indentObj = new Indentation((IndentedTextWriter)Output, Indent + 1); b.Append("\""); int i = 0; while(i < value.Length) { switch (value[i]) { case '\r': b.Append("\\r"); break; case '\t': b.Append("\\t"); break; case '\"': b.Append("\\\""); break; case '\'': b.Append("\\\'"); break; case '\\': b.Append("\\\\"); break; case '\0': b.Append("\\0"); break; case '\n': b.Append("\\n"); break; case '\u2028': case '\u2029': AppendEscapedChar(b,value[i]); break; default: b.Append(value[i]); break; } if (i > 0 && i % MaxLineLength == 0) { // // If current character is a high surrogate and the following // character is a low surrogate, don't break them. // Otherwise when we write the string to a file, we might lose // the characters. // if( Char.IsHighSurrogate(value[i]) && (i < value.Length -1) && Char.IsLowSurrogate(value[i+1])){ b.Append(value[++i]); } b.Append("\" +\r\n"); b.Append(indentObj.IndentationString); b.Append('\"'); } ++i; } b.Append("\""); return b.ToString(); } private string QuoteSnippetStringVerbatimStyle(string value) { StringBuilder b = new StringBuilder(value.Length+5); b.Append("@\""); for (int i=0; i/// Provides conversion to C-style formatting with escape codes. /// ////// /// Provides conversion to formatting with escape codes. /// /// private string QuoteSnippetString(string value) { // If the string is short, use C style quoting (e.g "\r\n") // Also do it if it is too long to fit in one line // If the string contains '\0', verbatim style won't work. if (value.Length < 256 || value.Length > 1500 || (value.IndexOf('\0') != -1)) return QuoteSnippetStringCStyle(value); // Otherwise, use 'verbatim' style quoting (e.g. @"foo") return QuoteSnippetStringVerbatimStyle(value); } ////// private void ProcessCompilerOutputLine(CompilerResults results, string line) { if (outputReg == null) outputReg = new Regex(@"(^([^(]+)(\(([0-9]+),([0-9]+)\))?: )?(error|warning) ([A-Z]+[0-9]+) ?: (.*)"); Match m = outputReg.Match(line); if (m.Success) { CompilerError ce = new CompilerError(); // The second element is the optional section if the error can be traced to a file. // Without it, the file name is meaningless. if (m.Groups[3].Success) { ce.FileName = m.Groups[2].Value; ce.Line = int.Parse(m.Groups[4].Value, CultureInfo.InvariantCulture); ce.Column = int.Parse(m.Groups[5].Value, CultureInfo.InvariantCulture); } if (string.Compare(m.Groups[6].Value, "warning", StringComparison.OrdinalIgnoreCase) == 0) { ce.IsWarning = true; } ce.ErrorNumber = m.Groups[7].Value; ce.ErrorText = m.Groups[8].Value; results.Errors.Add(ce); } } ////// Processes the ///returned from compilation. /// /// private string CmdArgsFromParameters(CompilerParameters options) { StringBuilder sb = new StringBuilder(128); if (options.GenerateExecutable) { sb.Append("/t:exe "); if (options.MainClass != null && options.MainClass.Length > 0) { sb.Append("/main:"); sb.Append(options.MainClass); sb.Append(" "); } } else { sb.Append("/t:library "); } // Get UTF8 output from the compiler sb.Append("/utf8output "); foreach (string s in options.ReferencedAssemblies) { sb.Append("/R:"); sb.Append("\""); sb.Append(s); sb.Append("\""); sb.Append(" "); } sb.Append("/out:"); sb.Append("\""); sb.Append(options.OutputAssembly); sb.Append("\""); sb.Append(" "); if (options.IncludeDebugInformation) { sb.Append("/D:DEBUG "); sb.Append("/debug+ "); sb.Append("/optimize- "); } else { sb.Append("/debug- "); sb.Append("/optimize+ "); } #if !FEATURE_PAL if (options.Win32Resource != null) { sb.Append("/win32res:\"" + options.Win32Resource + "\" "); } #endif // !FEATURE_PAL foreach (string s in options.EmbeddedResources) { sb.Append("/res:\""); sb.Append(s); sb.Append("\" "); } foreach (string s in options.LinkedResources) { sb.Append("/linkres:\""); sb.Append(s); sb.Append("\" "); } if (options.TreatWarningsAsErrors) { sb.Append("/warnaserror "); } if (options.WarningLevel >= 0) { sb.Append("/w:" + options.WarningLevel + " "); } if (options.CompilerOptions != null) { sb.Append(options.CompilerOptions + " "); } return sb.ToString(); } ////// Gets the command arguments from the specified ///. /// /// private void ContinueOnNewLine(string st) { Output.WriteLine(st); } ///[To be supplied.] ////// private string GetResponseFileCmdArgs(CompilerParameters options, string cmdArgs) { string responseFileName = options.TempFiles.AddExtension("cmdline"); Stream temp = new FileStream(responseFileName, FileMode.Create, FileAccess.Write, FileShare.Read); try { using (StreamWriter sw = new StreamWriter(temp, Encoding.UTF8)) { sw.Write(cmdArgs); sw.Flush(); } } finally { temp.Close(); } // Always specify the /noconfig flag (outside of the response file) return "/noconfig /fullpaths @\"" + responseFileName + "\""; } private void OutputIdentifier(string ident) { Output.Write(CreateEscapedIdentifier(ident)); } ///[To be supplied.] ////// private void OutputType(CodeTypeReference typeRef) { Output.Write(GetTypeOutput(typeRef)); } ////// Sets the output type. /// ////// private void GenerateArrayCreateExpression(CodeArrayCreateExpression e) { Output.Write("new "); CodeExpressionCollection init = e.Initializers; if (init.Count > 0) { OutputType(e.CreateType); if (e.CreateType.ArrayRank == 0) { // Unfortunately, many clients are already calling this without array // types. This will allow new clients to correctly use the array type and // not break existing clients. For VNext, stop doing this. Output.Write("[]"); } Output.WriteLine(" {"); Indent++; OutputExpressionList(init, true /*newlineBetweenItems*/); Indent--; Output.Write("}"); } else { Output.Write(GetBaseTypeOutput(e.CreateType)); Output.Write("["); if (e.SizeExpression != null) { GenerateExpression(e.SizeExpression); } else { Output.Write(e.Size); } Output.Write("]"); } } ////// Generates code for /// the specified CodeDom based array creation expression representation. /// ////// private void GenerateBaseReferenceExpression(CodeBaseReferenceExpression e) { Output.Write("base"); } ////// Generates /// code for the specified CodeDom based base reference expression /// representation. /// ////// private void GenerateBinaryOperatorExpression(CodeBinaryOperatorExpression e) { bool indentedExpression = false; Output.Write("("); GenerateExpression(e.Left); Output.Write(" "); if (e.Left is CodeBinaryOperatorExpression || e.Right is CodeBinaryOperatorExpression) { // In case the line gets too long with nested binary operators, we need to output them on // different lines. However we want to indent them to maintain readability, but this needs // to be done only once; if (!inNestedBinary) { indentedExpression = true; inNestedBinary = true; Indent += 3; } ContinueOnNewLine(""); } OutputOperator(e.Operator); Output.Write(" "); GenerateExpression(e.Right); Output.Write(")"); if (indentedExpression) { Indent -= 3; inNestedBinary = false; } } ////// Generates code for the specified CodeDom based binary operator /// expression representation. /// ////// private void GenerateCastExpression(CodeCastExpression e) { Output.Write("(("); OutputType(e.TargetType); Output.Write(")("); GenerateExpression(e.Expression); Output.Write("))"); } public void GenerateCodeFromMember(CodeTypeMember member, TextWriter writer, CodeGeneratorOptions options) { if (this.output != null) { throw new InvalidOperationException(SR.GetString(SR.CodeGenReentrance)); } this.options = (options == null) ? new CodeGeneratorOptions() : options; this.output = new IndentedTextWriter(writer, this.options.IndentString); try { CodeTypeDeclaration dummyClass = new CodeTypeDeclaration(); this.currentClass = dummyClass; GenerateTypeMember(member, dummyClass); } finally { this.currentClass = null; this.output = null; this.options = null; } } private void GenerateDefaultValueExpression(CodeDefaultValueExpression e) { Output.Write("default("); OutputType(e.Type); Output.Write(")"); } ////// Generates code for the specified CodeDom based cast expression /// representation. /// ////// private void GenerateDelegateCreateExpression(CodeDelegateCreateExpression e) { Output.Write("new "); OutputType(e.DelegateType); Output.Write("("); GenerateExpression(e.TargetObject); Output.Write("."); OutputIdentifier(e.MethodName); Output.Write(")"); } private void GenerateEvents(CodeTypeDeclaration e) { IEnumerator en = e.Members.GetEnumerator(); while (en.MoveNext()) { if (en.Current is CodeMemberEvent) { currentMember = (CodeTypeMember)en.Current; if (options.BlankLinesBetweenMembers) { Output.WriteLine(); } if (currentMember.StartDirectives.Count > 0) { GenerateDirectives(currentMember.StartDirectives); } GenerateCommentStatements(currentMember.Comments); CodeMemberEvent imp = (CodeMemberEvent)en.Current; if (imp.LinePragma != null) GenerateLinePragmaStart(imp.LinePragma); GenerateEvent(imp, e); if (imp.LinePragma != null) GenerateLinePragmaEnd(imp.LinePragma); if (currentMember.EndDirectives.Count > 0) { GenerateDirectives(currentMember.EndDirectives); } } } } private void GenerateFields(CodeTypeDeclaration e) { IEnumerator en = e.Members.GetEnumerator(); while (en.MoveNext()) { if (en.Current is CodeMemberField) { currentMember = (CodeTypeMember)en.Current; if (options.BlankLinesBetweenMembers) { Output.WriteLine(); } if (currentMember.StartDirectives.Count > 0) { GenerateDirectives(currentMember.StartDirectives); } GenerateCommentStatements(currentMember.Comments); CodeMemberField imp = (CodeMemberField)en.Current; if (imp.LinePragma != null) GenerateLinePragmaStart(imp.LinePragma); GenerateField(imp); if (imp.LinePragma != null) GenerateLinePragmaEnd(imp.LinePragma); if (currentMember.EndDirectives.Count > 0) { GenerateDirectives(currentMember.EndDirectives); } } } } ////// Generates code for the specified CodeDom based delegate creation /// expression representation. /// ////// private void GenerateFieldReferenceExpression(CodeFieldReferenceExpression e) { if (e.TargetObject != null) { GenerateExpression(e.TargetObject); Output.Write("."); } OutputIdentifier(e.FieldName); } private void GenerateArgumentReferenceExpression(CodeArgumentReferenceExpression e) { OutputIdentifier(e.ParameterName); } private void GenerateVariableReferenceExpression(CodeVariableReferenceExpression e) { OutputIdentifier(e.VariableName); } ////// Generates code for the specified CodeDom based field reference expression /// representation. /// ////// private void GenerateIndexerExpression(CodeIndexerExpression e) { GenerateExpression(e.TargetObject); Output.Write("["); bool first = true; foreach(CodeExpression exp in e.Indices) { if (first) { first = false; } else { Output.Write(", "); } GenerateExpression(exp); } Output.Write("]"); } private void GenerateArrayIndexerExpression(CodeArrayIndexerExpression e) { GenerateExpression(e.TargetObject); Output.Write("["); bool first = true; foreach(CodeExpression exp in e.Indices) { if (first) { first = false; } else { Output.Write(", "); } GenerateExpression(exp); } Output.Write("]"); } ////// Generates code for the specified CodeDom based indexer expression /// representation. /// ////// private void GenerateSnippetCompileUnit(CodeSnippetCompileUnit e) { GenerateDirectives(e.StartDirectives); if (e.LinePragma != null) GenerateLinePragmaStart(e.LinePragma); Output.WriteLine(e.Value); if (e.LinePragma != null) GenerateLinePragmaEnd(e.LinePragma); if (e.EndDirectives.Count > 0) { GenerateDirectives(e.EndDirectives); } } ///Generates code for the specified snippet code block /// ////// private void GenerateSnippetExpression(CodeSnippetExpression e) { Output.Write(e.Value); } ////// Generates code for the specified CodeDom based snippet expression /// representation. /// ////// private void GenerateMethodInvokeExpression(CodeMethodInvokeExpression e) { GenerateMethodReferenceExpression(e.Method); Output.Write("("); OutputExpressionList(e.Parameters); Output.Write(")"); } private void GenerateMethodReferenceExpression(CodeMethodReferenceExpression e) { if (e.TargetObject != null) { if (e.TargetObject is CodeBinaryOperatorExpression) { Output.Write("("); GenerateExpression(e.TargetObject); Output.Write(")"); } else { GenerateExpression(e.TargetObject); } Output.Write("."); } OutputIdentifier(e.MethodName); if( e.TypeArguments.Count > 0) { Output.Write(GetTypeArgumentsOutput(e.TypeArguments)); } } private bool GetUserData(CodeObject e, string property, bool defaultValue) { object o = e.UserData[property]; if (o != null && o is bool) { return (bool)o; } return defaultValue; } private void GenerateNamespace(CodeNamespace e) { GenerateCommentStatements(e.Comments); GenerateNamespaceStart(e); if (GetUserData(e, "GenerateImports", true)) { GenerateNamespaceImports(e); } Output.WriteLine(""); GenerateTypes(e); GenerateNamespaceEnd(e); } ////// Generates code for the specified CodeDom based method invoke expression /// representation. /// ////// private void GenerateStatement(CodeStatement e) { if (e.StartDirectives.Count > 0) { GenerateDirectives(e.StartDirectives); } if (e.LinePragma != null) { GenerateLinePragmaStart(e.LinePragma); } if (e is CodeCommentStatement) { GenerateCommentStatement((CodeCommentStatement)e); } else if (e is CodeMethodReturnStatement) { GenerateMethodReturnStatement((CodeMethodReturnStatement)e); } else if (e is CodeConditionStatement) { GenerateConditionStatement((CodeConditionStatement)e); } else if (e is CodeTryCatchFinallyStatement) { GenerateTryCatchFinallyStatement((CodeTryCatchFinallyStatement)e); } else if (e is CodeAssignStatement) { GenerateAssignStatement((CodeAssignStatement)e); } else if (e is CodeExpressionStatement) { GenerateExpressionStatement((CodeExpressionStatement)e); } else if (e is CodeIterationStatement) { GenerateIterationStatement((CodeIterationStatement)e); } else if (e is CodeThrowExceptionStatement) { GenerateThrowExceptionStatement((CodeThrowExceptionStatement)e); } else if (e is CodeSnippetStatement) { // Don't indent snippet statements, in order to preserve the column // information from the original code. This improves the debugging // experience. int savedIndent = Indent; Indent=0; GenerateSnippetStatement((CodeSnippetStatement)e); // Restore the indent Indent=savedIndent; } else if (e is CodeVariableDeclarationStatement) { GenerateVariableDeclarationStatement((CodeVariableDeclarationStatement)e); } else if (e is CodeAttachEventStatement) { GenerateAttachEventStatement((CodeAttachEventStatement)e); } else if (e is CodeRemoveEventStatement) { GenerateRemoveEventStatement((CodeRemoveEventStatement)e); } else if (e is CodeGotoStatement) { GenerateGotoStatement((CodeGotoStatement)e); } else if (e is CodeLabeledStatement) { GenerateLabeledStatement((CodeLabeledStatement)e); } else { throw new ArgumentException(SR.GetString(SR.InvalidElementType, e.GetType().FullName), "e"); } if (e.LinePragma != null) { GenerateLinePragmaEnd(e.LinePragma); } if (e.EndDirectives.Count > 0) { GenerateDirectives(e.EndDirectives); } } ////// Generates code for /// the specified CodeDom based statement representation. /// ////// private void GenerateStatements(CodeStatementCollection stms) { IEnumerator en = stms.GetEnumerator(); while (en.MoveNext()) { ((ICodeGenerator)this).GenerateCodeFromStatement((CodeStatement)en.Current, output.InnerWriter, options); } } ////// Generates code for the specified CodeDom based statement representations. /// ////// private void GenerateNamespaceImports(CodeNamespace e) { IEnumerator en = e.Imports.GetEnumerator(); while (en.MoveNext()) { CodeNamespaceImport imp = (CodeNamespaceImport)en.Current; if (imp.LinePragma != null) GenerateLinePragmaStart(imp.LinePragma); GenerateNamespaceImport(imp); if (imp.LinePragma != null) GenerateLinePragmaEnd(imp.LinePragma); } } private void GenerateEventReferenceExpression(CodeEventReferenceExpression e) { if (e.TargetObject != null) { GenerateExpression(e.TargetObject); Output.Write("."); } OutputIdentifier(e.EventName); } ////// Generates code for the specified CodeDom based namespace import /// representation. /// ////// private void GenerateDelegateInvokeExpression(CodeDelegateInvokeExpression e) { if (e.TargetObject != null) { GenerateExpression(e.TargetObject); } Output.Write("("); OutputExpressionList(e.Parameters); Output.Write(")"); } ////// Generates code for the specified CodeDom based delegate invoke /// expression representation. /// ////// private void GenerateObjectCreateExpression(CodeObjectCreateExpression e) { Output.Write("new "); OutputType(e.CreateType); Output.Write("("); OutputExpressionList(e.Parameters); Output.Write(")"); } ////// Generates code for the specified CodeDom based object creation expression /// representation. /// ////// private void GeneratePrimitiveExpression(CodePrimitiveExpression e) { if (e.Value is char) { GeneratePrimitiveChar((char)e.Value); } else if (e.Value is SByte) { // C# has no literal marker for types smaller than Int32 Output.Write(((SByte)e.Value).ToString(CultureInfo.InvariantCulture)); } else if (e.Value is UInt16) { // C# has no literal marker for types smaller than Int32, and you will // get a conversion error if you use "u" here. Output.Write(((UInt16)e.Value).ToString(CultureInfo.InvariantCulture)); } else if (e.Value is UInt32) { Output.Write(((UInt32)e.Value).ToString(CultureInfo.InvariantCulture)); Output.Write("u"); } else if (e.Value is UInt64) { Output.Write(((UInt64)e.Value).ToString(CultureInfo.InvariantCulture)); Output.Write("ul"); } else { GeneratePrimitiveExpressionBase(e); } } ////// Generates code for the specified CodeDom based primitive expression /// representation. /// ////// private void GeneratePrimitiveExpressionBase(CodePrimitiveExpression e) { if (e.Value == null) { Output.Write(NullToken); } else if (e.Value is string) { Output.Write(QuoteSnippetString((string)e.Value)); } else if (e.Value is char) { Output.Write("'" + e.Value.ToString() + "'"); } else if (e.Value is byte) { Output.Write(((byte)e.Value).ToString(CultureInfo.InvariantCulture)); } else if (e.Value is Int16) { Output.Write(((Int16)e.Value).ToString(CultureInfo.InvariantCulture)); } else if (e.Value is Int32) { Output.Write(((Int32)e.Value).ToString(CultureInfo.InvariantCulture)); } else if (e.Value is Int64) { Output.Write(((Int64)e.Value).ToString(CultureInfo.InvariantCulture)); } else if (e.Value is Single) { GenerateSingleFloatValue((Single)e.Value); } else if (e.Value is Double) { GenerateDoubleValue((Double)e.Value); } else if (e.Value is Decimal) { GenerateDecimalValue((Decimal)e.Value); } else if (e.Value is bool) { if ((bool)e.Value) { Output.Write("true"); } else { Output.Write("false"); } } else { throw new ArgumentException(SR.GetString(SR.InvalidPrimitiveType, e.Value.GetType().ToString())); } } private void GeneratePrimitiveChar(char c) { Output.Write('\''); switch (c) { case '\r': Output.Write("\\r"); break; case '\t': Output.Write("\\t"); break; case '\"': Output.Write("\\\""); break; case '\'': Output.Write("\\\'"); break; case '\\': Output.Write("\\\\"); break; case '\0': Output.Write("\\0"); break; case '\n': Output.Write("\\n"); break; case '\u2028': case '\u2029': case '\u0084': case '\u0085': AppendEscapedChar(null,c); break; default: if(Char.IsSurrogate(c)) { AppendEscapedChar(null,c); } else { Output.Write(c); } break; } Output.Write('\''); } private void AppendEscapedChar(StringBuilder b,char value) { if (b == null) { Output.Write("\\u"); Output.Write(((int)value).ToString("X4", CultureInfo.InvariantCulture)); } else { b.Append("\\u"); b.Append(((int)value).ToString("X4", CultureInfo.InvariantCulture)); } } private void GeneratePropertySetValueReferenceExpression(CodePropertySetValueReferenceExpression e) { Output.Write("value"); } ////// Generates code for the specified CodeDom based primitive expression /// representation. /// ////// private void GenerateThisReferenceExpression(CodeThisReferenceExpression e) { Output.Write("this"); } ////// Generates code for the specified CodeDom based this reference expression /// representation. /// ////// private void GenerateExpressionStatement(CodeExpressionStatement e) { GenerateExpression(e.Expression); if (!generatingForLoop) { Output.WriteLine(";"); } } ////// Generates code for the specified CodeDom based method invoke statement /// representation. /// ////// private void GenerateIterationStatement(CodeIterationStatement e) { generatingForLoop = true; Output.Write("for ("); GenerateStatement(e.InitStatement); Output.Write("; "); GenerateExpression(e.TestExpression); Output.Write("; "); GenerateStatement(e.IncrementStatement); Output.Write(")"); OutputStartingBrace(); generatingForLoop = false; Indent++; GenerateStatements(e.Statements); Indent--; Output.WriteLine("}"); } ////// Generates code for the specified CodeDom based for loop statement /// representation. /// ////// private void GenerateThrowExceptionStatement(CodeThrowExceptionStatement e) { Output.Write("throw"); if (e.ToThrow != null) { Output.Write(" "); GenerateExpression(e.ToThrow); } Output.WriteLine(";"); } private void GenerateComment(CodeComment e) { String commentLineStart = e.DocComment? "///": "//"; Output.Write(commentLineStart); Output.Write(" "); string value = e.Text; for (int i=0; i/// Generates code for the specified CodeDom based throw exception statement /// representation. /// ////// /// Generates code for the specified CodeDom based comment statement /// representation. /// /// private void GenerateCommentStatement(CodeCommentStatement e) { GenerateComment(e.Comment); } ////// private void GenerateCommentStatements(CodeCommentStatementCollection e) { foreach (CodeCommentStatement comment in e) { GenerateCommentStatement(comment); } } ///[To be supplied.] ////// private void GenerateMethodReturnStatement(CodeMethodReturnStatement e) { Output.Write("return"); if (e.Expression != null) { Output.Write(" "); GenerateExpression(e.Expression); } Output.WriteLine(";"); } ////// Generates code for the specified CodeDom based method return statement /// representation. /// ////// private void GenerateConditionStatement(CodeConditionStatement e) { Output.Write("if ("); GenerateExpression(e.Condition); Output.Write(")"); OutputStartingBrace(); Indent++; GenerateStatements(e.TrueStatements); Indent--; CodeStatementCollection falseStatemetns = e.FalseStatements; if (falseStatemetns.Count > 0) { Output.Write("}"); if (Options.ElseOnClosing) { Output.Write(" "); } else { Output.WriteLine(""); } Output.Write("else"); OutputStartingBrace(); Indent++; GenerateStatements(e.FalseStatements); Indent--; } Output.WriteLine("}"); } ////// Generates code for the specified CodeDom based if statement /// representation. /// ////// private void GenerateTryCatchFinallyStatement(CodeTryCatchFinallyStatement e) { Output.Write("try"); OutputStartingBrace(); Indent++; GenerateStatements(e.TryStatements); Indent--; CodeCatchClauseCollection catches = e.CatchClauses; if (catches.Count > 0) { IEnumerator en = catches.GetEnumerator(); while (en.MoveNext()) { Output.Write("}"); if (Options.ElseOnClosing) { Output.Write(" "); } else { Output.WriteLine(""); } CodeCatchClause current = (CodeCatchClause)en.Current; Output.Write("catch ("); OutputType(current.CatchExceptionType); Output.Write(" "); OutputIdentifier(current.LocalName); Output.Write(")"); OutputStartingBrace(); Indent++; GenerateStatements(current.Statements); Indent--; } } CodeStatementCollection finallyStatements = e.FinallyStatements; if (finallyStatements.Count > 0) { Output.Write("}"); if (Options.ElseOnClosing) { Output.Write(" "); } else { Output.WriteLine(""); } Output.Write("finally"); OutputStartingBrace(); Indent++; GenerateStatements(finallyStatements); Indent--; } Output.WriteLine("}"); } ////// Generates code for the specified CodeDom based try catch finally /// statement representation. /// ////// private void GenerateAssignStatement(CodeAssignStatement e) { GenerateExpression(e.Left); Output.Write(" = "); GenerateExpression(e.Right); if (!generatingForLoop) { Output.WriteLine(";"); } } ////// Generates code for the specified CodeDom based assignment statement /// representation. /// ////// private void GenerateAttachEventStatement(CodeAttachEventStatement e) { GenerateEventReferenceExpression(e.Event); Output.Write(" += "); GenerateExpression(e.Listener); Output.WriteLine(";"); } ////// Generates code for the specified CodeDom based attach event statement /// representation. /// ////// private void GenerateRemoveEventStatement(CodeRemoveEventStatement e) { GenerateEventReferenceExpression(e.Event); Output.Write(" -= "); GenerateExpression(e.Listener); Output.WriteLine(";"); } private void GenerateSnippetStatement(CodeSnippetStatement e) { Output.WriteLine(e.Value); } private void GenerateGotoStatement(CodeGotoStatement e) { Output.Write("goto "); Output.Write(e.Label); Output.WriteLine(";"); } private void GenerateLabeledStatement(CodeLabeledStatement e) { Indent--; Output.Write(e.Label); Output.WriteLine(":"); Indent++; if (e.Statement != null) { GenerateStatement(e.Statement); } } ////// Generates code for the specified CodeDom based detach event statement /// representation. /// ////// private void GenerateVariableDeclarationStatement(CodeVariableDeclarationStatement e) { OutputTypeNamePair(e.Type, e.Name); if (e.InitExpression != null) { Output.Write(" = "); GenerateExpression(e.InitExpression); } if (!generatingForLoop) { Output.WriteLine(";"); } } ////// Generates code for the specified CodeDom based variable declaration /// statement representation. /// ////// private void GenerateLinePragmaStart(CodeLinePragma e) { Output.WriteLine(""); Output.Write("#line "); Output.Write(e.LineNumber); Output.Write(" \""); Output.Write(e.FileName); Output.Write("\""); Output.WriteLine(""); } ////// Generates code for the specified CodeDom based line pragma start /// representation. /// ////// private void GenerateLinePragmaEnd(CodeLinePragma e) { Output.WriteLine(); Output.WriteLine("#line default"); Output.WriteLine("#line hidden"); } private void GenerateEvent(CodeMemberEvent e, CodeTypeDeclaration c) { if (IsCurrentDelegate || IsCurrentEnum) return; if (e.CustomAttributes.Count > 0) { GenerateAttributes(e.CustomAttributes); } if (e.PrivateImplementationType == null) { OutputMemberAccessModifier(e.Attributes); } Output.Write("event "); string name = e.Name; if (e.PrivateImplementationType != null) { name = e.PrivateImplementationType.BaseType + "." + name; } OutputTypeNamePair(e.Type, name); Output.WriteLine(";"); } ////// Generates code for the specified CodeDom based line pragma end /// representation. /// ////// private void GenerateExpression(CodeExpression e) { if (e is CodeArrayCreateExpression) { GenerateArrayCreateExpression((CodeArrayCreateExpression)e); } else if (e is CodeBaseReferenceExpression) { GenerateBaseReferenceExpression((CodeBaseReferenceExpression)e); } else if (e is CodeBinaryOperatorExpression) { GenerateBinaryOperatorExpression((CodeBinaryOperatorExpression)e); } else if (e is CodeCastExpression) { GenerateCastExpression((CodeCastExpression)e); } else if (e is CodeDelegateCreateExpression) { GenerateDelegateCreateExpression((CodeDelegateCreateExpression)e); } else if (e is CodeFieldReferenceExpression) { GenerateFieldReferenceExpression((CodeFieldReferenceExpression)e); } else if (e is CodeArgumentReferenceExpression) { GenerateArgumentReferenceExpression((CodeArgumentReferenceExpression)e); } else if (e is CodeVariableReferenceExpression) { GenerateVariableReferenceExpression((CodeVariableReferenceExpression)e); } else if (e is CodeIndexerExpression) { GenerateIndexerExpression((CodeIndexerExpression)e); } else if (e is CodeArrayIndexerExpression) { GenerateArrayIndexerExpression((CodeArrayIndexerExpression)e); } else if (e is CodeSnippetExpression) { GenerateSnippetExpression((CodeSnippetExpression)e); } else if (e is CodeMethodInvokeExpression) { GenerateMethodInvokeExpression((CodeMethodInvokeExpression)e); } else if (e is CodeMethodReferenceExpression) { GenerateMethodReferenceExpression((CodeMethodReferenceExpression)e); } else if (e is CodeEventReferenceExpression) { GenerateEventReferenceExpression((CodeEventReferenceExpression)e); } else if (e is CodeDelegateInvokeExpression) { GenerateDelegateInvokeExpression((CodeDelegateInvokeExpression)e); } else if (e is CodeObjectCreateExpression) { GenerateObjectCreateExpression((CodeObjectCreateExpression)e); } else if (e is CodeParameterDeclarationExpression) { GenerateParameterDeclarationExpression((CodeParameterDeclarationExpression)e); } else if (e is CodeDirectionExpression) { GenerateDirectionExpression((CodeDirectionExpression)e); } else if (e is CodePrimitiveExpression) { GeneratePrimitiveExpression((CodePrimitiveExpression)e); } else if (e is CodePropertyReferenceExpression) { GeneratePropertyReferenceExpression((CodePropertyReferenceExpression)e); } else if (e is CodePropertySetValueReferenceExpression) { GeneratePropertySetValueReferenceExpression((CodePropertySetValueReferenceExpression)e); } else if (e is CodeThisReferenceExpression) { GenerateThisReferenceExpression((CodeThisReferenceExpression)e); } else if (e is CodeTypeReferenceExpression) { GenerateTypeReferenceExpression((CodeTypeReferenceExpression)e); } else if (e is CodeTypeOfExpression) { GenerateTypeOfExpression((CodeTypeOfExpression)e); } else if (e is CodeDefaultValueExpression) { GenerateDefaultValueExpression((CodeDefaultValueExpression)e); } else { if (e == null) { throw new ArgumentNullException("e"); } else { throw new ArgumentException(SR.GetString(SR.InvalidElementType, e.GetType().FullName), "e"); } } } ///Generates code for the specified CodeDom code expression representation. ////// private void GenerateField(CodeMemberField e) { if (IsCurrentDelegate || IsCurrentInterface) return; if (IsCurrentEnum) { if (e.CustomAttributes.Count > 0) { GenerateAttributes(e.CustomAttributes); } OutputIdentifier(e.Name); if (e.InitExpression != null) { Output.Write(" = "); GenerateExpression(e.InitExpression); } Output.WriteLine(","); } else { if (e.CustomAttributes.Count > 0) { GenerateAttributes(e.CustomAttributes); } OutputMemberAccessModifier(e.Attributes); OutputVTableModifier(e.Attributes); OutputFieldScopeModifier(e.Attributes); OutputTypeNamePair(e.Type, e.Name); if (e.InitExpression != null) { Output.Write(" = "); GenerateExpression(e.InitExpression); } Output.WriteLine(";"); } } ////// Generates code for the specified CodeDom /// based field representation. /// ////// private void GenerateSnippetMember(CodeSnippetTypeMember e) { Output.Write(e.Text); } private void GenerateParameterDeclarationExpression(CodeParameterDeclarationExpression e) { if (e.CustomAttributes.Count > 0) { // Parameter attributes should be in-line for readability GenerateAttributes(e.CustomAttributes, null, true); } OutputDirection(e.Direction); OutputTypeNamePair(e.Type, e.Name); } private void GenerateEntryPointMethod(CodeEntryPointMethod e, CodeTypeDeclaration c) { if (e.CustomAttributes.Count > 0) { GenerateAttributes(e.CustomAttributes); } Output.Write("public static "); OutputType(e.ReturnType); Output.Write(" Main()"); OutputStartingBrace(); Indent++; GenerateStatements(e.Statements); Indent--; Output.WriteLine("}"); } private void GenerateMethods(CodeTypeDeclaration e) { IEnumerator en = e.Members.GetEnumerator(); while (en.MoveNext()) { if (en.Current is CodeMemberMethod && !(en.Current is CodeTypeConstructor) && !(en.Current is CodeConstructor)) { currentMember = (CodeTypeMember)en.Current; if (options.BlankLinesBetweenMembers) { Output.WriteLine(); } if (currentMember.StartDirectives.Count > 0) { GenerateDirectives(currentMember.StartDirectives); } GenerateCommentStatements(currentMember.Comments); CodeMemberMethod imp = (CodeMemberMethod)en.Current; if (imp.LinePragma != null) GenerateLinePragmaStart(imp.LinePragma); if (en.Current is CodeEntryPointMethod) { GenerateEntryPointMethod((CodeEntryPointMethod)en.Current, e); } else { GenerateMethod(imp, e); } if (imp.LinePragma != null) GenerateLinePragmaEnd(imp.LinePragma); if (currentMember.EndDirectives.Count > 0) { GenerateDirectives(currentMember.EndDirectives); } } } } ////// Generates code for the specified CodeDom based snippet class member /// representation. /// ////// private void GenerateMethod(CodeMemberMethod e, CodeTypeDeclaration c) { if (!(IsCurrentClass || IsCurrentStruct || IsCurrentInterface)) return; if (e.CustomAttributes.Count > 0) { GenerateAttributes(e.CustomAttributes); } if (e.ReturnTypeCustomAttributes.Count > 0) { GenerateAttributes(e.ReturnTypeCustomAttributes, "return: "); } if (!IsCurrentInterface) { if (e.PrivateImplementationType == null) { OutputMemberAccessModifier(e.Attributes); OutputVTableModifier(e.Attributes); OutputMemberScopeModifier(e.Attributes); } } else { // interfaces still need "new" OutputVTableModifier(e.Attributes); } OutputType(e.ReturnType); Output.Write(" "); if (e.PrivateImplementationType != null) { Output.Write(e.PrivateImplementationType.BaseType); Output.Write("."); } OutputIdentifier(e.Name); OutputTypeParameters(e.TypeParameters); Output.Write("("); OutputParameters(e.Parameters); Output.Write(")"); OutputTypeParameterConstraints(e.TypeParameters); if (!IsCurrentInterface && (e.Attributes & MemberAttributes.ScopeMask) != MemberAttributes.Abstract) { OutputStartingBrace(); Indent++; GenerateStatements(e.Statements); Indent--; Output.WriteLine("}"); } else { Output.WriteLine(";"); } } private void GenerateProperties(CodeTypeDeclaration e) { IEnumerator en = e.Members.GetEnumerator(); while (en.MoveNext()) { if (en.Current is CodeMemberProperty) { currentMember = (CodeTypeMember)en.Current; if (options.BlankLinesBetweenMembers) { Output.WriteLine(); } if (currentMember.StartDirectives.Count > 0) { GenerateDirectives(currentMember.StartDirectives); } GenerateCommentStatements(currentMember.Comments); CodeMemberProperty imp = (CodeMemberProperty)en.Current; if (imp.LinePragma != null) GenerateLinePragmaStart(imp.LinePragma); GenerateProperty(imp, e); if (imp.LinePragma != null) GenerateLinePragmaEnd(imp.LinePragma); if (currentMember.EndDirectives.Count > 0) { GenerateDirectives(currentMember.EndDirectives); } } } } ////// Generates code for the specified CodeDom based member method /// representation. /// ////// private void GenerateProperty(CodeMemberProperty e, CodeTypeDeclaration c) { if (!(IsCurrentClass || IsCurrentStruct || IsCurrentInterface)) return; if (e.CustomAttributes.Count > 0) { GenerateAttributes(e.CustomAttributes); } if (!IsCurrentInterface) { if (e.PrivateImplementationType == null) { OutputMemberAccessModifier(e.Attributes); OutputVTableModifier(e.Attributes); OutputMemberScopeModifier(e.Attributes); } } else { OutputVTableModifier(e.Attributes); } OutputType(e.Type); Output.Write(" "); if (e.PrivateImplementationType != null && !IsCurrentInterface) { Output.Write(e.PrivateImplementationType.BaseType); Output.Write("."); } if (e.Parameters.Count > 0 && String.Compare(e.Name, "Item", StringComparison.OrdinalIgnoreCase) == 0) { Output.Write("this["); OutputParameters(e.Parameters); Output.Write("]"); } else { OutputIdentifier(e.Name); } OutputStartingBrace(); Indent++; if (e.HasGet) { if (IsCurrentInterface || (e.Attributes & MemberAttributes.ScopeMask) == MemberAttributes.Abstract) { Output.WriteLine("get;"); } else { Output.Write("get"); OutputStartingBrace(); Indent++; GenerateStatements(e.GetStatements); Indent--; Output.WriteLine("}"); } } if (e.HasSet) { if (IsCurrentInterface || (e.Attributes & MemberAttributes.ScopeMask) == MemberAttributes.Abstract) { Output.WriteLine("set;"); } else { Output.Write("set"); OutputStartingBrace(); Indent++; GenerateStatements(e.SetStatements); Indent--; Output.WriteLine("}"); } } Indent--; Output.WriteLine("}"); } private void GenerateSingleFloatValue(Single s) { if( float.IsNaN(s)) { Output.Write("float.NaN"); } else if( float.IsNegativeInfinity(s)) { Output.Write("float.NegativeInfinity"); } else if( float.IsPositiveInfinity(s)) { Output.Write("float.PositiveInfinity"); } else { Output.Write(s.ToString(CultureInfo.InvariantCulture)); Output.Write('F'); } } private void GenerateDoubleValue(double d) { if( double.IsNaN(d)) { Output.Write("double.NaN"); } else if( double.IsNegativeInfinity(d)) { Output.Write("double.NegativeInfinity"); } else if( double.IsPositiveInfinity(d)) { Output.Write("double.PositiveInfinity"); } else { Output.Write(d.ToString("R", CultureInfo.InvariantCulture)); } } private void GenerateDecimalValue(Decimal d) { Output.Write(d.ToString(CultureInfo.InvariantCulture)); Output.Write('m'); } private void OutputVTableModifier(MemberAttributes attributes) { switch (attributes & MemberAttributes.VTableMask) { case MemberAttributes.New: Output.Write("new "); break; } } ////// Generates code for the specified CodeDom based property representation. /// ////// private void OutputMemberAccessModifier(MemberAttributes attributes) { switch (attributes & MemberAttributes.AccessMask) { case MemberAttributes.Assembly: Output.Write("internal "); break; case MemberAttributes.FamilyAndAssembly: Output.Write("internal "); /*FamANDAssem*/ 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; } } private void OutputMemberScopeModifier(MemberAttributes attributes) { switch (attributes & MemberAttributes.ScopeMask) { case MemberAttributes.Abstract: Output.Write("abstract "); break; case MemberAttributes.Final: Output.Write(""); break; case MemberAttributes.Static: Output.Write("static "); break; case MemberAttributes.Override: Output.Write("override "); break; default: switch (attributes & MemberAttributes.AccessMask) { case MemberAttributes.Family: case MemberAttributes.Public: case MemberAttributes.Assembly: Output.Write("virtual "); break; default: // nothing; break; } break; } } ////// Generates code for the specified member access modifier. /// ////// private 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; } } private void OutputFieldScopeModifier(MemberAttributes attributes) { switch (attributes & MemberAttributes.ScopeMask) { case MemberAttributes.Final: break; case MemberAttributes.Static: Output.Write("static "); break; case MemberAttributes.Const: Output.Write("const "); break; default: break; } } ////// Generates code for the specified operator. /// ////// private void GeneratePropertyReferenceExpression(CodePropertyReferenceExpression e) { if (e.TargetObject != null) { GenerateExpression(e.TargetObject); Output.Write("."); } OutputIdentifier(e.PropertyName); } private void GenerateConstructors(CodeTypeDeclaration e) { IEnumerator en = e.Members.GetEnumerator(); while (en.MoveNext()) { if (en.Current is CodeConstructor) { currentMember = (CodeTypeMember)en.Current; if (options.BlankLinesBetweenMembers) { Output.WriteLine(); } if (currentMember.StartDirectives.Count > 0) { GenerateDirectives(currentMember.StartDirectives); } GenerateCommentStatements(currentMember.Comments); CodeConstructor imp = (CodeConstructor)en.Current; if (imp.LinePragma != null) GenerateLinePragmaStart(imp.LinePragma); GenerateConstructor(imp, e); if (imp.LinePragma != null) GenerateLinePragmaEnd(imp.LinePragma); if (currentMember.EndDirectives.Count > 0) { GenerateDirectives(currentMember.EndDirectives); } } } } ////// Generates code for the specified CodeDom based property reference /// expression representation. /// ////// private void GenerateConstructor(CodeConstructor e, CodeTypeDeclaration c) { if (!(IsCurrentClass || IsCurrentStruct)) return; if (e.CustomAttributes.Count > 0) { GenerateAttributes(e.CustomAttributes); } OutputMemberAccessModifier(e.Attributes); OutputIdentifier(CurrentTypeName); Output.Write("("); OutputParameters(e.Parameters); Output.Write(")"); CodeExpressionCollection baseArgs = e.BaseConstructorArgs; CodeExpressionCollection thisArgs = e.ChainedConstructorArgs; if (baseArgs.Count > 0) { Output.WriteLine(" : "); Indent++; Indent++; Output.Write("base("); OutputExpressionList(baseArgs); Output.Write(")"); Indent--; Indent--; } if (thisArgs.Count > 0) { Output.WriteLine(" : "); Indent++; Indent++; Output.Write("this("); OutputExpressionList(thisArgs); Output.Write(")"); Indent--; Indent--; } OutputStartingBrace(); Indent++; GenerateStatements(e.Statements); Indent--; Output.WriteLine("}"); } ////// Generates code for the specified CodeDom based constructor /// representation. /// ////// private void GenerateTypeConstructor(CodeTypeConstructor e) { if (!(IsCurrentClass || IsCurrentStruct)) return; if (e.CustomAttributes.Count > 0) { GenerateAttributes(e.CustomAttributes); } Output.Write("static "); Output.Write(CurrentTypeName); Output.Write("()"); OutputStartingBrace(); Indent++; GenerateStatements(e.Statements); Indent--; Output.WriteLine("}"); } ////// Generates code for the specified CodeDom based class constructor /// representation. /// ////// private void GenerateTypeReferenceExpression(CodeTypeReferenceExpression e) { OutputType(e.Type); } ////// Generates code for the specified CodeDom based type reference expression /// representation. /// ////// private void GenerateTypeOfExpression(CodeTypeOfExpression e) { Output.Write("typeof("); OutputType(e.Type); Output.Write(")"); } private void GenerateType(CodeTypeDeclaration e) { currentClass = e; if (e.StartDirectives.Count > 0) { GenerateDirectives(e.StartDirectives); } GenerateCommentStatements(e.Comments); if (e.LinePragma != null) GenerateLinePragmaStart(e.LinePragma); GenerateTypeStart(e); if (Options.VerbatimOrder) { foreach (CodeTypeMember member in e.Members) { GenerateTypeMember(member, e); } } else { GenerateFields(e); GenerateSnippetMembers(e); GenerateTypeConstructors(e); GenerateConstructors(e); GenerateProperties(e); GenerateEvents(e); GenerateMethods(e); GenerateNestedTypes(e); } // Nested types clobber the current class, so reset it. currentClass = e; GenerateTypeEnd(e); if (e.LinePragma != null) GenerateLinePragmaEnd(e.LinePragma); if (e.EndDirectives.Count > 0) { GenerateDirectives(e.EndDirectives); } } ////// Generates code for the specified CodeDom based type of expression /// representation. /// ////// private void GenerateTypes(CodeNamespace e) { foreach (CodeTypeDeclaration c in e.Types) { if (options.BlankLinesBetweenMembers) { Output.WriteLine(); } ((ICodeGenerator)this).GenerateCodeFromType(c, output.InnerWriter, options); } } ///Generates code for the specified CodeDom namespace representation and the classes it /// contains. ////// private void GenerateTypeStart(CodeTypeDeclaration e) { if (e.CustomAttributes.Count > 0) { GenerateAttributes(e.CustomAttributes); } if (IsCurrentDelegate) { switch (e.TypeAttributes & TypeAttributes.VisibilityMask) { case TypeAttributes.Public: Output.Write("public "); break; case TypeAttributes.NotPublic: default: break; } CodeTypeDelegate del = (CodeTypeDelegate)e; Output.Write("delegate "); OutputType(del.ReturnType); Output.Write(" "); OutputIdentifier(e.Name); Output.Write("("); OutputParameters(del.Parameters); Output.WriteLine(");"); } else { OutputTypeAttributes(e); OutputIdentifier(e.Name); OutputTypeParameters(e.TypeParameters); bool first = true; foreach (CodeTypeReference typeRef in e.BaseTypes) { if (first) { Output.Write(" : "); first = false; } else { Output.Write(", "); } OutputType(typeRef); } OutputTypeParameterConstraints(e.TypeParameters); OutputStartingBrace(); Indent++; } } private void GenerateTypeMember(CodeTypeMember member, CodeTypeDeclaration declaredType) { if (options.BlankLinesBetweenMembers) { Output.WriteLine(); } if (member is CodeTypeDeclaration) { ((ICodeGenerator)this).GenerateCodeFromType((CodeTypeDeclaration)member, output.InnerWriter, options); // Nested types clobber the current class, so reset it. currentClass = declaredType; // For nested types, comments and line pragmas are handled separately, so return here return; } if (member.StartDirectives.Count > 0) { GenerateDirectives(member.StartDirectives); } GenerateCommentStatements(member.Comments); if (member.LinePragma != null) { GenerateLinePragmaStart(member.LinePragma); } if (member is CodeMemberField) { GenerateField((CodeMemberField)member); } else if (member is CodeMemberProperty) { GenerateProperty((CodeMemberProperty)member, declaredType); } else if (member is CodeMemberMethod) { if (member is CodeConstructor) { GenerateConstructor((CodeConstructor)member, declaredType); } else if (member is CodeTypeConstructor) { GenerateTypeConstructor((CodeTypeConstructor) member); } else if (member is CodeEntryPointMethod) { GenerateEntryPointMethod((CodeEntryPointMethod)member, declaredType); } else { GenerateMethod((CodeMemberMethod)member, declaredType); } } else if (member is CodeMemberEvent) { GenerateEvent((CodeMemberEvent)member, declaredType); } else if (member is CodeSnippetTypeMember) { // Don't indent snippets, in order to preserve the column // information from the original code. This improves the debugging // experience. int savedIndent = Indent; Indent=0; GenerateSnippetMember((CodeSnippetTypeMember)member); // Restore the indent Indent=savedIndent; // Generate an extra new line at the end of the snippet. // If the snippet is comment and this type only contains comments. // The generated code will not compile. Output.WriteLine(); } if (member.LinePragma != null) { GenerateLinePragmaEnd(member.LinePragma); } if (member.EndDirectives.Count > 0) { GenerateDirectives(member.EndDirectives); } } private void GenerateTypeConstructors(CodeTypeDeclaration e) { IEnumerator en = e.Members.GetEnumerator(); while (en.MoveNext()) { if (en.Current is CodeTypeConstructor) { currentMember = (CodeTypeMember)en.Current; if (options.BlankLinesBetweenMembers) { Output.WriteLine(); } if (currentMember.StartDirectives.Count > 0) { GenerateDirectives(currentMember.StartDirectives); } GenerateCommentStatements(currentMember.Comments); CodeTypeConstructor imp = (CodeTypeConstructor)en.Current; if (imp.LinePragma != null) GenerateLinePragmaStart(imp.LinePragma); GenerateTypeConstructor(imp); if (imp.LinePragma != null) GenerateLinePragmaEnd(imp.LinePragma); if (currentMember.EndDirectives.Count > 0) { GenerateDirectives(currentMember.EndDirectives); } } } } private void GenerateSnippetMembers(CodeTypeDeclaration e) { IEnumerator en = e.Members.GetEnumerator(); bool hasSnippet = false; while (en.MoveNext()) { if (en.Current is CodeSnippetTypeMember) { hasSnippet = true; currentMember = (CodeTypeMember)en.Current; if (options.BlankLinesBetweenMembers) { Output.WriteLine(); } if (currentMember.StartDirectives.Count > 0) { GenerateDirectives(currentMember.StartDirectives); } GenerateCommentStatements(currentMember.Comments); CodeSnippetTypeMember imp = (CodeSnippetTypeMember)en.Current; if (imp.LinePragma != null) GenerateLinePragmaStart(imp.LinePragma); // Don't indent snippets, in order to preserve the column // information from the original code. This improves the debugging // experience. int savedIndent = Indent; Indent=0; GenerateSnippetMember(imp); // Restore the indent Indent=savedIndent; if (imp.LinePragma != null) GenerateLinePragmaEnd(imp.LinePragma); if (currentMember.EndDirectives.Count > 0) { GenerateDirectives(currentMember.EndDirectives); } } } // Generate an extra new line at the end of the snippet. // If the snippet is comment and this type only contains comments. // The generated code will not compile. if(hasSnippet) { Output.WriteLine(); } } private void GenerateNestedTypes(CodeTypeDeclaration e) { IEnumerator en = e.Members.GetEnumerator(); while (en.MoveNext()) { if (en.Current is CodeTypeDeclaration) { if (options.BlankLinesBetweenMembers) { Output.WriteLine(); } CodeTypeDeclaration currentClass = (CodeTypeDeclaration)en.Current; ((ICodeGenerator)this).GenerateCodeFromType(currentClass, output.InnerWriter, options); } } } ////// Generates code for the specified CodeDom based class start /// representation. /// ////// private void GenerateNamespaces(CodeCompileUnit e) { foreach (CodeNamespace n in e.Namespaces) { ((ICodeGenerator)this).GenerateCodeFromNamespace(n, output.InnerWriter, options); } } ///Generates code for the namepsaces in the specifield CodeDom compile unit. /// ////// private void OutputAttributeArgument(CodeAttributeArgument arg) { if (arg.Name != null && arg.Name.Length > 0) { OutputIdentifier(arg.Name); Output.Write("="); } ((ICodeGenerator)this).GenerateCodeFromExpression(arg.Value, output.InnerWriter, options); } ////// Outputs an argument in a attribute block. /// ////// private void OutputDirection(FieldDirection dir) { switch (dir) { case FieldDirection.In: break; case FieldDirection.Out: Output.Write("out "); break; case FieldDirection.Ref: Output.Write("ref "); break; } } ////// Generates code for the specified System.CodeDom.FieldDirection. /// ////// private void OutputExpressionList(CodeExpressionCollection expressions) { OutputExpressionList(expressions, false /*newlineBetweenItems*/); } ////// Generates code for the specified expression list. /// ////// private void OutputExpressionList(CodeExpressionCollection expressions, bool newlineBetweenItems) { bool first = true; IEnumerator en = expressions.GetEnumerator(); Indent++; while (en.MoveNext()) { if (first) { first = false; } else { if (newlineBetweenItems) ContinueOnNewLine(","); else Output.Write(", "); } ((ICodeGenerator)this).GenerateCodeFromExpression((CodeExpression)en.Current, output.InnerWriter, options); } Indent--; } ////// Generates code for the specified expression list. /// ////// private void OutputParameters(CodeParameterDeclarationExpressionCollection parameters) { bool first = true; bool multiline = parameters.Count > ParameterMultilineThreshold; if (multiline) { Indent += 3; } IEnumerator en = parameters.GetEnumerator(); while (en.MoveNext()) { CodeParameterDeclarationExpression current = (CodeParameterDeclarationExpression)en.Current; if (first) { first = false; } else { Output.Write(", "); } if (multiline) { ContinueOnNewLine(""); } GenerateExpression(current); } if (multiline) { Indent -= 3; } } ////// Generates code for the specified parameters. /// ////// private void OutputTypeNamePair(CodeTypeReference typeRef, string name) { OutputType(typeRef); Output.Write(" "); OutputIdentifier(name); } private void OutputTypeParameters(CodeTypeParameterCollection typeParameters) { if( typeParameters.Count == 0) { return; } Output.Write('<'); bool first = true; for(int i = 0; i < typeParameters.Count; i++) { if( first) { first = false; } else { Output.Write(", "); } if (typeParameters[i].CustomAttributes.Count > 0) { GenerateAttributes(typeParameters[i].CustomAttributes, null, true); Output.Write(' '); } Output.Write(typeParameters[i].Name); } Output.Write('>'); } private void OutputTypeParameterConstraints(CodeTypeParameterCollection typeParameters) { if( typeParameters.Count == 0) { return; } for(int i = 0; i < typeParameters.Count; i++) { // generating something like: "where KeyType: IComparable, IEnumerable" Output.WriteLine(); Indent++; bool first = true; if( typeParameters[i].Constraints.Count > 0) { foreach (CodeTypeReference typeRef in typeParameters[i].Constraints) { if (first) { Output.Write("where "); Output.Write(typeParameters[i].Name); Output.Write(" : "); first = false; } else { Output.Write(", "); } OutputType(typeRef); } } if( typeParameters[i].HasConstructorConstraint) { if( first) { Output.Write("where "); Output.Write(typeParameters[i].Name); Output.Write(" : new()"); } else { Output.Write(", new ()"); } } Indent--; } } private void OutputTypeAttributes(CodeTypeDeclaration e) { if((e.Attributes & MemberAttributes.New) != 0) { Output.Write("new "); } TypeAttributes attributes = e.TypeAttributes; switch(attributes & TypeAttributes.VisibilityMask) { case TypeAttributes.Public: case TypeAttributes.NestedPublic: Output.Write("public "); break; case TypeAttributes.NestedPrivate: Output.Write("private "); break; case TypeAttributes.NestedFamily: Output.Write("protected "); break; case TypeAttributes.NotPublic: case TypeAttributes.NestedAssembly: case TypeAttributes.NestedFamANDAssem: Output.Write("internal "); break; case TypeAttributes.NestedFamORAssem: Output.Write("protected internal "); break; } if (e.IsStruct) { if (e.IsPartial) { Output.Write("partial "); } Output.Write("struct "); } else if (e.IsEnum) { Output.Write("enum "); } else { switch (attributes & TypeAttributes.ClassSemanticsMask) { case TypeAttributes.Class: if ((attributes & TypeAttributes.Sealed) == TypeAttributes.Sealed) { Output.Write("sealed "); } if ((attributes & TypeAttributes.Abstract) == TypeAttributes.Abstract) { Output.Write("abstract "); } if (e.IsPartial) { Output.Write("partial "); } Output.Write("class "); break; case TypeAttributes.Interface: if (e.IsPartial) { Output.Write("partial "); } Output.Write("interface "); break; } } } ////// Generates code for the specified object type and name pair. /// ////// private void GenerateTypeEnd(CodeTypeDeclaration e) { if (!IsCurrentDelegate) { Indent--; Output.WriteLine("}"); } } ////// Generates code for the specified CodeDom based class end representation. /// ////// private void GenerateNamespaceStart(CodeNamespace e) { if (e.Name != null && e.Name.Length > 0) { Output.Write("namespace "); string[] names = e.Name.Split('.'); Debug.Assert( names.Length > 0); OutputIdentifier(names[0]); for( int i = 1; i< names.Length; i++) { Output.Write("."); OutputIdentifier(names[i]); } OutputStartingBrace(); Indent++; } } ////// Generates code for the specified CodeDom based namespace start /// representation. /// ////// private void GenerateCompileUnit(CodeCompileUnit e) { GenerateCompileUnitStart(e); GenerateNamespaces(e); GenerateCompileUnitEnd(e); } ///Generates code for the specified CodeDom /// compile unit representation. ////// private void GenerateCompileUnitStart(CodeCompileUnit e) { if (e.StartDirectives.Count > 0) { GenerateDirectives(e.StartDirectives); } Output.WriteLine("//------------------------------------------------------------------------------"); Output.Write("// <"); Output.WriteLine(SR.GetString(SR.AutoGen_Comment_Line1)); Output.Write("// "); Output.WriteLine(SR.GetString(SR.AutoGen_Comment_Line2)); Output.Write("// "); Output.Write(SR.GetString(SR.AutoGen_Comment_Line3)); Output.WriteLine(System.Environment.Version.ToString()); Output.WriteLine("//"); Output.Write("// "); Output.WriteLine(SR.GetString(SR.AutoGen_Comment_Line4)); Output.Write("// "); Output.WriteLine(SR.GetString(SR.AutoGen_Comment_Line5)); Output.Write("// "); Output.WriteLine(SR.GetString(SR.AutoGen_Comment_Line1)); Output.WriteLine("//------------------------------------------------------------------------------"); Output.WriteLine(""); SortedList importList; // CSharp needs to put assembly attributes after using statements. // Since we need to create a empty namespace even if we don't need it, // using will generated after assembly attributes. importList = new SortedList(StringComparer.Ordinal); foreach (CodeNamespace nspace in e.Namespaces) { if( String.IsNullOrEmpty(nspace.Name)) { // mark the namespace to stop it generating its own import list nspace.UserData["GenerateImports"] = false; // Collect the unique list of imports foreach (CodeNamespaceImport import in nspace.Imports) { if (!importList.Contains(import.Namespace)) { importList.Add(import.Namespace, import.Namespace); } } } } // now output the imports foreach(string import in importList.Keys) { Output.Write("using "); OutputIdentifier(import); Output.WriteLine(";"); } if( importList.Keys.Count > 0) { Output.WriteLine(""); } // in C# the best place to put these is at the top level. if (e.AssemblyCustomAttributes.Count > 0) { GenerateAttributes(e.AssemblyCustomAttributes, "assembly: "); Output.WriteLine(""); } } ////// Generates code for the specified CodeDom based compile unit start /// representation. /// ////// private void GenerateCompileUnitEnd(CodeCompileUnit e) { if (e.EndDirectives.Count > 0) { GenerateDirectives(e.EndDirectives); } } ////// Generates code for the specified CodeDom based compile unit end /// representation. /// ////// private void GenerateDirectionExpression(CodeDirectionExpression e) { OutputDirection(e.Direction); GenerateExpression(e.Expression); } private void GenerateDirectives(CodeDirectiveCollection directives) { for (int i = 0; i < directives.Count; i++) { CodeDirective directive = directives[i]; if (directive is CodeChecksumPragma) { GenerateChecksumPragma((CodeChecksumPragma)directive); } else if (directive is CodeRegionDirective) { GenerateCodeRegionDirective((CodeRegionDirective)directive); } } } private void GenerateChecksumPragma(CodeChecksumPragma checksumPragma) { Output.Write("#pragma checksum \""); Output.Write(checksumPragma.FileName); Output.Write("\" \""); Output.Write(checksumPragma.ChecksumAlgorithmId.ToString("B", CultureInfo.InvariantCulture)); Output.Write("\" \""); if (checksumPragma.ChecksumData != null) { foreach(Byte b in checksumPragma.ChecksumData) { Output.Write(b.ToString("X2", CultureInfo.InvariantCulture)); } } Output.WriteLine("\""); } private void GenerateCodeRegionDirective(CodeRegionDirective regionDirective) { if (regionDirective.RegionMode == CodeRegionMode.Start) { Output.Write("#region "); Output.WriteLine(regionDirective.RegionText); } else if (regionDirective.RegionMode == CodeRegionMode.End) { Output.WriteLine("#endregion"); } } ///[To be supplied.] ////// private void GenerateNamespaceEnd(CodeNamespace e) { if (e.Name != null && e.Name.Length > 0) { Indent--; Output.WriteLine("}"); } } ////// Generates code for the specified CodeDom based namespace end /// representation. /// ////// private void GenerateNamespaceImport(CodeNamespaceImport e) { Output.Write("using "); OutputIdentifier(e.Namespace); Output.WriteLine(";"); } ////// Generates code for the specified CodeDom based namespace import /// representation. /// ////// private void GenerateAttributeDeclarationsStart(CodeAttributeDeclarationCollection attributes) { Output.Write("["); } ////// Generates code for the specified CodeDom based attribute block start /// representation. /// ////// private void GenerateAttributeDeclarationsEnd(CodeAttributeDeclarationCollection attributes) { Output.Write("]"); } private void GenerateAttributes(CodeAttributeDeclarationCollection attributes) { GenerateAttributes(attributes, null, false); } private void GenerateAttributes(CodeAttributeDeclarationCollection attributes, string prefix) { GenerateAttributes(attributes, prefix, false); } private void GenerateAttributes(CodeAttributeDeclarationCollection attributes, string prefix, bool inLine) { if (attributes.Count == 0) return; IEnumerator en = attributes.GetEnumerator(); bool paramArray =false; while (en.MoveNext()) { // we need to convert paramArrayAttribute to params keyword to // make csharp compiler happy. In addition, params keyword needs to be after // other attributes. CodeAttributeDeclaration current = (CodeAttributeDeclaration)en.Current; if( current.Name.Equals("system.paramarrayattribute", StringComparison.OrdinalIgnoreCase)) { paramArray = true; continue; } GenerateAttributeDeclarationsStart(attributes); if (prefix != null) { Output.Write(prefix); } if( current.AttributeType != null) { Output.Write(GetTypeOutput(current.AttributeType)); } Output.Write("("); bool firstArg = true; foreach (CodeAttributeArgument arg in current.Arguments) { if (firstArg) { firstArg = false; } else { Output.Write(", "); } OutputAttributeArgument(arg); } Output.Write(")"); GenerateAttributeDeclarationsEnd(attributes); if (inLine) { Output.Write(" "); } else { Output.WriteLine(); } } if( paramArray) { if (prefix != null) { Output.Write(prefix); } Output.Write("params"); if (inLine) { Output.Write(" "); } else { Output.WriteLine(); } } } static bool IsKeyword(string value) { return FixedStringLookup.Contains(keywords, value, false); } static bool IsPrefixTwoUnderscore(string value) { if( value.Length < 3) { return false; } else { return ((value[0] == '_') && (value[1] == '_') && (value[2] != '_')); } } public bool Supports(GeneratorSupport support) { return ((support & LanguageSupport) == support); } ////// Generates code for the specified CodeDom based attribute block end /// representation. /// ////// public bool IsValidIdentifier(string value) { // identifiers must be 1 char or longer // if (value == null || value.Length == 0) { return false; } if (value.Length > 512) return false; // identifiers cannot be a keyword, unless they are escaped with an '@' // if (value[0] != '@') { if (IsKeyword(value)) return false; } else { value = value.Substring(1); } return CodeGenerator.IsValidLanguageIndependentIdentifier(value); } public void ValidateIdentifier(string value) { if (!IsValidIdentifier(value)) { throw new ArgumentException(SR.GetString(SR.InvalidIdentifier, value)); } } public string CreateValidIdentifier(string name) { if(IsPrefixTwoUnderscore(name)) { name = "_" + name; } while (IsKeyword(name)) { name = "_" + name; } return name; } public string CreateEscapedIdentifier(string name) { // Any identifier started with two consecutive underscores are // reserved by CSharp. if (IsKeyword(name) || IsPrefixTwoUnderscore(name)) { return "@" + name; } return name; } // returns the type name without any array declaration. private string GetBaseTypeOutput(CodeTypeReference typeRef) { string s = typeRef.BaseType; if (s.Length == 0) { s = "void"; return s; } string lowerCaseString = s.ToLower( CultureInfo.InvariantCulture); switch (lowerCaseString) { case "system.int16": s = "short"; break; case "system.int32": s = "int"; break; case "system.int64": s = "long"; break; case "system.string": s = "string"; break; case "system.object": s = "object"; break; case "system.boolean": s = "bool"; break; case "system.void": s = "void"; break; case "system.char": s = "char"; break; case "system.byte": s = "byte"; break; case "system.uint16": s = "ushort"; break; case "system.uint32": s = "uint"; break; case "system.uint64": s = "ulong"; break; case "system.sbyte": s = "sbyte"; break; case "system.single": s = "float"; break; case "system.double": s = "double"; break; case "system.decimal": s = "decimal"; break; default: // replace + with . for nested classes. // StringBuilder sb = new StringBuilder(s.Length + 10); if(typeRef.Options == CodeTypeReferenceOptions.GlobalReference) { sb.Append("global::"); } string baseType = typeRef.BaseType; int lastIndex = 0; int currentTypeArgStart = 0; for (int i=0; i/// Gets whether the specified value is a valid identifier. /// ///= '0' && baseType[i] <='9') { numTypeArgs = numTypeArgs*10 + (baseType[i] - '0'); i++; } GetTypeArgumentsOutput(typeRef.TypeArguments, currentTypeArgStart, numTypeArgs, sb); currentTypeArgStart += numTypeArgs; // Arity can be in the middle of a nested type name, so we might have a . or + after it. // Skip it if so. if (i < baseType.Length && (baseType[i] =='+' || baseType[i] == '.')) { sb.Append('.'); i++; } lastIndex = i; break; } } if (lastIndex < baseType.Length) sb.Append(CreateEscapedIdentifier(baseType.Substring(lastIndex))); return sb.ToString(); } return s; } private String GetTypeArgumentsOutput(CodeTypeReferenceCollection typeArguments) { StringBuilder sb = new StringBuilder(128); GetTypeArgumentsOutput(typeArguments, 0, typeArguments.Count, sb); return sb.ToString(); } private void GetTypeArgumentsOutput(CodeTypeReferenceCollection typeArguments, int start, int length, StringBuilder sb) { sb.Append('<'); bool first = true; for( int i = start; i < start+length; i++) { if( first) { first = false; } else { sb.Append(", "); } // it's possible that we call GetTypeArgumentsOutput with an empty typeArguments collection. This is the case // for open types, so we want to just output the brackets and commas. if (i < typeArguments.Count) sb.Append(GetTypeOutput(typeArguments[i])); } sb.Append('>'); } public string GetTypeOutput(CodeTypeReference typeRef) { string s = String.Empty; CodeTypeReference baseTypeRef = typeRef; while(baseTypeRef.ArrayElementType != null) { baseTypeRef = baseTypeRef.ArrayElementType; } s += GetBaseTypeOutput(baseTypeRef); while(typeRef !=null && typeRef.ArrayRank > 0) { char [] results = new char [typeRef.ArrayRank + 1]; results[0] = '['; results[typeRef.ArrayRank] = ']'; for (int i = 1; i < typeRef.ArrayRank; i++) { results[i] = ','; } s += new string(results); typeRef = typeRef.ArrayElementType; } return s; } private void OutputStartingBrace() { if (Options.BracingStyle == "C") { Output.WriteLine(""); Output.WriteLine("{"); } else { Output.WriteLine(" {"); } } private CompilerResults FromFileBatch(CompilerParameters options, string[] fileNames) { if( options == null) { throw new ArgumentNullException("options"); } if (fileNames == null) throw new ArgumentNullException("fileNames"); new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); string outputFile = null; int retValue = 0; CompilerResults results = new CompilerResults(options.TempFiles); SecurityPermission perm1 = new SecurityPermission(SecurityPermissionFlag.ControlEvidence); perm1.Assert(); try { results.Evidence = options.Evidence; } finally { SecurityPermission.RevertAssert(); } bool createdEmptyAssembly = false; if (options.OutputAssembly == null || options.OutputAssembly.Length == 0) { string extension = (options.GenerateExecutable) ? "exe" : "dll"; options.OutputAssembly = results.TempFiles.AddExtension(extension, !options.GenerateInMemory); // Create an empty assembly. This is so that the file will have permissions that // we can later access with our current credential. If we don't do this, the compiler // could end up creating an assembly that we cannot open. new FileStream(options.OutputAssembly, FileMode.Create, FileAccess.ReadWrite).Close(); createdEmptyAssembly = true; } #if FEATURE_PAL string pdbname = "ildb"; #else string pdbname = "pdb"; #endif // Don't delete pdbs when debug=false but they have specified pdbonly. if (options.CompilerOptions!= null && CultureInfo.InvariantCulture.CompareInfo.IndexOf(options.CompilerOptions,"/debug:pdbonly", CompareOptions.IgnoreCase) != -1) results.TempFiles.AddExtension(pdbname, true); else results.TempFiles.AddExtension(pdbname); string args = CmdArgsFromParameters(options) + " " + JoinStringArray(fileNames, " "); // Use a response file if the compiler supports it string responseFileArgs = GetResponseFileCmdArgs(options, args); string trueArgs = null; if (responseFileArgs != null) { trueArgs = args; args = responseFileArgs; } Compile(options, RedistVersionInfo.GetCompilerPath(provOptions, CompilerName), CompilerName, args, ref outputFile, ref retValue, trueArgs); results.NativeCompilerReturnValue = retValue; // only look for errors/warnings if the compile failed or the caller set the warning level if (retValue != 0 || options.WarningLevel > 0) { FileStream outputStream = new FileStream(outputFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); try { if (outputStream.Length > 0) { // The output of the compiler is in UTF8 StreamReader sr = new StreamReader(outputStream, Encoding.UTF8); string line; do { line = sr.ReadLine(); if (line != null) { results.Output.Add(line); ProcessCompilerOutputLine(results, line); } } while (line != null); } } finally { outputStream.Close(); } // Delete the empty assembly if we created one if (retValue != 0 && createdEmptyAssembly) File.Delete(options.OutputAssembly); } if (!results.Errors.HasErrors && options.GenerateInMemory) { FileStream fs = new FileStream(options.OutputAssembly, FileMode.Open, FileAccess.Read, FileShare.Read); try { int fileLen = (int)fs.Length; byte[] b = new byte[fileLen]; fs.Read(b, 0, fileLen); SecurityPermission perm = new SecurityPermission(SecurityPermissionFlag.ControlEvidence); perm.Assert(); try { results.CompiledAssembly = Assembly.Load(b,null,options.Evidence); } finally { SecurityPermission.RevertAssert(); } } finally { fs.Close(); } } else { results.PathToAssembly = options.OutputAssembly; } return results; } /// CompilerResults ICodeCompiler.CompileAssemblyFromDom(CompilerParameters options, CodeCompileUnit e) { if( options == null) { throw new ArgumentNullException("options"); } try { return FromDom(options, e); } finally { options.TempFiles.SafeDelete(); } } /// CompilerResults ICodeCompiler.CompileAssemblyFromFile(CompilerParameters options, string fileName) { if( options == null) { throw new ArgumentNullException("options"); } try { return FromFile(options, fileName); } finally { options.TempFiles.SafeDelete(); } } /// CompilerResults ICodeCompiler.CompileAssemblyFromSource(CompilerParameters options, string source) { if( options == null) { throw new ArgumentNullException("options"); } try { return FromSource(options, source); } finally { options.TempFiles.SafeDelete(); } } /// CompilerResults ICodeCompiler.CompileAssemblyFromSourceBatch(CompilerParameters options, string[] sources) { if( options == null) { throw new ArgumentNullException("options"); } try { return FromSourceBatch(options, sources); } finally { options.TempFiles.SafeDelete(); } } /// CompilerResults ICodeCompiler.CompileAssemblyFromFileBatch(CompilerParameters options, string[] fileNames) { if( options == null) { throw new ArgumentNullException("options"); } if (fileNames == null) throw new ArgumentNullException("fileNames"); try { // Try opening the files to make sure they exists. This will throw an exception // if it doesn't foreach (string fileName in fileNames) { using (Stream str = File.OpenRead(fileName)) { } } return FromFileBatch(options, fileNames); } finally { options.TempFiles.SafeDelete(); } } /// CompilerResults ICodeCompiler.CompileAssemblyFromDomBatch(CompilerParameters options, CodeCompileUnit[] ea) { if( options == null) { throw new ArgumentNullException("options"); } try { return FromDomBatch(options, ea); } finally { options.TempFiles.SafeDelete(); } } internal void Compile(CompilerParameters options, string compilerDirectory, string compilerExe, string arguments, ref string outputFile, ref int nativeReturnValue, string trueArgs) { string errorFile = null; outputFile = options.TempFiles.AddExtension("out"); // We try to execute the compiler with a full path name. string fullname = Path.Combine(compilerDirectory, compilerExe); if (File.Exists(fullname)) { string trueCmdLine = null; if (trueArgs != null) trueCmdLine = "\"" + fullname + "\" " + trueArgs; nativeReturnValue = Executor.ExecWaitWithCapture(options.SafeUserToken, "\"" + fullname + "\" " + arguments, Environment.CurrentDirectory, options.TempFiles, ref outputFile, ref errorFile, trueCmdLine); } else { throw new InvalidOperationException(SR.GetString(SR.CompilerNotFound, fullname)); } } /// /// private CompilerResults FromDom(CompilerParameters options, CodeCompileUnit e) { if( options == null) { throw new ArgumentNullException("options"); } new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); CodeCompileUnit[] units = new CodeCompileUnit[1]; units[0] = e; return FromDomBatch(options, units); } ////// Compiles the specified compile unit and options, and returns the results /// from the compilation. /// ////// private CompilerResults FromFile(CompilerParameters options, string fileName) { if( options == null) { throw new ArgumentNullException("options"); } if (fileName == null) throw new ArgumentNullException("fileName"); new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); // Try opening the file to make sure it exists. This will throw an exception // if it doesn't using (Stream str = File.OpenRead(fileName)) { } string[] filenames = new string[1]; filenames[0] = fileName; return FromFileBatch(options, filenames); } ////// Compiles the specified file using the specified options, and returns the /// results from the compilation. /// ////// private CompilerResults FromSource(CompilerParameters options, string source) { if( options == null) { throw new ArgumentNullException("options"); } new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); string[] sources = new string[1]; sources[0] = source; return FromSourceBatch(options, sources); } ////// Compiles the specified source code using the specified options, and /// returns the results from the compilation. /// ////// private CompilerResults FromDomBatch(CompilerParameters options, CodeCompileUnit[] ea) { if( options == null) { throw new ArgumentNullException("options"); } if (ea == null) throw new ArgumentNullException("ea"); new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); string[] filenames = new string[ea.Length]; CompilerResults results = null; #if !FEATURE_PAL // the extra try-catch is here to mitigate exception filter injection attacks. try { WindowsImpersonationContext impersonation = Executor.RevertImpersonation(); try { #endif // !FEATURE_PAL for (int i = 0; i < ea.Length; i++) { if (ea[i] == null) continue; // the other two batch methods just work if one element is null, so we'll match that. ResolveReferencedAssemblies(options, ea[i]); filenames[i] = options.TempFiles.AddExtension(i + FileExtension); Stream temp = new FileStream(filenames[i], FileMode.Create, FileAccess.Write, FileShare.Read); try { using (StreamWriter sw = new StreamWriter(temp, Encoding.UTF8)){ ((ICodeGenerator)this).GenerateCodeFromCompileUnit(ea[i], sw, Options); sw.Flush(); } } finally { temp.Close(); } } results = FromFileBatch(options, filenames); #if !FEATURE_PAL } finally { Executor.ReImpersonate(impersonation); } } catch { throw; } #endif // !FEATURE_PAL return results; } ////// Compiles the specified compile units and /// options, and returns the results from the compilation. /// ////// private void ResolveReferencedAssemblies(CompilerParameters options, CodeCompileUnit e) { if (e.ReferencedAssemblies.Count > 0) { foreach(string assemblyName in e.ReferencedAssemblies) { if (!options.ReferencedAssemblies.Contains(assemblyName)) { options.ReferencedAssemblies.Add(assemblyName); } } } } ////// Because CodeCompileUnit and CompilerParameters both have a referenced assemblies /// property, they must be reconciled. However, because you can compile multiple /// compile units with one set of options, it will simply merge them. /// ////// private CompilerResults FromSourceBatch(CompilerParameters options, string[] sources) { if( options == null) { throw new ArgumentNullException("options"); } if (sources == null) throw new ArgumentNullException("sources"); new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); string[] filenames = new string[sources.Length]; CompilerResults results = null; #if !FEATURE_PAL // the extra try-catch is here to mitigate exception filter injection attacks. try { WindowsImpersonationContext impersonation = Executor.RevertImpersonation(); try { #endif // !FEATURE_PAL for (int i = 0; i < sources.Length; i++) { string name = options.TempFiles.AddExtension(i + FileExtension); Stream temp = new FileStream(name, FileMode.Create, FileAccess.Write, FileShare.Read); try { using (StreamWriter sw = new StreamWriter(temp, Encoding.UTF8)) { sw.Write(sources[i]); sw.Flush(); } } finally { temp.Close(); } filenames[i] = name; } results = FromFileBatch(options, filenames); #if !FEATURE_PAL } finally { Executor.ReImpersonate(impersonation); } } catch { throw; } #endif // !FEATURE_PAL return results; } ////// Compiles the specified source code strings using the specified options, and /// returns the results from the compilation. /// ////// private static string JoinStringArray(string[] sa, string separator) { if (sa == null || sa.Length == 0) return String.Empty; if (sa.Length == 1) { return "\"" + sa[0] + "\""; } StringBuilder sb = new StringBuilder(); for (int i = 0; i < sa.Length - 1; i++) { sb.Append("\""); sb.Append(sa[i]); sb.Append("\""); sb.Append(separator); } sb.Append("\""); sb.Append(sa[sa.Length - 1]); sb.Append("\""); return sb.ToString(); } ///Joins the specified string arrays. ///void ICodeGenerator.GenerateCodeFromType(CodeTypeDeclaration e, TextWriter w, CodeGeneratorOptions o) { bool setLocal = false; if (output != null && w != output.InnerWriter) { throw new InvalidOperationException(SR.GetString(SR.CodeGenOutputWriter)); } if (output == null) { setLocal = true; options = (o == null) ? new CodeGeneratorOptions() : o; output = new IndentedTextWriter(w, options.IndentString); } try { GenerateType(e); } finally { if (setLocal) { output = null; options = null; } } } /// void ICodeGenerator.GenerateCodeFromExpression(CodeExpression e, TextWriter w, CodeGeneratorOptions o) { bool setLocal = false; if (output != null && w != output.InnerWriter) { throw new InvalidOperationException(SR.GetString(SR.CodeGenOutputWriter)); } if (output == null) { setLocal = true; options = (o == null) ? new CodeGeneratorOptions() : o; output = new IndentedTextWriter(w, options.IndentString); } try { GenerateExpression(e); } finally { if (setLocal) { output = null; options = null; } } } /// void ICodeGenerator.GenerateCodeFromCompileUnit(CodeCompileUnit e, TextWriter w, CodeGeneratorOptions o) { bool setLocal = false; if (output != null && w != output.InnerWriter) { throw new InvalidOperationException(SR.GetString(SR.CodeGenOutputWriter)); } if (output == null) { setLocal = true; options = (o == null) ? new CodeGeneratorOptions() : o; output = new IndentedTextWriter(w, options.IndentString); } try { if (e is CodeSnippetCompileUnit) { GenerateSnippetCompileUnit((CodeSnippetCompileUnit) e); } else { GenerateCompileUnit(e); } } finally { if (setLocal) { output = null; options = null; } } } /// void ICodeGenerator.GenerateCodeFromNamespace(CodeNamespace e, TextWriter w, CodeGeneratorOptions o) { bool setLocal = false; if (output != null && w != output.InnerWriter) { throw new InvalidOperationException(SR.GetString(SR.CodeGenOutputWriter)); } if (output == null) { setLocal = true; options = (o == null) ? new CodeGeneratorOptions() : o; output = new IndentedTextWriter(w, options.IndentString); } try { GenerateNamespace(e); } finally { if (setLocal) { output = null; options = null; } } } /// void ICodeGenerator.GenerateCodeFromStatement(CodeStatement e, TextWriter w, CodeGeneratorOptions o) { bool setLocal = false; if (output != null && w != output.InnerWriter) { throw new InvalidOperationException(SR.GetString(SR.CodeGenOutputWriter)); } if (output == null) { setLocal = true; options = (o == null) ? new CodeGeneratorOptions() : o; output = new IndentedTextWriter(w, options.IndentString); } try { GenerateStatement(e); } finally { if (setLocal) { output = null; options = null; } } } } internal class CSharpTypeAttributeConverter : CSharpModifierAttributeConverter { private static string[] names; private static object[] values; private static CSharpTypeAttributeConverter defaultConverter; private CSharpTypeAttributeConverter() { // no need to create an instance; use Default } public static CSharpTypeAttributeConverter Default { get { if (defaultConverter == null) { defaultConverter = new CSharpTypeAttributeConverter(); } return defaultConverter; } } /// /// Retrieves an array of names for attributes. /// protected override string[] Names { get { if (names == null) { names = new string[] { "Public", "Internal" }; } return names; } } ////// Retrieves an array of values for attributes. /// protected override object[] Values { get { if (values == null) { values = new object[] { (object)TypeAttributes.Public, (object)TypeAttributes.NotPublic }; } return values; } } protected override object DefaultValue { get { return TypeAttributes.NotPublic; } } } internal class CSharpMemberAttributeConverter : CSharpModifierAttributeConverter { private static string[] names; private static object[] values; private static CSharpMemberAttributeConverter defaultConverter; private CSharpMemberAttributeConverter() { // no need to create an instance; use Default } public static CSharpMemberAttributeConverter Default { get { if (defaultConverter == null) { defaultConverter = new CSharpMemberAttributeConverter(); } return defaultConverter; } } ////// Retrieves an array of names for attributes. /// protected override string[] Names { get { if (names == null) { names = new string[] { "Public", "Protected", "Protected Internal", "Internal", "Private" }; } return names; } } ////// Retrieves an array of values for attributes. /// protected override object[] Values { get { if (values == null) { values = new object[] { (object)MemberAttributes.Public, (object)MemberAttributes.Family, (object)MemberAttributes.FamilyOrAssembly, (object)MemberAttributes.Assembly, (object)MemberAttributes.Private }; } return values; } } protected override object DefaultValue { get { return MemberAttributes.Private; } } } ////// This type converter provides common values for MemberAttributes /// internal abstract class CSharpModifierAttributeConverter : TypeConverter { protected abstract object[] Values { get; } protected abstract string[] Names { get; } protected abstract object DefaultValue { get; } ////// We override this because we can convert from string types. /// public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { if (sourceType == typeof(string)) { return true; } return base.CanConvertFrom(context, sourceType); } ////// Converts the given object to the converter's native type. /// public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { if (value is string) { string name = (string)value; string[] names = Names; for (int i = 0; i < names.Length; i++) { if (names[i].Equals(name)) { return Values[i]; } } } return DefaultValue; } ////// Converts the given object to another type. The most common types to convert /// are to and from a string object. The default implementation will make a call /// to ToString on the object if the object is valid and if the destination /// type is string. If this cannot convert to the desitnation type, this will /// throw a NotSupportedException. /// public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { if (destinationType == null) { throw new ArgumentNullException("destinationType"); } if (destinationType == typeof(string)) { object[] modifiers = Values; for (int i = 0; i < modifiers.Length; i++) { if (modifiers[i].Equals(value)) { return Names[i]; } } return SR.GetString(SR.toStringUnknown); } return base.ConvertTo(context, culture, value, destinationType); } ////// Determines if the list of standard values returned from /// GetStandardValues is an exclusive list. If the list /// is exclusive, then no other values are valid, such as /// in an enum data type. If the list is not exclusive, /// then there are other valid values besides the list of /// standard values GetStandardValues provides. /// public override bool GetStandardValuesExclusive(ITypeDescriptorContext context) { return true; } ////// Determines if this object supports a standard set of values /// that can be picked from a list. /// public override bool GetStandardValuesSupported(ITypeDescriptorContext context) { return true; } ////// Retrieves a collection containing a set of standard values /// for the data type this validator is designed for. This /// will return null if the data type does not support a /// standard set of values. /// public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context) { return new StandardValuesCollection(Values); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace Microsoft.CSharp { using System.Diagnostics; using System; using System.IO; using System.Collections; using System.Collections.Specialized; using System.ComponentModel; using System.Reflection; using System.CodeDom; using System.CodeDom.Compiler; using System.Text; using System.Text.RegularExpressions; using System.Globalization; using System.Security.Permissions; using System.Security.Principal; using System.Collections.Generic; ////// [PermissionSet(SecurityAction.LinkDemand, Name="FullTrust")] [PermissionSet(SecurityAction.InheritanceDemand, Name="FullTrust")] public class CSharpCodeProvider: CodeDomProvider { private CSharpCodeGenerator generator; public CSharpCodeProvider() { generator = new CSharpCodeGenerator(); } public CSharpCodeProvider(IDictionary[To be supplied.] ///providerOptions) { if (providerOptions == null) { throw new ArgumentNullException("providerOptions"); } generator = new CSharpCodeGenerator(providerOptions); } /// /// public override string FileExtension { get { return "cs"; } } [Obsolete("Callers should not use the ICodeGenerator interface and should instead use the methods directly on the CodeDomProvider class.")] public override ICodeGenerator CreateGenerator() { return (ICodeGenerator)generator; } [Obsolete("Callers should not use the ICodeCompiler interface and should instead use the methods directly on the CodeDomProvider class.")] public override ICodeCompiler CreateCompiler() { return (ICodeCompiler)generator; } ///Retrieves the default extension to use when saving files using this code dom provider. ////// This method allows a code dom provider implementation to provide a different type converter /// for a given data type. At design time, a designer may pass data types through this /// method to see if the code dom provider wants to provide an additional converter. /// A typical way this would be used is if the language this code dom provider implements /// does not support all of the values of the MemberAttributes enumeration, or if the language /// uses different names (Protected instead of Family, for example). The default /// implementation just calls TypeDescriptor.GetConverter for the given type. /// public override TypeConverter GetConverter(Type type) { if (type == typeof(MemberAttributes)) { return CSharpMemberAttributeConverter.Default; } else if (type == typeof(TypeAttributes)) { return CSharpTypeAttributeConverter.Default; } return base.GetConverter(type); } public override void GenerateCodeFromMember(CodeTypeMember member, TextWriter writer, CodeGeneratorOptions options) { generator.GenerateCodeFromMember(member, writer, options); } } ////// internal class CSharpCodeGenerator : ICodeCompiler, ICodeGenerator{ private IndentedTextWriter output; private CodeGeneratorOptions options; private CodeTypeDeclaration currentClass; private CodeTypeMember currentMember; private bool inNestedBinary = false; private IDictionary/// C# (C Sharp) Code Generator. /// ///provOptions; private const int ParameterMultilineThreshold = 15; private const int MaxLineLength = 80; private const GeneratorSupport LanguageSupport = GeneratorSupport.ArraysOfArrays | GeneratorSupport.EntryPointMethod | GeneratorSupport.GotoStatements | GeneratorSupport.MultidimensionalArrays | GeneratorSupport.StaticConstructors | GeneratorSupport.TryCatchStatements | GeneratorSupport.ReturnTypeAttributes | GeneratorSupport.AssemblyAttributes | GeneratorSupport.DeclareValueTypes | GeneratorSupport.DeclareEnums | GeneratorSupport.DeclareEvents | GeneratorSupport.DeclareDelegates | GeneratorSupport.DeclareInterfaces | GeneratorSupport.ParameterAttributes | GeneratorSupport.ReferenceParameters | GeneratorSupport.ChainedConstructorArguments | GeneratorSupport.NestedTypes | GeneratorSupport.MultipleInterfaceMembers | GeneratorSupport.PublicStaticMembers | GeneratorSupport.ComplexExpressions | #if !FEATURE_PAL GeneratorSupport.Win32Resources | #endif // !FEATURE_PAL GeneratorSupport.Resources| GeneratorSupport.PartialTypes | GeneratorSupport.GenericTypeReference | GeneratorSupport.GenericTypeDeclaration | GeneratorSupport.DeclareIndexerProperties; private static Regex outputReg; private static readonly string[][] keywords = new string[][] { null, // 1 character new string[] { // 2 characters "as", "do", "if", "in", "is", }, new string[] { // 3 characters "for", "int", "new", "out", "ref", "try", }, new string[] { // 4 characters "base", "bool", "byte", "case", "char", "else", "enum", "goto", "lock", "long", "null", "this", "true", "uint", "void", }, new string[] { // 5 characters "break", "catch", "class", "const", "event", "false", "fixed", "float", "sbyte", "short", "throw", "ulong", "using", "where", "while", "yield", }, new string[] { // 6 characters "double", "extern", "object", "params", "public", "return", "sealed", "sizeof", "static", "string", "struct", "switch", "typeof", "unsafe", "ushort", }, new string[] { // 7 characters "checked", "decimal", "default", "finally", "foreach", "partial", "private", "virtual", }, new string[] { // 8 characters "abstract", "continue", "delegate", "explicit", "implicit", "internal", "operator", "override", "readonly", "volatile", }, new string[] { // 9 characters "__arglist", "__makeref", "__reftype", "interface", "namespace", "protected", "unchecked", }, new string[] { // 10 characters "__refvalue", "stackalloc", }, }; internal CSharpCodeGenerator() { } internal CSharpCodeGenerator(IDictionary providerOptions) { provOptions = providerOptions; } #if DEBUG static CSharpCodeGenerator() { FixedStringLookup.VerifyLookupTable(keywords, false); // Sanity check: try some values; Debug.Assert(IsKeyword("for")); Debug.Assert(!IsKeyword("foR")); Debug.Assert(IsKeyword("operator")); Debug.Assert(!IsKeyword("blah")); } #endif private bool generatingForLoop = false; /// /// private string FileExtension { get { return ".cs"; } } ////// Gets /// or sets the file extension to use for source files. /// ////// #if !PLATFORM_UNIX private string CompilerName { get { return "csc.exe"; } } #else // !PLATFORM_UNIX private string CompilerName { get { return "csc"; } } #endif // !PLATFORM_UNIX ////// Gets or /// sets the name of the compiler executable. /// ////// private string CurrentTypeName { get { if (currentClass != null) { return currentClass.Name; } return "<% unknown %>"; } } private int Indent { get { return output.Indent; } set { output.Indent = value; } } ////// Gets or sets the current class name. /// ////// private bool IsCurrentInterface { get { if (currentClass != null && !(currentClass is CodeTypeDelegate)) { return currentClass.IsInterface; } return false; } } ////// Gets or sets a value indicating whether the current object being /// generated is an interface. /// ////// private bool IsCurrentClass { get { if (currentClass != null && !(currentClass is CodeTypeDelegate)) { return currentClass.IsClass; } return false; } } ////// Gets or sets a value indicating whether the current object being generated /// is a class. /// ////// private bool IsCurrentStruct { get { if (currentClass != null && !(currentClass is CodeTypeDelegate)) { return currentClass.IsStruct; } return false; } } ////// Gets or sets a value indicating whether the current object being generated /// is a struct. /// ////// private bool IsCurrentEnum { get { if (currentClass != null && !(currentClass is CodeTypeDelegate)) { return currentClass.IsEnum; } return false; } } ////// Gets or sets a value indicating whether the current object being generated /// is an enumeration. /// ////// private bool IsCurrentDelegate { get { if (currentClass != null && currentClass is CodeTypeDelegate) { return true; } return false; } } ////// Gets or sets a value indicating whether the current object being generated /// is a delegate. /// ////// private string NullToken { get { return "null"; } } ////// Gets the token used to represent ///. /// /// private CodeGeneratorOptions Options { get { return options; } } private TextWriter Output { get { return output; } } ///[To be supplied.] ////// private string QuoteSnippetStringCStyle(string value) { StringBuilder b = new StringBuilder(value.Length+5); Indentation indentObj = new Indentation((IndentedTextWriter)Output, Indent + 1); b.Append("\""); int i = 0; while(i < value.Length) { switch (value[i]) { case '\r': b.Append("\\r"); break; case '\t': b.Append("\\t"); break; case '\"': b.Append("\\\""); break; case '\'': b.Append("\\\'"); break; case '\\': b.Append("\\\\"); break; case '\0': b.Append("\\0"); break; case '\n': b.Append("\\n"); break; case '\u2028': case '\u2029': AppendEscapedChar(b,value[i]); break; default: b.Append(value[i]); break; } if (i > 0 && i % MaxLineLength == 0) { // // If current character is a high surrogate and the following // character is a low surrogate, don't break them. // Otherwise when we write the string to a file, we might lose // the characters. // if( Char.IsHighSurrogate(value[i]) && (i < value.Length -1) && Char.IsLowSurrogate(value[i+1])){ b.Append(value[++i]); } b.Append("\" +\r\n"); b.Append(indentObj.IndentationString); b.Append('\"'); } ++i; } b.Append("\""); return b.ToString(); } private string QuoteSnippetStringVerbatimStyle(string value) { StringBuilder b = new StringBuilder(value.Length+5); b.Append("@\""); for (int i=0; i/// Provides conversion to C-style formatting with escape codes. /// ////// /// Provides conversion to formatting with escape codes. /// /// private string QuoteSnippetString(string value) { // If the string is short, use C style quoting (e.g "\r\n") // Also do it if it is too long to fit in one line // If the string contains '\0', verbatim style won't work. if (value.Length < 256 || value.Length > 1500 || (value.IndexOf('\0') != -1)) return QuoteSnippetStringCStyle(value); // Otherwise, use 'verbatim' style quoting (e.g. @"foo") return QuoteSnippetStringVerbatimStyle(value); } ////// private void ProcessCompilerOutputLine(CompilerResults results, string line) { if (outputReg == null) outputReg = new Regex(@"(^([^(]+)(\(([0-9]+),([0-9]+)\))?: )?(error|warning) ([A-Z]+[0-9]+) ?: (.*)"); Match m = outputReg.Match(line); if (m.Success) { CompilerError ce = new CompilerError(); // The second element is the optional section if the error can be traced to a file. // Without it, the file name is meaningless. if (m.Groups[3].Success) { ce.FileName = m.Groups[2].Value; ce.Line = int.Parse(m.Groups[4].Value, CultureInfo.InvariantCulture); ce.Column = int.Parse(m.Groups[5].Value, CultureInfo.InvariantCulture); } if (string.Compare(m.Groups[6].Value, "warning", StringComparison.OrdinalIgnoreCase) == 0) { ce.IsWarning = true; } ce.ErrorNumber = m.Groups[7].Value; ce.ErrorText = m.Groups[8].Value; results.Errors.Add(ce); } } ////// Processes the ///returned from compilation. /// /// private string CmdArgsFromParameters(CompilerParameters options) { StringBuilder sb = new StringBuilder(128); if (options.GenerateExecutable) { sb.Append("/t:exe "); if (options.MainClass != null && options.MainClass.Length > 0) { sb.Append("/main:"); sb.Append(options.MainClass); sb.Append(" "); } } else { sb.Append("/t:library "); } // Get UTF8 output from the compiler sb.Append("/utf8output "); foreach (string s in options.ReferencedAssemblies) { sb.Append("/R:"); sb.Append("\""); sb.Append(s); sb.Append("\""); sb.Append(" "); } sb.Append("/out:"); sb.Append("\""); sb.Append(options.OutputAssembly); sb.Append("\""); sb.Append(" "); if (options.IncludeDebugInformation) { sb.Append("/D:DEBUG "); sb.Append("/debug+ "); sb.Append("/optimize- "); } else { sb.Append("/debug- "); sb.Append("/optimize+ "); } #if !FEATURE_PAL if (options.Win32Resource != null) { sb.Append("/win32res:\"" + options.Win32Resource + "\" "); } #endif // !FEATURE_PAL foreach (string s in options.EmbeddedResources) { sb.Append("/res:\""); sb.Append(s); sb.Append("\" "); } foreach (string s in options.LinkedResources) { sb.Append("/linkres:\""); sb.Append(s); sb.Append("\" "); } if (options.TreatWarningsAsErrors) { sb.Append("/warnaserror "); } if (options.WarningLevel >= 0) { sb.Append("/w:" + options.WarningLevel + " "); } if (options.CompilerOptions != null) { sb.Append(options.CompilerOptions + " "); } return sb.ToString(); } ////// Gets the command arguments from the specified ///. /// /// private void ContinueOnNewLine(string st) { Output.WriteLine(st); } ///[To be supplied.] ////// private string GetResponseFileCmdArgs(CompilerParameters options, string cmdArgs) { string responseFileName = options.TempFiles.AddExtension("cmdline"); Stream temp = new FileStream(responseFileName, FileMode.Create, FileAccess.Write, FileShare.Read); try { using (StreamWriter sw = new StreamWriter(temp, Encoding.UTF8)) { sw.Write(cmdArgs); sw.Flush(); } } finally { temp.Close(); } // Always specify the /noconfig flag (outside of the response file) return "/noconfig /fullpaths @\"" + responseFileName + "\""; } private void OutputIdentifier(string ident) { Output.Write(CreateEscapedIdentifier(ident)); } ///[To be supplied.] ////// private void OutputType(CodeTypeReference typeRef) { Output.Write(GetTypeOutput(typeRef)); } ////// Sets the output type. /// ////// private void GenerateArrayCreateExpression(CodeArrayCreateExpression e) { Output.Write("new "); CodeExpressionCollection init = e.Initializers; if (init.Count > 0) { OutputType(e.CreateType); if (e.CreateType.ArrayRank == 0) { // Unfortunately, many clients are already calling this without array // types. This will allow new clients to correctly use the array type and // not break existing clients. For VNext, stop doing this. Output.Write("[]"); } Output.WriteLine(" {"); Indent++; OutputExpressionList(init, true /*newlineBetweenItems*/); Indent--; Output.Write("}"); } else { Output.Write(GetBaseTypeOutput(e.CreateType)); Output.Write("["); if (e.SizeExpression != null) { GenerateExpression(e.SizeExpression); } else { Output.Write(e.Size); } Output.Write("]"); } } ////// Generates code for /// the specified CodeDom based array creation expression representation. /// ////// private void GenerateBaseReferenceExpression(CodeBaseReferenceExpression e) { Output.Write("base"); } ////// Generates /// code for the specified CodeDom based base reference expression /// representation. /// ////// private void GenerateBinaryOperatorExpression(CodeBinaryOperatorExpression e) { bool indentedExpression = false; Output.Write("("); GenerateExpression(e.Left); Output.Write(" "); if (e.Left is CodeBinaryOperatorExpression || e.Right is CodeBinaryOperatorExpression) { // In case the line gets too long with nested binary operators, we need to output them on // different lines. However we want to indent them to maintain readability, but this needs // to be done only once; if (!inNestedBinary) { indentedExpression = true; inNestedBinary = true; Indent += 3; } ContinueOnNewLine(""); } OutputOperator(e.Operator); Output.Write(" "); GenerateExpression(e.Right); Output.Write(")"); if (indentedExpression) { Indent -= 3; inNestedBinary = false; } } ////// Generates code for the specified CodeDom based binary operator /// expression representation. /// ////// private void GenerateCastExpression(CodeCastExpression e) { Output.Write("(("); OutputType(e.TargetType); Output.Write(")("); GenerateExpression(e.Expression); Output.Write("))"); } public void GenerateCodeFromMember(CodeTypeMember member, TextWriter writer, CodeGeneratorOptions options) { if (this.output != null) { throw new InvalidOperationException(SR.GetString(SR.CodeGenReentrance)); } this.options = (options == null) ? new CodeGeneratorOptions() : options; this.output = new IndentedTextWriter(writer, this.options.IndentString); try { CodeTypeDeclaration dummyClass = new CodeTypeDeclaration(); this.currentClass = dummyClass; GenerateTypeMember(member, dummyClass); } finally { this.currentClass = null; this.output = null; this.options = null; } } private void GenerateDefaultValueExpression(CodeDefaultValueExpression e) { Output.Write("default("); OutputType(e.Type); Output.Write(")"); } ////// Generates code for the specified CodeDom based cast expression /// representation. /// ////// private void GenerateDelegateCreateExpression(CodeDelegateCreateExpression e) { Output.Write("new "); OutputType(e.DelegateType); Output.Write("("); GenerateExpression(e.TargetObject); Output.Write("."); OutputIdentifier(e.MethodName); Output.Write(")"); } private void GenerateEvents(CodeTypeDeclaration e) { IEnumerator en = e.Members.GetEnumerator(); while (en.MoveNext()) { if (en.Current is CodeMemberEvent) { currentMember = (CodeTypeMember)en.Current; if (options.BlankLinesBetweenMembers) { Output.WriteLine(); } if (currentMember.StartDirectives.Count > 0) { GenerateDirectives(currentMember.StartDirectives); } GenerateCommentStatements(currentMember.Comments); CodeMemberEvent imp = (CodeMemberEvent)en.Current; if (imp.LinePragma != null) GenerateLinePragmaStart(imp.LinePragma); GenerateEvent(imp, e); if (imp.LinePragma != null) GenerateLinePragmaEnd(imp.LinePragma); if (currentMember.EndDirectives.Count > 0) { GenerateDirectives(currentMember.EndDirectives); } } } } private void GenerateFields(CodeTypeDeclaration e) { IEnumerator en = e.Members.GetEnumerator(); while (en.MoveNext()) { if (en.Current is CodeMemberField) { currentMember = (CodeTypeMember)en.Current; if (options.BlankLinesBetweenMembers) { Output.WriteLine(); } if (currentMember.StartDirectives.Count > 0) { GenerateDirectives(currentMember.StartDirectives); } GenerateCommentStatements(currentMember.Comments); CodeMemberField imp = (CodeMemberField)en.Current; if (imp.LinePragma != null) GenerateLinePragmaStart(imp.LinePragma); GenerateField(imp); if (imp.LinePragma != null) GenerateLinePragmaEnd(imp.LinePragma); if (currentMember.EndDirectives.Count > 0) { GenerateDirectives(currentMember.EndDirectives); } } } } ////// Generates code for the specified CodeDom based delegate creation /// expression representation. /// ////// private void GenerateFieldReferenceExpression(CodeFieldReferenceExpression e) { if (e.TargetObject != null) { GenerateExpression(e.TargetObject); Output.Write("."); } OutputIdentifier(e.FieldName); } private void GenerateArgumentReferenceExpression(CodeArgumentReferenceExpression e) { OutputIdentifier(e.ParameterName); } private void GenerateVariableReferenceExpression(CodeVariableReferenceExpression e) { OutputIdentifier(e.VariableName); } ////// Generates code for the specified CodeDom based field reference expression /// representation. /// ////// private void GenerateIndexerExpression(CodeIndexerExpression e) { GenerateExpression(e.TargetObject); Output.Write("["); bool first = true; foreach(CodeExpression exp in e.Indices) { if (first) { first = false; } else { Output.Write(", "); } GenerateExpression(exp); } Output.Write("]"); } private void GenerateArrayIndexerExpression(CodeArrayIndexerExpression e) { GenerateExpression(e.TargetObject); Output.Write("["); bool first = true; foreach(CodeExpression exp in e.Indices) { if (first) { first = false; } else { Output.Write(", "); } GenerateExpression(exp); } Output.Write("]"); } ////// Generates code for the specified CodeDom based indexer expression /// representation. /// ////// private void GenerateSnippetCompileUnit(CodeSnippetCompileUnit e) { GenerateDirectives(e.StartDirectives); if (e.LinePragma != null) GenerateLinePragmaStart(e.LinePragma); Output.WriteLine(e.Value); if (e.LinePragma != null) GenerateLinePragmaEnd(e.LinePragma); if (e.EndDirectives.Count > 0) { GenerateDirectives(e.EndDirectives); } } ///Generates code for the specified snippet code block /// ////// private void GenerateSnippetExpression(CodeSnippetExpression e) { Output.Write(e.Value); } ////// Generates code for the specified CodeDom based snippet expression /// representation. /// ////// private void GenerateMethodInvokeExpression(CodeMethodInvokeExpression e) { GenerateMethodReferenceExpression(e.Method); Output.Write("("); OutputExpressionList(e.Parameters); Output.Write(")"); } private void GenerateMethodReferenceExpression(CodeMethodReferenceExpression e) { if (e.TargetObject != null) { if (e.TargetObject is CodeBinaryOperatorExpression) { Output.Write("("); GenerateExpression(e.TargetObject); Output.Write(")"); } else { GenerateExpression(e.TargetObject); } Output.Write("."); } OutputIdentifier(e.MethodName); if( e.TypeArguments.Count > 0) { Output.Write(GetTypeArgumentsOutput(e.TypeArguments)); } } private bool GetUserData(CodeObject e, string property, bool defaultValue) { object o = e.UserData[property]; if (o != null && o is bool) { return (bool)o; } return defaultValue; } private void GenerateNamespace(CodeNamespace e) { GenerateCommentStatements(e.Comments); GenerateNamespaceStart(e); if (GetUserData(e, "GenerateImports", true)) { GenerateNamespaceImports(e); } Output.WriteLine(""); GenerateTypes(e); GenerateNamespaceEnd(e); } ////// Generates code for the specified CodeDom based method invoke expression /// representation. /// ////// private void GenerateStatement(CodeStatement e) { if (e.StartDirectives.Count > 0) { GenerateDirectives(e.StartDirectives); } if (e.LinePragma != null) { GenerateLinePragmaStart(e.LinePragma); } if (e is CodeCommentStatement) { GenerateCommentStatement((CodeCommentStatement)e); } else if (e is CodeMethodReturnStatement) { GenerateMethodReturnStatement((CodeMethodReturnStatement)e); } else if (e is CodeConditionStatement) { GenerateConditionStatement((CodeConditionStatement)e); } else if (e is CodeTryCatchFinallyStatement) { GenerateTryCatchFinallyStatement((CodeTryCatchFinallyStatement)e); } else if (e is CodeAssignStatement) { GenerateAssignStatement((CodeAssignStatement)e); } else if (e is CodeExpressionStatement) { GenerateExpressionStatement((CodeExpressionStatement)e); } else if (e is CodeIterationStatement) { GenerateIterationStatement((CodeIterationStatement)e); } else if (e is CodeThrowExceptionStatement) { GenerateThrowExceptionStatement((CodeThrowExceptionStatement)e); } else if (e is CodeSnippetStatement) { // Don't indent snippet statements, in order to preserve the column // information from the original code. This improves the debugging // experience. int savedIndent = Indent; Indent=0; GenerateSnippetStatement((CodeSnippetStatement)e); // Restore the indent Indent=savedIndent; } else if (e is CodeVariableDeclarationStatement) { GenerateVariableDeclarationStatement((CodeVariableDeclarationStatement)e); } else if (e is CodeAttachEventStatement) { GenerateAttachEventStatement((CodeAttachEventStatement)e); } else if (e is CodeRemoveEventStatement) { GenerateRemoveEventStatement((CodeRemoveEventStatement)e); } else if (e is CodeGotoStatement) { GenerateGotoStatement((CodeGotoStatement)e); } else if (e is CodeLabeledStatement) { GenerateLabeledStatement((CodeLabeledStatement)e); } else { throw new ArgumentException(SR.GetString(SR.InvalidElementType, e.GetType().FullName), "e"); } if (e.LinePragma != null) { GenerateLinePragmaEnd(e.LinePragma); } if (e.EndDirectives.Count > 0) { GenerateDirectives(e.EndDirectives); } } ////// Generates code for /// the specified CodeDom based statement representation. /// ////// private void GenerateStatements(CodeStatementCollection stms) { IEnumerator en = stms.GetEnumerator(); while (en.MoveNext()) { ((ICodeGenerator)this).GenerateCodeFromStatement((CodeStatement)en.Current, output.InnerWriter, options); } } ////// Generates code for the specified CodeDom based statement representations. /// ////// private void GenerateNamespaceImports(CodeNamespace e) { IEnumerator en = e.Imports.GetEnumerator(); while (en.MoveNext()) { CodeNamespaceImport imp = (CodeNamespaceImport)en.Current; if (imp.LinePragma != null) GenerateLinePragmaStart(imp.LinePragma); GenerateNamespaceImport(imp); if (imp.LinePragma != null) GenerateLinePragmaEnd(imp.LinePragma); } } private void GenerateEventReferenceExpression(CodeEventReferenceExpression e) { if (e.TargetObject != null) { GenerateExpression(e.TargetObject); Output.Write("."); } OutputIdentifier(e.EventName); } ////// Generates code for the specified CodeDom based namespace import /// representation. /// ////// private void GenerateDelegateInvokeExpression(CodeDelegateInvokeExpression e) { if (e.TargetObject != null) { GenerateExpression(e.TargetObject); } Output.Write("("); OutputExpressionList(e.Parameters); Output.Write(")"); } ////// Generates code for the specified CodeDom based delegate invoke /// expression representation. /// ////// private void GenerateObjectCreateExpression(CodeObjectCreateExpression e) { Output.Write("new "); OutputType(e.CreateType); Output.Write("("); OutputExpressionList(e.Parameters); Output.Write(")"); } ////// Generates code for the specified CodeDom based object creation expression /// representation. /// ////// private void GeneratePrimitiveExpression(CodePrimitiveExpression e) { if (e.Value is char) { GeneratePrimitiveChar((char)e.Value); } else if (e.Value is SByte) { // C# has no literal marker for types smaller than Int32 Output.Write(((SByte)e.Value).ToString(CultureInfo.InvariantCulture)); } else if (e.Value is UInt16) { // C# has no literal marker for types smaller than Int32, and you will // get a conversion error if you use "u" here. Output.Write(((UInt16)e.Value).ToString(CultureInfo.InvariantCulture)); } else if (e.Value is UInt32) { Output.Write(((UInt32)e.Value).ToString(CultureInfo.InvariantCulture)); Output.Write("u"); } else if (e.Value is UInt64) { Output.Write(((UInt64)e.Value).ToString(CultureInfo.InvariantCulture)); Output.Write("ul"); } else { GeneratePrimitiveExpressionBase(e); } } ////// Generates code for the specified CodeDom based primitive expression /// representation. /// ////// private void GeneratePrimitiveExpressionBase(CodePrimitiveExpression e) { if (e.Value == null) { Output.Write(NullToken); } else if (e.Value is string) { Output.Write(QuoteSnippetString((string)e.Value)); } else if (e.Value is char) { Output.Write("'" + e.Value.ToString() + "'"); } else if (e.Value is byte) { Output.Write(((byte)e.Value).ToString(CultureInfo.InvariantCulture)); } else if (e.Value is Int16) { Output.Write(((Int16)e.Value).ToString(CultureInfo.InvariantCulture)); } else if (e.Value is Int32) { Output.Write(((Int32)e.Value).ToString(CultureInfo.InvariantCulture)); } else if (e.Value is Int64) { Output.Write(((Int64)e.Value).ToString(CultureInfo.InvariantCulture)); } else if (e.Value is Single) { GenerateSingleFloatValue((Single)e.Value); } else if (e.Value is Double) { GenerateDoubleValue((Double)e.Value); } else if (e.Value is Decimal) { GenerateDecimalValue((Decimal)e.Value); } else if (e.Value is bool) { if ((bool)e.Value) { Output.Write("true"); } else { Output.Write("false"); } } else { throw new ArgumentException(SR.GetString(SR.InvalidPrimitiveType, e.Value.GetType().ToString())); } } private void GeneratePrimitiveChar(char c) { Output.Write('\''); switch (c) { case '\r': Output.Write("\\r"); break; case '\t': Output.Write("\\t"); break; case '\"': Output.Write("\\\""); break; case '\'': Output.Write("\\\'"); break; case '\\': Output.Write("\\\\"); break; case '\0': Output.Write("\\0"); break; case '\n': Output.Write("\\n"); break; case '\u2028': case '\u2029': case '\u0084': case '\u0085': AppendEscapedChar(null,c); break; default: if(Char.IsSurrogate(c)) { AppendEscapedChar(null,c); } else { Output.Write(c); } break; } Output.Write('\''); } private void AppendEscapedChar(StringBuilder b,char value) { if (b == null) { Output.Write("\\u"); Output.Write(((int)value).ToString("X4", CultureInfo.InvariantCulture)); } else { b.Append("\\u"); b.Append(((int)value).ToString("X4", CultureInfo.InvariantCulture)); } } private void GeneratePropertySetValueReferenceExpression(CodePropertySetValueReferenceExpression e) { Output.Write("value"); } ////// Generates code for the specified CodeDom based primitive expression /// representation. /// ////// private void GenerateThisReferenceExpression(CodeThisReferenceExpression e) { Output.Write("this"); } ////// Generates code for the specified CodeDom based this reference expression /// representation. /// ////// private void GenerateExpressionStatement(CodeExpressionStatement e) { GenerateExpression(e.Expression); if (!generatingForLoop) { Output.WriteLine(";"); } } ////// Generates code for the specified CodeDom based method invoke statement /// representation. /// ////// private void GenerateIterationStatement(CodeIterationStatement e) { generatingForLoop = true; Output.Write("for ("); GenerateStatement(e.InitStatement); Output.Write("; "); GenerateExpression(e.TestExpression); Output.Write("; "); GenerateStatement(e.IncrementStatement); Output.Write(")"); OutputStartingBrace(); generatingForLoop = false; Indent++; GenerateStatements(e.Statements); Indent--; Output.WriteLine("}"); } ////// Generates code for the specified CodeDom based for loop statement /// representation. /// ////// private void GenerateThrowExceptionStatement(CodeThrowExceptionStatement e) { Output.Write("throw"); if (e.ToThrow != null) { Output.Write(" "); GenerateExpression(e.ToThrow); } Output.WriteLine(";"); } private void GenerateComment(CodeComment e) { String commentLineStart = e.DocComment? "///": "//"; Output.Write(commentLineStart); Output.Write(" "); string value = e.Text; for (int i=0; i/// Generates code for the specified CodeDom based throw exception statement /// representation. /// ////// /// Generates code for the specified CodeDom based comment statement /// representation. /// /// private void GenerateCommentStatement(CodeCommentStatement e) { GenerateComment(e.Comment); } ////// private void GenerateCommentStatements(CodeCommentStatementCollection e) { foreach (CodeCommentStatement comment in e) { GenerateCommentStatement(comment); } } ///[To be supplied.] ////// private void GenerateMethodReturnStatement(CodeMethodReturnStatement e) { Output.Write("return"); if (e.Expression != null) { Output.Write(" "); GenerateExpression(e.Expression); } Output.WriteLine(";"); } ////// Generates code for the specified CodeDom based method return statement /// representation. /// ////// private void GenerateConditionStatement(CodeConditionStatement e) { Output.Write("if ("); GenerateExpression(e.Condition); Output.Write(")"); OutputStartingBrace(); Indent++; GenerateStatements(e.TrueStatements); Indent--; CodeStatementCollection falseStatemetns = e.FalseStatements; if (falseStatemetns.Count > 0) { Output.Write("}"); if (Options.ElseOnClosing) { Output.Write(" "); } else { Output.WriteLine(""); } Output.Write("else"); OutputStartingBrace(); Indent++; GenerateStatements(e.FalseStatements); Indent--; } Output.WriteLine("}"); } ////// Generates code for the specified CodeDom based if statement /// representation. /// ////// private void GenerateTryCatchFinallyStatement(CodeTryCatchFinallyStatement e) { Output.Write("try"); OutputStartingBrace(); Indent++; GenerateStatements(e.TryStatements); Indent--; CodeCatchClauseCollection catches = e.CatchClauses; if (catches.Count > 0) { IEnumerator en = catches.GetEnumerator(); while (en.MoveNext()) { Output.Write("}"); if (Options.ElseOnClosing) { Output.Write(" "); } else { Output.WriteLine(""); } CodeCatchClause current = (CodeCatchClause)en.Current; Output.Write("catch ("); OutputType(current.CatchExceptionType); Output.Write(" "); OutputIdentifier(current.LocalName); Output.Write(")"); OutputStartingBrace(); Indent++; GenerateStatements(current.Statements); Indent--; } } CodeStatementCollection finallyStatements = e.FinallyStatements; if (finallyStatements.Count > 0) { Output.Write("}"); if (Options.ElseOnClosing) { Output.Write(" "); } else { Output.WriteLine(""); } Output.Write("finally"); OutputStartingBrace(); Indent++; GenerateStatements(finallyStatements); Indent--; } Output.WriteLine("}"); } ////// Generates code for the specified CodeDom based try catch finally /// statement representation. /// ////// private void GenerateAssignStatement(CodeAssignStatement e) { GenerateExpression(e.Left); Output.Write(" = "); GenerateExpression(e.Right); if (!generatingForLoop) { Output.WriteLine(";"); } } ////// Generates code for the specified CodeDom based assignment statement /// representation. /// ////// private void GenerateAttachEventStatement(CodeAttachEventStatement e) { GenerateEventReferenceExpression(e.Event); Output.Write(" += "); GenerateExpression(e.Listener); Output.WriteLine(";"); } ////// Generates code for the specified CodeDom based attach event statement /// representation. /// ////// private void GenerateRemoveEventStatement(CodeRemoveEventStatement e) { GenerateEventReferenceExpression(e.Event); Output.Write(" -= "); GenerateExpression(e.Listener); Output.WriteLine(";"); } private void GenerateSnippetStatement(CodeSnippetStatement e) { Output.WriteLine(e.Value); } private void GenerateGotoStatement(CodeGotoStatement e) { Output.Write("goto "); Output.Write(e.Label); Output.WriteLine(";"); } private void GenerateLabeledStatement(CodeLabeledStatement e) { Indent--; Output.Write(e.Label); Output.WriteLine(":"); Indent++; if (e.Statement != null) { GenerateStatement(e.Statement); } } ////// Generates code for the specified CodeDom based detach event statement /// representation. /// ////// private void GenerateVariableDeclarationStatement(CodeVariableDeclarationStatement e) { OutputTypeNamePair(e.Type, e.Name); if (e.InitExpression != null) { Output.Write(" = "); GenerateExpression(e.InitExpression); } if (!generatingForLoop) { Output.WriteLine(";"); } } ////// Generates code for the specified CodeDom based variable declaration /// statement representation. /// ////// private void GenerateLinePragmaStart(CodeLinePragma e) { Output.WriteLine(""); Output.Write("#line "); Output.Write(e.LineNumber); Output.Write(" \""); Output.Write(e.FileName); Output.Write("\""); Output.WriteLine(""); } ////// Generates code for the specified CodeDom based line pragma start /// representation. /// ////// private void GenerateLinePragmaEnd(CodeLinePragma e) { Output.WriteLine(); Output.WriteLine("#line default"); Output.WriteLine("#line hidden"); } private void GenerateEvent(CodeMemberEvent e, CodeTypeDeclaration c) { if (IsCurrentDelegate || IsCurrentEnum) return; if (e.CustomAttributes.Count > 0) { GenerateAttributes(e.CustomAttributes); } if (e.PrivateImplementationType == null) { OutputMemberAccessModifier(e.Attributes); } Output.Write("event "); string name = e.Name; if (e.PrivateImplementationType != null) { name = e.PrivateImplementationType.BaseType + "." + name; } OutputTypeNamePair(e.Type, name); Output.WriteLine(";"); } ////// Generates code for the specified CodeDom based line pragma end /// representation. /// ////// private void GenerateExpression(CodeExpression e) { if (e is CodeArrayCreateExpression) { GenerateArrayCreateExpression((CodeArrayCreateExpression)e); } else if (e is CodeBaseReferenceExpression) { GenerateBaseReferenceExpression((CodeBaseReferenceExpression)e); } else if (e is CodeBinaryOperatorExpression) { GenerateBinaryOperatorExpression((CodeBinaryOperatorExpression)e); } else if (e is CodeCastExpression) { GenerateCastExpression((CodeCastExpression)e); } else if (e is CodeDelegateCreateExpression) { GenerateDelegateCreateExpression((CodeDelegateCreateExpression)e); } else if (e is CodeFieldReferenceExpression) { GenerateFieldReferenceExpression((CodeFieldReferenceExpression)e); } else if (e is CodeArgumentReferenceExpression) { GenerateArgumentReferenceExpression((CodeArgumentReferenceExpression)e); } else if (e is CodeVariableReferenceExpression) { GenerateVariableReferenceExpression((CodeVariableReferenceExpression)e); } else if (e is CodeIndexerExpression) { GenerateIndexerExpression((CodeIndexerExpression)e); } else if (e is CodeArrayIndexerExpression) { GenerateArrayIndexerExpression((CodeArrayIndexerExpression)e); } else if (e is CodeSnippetExpression) { GenerateSnippetExpression((CodeSnippetExpression)e); } else if (e is CodeMethodInvokeExpression) { GenerateMethodInvokeExpression((CodeMethodInvokeExpression)e); } else if (e is CodeMethodReferenceExpression) { GenerateMethodReferenceExpression((CodeMethodReferenceExpression)e); } else if (e is CodeEventReferenceExpression) { GenerateEventReferenceExpression((CodeEventReferenceExpression)e); } else if (e is CodeDelegateInvokeExpression) { GenerateDelegateInvokeExpression((CodeDelegateInvokeExpression)e); } else if (e is CodeObjectCreateExpression) { GenerateObjectCreateExpression((CodeObjectCreateExpression)e); } else if (e is CodeParameterDeclarationExpression) { GenerateParameterDeclarationExpression((CodeParameterDeclarationExpression)e); } else if (e is CodeDirectionExpression) { GenerateDirectionExpression((CodeDirectionExpression)e); } else if (e is CodePrimitiveExpression) { GeneratePrimitiveExpression((CodePrimitiveExpression)e); } else if (e is CodePropertyReferenceExpression) { GeneratePropertyReferenceExpression((CodePropertyReferenceExpression)e); } else if (e is CodePropertySetValueReferenceExpression) { GeneratePropertySetValueReferenceExpression((CodePropertySetValueReferenceExpression)e); } else if (e is CodeThisReferenceExpression) { GenerateThisReferenceExpression((CodeThisReferenceExpression)e); } else if (e is CodeTypeReferenceExpression) { GenerateTypeReferenceExpression((CodeTypeReferenceExpression)e); } else if (e is CodeTypeOfExpression) { GenerateTypeOfExpression((CodeTypeOfExpression)e); } else if (e is CodeDefaultValueExpression) { GenerateDefaultValueExpression((CodeDefaultValueExpression)e); } else { if (e == null) { throw new ArgumentNullException("e"); } else { throw new ArgumentException(SR.GetString(SR.InvalidElementType, e.GetType().FullName), "e"); } } } ///Generates code for the specified CodeDom code expression representation. ////// private void GenerateField(CodeMemberField e) { if (IsCurrentDelegate || IsCurrentInterface) return; if (IsCurrentEnum) { if (e.CustomAttributes.Count > 0) { GenerateAttributes(e.CustomAttributes); } OutputIdentifier(e.Name); if (e.InitExpression != null) { Output.Write(" = "); GenerateExpression(e.InitExpression); } Output.WriteLine(","); } else { if (e.CustomAttributes.Count > 0) { GenerateAttributes(e.CustomAttributes); } OutputMemberAccessModifier(e.Attributes); OutputVTableModifier(e.Attributes); OutputFieldScopeModifier(e.Attributes); OutputTypeNamePair(e.Type, e.Name); if (e.InitExpression != null) { Output.Write(" = "); GenerateExpression(e.InitExpression); } Output.WriteLine(";"); } } ////// Generates code for the specified CodeDom /// based field representation. /// ////// private void GenerateSnippetMember(CodeSnippetTypeMember e) { Output.Write(e.Text); } private void GenerateParameterDeclarationExpression(CodeParameterDeclarationExpression e) { if (e.CustomAttributes.Count > 0) { // Parameter attributes should be in-line for readability GenerateAttributes(e.CustomAttributes, null, true); } OutputDirection(e.Direction); OutputTypeNamePair(e.Type, e.Name); } private void GenerateEntryPointMethod(CodeEntryPointMethod e, CodeTypeDeclaration c) { if (e.CustomAttributes.Count > 0) { GenerateAttributes(e.CustomAttributes); } Output.Write("public static "); OutputType(e.ReturnType); Output.Write(" Main()"); OutputStartingBrace(); Indent++; GenerateStatements(e.Statements); Indent--; Output.WriteLine("}"); } private void GenerateMethods(CodeTypeDeclaration e) { IEnumerator en = e.Members.GetEnumerator(); while (en.MoveNext()) { if (en.Current is CodeMemberMethod && !(en.Current is CodeTypeConstructor) && !(en.Current is CodeConstructor)) { currentMember = (CodeTypeMember)en.Current; if (options.BlankLinesBetweenMembers) { Output.WriteLine(); } if (currentMember.StartDirectives.Count > 0) { GenerateDirectives(currentMember.StartDirectives); } GenerateCommentStatements(currentMember.Comments); CodeMemberMethod imp = (CodeMemberMethod)en.Current; if (imp.LinePragma != null) GenerateLinePragmaStart(imp.LinePragma); if (en.Current is CodeEntryPointMethod) { GenerateEntryPointMethod((CodeEntryPointMethod)en.Current, e); } else { GenerateMethod(imp, e); } if (imp.LinePragma != null) GenerateLinePragmaEnd(imp.LinePragma); if (currentMember.EndDirectives.Count > 0) { GenerateDirectives(currentMember.EndDirectives); } } } } ////// Generates code for the specified CodeDom based snippet class member /// representation. /// ////// private void GenerateMethod(CodeMemberMethod e, CodeTypeDeclaration c) { if (!(IsCurrentClass || IsCurrentStruct || IsCurrentInterface)) return; if (e.CustomAttributes.Count > 0) { GenerateAttributes(e.CustomAttributes); } if (e.ReturnTypeCustomAttributes.Count > 0) { GenerateAttributes(e.ReturnTypeCustomAttributes, "return: "); } if (!IsCurrentInterface) { if (e.PrivateImplementationType == null) { OutputMemberAccessModifier(e.Attributes); OutputVTableModifier(e.Attributes); OutputMemberScopeModifier(e.Attributes); } } else { // interfaces still need "new" OutputVTableModifier(e.Attributes); } OutputType(e.ReturnType); Output.Write(" "); if (e.PrivateImplementationType != null) { Output.Write(e.PrivateImplementationType.BaseType); Output.Write("."); } OutputIdentifier(e.Name); OutputTypeParameters(e.TypeParameters); Output.Write("("); OutputParameters(e.Parameters); Output.Write(")"); OutputTypeParameterConstraints(e.TypeParameters); if (!IsCurrentInterface && (e.Attributes & MemberAttributes.ScopeMask) != MemberAttributes.Abstract) { OutputStartingBrace(); Indent++; GenerateStatements(e.Statements); Indent--; Output.WriteLine("}"); } else { Output.WriteLine(";"); } } private void GenerateProperties(CodeTypeDeclaration e) { IEnumerator en = e.Members.GetEnumerator(); while (en.MoveNext()) { if (en.Current is CodeMemberProperty) { currentMember = (CodeTypeMember)en.Current; if (options.BlankLinesBetweenMembers) { Output.WriteLine(); } if (currentMember.StartDirectives.Count > 0) { GenerateDirectives(currentMember.StartDirectives); } GenerateCommentStatements(currentMember.Comments); CodeMemberProperty imp = (CodeMemberProperty)en.Current; if (imp.LinePragma != null) GenerateLinePragmaStart(imp.LinePragma); GenerateProperty(imp, e); if (imp.LinePragma != null) GenerateLinePragmaEnd(imp.LinePragma); if (currentMember.EndDirectives.Count > 0) { GenerateDirectives(currentMember.EndDirectives); } } } } ////// Generates code for the specified CodeDom based member method /// representation. /// ////// private void GenerateProperty(CodeMemberProperty e, CodeTypeDeclaration c) { if (!(IsCurrentClass || IsCurrentStruct || IsCurrentInterface)) return; if (e.CustomAttributes.Count > 0) { GenerateAttributes(e.CustomAttributes); } if (!IsCurrentInterface) { if (e.PrivateImplementationType == null) { OutputMemberAccessModifier(e.Attributes); OutputVTableModifier(e.Attributes); OutputMemberScopeModifier(e.Attributes); } } else { OutputVTableModifier(e.Attributes); } OutputType(e.Type); Output.Write(" "); if (e.PrivateImplementationType != null && !IsCurrentInterface) { Output.Write(e.PrivateImplementationType.BaseType); Output.Write("."); } if (e.Parameters.Count > 0 && String.Compare(e.Name, "Item", StringComparison.OrdinalIgnoreCase) == 0) { Output.Write("this["); OutputParameters(e.Parameters); Output.Write("]"); } else { OutputIdentifier(e.Name); } OutputStartingBrace(); Indent++; if (e.HasGet) { if (IsCurrentInterface || (e.Attributes & MemberAttributes.ScopeMask) == MemberAttributes.Abstract) { Output.WriteLine("get;"); } else { Output.Write("get"); OutputStartingBrace(); Indent++; GenerateStatements(e.GetStatements); Indent--; Output.WriteLine("}"); } } if (e.HasSet) { if (IsCurrentInterface || (e.Attributes & MemberAttributes.ScopeMask) == MemberAttributes.Abstract) { Output.WriteLine("set;"); } else { Output.Write("set"); OutputStartingBrace(); Indent++; GenerateStatements(e.SetStatements); Indent--; Output.WriteLine("}"); } } Indent--; Output.WriteLine("}"); } private void GenerateSingleFloatValue(Single s) { if( float.IsNaN(s)) { Output.Write("float.NaN"); } else if( float.IsNegativeInfinity(s)) { Output.Write("float.NegativeInfinity"); } else if( float.IsPositiveInfinity(s)) { Output.Write("float.PositiveInfinity"); } else { Output.Write(s.ToString(CultureInfo.InvariantCulture)); Output.Write('F'); } } private void GenerateDoubleValue(double d) { if( double.IsNaN(d)) { Output.Write("double.NaN"); } else if( double.IsNegativeInfinity(d)) { Output.Write("double.NegativeInfinity"); } else if( double.IsPositiveInfinity(d)) { Output.Write("double.PositiveInfinity"); } else { Output.Write(d.ToString("R", CultureInfo.InvariantCulture)); } } private void GenerateDecimalValue(Decimal d) { Output.Write(d.ToString(CultureInfo.InvariantCulture)); Output.Write('m'); } private void OutputVTableModifier(MemberAttributes attributes) { switch (attributes & MemberAttributes.VTableMask) { case MemberAttributes.New: Output.Write("new "); break; } } ////// Generates code for the specified CodeDom based property representation. /// ////// private void OutputMemberAccessModifier(MemberAttributes attributes) { switch (attributes & MemberAttributes.AccessMask) { case MemberAttributes.Assembly: Output.Write("internal "); break; case MemberAttributes.FamilyAndAssembly: Output.Write("internal "); /*FamANDAssem*/ 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; } } private void OutputMemberScopeModifier(MemberAttributes attributes) { switch (attributes & MemberAttributes.ScopeMask) { case MemberAttributes.Abstract: Output.Write("abstract "); break; case MemberAttributes.Final: Output.Write(""); break; case MemberAttributes.Static: Output.Write("static "); break; case MemberAttributes.Override: Output.Write("override "); break; default: switch (attributes & MemberAttributes.AccessMask) { case MemberAttributes.Family: case MemberAttributes.Public: case MemberAttributes.Assembly: Output.Write("virtual "); break; default: // nothing; break; } break; } } ////// Generates code for the specified member access modifier. /// ////// private 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; } } private void OutputFieldScopeModifier(MemberAttributes attributes) { switch (attributes & MemberAttributes.ScopeMask) { case MemberAttributes.Final: break; case MemberAttributes.Static: Output.Write("static "); break; case MemberAttributes.Const: Output.Write("const "); break; default: break; } } ////// Generates code for the specified operator. /// ////// private void GeneratePropertyReferenceExpression(CodePropertyReferenceExpression e) { if (e.TargetObject != null) { GenerateExpression(e.TargetObject); Output.Write("."); } OutputIdentifier(e.PropertyName); } private void GenerateConstructors(CodeTypeDeclaration e) { IEnumerator en = e.Members.GetEnumerator(); while (en.MoveNext()) { if (en.Current is CodeConstructor) { currentMember = (CodeTypeMember)en.Current; if (options.BlankLinesBetweenMembers) { Output.WriteLine(); } if (currentMember.StartDirectives.Count > 0) { GenerateDirectives(currentMember.StartDirectives); } GenerateCommentStatements(currentMember.Comments); CodeConstructor imp = (CodeConstructor)en.Current; if (imp.LinePragma != null) GenerateLinePragmaStart(imp.LinePragma); GenerateConstructor(imp, e); if (imp.LinePragma != null) GenerateLinePragmaEnd(imp.LinePragma); if (currentMember.EndDirectives.Count > 0) { GenerateDirectives(currentMember.EndDirectives); } } } } ////// Generates code for the specified CodeDom based property reference /// expression representation. /// ////// private void GenerateConstructor(CodeConstructor e, CodeTypeDeclaration c) { if (!(IsCurrentClass || IsCurrentStruct)) return; if (e.CustomAttributes.Count > 0) { GenerateAttributes(e.CustomAttributes); } OutputMemberAccessModifier(e.Attributes); OutputIdentifier(CurrentTypeName); Output.Write("("); OutputParameters(e.Parameters); Output.Write(")"); CodeExpressionCollection baseArgs = e.BaseConstructorArgs; CodeExpressionCollection thisArgs = e.ChainedConstructorArgs; if (baseArgs.Count > 0) { Output.WriteLine(" : "); Indent++; Indent++; Output.Write("base("); OutputExpressionList(baseArgs); Output.Write(")"); Indent--; Indent--; } if (thisArgs.Count > 0) { Output.WriteLine(" : "); Indent++; Indent++; Output.Write("this("); OutputExpressionList(thisArgs); Output.Write(")"); Indent--; Indent--; } OutputStartingBrace(); Indent++; GenerateStatements(e.Statements); Indent--; Output.WriteLine("}"); } ////// Generates code for the specified CodeDom based constructor /// representation. /// ////// private void GenerateTypeConstructor(CodeTypeConstructor e) { if (!(IsCurrentClass || IsCurrentStruct)) return; if (e.CustomAttributes.Count > 0) { GenerateAttributes(e.CustomAttributes); } Output.Write("static "); Output.Write(CurrentTypeName); Output.Write("()"); OutputStartingBrace(); Indent++; GenerateStatements(e.Statements); Indent--; Output.WriteLine("}"); } ////// Generates code for the specified CodeDom based class constructor /// representation. /// ////// private void GenerateTypeReferenceExpression(CodeTypeReferenceExpression e) { OutputType(e.Type); } ////// Generates code for the specified CodeDom based type reference expression /// representation. /// ////// private void GenerateTypeOfExpression(CodeTypeOfExpression e) { Output.Write("typeof("); OutputType(e.Type); Output.Write(")"); } private void GenerateType(CodeTypeDeclaration e) { currentClass = e; if (e.StartDirectives.Count > 0) { GenerateDirectives(e.StartDirectives); } GenerateCommentStatements(e.Comments); if (e.LinePragma != null) GenerateLinePragmaStart(e.LinePragma); GenerateTypeStart(e); if (Options.VerbatimOrder) { foreach (CodeTypeMember member in e.Members) { GenerateTypeMember(member, e); } } else { GenerateFields(e); GenerateSnippetMembers(e); GenerateTypeConstructors(e); GenerateConstructors(e); GenerateProperties(e); GenerateEvents(e); GenerateMethods(e); GenerateNestedTypes(e); } // Nested types clobber the current class, so reset it. currentClass = e; GenerateTypeEnd(e); if (e.LinePragma != null) GenerateLinePragmaEnd(e.LinePragma); if (e.EndDirectives.Count > 0) { GenerateDirectives(e.EndDirectives); } } ////// Generates code for the specified CodeDom based type of expression /// representation. /// ////// private void GenerateTypes(CodeNamespace e) { foreach (CodeTypeDeclaration c in e.Types) { if (options.BlankLinesBetweenMembers) { Output.WriteLine(); } ((ICodeGenerator)this).GenerateCodeFromType(c, output.InnerWriter, options); } } ///Generates code for the specified CodeDom namespace representation and the classes it /// contains. ////// private void GenerateTypeStart(CodeTypeDeclaration e) { if (e.CustomAttributes.Count > 0) { GenerateAttributes(e.CustomAttributes); } if (IsCurrentDelegate) { switch (e.TypeAttributes & TypeAttributes.VisibilityMask) { case TypeAttributes.Public: Output.Write("public "); break; case TypeAttributes.NotPublic: default: break; } CodeTypeDelegate del = (CodeTypeDelegate)e; Output.Write("delegate "); OutputType(del.ReturnType); Output.Write(" "); OutputIdentifier(e.Name); Output.Write("("); OutputParameters(del.Parameters); Output.WriteLine(");"); } else { OutputTypeAttributes(e); OutputIdentifier(e.Name); OutputTypeParameters(e.TypeParameters); bool first = true; foreach (CodeTypeReference typeRef in e.BaseTypes) { if (first) { Output.Write(" : "); first = false; } else { Output.Write(", "); } OutputType(typeRef); } OutputTypeParameterConstraints(e.TypeParameters); OutputStartingBrace(); Indent++; } } private void GenerateTypeMember(CodeTypeMember member, CodeTypeDeclaration declaredType) { if (options.BlankLinesBetweenMembers) { Output.WriteLine(); } if (member is CodeTypeDeclaration) { ((ICodeGenerator)this).GenerateCodeFromType((CodeTypeDeclaration)member, output.InnerWriter, options); // Nested types clobber the current class, so reset it. currentClass = declaredType; // For nested types, comments and line pragmas are handled separately, so return here return; } if (member.StartDirectives.Count > 0) { GenerateDirectives(member.StartDirectives); } GenerateCommentStatements(member.Comments); if (member.LinePragma != null) { GenerateLinePragmaStart(member.LinePragma); } if (member is CodeMemberField) { GenerateField((CodeMemberField)member); } else if (member is CodeMemberProperty) { GenerateProperty((CodeMemberProperty)member, declaredType); } else if (member is CodeMemberMethod) { if (member is CodeConstructor) { GenerateConstructor((CodeConstructor)member, declaredType); } else if (member is CodeTypeConstructor) { GenerateTypeConstructor((CodeTypeConstructor) member); } else if (member is CodeEntryPointMethod) { GenerateEntryPointMethod((CodeEntryPointMethod)member, declaredType); } else { GenerateMethod((CodeMemberMethod)member, declaredType); } } else if (member is CodeMemberEvent) { GenerateEvent((CodeMemberEvent)member, declaredType); } else if (member is CodeSnippetTypeMember) { // Don't indent snippets, in order to preserve the column // information from the original code. This improves the debugging // experience. int savedIndent = Indent; Indent=0; GenerateSnippetMember((CodeSnippetTypeMember)member); // Restore the indent Indent=savedIndent; // Generate an extra new line at the end of the snippet. // If the snippet is comment and this type only contains comments. // The generated code will not compile. Output.WriteLine(); } if (member.LinePragma != null) { GenerateLinePragmaEnd(member.LinePragma); } if (member.EndDirectives.Count > 0) { GenerateDirectives(member.EndDirectives); } } private void GenerateTypeConstructors(CodeTypeDeclaration e) { IEnumerator en = e.Members.GetEnumerator(); while (en.MoveNext()) { if (en.Current is CodeTypeConstructor) { currentMember = (CodeTypeMember)en.Current; if (options.BlankLinesBetweenMembers) { Output.WriteLine(); } if (currentMember.StartDirectives.Count > 0) { GenerateDirectives(currentMember.StartDirectives); } GenerateCommentStatements(currentMember.Comments); CodeTypeConstructor imp = (CodeTypeConstructor)en.Current; if (imp.LinePragma != null) GenerateLinePragmaStart(imp.LinePragma); GenerateTypeConstructor(imp); if (imp.LinePragma != null) GenerateLinePragmaEnd(imp.LinePragma); if (currentMember.EndDirectives.Count > 0) { GenerateDirectives(currentMember.EndDirectives); } } } } private void GenerateSnippetMembers(CodeTypeDeclaration e) { IEnumerator en = e.Members.GetEnumerator(); bool hasSnippet = false; while (en.MoveNext()) { if (en.Current is CodeSnippetTypeMember) { hasSnippet = true; currentMember = (CodeTypeMember)en.Current; if (options.BlankLinesBetweenMembers) { Output.WriteLine(); } if (currentMember.StartDirectives.Count > 0) { GenerateDirectives(currentMember.StartDirectives); } GenerateCommentStatements(currentMember.Comments); CodeSnippetTypeMember imp = (CodeSnippetTypeMember)en.Current; if (imp.LinePragma != null) GenerateLinePragmaStart(imp.LinePragma); // Don't indent snippets, in order to preserve the column // information from the original code. This improves the debugging // experience. int savedIndent = Indent; Indent=0; GenerateSnippetMember(imp); // Restore the indent Indent=savedIndent; if (imp.LinePragma != null) GenerateLinePragmaEnd(imp.LinePragma); if (currentMember.EndDirectives.Count > 0) { GenerateDirectives(currentMember.EndDirectives); } } } // Generate an extra new line at the end of the snippet. // If the snippet is comment and this type only contains comments. // The generated code will not compile. if(hasSnippet) { Output.WriteLine(); } } private void GenerateNestedTypes(CodeTypeDeclaration e) { IEnumerator en = e.Members.GetEnumerator(); while (en.MoveNext()) { if (en.Current is CodeTypeDeclaration) { if (options.BlankLinesBetweenMembers) { Output.WriteLine(); } CodeTypeDeclaration currentClass = (CodeTypeDeclaration)en.Current; ((ICodeGenerator)this).GenerateCodeFromType(currentClass, output.InnerWriter, options); } } } ////// Generates code for the specified CodeDom based class start /// representation. /// ////// private void GenerateNamespaces(CodeCompileUnit e) { foreach (CodeNamespace n in e.Namespaces) { ((ICodeGenerator)this).GenerateCodeFromNamespace(n, output.InnerWriter, options); } } ///Generates code for the namepsaces in the specifield CodeDom compile unit. /// ////// private void OutputAttributeArgument(CodeAttributeArgument arg) { if (arg.Name != null && arg.Name.Length > 0) { OutputIdentifier(arg.Name); Output.Write("="); } ((ICodeGenerator)this).GenerateCodeFromExpression(arg.Value, output.InnerWriter, options); } ////// Outputs an argument in a attribute block. /// ////// private void OutputDirection(FieldDirection dir) { switch (dir) { case FieldDirection.In: break; case FieldDirection.Out: Output.Write("out "); break; case FieldDirection.Ref: Output.Write("ref "); break; } } ////// Generates code for the specified System.CodeDom.FieldDirection. /// ////// private void OutputExpressionList(CodeExpressionCollection expressions) { OutputExpressionList(expressions, false /*newlineBetweenItems*/); } ////// Generates code for the specified expression list. /// ////// private void OutputExpressionList(CodeExpressionCollection expressions, bool newlineBetweenItems) { bool first = true; IEnumerator en = expressions.GetEnumerator(); Indent++; while (en.MoveNext()) { if (first) { first = false; } else { if (newlineBetweenItems) ContinueOnNewLine(","); else Output.Write(", "); } ((ICodeGenerator)this).GenerateCodeFromExpression((CodeExpression)en.Current, output.InnerWriter, options); } Indent--; } ////// Generates code for the specified expression list. /// ////// private void OutputParameters(CodeParameterDeclarationExpressionCollection parameters) { bool first = true; bool multiline = parameters.Count > ParameterMultilineThreshold; if (multiline) { Indent += 3; } IEnumerator en = parameters.GetEnumerator(); while (en.MoveNext()) { CodeParameterDeclarationExpression current = (CodeParameterDeclarationExpression)en.Current; if (first) { first = false; } else { Output.Write(", "); } if (multiline) { ContinueOnNewLine(""); } GenerateExpression(current); } if (multiline) { Indent -= 3; } } ////// Generates code for the specified parameters. /// ////// private void OutputTypeNamePair(CodeTypeReference typeRef, string name) { OutputType(typeRef); Output.Write(" "); OutputIdentifier(name); } private void OutputTypeParameters(CodeTypeParameterCollection typeParameters) { if( typeParameters.Count == 0) { return; } Output.Write('<'); bool first = true; for(int i = 0; i < typeParameters.Count; i++) { if( first) { first = false; } else { Output.Write(", "); } if (typeParameters[i].CustomAttributes.Count > 0) { GenerateAttributes(typeParameters[i].CustomAttributes, null, true); Output.Write(' '); } Output.Write(typeParameters[i].Name); } Output.Write('>'); } private void OutputTypeParameterConstraints(CodeTypeParameterCollection typeParameters) { if( typeParameters.Count == 0) { return; } for(int i = 0; i < typeParameters.Count; i++) { // generating something like: "where KeyType: IComparable, IEnumerable" Output.WriteLine(); Indent++; bool first = true; if( typeParameters[i].Constraints.Count > 0) { foreach (CodeTypeReference typeRef in typeParameters[i].Constraints) { if (first) { Output.Write("where "); Output.Write(typeParameters[i].Name); Output.Write(" : "); first = false; } else { Output.Write(", "); } OutputType(typeRef); } } if( typeParameters[i].HasConstructorConstraint) { if( first) { Output.Write("where "); Output.Write(typeParameters[i].Name); Output.Write(" : new()"); } else { Output.Write(", new ()"); } } Indent--; } } private void OutputTypeAttributes(CodeTypeDeclaration e) { if((e.Attributes & MemberAttributes.New) != 0) { Output.Write("new "); } TypeAttributes attributes = e.TypeAttributes; switch(attributes & TypeAttributes.VisibilityMask) { case TypeAttributes.Public: case TypeAttributes.NestedPublic: Output.Write("public "); break; case TypeAttributes.NestedPrivate: Output.Write("private "); break; case TypeAttributes.NestedFamily: Output.Write("protected "); break; case TypeAttributes.NotPublic: case TypeAttributes.NestedAssembly: case TypeAttributes.NestedFamANDAssem: Output.Write("internal "); break; case TypeAttributes.NestedFamORAssem: Output.Write("protected internal "); break; } if (e.IsStruct) { if (e.IsPartial) { Output.Write("partial "); } Output.Write("struct "); } else if (e.IsEnum) { Output.Write("enum "); } else { switch (attributes & TypeAttributes.ClassSemanticsMask) { case TypeAttributes.Class: if ((attributes & TypeAttributes.Sealed) == TypeAttributes.Sealed) { Output.Write("sealed "); } if ((attributes & TypeAttributes.Abstract) == TypeAttributes.Abstract) { Output.Write("abstract "); } if (e.IsPartial) { Output.Write("partial "); } Output.Write("class "); break; case TypeAttributes.Interface: if (e.IsPartial) { Output.Write("partial "); } Output.Write("interface "); break; } } } ////// Generates code for the specified object type and name pair. /// ////// private void GenerateTypeEnd(CodeTypeDeclaration e) { if (!IsCurrentDelegate) { Indent--; Output.WriteLine("}"); } } ////// Generates code for the specified CodeDom based class end representation. /// ////// private void GenerateNamespaceStart(CodeNamespace e) { if (e.Name != null && e.Name.Length > 0) { Output.Write("namespace "); string[] names = e.Name.Split('.'); Debug.Assert( names.Length > 0); OutputIdentifier(names[0]); for( int i = 1; i< names.Length; i++) { Output.Write("."); OutputIdentifier(names[i]); } OutputStartingBrace(); Indent++; } } ////// Generates code for the specified CodeDom based namespace start /// representation. /// ////// private void GenerateCompileUnit(CodeCompileUnit e) { GenerateCompileUnitStart(e); GenerateNamespaces(e); GenerateCompileUnitEnd(e); } ///Generates code for the specified CodeDom /// compile unit representation. ////// private void GenerateCompileUnitStart(CodeCompileUnit e) { if (e.StartDirectives.Count > 0) { GenerateDirectives(e.StartDirectives); } Output.WriteLine("//------------------------------------------------------------------------------"); Output.Write("// <"); Output.WriteLine(SR.GetString(SR.AutoGen_Comment_Line1)); Output.Write("// "); Output.WriteLine(SR.GetString(SR.AutoGen_Comment_Line2)); Output.Write("// "); Output.Write(SR.GetString(SR.AutoGen_Comment_Line3)); Output.WriteLine(System.Environment.Version.ToString()); Output.WriteLine("//"); Output.Write("// "); Output.WriteLine(SR.GetString(SR.AutoGen_Comment_Line4)); Output.Write("// "); Output.WriteLine(SR.GetString(SR.AutoGen_Comment_Line5)); Output.Write("// "); Output.WriteLine(SR.GetString(SR.AutoGen_Comment_Line1)); Output.WriteLine("//------------------------------------------------------------------------------"); Output.WriteLine(""); SortedList importList; // CSharp needs to put assembly attributes after using statements. // Since we need to create a empty namespace even if we don't need it, // using will generated after assembly attributes. importList = new SortedList(StringComparer.Ordinal); foreach (CodeNamespace nspace in e.Namespaces) { if( String.IsNullOrEmpty(nspace.Name)) { // mark the namespace to stop it generating its own import list nspace.UserData["GenerateImports"] = false; // Collect the unique list of imports foreach (CodeNamespaceImport import in nspace.Imports) { if (!importList.Contains(import.Namespace)) { importList.Add(import.Namespace, import.Namespace); } } } } // now output the imports foreach(string import in importList.Keys) { Output.Write("using "); OutputIdentifier(import); Output.WriteLine(";"); } if( importList.Keys.Count > 0) { Output.WriteLine(""); } // in C# the best place to put these is at the top level. if (e.AssemblyCustomAttributes.Count > 0) { GenerateAttributes(e.AssemblyCustomAttributes, "assembly: "); Output.WriteLine(""); } } ////// Generates code for the specified CodeDom based compile unit start /// representation. /// ////// private void GenerateCompileUnitEnd(CodeCompileUnit e) { if (e.EndDirectives.Count > 0) { GenerateDirectives(e.EndDirectives); } } ////// Generates code for the specified CodeDom based compile unit end /// representation. /// ////// private void GenerateDirectionExpression(CodeDirectionExpression e) { OutputDirection(e.Direction); GenerateExpression(e.Expression); } private void GenerateDirectives(CodeDirectiveCollection directives) { for (int i = 0; i < directives.Count; i++) { CodeDirective directive = directives[i]; if (directive is CodeChecksumPragma) { GenerateChecksumPragma((CodeChecksumPragma)directive); } else if (directive is CodeRegionDirective) { GenerateCodeRegionDirective((CodeRegionDirective)directive); } } } private void GenerateChecksumPragma(CodeChecksumPragma checksumPragma) { Output.Write("#pragma checksum \""); Output.Write(checksumPragma.FileName); Output.Write("\" \""); Output.Write(checksumPragma.ChecksumAlgorithmId.ToString("B", CultureInfo.InvariantCulture)); Output.Write("\" \""); if (checksumPragma.ChecksumData != null) { foreach(Byte b in checksumPragma.ChecksumData) { Output.Write(b.ToString("X2", CultureInfo.InvariantCulture)); } } Output.WriteLine("\""); } private void GenerateCodeRegionDirective(CodeRegionDirective regionDirective) { if (regionDirective.RegionMode == CodeRegionMode.Start) { Output.Write("#region "); Output.WriteLine(regionDirective.RegionText); } else if (regionDirective.RegionMode == CodeRegionMode.End) { Output.WriteLine("#endregion"); } } ///[To be supplied.] ////// private void GenerateNamespaceEnd(CodeNamespace e) { if (e.Name != null && e.Name.Length > 0) { Indent--; Output.WriteLine("}"); } } ////// Generates code for the specified CodeDom based namespace end /// representation. /// ////// private void GenerateNamespaceImport(CodeNamespaceImport e) { Output.Write("using "); OutputIdentifier(e.Namespace); Output.WriteLine(";"); } ////// Generates code for the specified CodeDom based namespace import /// representation. /// ////// private void GenerateAttributeDeclarationsStart(CodeAttributeDeclarationCollection attributes) { Output.Write("["); } ////// Generates code for the specified CodeDom based attribute block start /// representation. /// ////// private void GenerateAttributeDeclarationsEnd(CodeAttributeDeclarationCollection attributes) { Output.Write("]"); } private void GenerateAttributes(CodeAttributeDeclarationCollection attributes) { GenerateAttributes(attributes, null, false); } private void GenerateAttributes(CodeAttributeDeclarationCollection attributes, string prefix) { GenerateAttributes(attributes, prefix, false); } private void GenerateAttributes(CodeAttributeDeclarationCollection attributes, string prefix, bool inLine) { if (attributes.Count == 0) return; IEnumerator en = attributes.GetEnumerator(); bool paramArray =false; while (en.MoveNext()) { // we need to convert paramArrayAttribute to params keyword to // make csharp compiler happy. In addition, params keyword needs to be after // other attributes. CodeAttributeDeclaration current = (CodeAttributeDeclaration)en.Current; if( current.Name.Equals("system.paramarrayattribute", StringComparison.OrdinalIgnoreCase)) { paramArray = true; continue; } GenerateAttributeDeclarationsStart(attributes); if (prefix != null) { Output.Write(prefix); } if( current.AttributeType != null) { Output.Write(GetTypeOutput(current.AttributeType)); } Output.Write("("); bool firstArg = true; foreach (CodeAttributeArgument arg in current.Arguments) { if (firstArg) { firstArg = false; } else { Output.Write(", "); } OutputAttributeArgument(arg); } Output.Write(")"); GenerateAttributeDeclarationsEnd(attributes); if (inLine) { Output.Write(" "); } else { Output.WriteLine(); } } if( paramArray) { if (prefix != null) { Output.Write(prefix); } Output.Write("params"); if (inLine) { Output.Write(" "); } else { Output.WriteLine(); } } } static bool IsKeyword(string value) { return FixedStringLookup.Contains(keywords, value, false); } static bool IsPrefixTwoUnderscore(string value) { if( value.Length < 3) { return false; } else { return ((value[0] == '_') && (value[1] == '_') && (value[2] != '_')); } } public bool Supports(GeneratorSupport support) { return ((support & LanguageSupport) == support); } ////// Generates code for the specified CodeDom based attribute block end /// representation. /// ////// public bool IsValidIdentifier(string value) { // identifiers must be 1 char or longer // if (value == null || value.Length == 0) { return false; } if (value.Length > 512) return false; // identifiers cannot be a keyword, unless they are escaped with an '@' // if (value[0] != '@') { if (IsKeyword(value)) return false; } else { value = value.Substring(1); } return CodeGenerator.IsValidLanguageIndependentIdentifier(value); } public void ValidateIdentifier(string value) { if (!IsValidIdentifier(value)) { throw new ArgumentException(SR.GetString(SR.InvalidIdentifier, value)); } } public string CreateValidIdentifier(string name) { if(IsPrefixTwoUnderscore(name)) { name = "_" + name; } while (IsKeyword(name)) { name = "_" + name; } return name; } public string CreateEscapedIdentifier(string name) { // Any identifier started with two consecutive underscores are // reserved by CSharp. if (IsKeyword(name) || IsPrefixTwoUnderscore(name)) { return "@" + name; } return name; } // returns the type name without any array declaration. private string GetBaseTypeOutput(CodeTypeReference typeRef) { string s = typeRef.BaseType; if (s.Length == 0) { s = "void"; return s; } string lowerCaseString = s.ToLower( CultureInfo.InvariantCulture); switch (lowerCaseString) { case "system.int16": s = "short"; break; case "system.int32": s = "int"; break; case "system.int64": s = "long"; break; case "system.string": s = "string"; break; case "system.object": s = "object"; break; case "system.boolean": s = "bool"; break; case "system.void": s = "void"; break; case "system.char": s = "char"; break; case "system.byte": s = "byte"; break; case "system.uint16": s = "ushort"; break; case "system.uint32": s = "uint"; break; case "system.uint64": s = "ulong"; break; case "system.sbyte": s = "sbyte"; break; case "system.single": s = "float"; break; case "system.double": s = "double"; break; case "system.decimal": s = "decimal"; break; default: // replace + with . for nested classes. // StringBuilder sb = new StringBuilder(s.Length + 10); if(typeRef.Options == CodeTypeReferenceOptions.GlobalReference) { sb.Append("global::"); } string baseType = typeRef.BaseType; int lastIndex = 0; int currentTypeArgStart = 0; for (int i=0; i/// Gets whether the specified value is a valid identifier. /// ///= '0' && baseType[i] <='9') { numTypeArgs = numTypeArgs*10 + (baseType[i] - '0'); i++; } GetTypeArgumentsOutput(typeRef.TypeArguments, currentTypeArgStart, numTypeArgs, sb); currentTypeArgStart += numTypeArgs; // Arity can be in the middle of a nested type name, so we might have a . or + after it. // Skip it if so. if (i < baseType.Length && (baseType[i] =='+' || baseType[i] == '.')) { sb.Append('.'); i++; } lastIndex = i; break; } } if (lastIndex < baseType.Length) sb.Append(CreateEscapedIdentifier(baseType.Substring(lastIndex))); return sb.ToString(); } return s; } private String GetTypeArgumentsOutput(CodeTypeReferenceCollection typeArguments) { StringBuilder sb = new StringBuilder(128); GetTypeArgumentsOutput(typeArguments, 0, typeArguments.Count, sb); return sb.ToString(); } private void GetTypeArgumentsOutput(CodeTypeReferenceCollection typeArguments, int start, int length, StringBuilder sb) { sb.Append('<'); bool first = true; for( int i = start; i < start+length; i++) { if( first) { first = false; } else { sb.Append(", "); } // it's possible that we call GetTypeArgumentsOutput with an empty typeArguments collection. This is the case // for open types, so we want to just output the brackets and commas. if (i < typeArguments.Count) sb.Append(GetTypeOutput(typeArguments[i])); } sb.Append('>'); } public string GetTypeOutput(CodeTypeReference typeRef) { string s = String.Empty; CodeTypeReference baseTypeRef = typeRef; while(baseTypeRef.ArrayElementType != null) { baseTypeRef = baseTypeRef.ArrayElementType; } s += GetBaseTypeOutput(baseTypeRef); while(typeRef !=null && typeRef.ArrayRank > 0) { char [] results = new char [typeRef.ArrayRank + 1]; results[0] = '['; results[typeRef.ArrayRank] = ']'; for (int i = 1; i < typeRef.ArrayRank; i++) { results[i] = ','; } s += new string(results); typeRef = typeRef.ArrayElementType; } return s; } private void OutputStartingBrace() { if (Options.BracingStyle == "C") { Output.WriteLine(""); Output.WriteLine("{"); } else { Output.WriteLine(" {"); } } private CompilerResults FromFileBatch(CompilerParameters options, string[] fileNames) { if( options == null) { throw new ArgumentNullException("options"); } if (fileNames == null) throw new ArgumentNullException("fileNames"); new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); string outputFile = null; int retValue = 0; CompilerResults results = new CompilerResults(options.TempFiles); SecurityPermission perm1 = new SecurityPermission(SecurityPermissionFlag.ControlEvidence); perm1.Assert(); try { results.Evidence = options.Evidence; } finally { SecurityPermission.RevertAssert(); } bool createdEmptyAssembly = false; if (options.OutputAssembly == null || options.OutputAssembly.Length == 0) { string extension = (options.GenerateExecutable) ? "exe" : "dll"; options.OutputAssembly = results.TempFiles.AddExtension(extension, !options.GenerateInMemory); // Create an empty assembly. This is so that the file will have permissions that // we can later access with our current credential. If we don't do this, the compiler // could end up creating an assembly that we cannot open. new FileStream(options.OutputAssembly, FileMode.Create, FileAccess.ReadWrite).Close(); createdEmptyAssembly = true; } #if FEATURE_PAL string pdbname = "ildb"; #else string pdbname = "pdb"; #endif // Don't delete pdbs when debug=false but they have specified pdbonly. if (options.CompilerOptions!= null && CultureInfo.InvariantCulture.CompareInfo.IndexOf(options.CompilerOptions,"/debug:pdbonly", CompareOptions.IgnoreCase) != -1) results.TempFiles.AddExtension(pdbname, true); else results.TempFiles.AddExtension(pdbname); string args = CmdArgsFromParameters(options) + " " + JoinStringArray(fileNames, " "); // Use a response file if the compiler supports it string responseFileArgs = GetResponseFileCmdArgs(options, args); string trueArgs = null; if (responseFileArgs != null) { trueArgs = args; args = responseFileArgs; } Compile(options, RedistVersionInfo.GetCompilerPath(provOptions, CompilerName), CompilerName, args, ref outputFile, ref retValue, trueArgs); results.NativeCompilerReturnValue = retValue; // only look for errors/warnings if the compile failed or the caller set the warning level if (retValue != 0 || options.WarningLevel > 0) { FileStream outputStream = new FileStream(outputFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); try { if (outputStream.Length > 0) { // The output of the compiler is in UTF8 StreamReader sr = new StreamReader(outputStream, Encoding.UTF8); string line; do { line = sr.ReadLine(); if (line != null) { results.Output.Add(line); ProcessCompilerOutputLine(results, line); } } while (line != null); } } finally { outputStream.Close(); } // Delete the empty assembly if we created one if (retValue != 0 && createdEmptyAssembly) File.Delete(options.OutputAssembly); } if (!results.Errors.HasErrors && options.GenerateInMemory) { FileStream fs = new FileStream(options.OutputAssembly, FileMode.Open, FileAccess.Read, FileShare.Read); try { int fileLen = (int)fs.Length; byte[] b = new byte[fileLen]; fs.Read(b, 0, fileLen); SecurityPermission perm = new SecurityPermission(SecurityPermissionFlag.ControlEvidence); perm.Assert(); try { results.CompiledAssembly = Assembly.Load(b,null,options.Evidence); } finally { SecurityPermission.RevertAssert(); } } finally { fs.Close(); } } else { results.PathToAssembly = options.OutputAssembly; } return results; } /// CompilerResults ICodeCompiler.CompileAssemblyFromDom(CompilerParameters options, CodeCompileUnit e) { if( options == null) { throw new ArgumentNullException("options"); } try { return FromDom(options, e); } finally { options.TempFiles.SafeDelete(); } } /// CompilerResults ICodeCompiler.CompileAssemblyFromFile(CompilerParameters options, string fileName) { if( options == null) { throw new ArgumentNullException("options"); } try { return FromFile(options, fileName); } finally { options.TempFiles.SafeDelete(); } } /// CompilerResults ICodeCompiler.CompileAssemblyFromSource(CompilerParameters options, string source) { if( options == null) { throw new ArgumentNullException("options"); } try { return FromSource(options, source); } finally { options.TempFiles.SafeDelete(); } } /// CompilerResults ICodeCompiler.CompileAssemblyFromSourceBatch(CompilerParameters options, string[] sources) { if( options == null) { throw new ArgumentNullException("options"); } try { return FromSourceBatch(options, sources); } finally { options.TempFiles.SafeDelete(); } } /// CompilerResults ICodeCompiler.CompileAssemblyFromFileBatch(CompilerParameters options, string[] fileNames) { if( options == null) { throw new ArgumentNullException("options"); } if (fileNames == null) throw new ArgumentNullException("fileNames"); try { // Try opening the files to make sure they exists. This will throw an exception // if it doesn't foreach (string fileName in fileNames) { using (Stream str = File.OpenRead(fileName)) { } } return FromFileBatch(options, fileNames); } finally { options.TempFiles.SafeDelete(); } } /// CompilerResults ICodeCompiler.CompileAssemblyFromDomBatch(CompilerParameters options, CodeCompileUnit[] ea) { if( options == null) { throw new ArgumentNullException("options"); } try { return FromDomBatch(options, ea); } finally { options.TempFiles.SafeDelete(); } } internal void Compile(CompilerParameters options, string compilerDirectory, string compilerExe, string arguments, ref string outputFile, ref int nativeReturnValue, string trueArgs) { string errorFile = null; outputFile = options.TempFiles.AddExtension("out"); // We try to execute the compiler with a full path name. string fullname = Path.Combine(compilerDirectory, compilerExe); if (File.Exists(fullname)) { string trueCmdLine = null; if (trueArgs != null) trueCmdLine = "\"" + fullname + "\" " + trueArgs; nativeReturnValue = Executor.ExecWaitWithCapture(options.SafeUserToken, "\"" + fullname + "\" " + arguments, Environment.CurrentDirectory, options.TempFiles, ref outputFile, ref errorFile, trueCmdLine); } else { throw new InvalidOperationException(SR.GetString(SR.CompilerNotFound, fullname)); } } /// /// private CompilerResults FromDom(CompilerParameters options, CodeCompileUnit e) { if( options == null) { throw new ArgumentNullException("options"); } new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); CodeCompileUnit[] units = new CodeCompileUnit[1]; units[0] = e; return FromDomBatch(options, units); } ////// Compiles the specified compile unit and options, and returns the results /// from the compilation. /// ////// private CompilerResults FromFile(CompilerParameters options, string fileName) { if( options == null) { throw new ArgumentNullException("options"); } if (fileName == null) throw new ArgumentNullException("fileName"); new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); // Try opening the file to make sure it exists. This will throw an exception // if it doesn't using (Stream str = File.OpenRead(fileName)) { } string[] filenames = new string[1]; filenames[0] = fileName; return FromFileBatch(options, filenames); } ////// Compiles the specified file using the specified options, and returns the /// results from the compilation. /// ////// private CompilerResults FromSource(CompilerParameters options, string source) { if( options == null) { throw new ArgumentNullException("options"); } new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); string[] sources = new string[1]; sources[0] = source; return FromSourceBatch(options, sources); } ////// Compiles the specified source code using the specified options, and /// returns the results from the compilation. /// ////// private CompilerResults FromDomBatch(CompilerParameters options, CodeCompileUnit[] ea) { if( options == null) { throw new ArgumentNullException("options"); } if (ea == null) throw new ArgumentNullException("ea"); new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); string[] filenames = new string[ea.Length]; CompilerResults results = null; #if !FEATURE_PAL // the extra try-catch is here to mitigate exception filter injection attacks. try { WindowsImpersonationContext impersonation = Executor.RevertImpersonation(); try { #endif // !FEATURE_PAL for (int i = 0; i < ea.Length; i++) { if (ea[i] == null) continue; // the other two batch methods just work if one element is null, so we'll match that. ResolveReferencedAssemblies(options, ea[i]); filenames[i] = options.TempFiles.AddExtension(i + FileExtension); Stream temp = new FileStream(filenames[i], FileMode.Create, FileAccess.Write, FileShare.Read); try { using (StreamWriter sw = new StreamWriter(temp, Encoding.UTF8)){ ((ICodeGenerator)this).GenerateCodeFromCompileUnit(ea[i], sw, Options); sw.Flush(); } } finally { temp.Close(); } } results = FromFileBatch(options, filenames); #if !FEATURE_PAL } finally { Executor.ReImpersonate(impersonation); } } catch { throw; } #endif // !FEATURE_PAL return results; } ////// Compiles the specified compile units and /// options, and returns the results from the compilation. /// ////// private void ResolveReferencedAssemblies(CompilerParameters options, CodeCompileUnit e) { if (e.ReferencedAssemblies.Count > 0) { foreach(string assemblyName in e.ReferencedAssemblies) { if (!options.ReferencedAssemblies.Contains(assemblyName)) { options.ReferencedAssemblies.Add(assemblyName); } } } } ////// Because CodeCompileUnit and CompilerParameters both have a referenced assemblies /// property, they must be reconciled. However, because you can compile multiple /// compile units with one set of options, it will simply merge them. /// ////// private CompilerResults FromSourceBatch(CompilerParameters options, string[] sources) { if( options == null) { throw new ArgumentNullException("options"); } if (sources == null) throw new ArgumentNullException("sources"); new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); string[] filenames = new string[sources.Length]; CompilerResults results = null; #if !FEATURE_PAL // the extra try-catch is here to mitigate exception filter injection attacks. try { WindowsImpersonationContext impersonation = Executor.RevertImpersonation(); try { #endif // !FEATURE_PAL for (int i = 0; i < sources.Length; i++) { string name = options.TempFiles.AddExtension(i + FileExtension); Stream temp = new FileStream(name, FileMode.Create, FileAccess.Write, FileShare.Read); try { using (StreamWriter sw = new StreamWriter(temp, Encoding.UTF8)) { sw.Write(sources[i]); sw.Flush(); } } finally { temp.Close(); } filenames[i] = name; } results = FromFileBatch(options, filenames); #if !FEATURE_PAL } finally { Executor.ReImpersonate(impersonation); } } catch { throw; } #endif // !FEATURE_PAL return results; } ////// Compiles the specified source code strings using the specified options, and /// returns the results from the compilation. /// ////// private static string JoinStringArray(string[] sa, string separator) { if (sa == null || sa.Length == 0) return String.Empty; if (sa.Length == 1) { return "\"" + sa[0] + "\""; } StringBuilder sb = new StringBuilder(); for (int i = 0; i < sa.Length - 1; i++) { sb.Append("\""); sb.Append(sa[i]); sb.Append("\""); sb.Append(separator); } sb.Append("\""); sb.Append(sa[sa.Length - 1]); sb.Append("\""); return sb.ToString(); } ///Joins the specified string arrays. ///void ICodeGenerator.GenerateCodeFromType(CodeTypeDeclaration e, TextWriter w, CodeGeneratorOptions o) { bool setLocal = false; if (output != null && w != output.InnerWriter) { throw new InvalidOperationException(SR.GetString(SR.CodeGenOutputWriter)); } if (output == null) { setLocal = true; options = (o == null) ? new CodeGeneratorOptions() : o; output = new IndentedTextWriter(w, options.IndentString); } try { GenerateType(e); } finally { if (setLocal) { output = null; options = null; } } } /// void ICodeGenerator.GenerateCodeFromExpression(CodeExpression e, TextWriter w, CodeGeneratorOptions o) { bool setLocal = false; if (output != null && w != output.InnerWriter) { throw new InvalidOperationException(SR.GetString(SR.CodeGenOutputWriter)); } if (output == null) { setLocal = true; options = (o == null) ? new CodeGeneratorOptions() : o; output = new IndentedTextWriter(w, options.IndentString); } try { GenerateExpression(e); } finally { if (setLocal) { output = null; options = null; } } } /// void ICodeGenerator.GenerateCodeFromCompileUnit(CodeCompileUnit e, TextWriter w, CodeGeneratorOptions o) { bool setLocal = false; if (output != null && w != output.InnerWriter) { throw new InvalidOperationException(SR.GetString(SR.CodeGenOutputWriter)); } if (output == null) { setLocal = true; options = (o == null) ? new CodeGeneratorOptions() : o; output = new IndentedTextWriter(w, options.IndentString); } try { if (e is CodeSnippetCompileUnit) { GenerateSnippetCompileUnit((CodeSnippetCompileUnit) e); } else { GenerateCompileUnit(e); } } finally { if (setLocal) { output = null; options = null; } } } /// void ICodeGenerator.GenerateCodeFromNamespace(CodeNamespace e, TextWriter w, CodeGeneratorOptions o) { bool setLocal = false; if (output != null && w != output.InnerWriter) { throw new InvalidOperationException(SR.GetString(SR.CodeGenOutputWriter)); } if (output == null) { setLocal = true; options = (o == null) ? new CodeGeneratorOptions() : o; output = new IndentedTextWriter(w, options.IndentString); } try { GenerateNamespace(e); } finally { if (setLocal) { output = null; options = null; } } } /// void ICodeGenerator.GenerateCodeFromStatement(CodeStatement e, TextWriter w, CodeGeneratorOptions o) { bool setLocal = false; if (output != null && w != output.InnerWriter) { throw new InvalidOperationException(SR.GetString(SR.CodeGenOutputWriter)); } if (output == null) { setLocal = true; options = (o == null) ? new CodeGeneratorOptions() : o; output = new IndentedTextWriter(w, options.IndentString); } try { GenerateStatement(e); } finally { if (setLocal) { output = null; options = null; } } } } internal class CSharpTypeAttributeConverter : CSharpModifierAttributeConverter { private static string[] names; private static object[] values; private static CSharpTypeAttributeConverter defaultConverter; private CSharpTypeAttributeConverter() { // no need to create an instance; use Default } public static CSharpTypeAttributeConverter Default { get { if (defaultConverter == null) { defaultConverter = new CSharpTypeAttributeConverter(); } return defaultConverter; } } /// /// Retrieves an array of names for attributes. /// protected override string[] Names { get { if (names == null) { names = new string[] { "Public", "Internal" }; } return names; } } ////// Retrieves an array of values for attributes. /// protected override object[] Values { get { if (values == null) { values = new object[] { (object)TypeAttributes.Public, (object)TypeAttributes.NotPublic }; } return values; } } protected override object DefaultValue { get { return TypeAttributes.NotPublic; } } } internal class CSharpMemberAttributeConverter : CSharpModifierAttributeConverter { private static string[] names; private static object[] values; private static CSharpMemberAttributeConverter defaultConverter; private CSharpMemberAttributeConverter() { // no need to create an instance; use Default } public static CSharpMemberAttributeConverter Default { get { if (defaultConverter == null) { defaultConverter = new CSharpMemberAttributeConverter(); } return defaultConverter; } } ////// Retrieves an array of names for attributes. /// protected override string[] Names { get { if (names == null) { names = new string[] { "Public", "Protected", "Protected Internal", "Internal", "Private" }; } return names; } } ////// Retrieves an array of values for attributes. /// protected override object[] Values { get { if (values == null) { values = new object[] { (object)MemberAttributes.Public, (object)MemberAttributes.Family, (object)MemberAttributes.FamilyOrAssembly, (object)MemberAttributes.Assembly, (object)MemberAttributes.Private }; } return values; } } protected override object DefaultValue { get { return MemberAttributes.Private; } } } ////// This type converter provides common values for MemberAttributes /// internal abstract class CSharpModifierAttributeConverter : TypeConverter { protected abstract object[] Values { get; } protected abstract string[] Names { get; } protected abstract object DefaultValue { get; } ////// We override this because we can convert from string types. /// public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { if (sourceType == typeof(string)) { return true; } return base.CanConvertFrom(context, sourceType); } ////// Converts the given object to the converter's native type. /// public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { if (value is string) { string name = (string)value; string[] names = Names; for (int i = 0; i < names.Length; i++) { if (names[i].Equals(name)) { return Values[i]; } } } return DefaultValue; } ////// Converts the given object to another type. The most common types to convert /// are to and from a string object. The default implementation will make a call /// to ToString on the object if the object is valid and if the destination /// type is string. If this cannot convert to the desitnation type, this will /// throw a NotSupportedException. /// public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { if (destinationType == null) { throw new ArgumentNullException("destinationType"); } if (destinationType == typeof(string)) { object[] modifiers = Values; for (int i = 0; i < modifiers.Length; i++) { if (modifiers[i].Equals(value)) { return Names[i]; } } return SR.GetString(SR.toStringUnknown); } return base.ConvertTo(context, culture, value, destinationType); } ////// Determines if the list of standard values returned from /// GetStandardValues is an exclusive list. If the list /// is exclusive, then no other values are valid, such as /// in an enum data type. If the list is not exclusive, /// then there are other valid values besides the list of /// standard values GetStandardValues provides. /// public override bool GetStandardValuesExclusive(ITypeDescriptorContext context) { return true; } ////// Determines if this object supports a standard set of values /// that can be picked from a list. /// public override bool GetStandardValuesSupported(ITypeDescriptorContext context) { return true; } ////// Retrieves a collection containing a set of standard values /// for the data type this validator is designed for. This /// will return null if the data type does not support a /// standard set of values. /// public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context) { return new StandardValuesCollection(Values); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- BamlLocalizabilityResolver.cs
- RemoteWebConfigurationHost.cs
- TextModifierScope.cs
- SqlCommandBuilder.cs
- Bind.cs
- FileSystemEnumerable.cs
- ModelItem.cs
- Hashtable.cs
- DataGridViewEditingControlShowingEventArgs.cs
- ErrorHandlerModule.cs
- BrowserCapabilitiesFactory.cs
- SerializableAttribute.cs
- CommonXSendMessage.cs
- SqlTrackingWorkflowInstance.cs
- CustomUserNameSecurityTokenAuthenticator.cs
- UInt64Converter.cs
- SafeEventLogReadHandle.cs
- Msec.cs
- CodeSnippetStatement.cs
- HostDesigntimeLicenseContext.cs
- HyperLinkStyle.cs
- XamlReaderHelper.cs
- MemberInfoSerializationHolder.cs
- XmlUtilWriter.cs
- HtmlEncodedRawTextWriter.cs
- SpecialTypeDataContract.cs
- TimelineCollection.cs
- StylusPointDescription.cs
- ConsumerConnectionPointCollection.cs
- ScriptIgnoreAttribute.cs
- OrderedDictionary.cs
- SHA1Managed.cs
- WriteableBitmap.cs
- FrameworkContextData.cs
- CheckBox.cs
- FormClosedEvent.cs
- FilteredDataSetHelper.cs
- TextEditorCharacters.cs
- WeakReferenceEnumerator.cs
- PerformanceCounterManager.cs
- MessageOperationFormatter.cs
- TagPrefixCollection.cs
- GridItem.cs
- SelectedDatesCollection.cs
- EntityReference.cs
- FormViewDeletedEventArgs.cs
- AnnotationHighlightLayer.cs
- WebPartCatalogAddVerb.cs
- StringDictionary.cs
- ClientSession.cs
- ChildChangedEventArgs.cs
- SecurityResources.cs
- SqlAggregateChecker.cs
- DescriptionAttribute.cs
- CategoryGridEntry.cs
- GraphicsState.cs
- WhileDesigner.cs
- ColumnMapCopier.cs
- Compensate.cs
- PersonalizationAdministration.cs
- OleDbDataReader.cs
- Assert.cs
- ValidationVisibilityAttribute.cs
- XmlQueryType.cs
- SettingsSavedEventArgs.cs
- XmlBinaryReaderSession.cs
- StructuredTypeEmitter.cs
- AsyncOperationManager.cs
- TreeNodeStyleCollection.cs
- Metafile.cs
- PasswordBox.cs
- InvalidCastException.cs
- cache.cs
- FormatConvertedBitmap.cs
- KoreanLunisolarCalendar.cs
- DataGridViewCellConverter.cs
- AdornerHitTestResult.cs
- Binding.cs
- XamlPoint3DCollectionSerializer.cs
- MobileComponentEditorPage.cs
- WindowsListViewGroup.cs
- TerminatorSinks.cs
- DataStorage.cs
- InplaceBitmapMetadataWriter.cs
- SHA512.cs
- Misc.cs
- ContentDisposition.cs
- UpdatePanelTrigger.cs
- Configuration.cs
- XmlAttributeAttribute.cs
- ControlCachePolicy.cs
- AssemblyBuilder.cs
- SHA512Managed.cs
- LogicalExpr.cs
- ParserExtension.cs
- GridViewRowEventArgs.cs
- SimpleLine.cs
- DataPagerFieldCollection.cs
- AuthenticatingEventArgs.cs
- TemplateField.cs