2 // CodeGenerator.GenerateFromCompileUnit Tests
5 // Ilker Cetinkaya (mail@ilker.de)
7 // This is a specific test for an issue on GenerateFromCompileUnit.
8 // Up until 2012 (version 2.10.n) the method emits attribute first
9 // and imports afterwards on global namespace scope. Example:
12 // [assembly: AssemblyVersion("1.0")]
13 // using System.Reflection;
16 // This in particular causes compiler to bail with CS1529.
17 // Albeit well aware that this is a _language specific_ issue
18 // (or requirement), the actual fix is aimed on CodeGenerator since
19 // the wrong emit order is as well in GenerateFromCompileUnit of abstract
20 // base. The probability to harm any other language generators
21 // is very low. It's near common sense to have imports on top
22 // on global namespace / file level.
24 // The test is being repeated for the internal `CSharpCodeGenerator`.
25 // See `Microsoft.CSharp` (Mono.CSharp namespace) for details.
27 // This test verifies the issue as well as describes correct expectation.
31 using System.CodeDom.Compiler;
32 using Microsoft.CSharp;
35 using NUnit.Framework;
37 namespace MonoTests.System.CodeDom.Compiler
40 public class CodeGeneratorGenerateFromCompileUnitTest {
42 [Ignore ("This test is wrong; on .NET, ATTRIBUTE is not written and this attributePosition is always < 0.")]
43 public void When_Having_AssemblyAttribute_And_Using_Namespace_It_Should_Generate_Namespace_First_And_Attribute_Afterwards () {
44 ICodeGenerator generator = new SampleCodeGenerator ();
45 var compileUnit = ACompileUnitWithAttributeAndNamespace ();
46 var writer = new StringWriter ();
47 var options = new CodeGeneratorOptions ();
49 generator.GenerateCodeFromCompileUnit (compileUnit, writer, options);
51 string result = writer.ToString ();
53 int importPosition = result.IndexOf (IMPORT);
54 int attributePosition = result.IndexOf (ATTRIBUTE);
56 AssertHelper.Greater (attributePosition, importPosition, "Actual order: " + result);
60 public void CodeSnippetBlankLines ()
62 var opt = new CodeGeneratorOptions () {
63 BlankLinesBetweenMembers = false,
67 var ccu = new CodeCompileUnit ();
68 var ns = new CodeNamespace ("Foo");
69 ccu.Namespaces.Add (ns);
70 var t = new CodeTypeDeclaration ("Bar");
73 t.Members.Add (new CodeSnippetTypeMember ("#line hidden"));
74 t.Members.Add (new CodeSnippetTypeMember ("#line hidden2"));
76 t.Members.Add (new CodeMemberMethod () { Name = "Foo" });
78 using (var sw = new StringWriter ()) {
79 new CSharpCodeProvider ().GenerateCodeFromCompileUnit (ccu, sw, opt);
80 var str = sw.ToString ();
82 Assert.IsFalse (str.Contains ("hidden2private"), "#0");
83 Assert.IsTrue (str.Contains( "#line hidden#line hidden2"), "#1");
88 public void CodeSnippetBlankLinesVerbatimOrder ()
90 var opt = new CodeGeneratorOptions () {
91 BlankLinesBetweenMembers = false,
95 var ccu = new CodeCompileUnit ();
96 var ns = new CodeNamespace ("Foo");
97 ccu.Namespaces.Add (ns);
98 var t = new CodeTypeDeclaration ("Bar");
101 t.Members.Add (new CodeSnippetTypeMember ("#line hidden"));
102 t.Members.Add (new CodeSnippetTypeMember ("#line hidden2"));
104 t.Members.Add (new CodeMemberMethod () { Name = "Foo" });
106 using (var sw = new StringWriter ()) {
107 new CSharpCodeProvider ().GenerateCodeFromCompileUnit (ccu, sw, opt);
108 var str = sw.ToString ();
110 Assert.IsFalse (str.Contains ("hidden2private"), "#0");
111 Assert.IsFalse (str.Contains( "#line hidden#line hidden2"), "#1");
112 Assert.IsTrue (str.Contains( "#line hidden" + Environment.NewLine), "#2");
113 Assert.IsTrue (str.Contains( "#line hidden2" + Environment.NewLine), "#3");
117 private const string ATTRIBUTE = "ATTRIBUTE";
118 private const string IMPORT = "IMPORT";
120 private CodeCompileUnit ACompileUnitWithAttributeAndNamespace () {
121 var compileUnit = new CodeCompileUnit ();
122 var importNs = new CodeNamespace ();
124 importNs.Imports.Add (new CodeNamespaceImport (IMPORT));
126 compileUnit.AssemblyCustomAttributes.Add (new CodeAttributeDeclaration (ATTRIBUTE));
127 compileUnit.Namespaces.Add (importNs);
132 private class SampleCodeGenerator : CodeGenerator {
134 protected override void GenerateAttributeDeclarationsStart (CodeAttributeDeclarationCollection attributes) { Output.Write ("ATTRIBUTE"); }
135 protected override void GenerateAttributeDeclarationsEnd (CodeAttributeDeclarationCollection attributes) {}
136 protected override void GenerateNamespaceImport (CodeNamespaceImport i) { Output.Write ("IMPORT"); }
138 protected override string NullToken { get { return string.Empty; } }
139 protected override void GenerateArgumentReferenceExpression (CodeArgumentReferenceExpression e) {}
140 protected override void GenerateArrayCreateExpression (CodeArrayCreateExpression e) {}
141 protected override void GenerateArrayIndexerExpression (CodeArrayIndexerExpression e) {}
142 protected override void GenerateAssignStatement (CodeAssignStatement s) {}
143 protected override void GenerateAttachEventStatement (CodeAttachEventStatement s) {}
144 protected override void GenerateBaseReferenceExpression (CodeBaseReferenceExpression e) {}
145 protected override void GenerateCastExpression (CodeCastExpression e) {}
146 protected override void GenerateComment (CodeComment comment) {}
147 protected override void GenerateConditionStatement (CodeConditionStatement s) {}
148 protected override void GenerateConstructor (CodeConstructor x, CodeTypeDeclaration d) {}
149 protected override void GenerateDelegateCreateExpression (CodeDelegateCreateExpression e) {}
150 protected override void GenerateDelegateInvokeExpression (CodeDelegateInvokeExpression e) {}
151 protected override void GenerateEntryPointMethod (CodeEntryPointMethod m, CodeTypeDeclaration d) {}
152 protected override void GenerateEvent (CodeMemberEvent ev, CodeTypeDeclaration d) {}
153 protected override void GenerateEventReferenceExpression (CodeEventReferenceExpression e) {}
154 protected override void GenerateExpressionStatement (CodeExpressionStatement statement) {}
155 protected override void GenerateField (CodeMemberField f) {}
156 protected override void GenerateFieldReferenceExpression (CodeFieldReferenceExpression e) {}
157 protected override void GenerateGotoStatement (CodeGotoStatement statement) {}
158 protected override void GenerateIndexerExpression (CodeIndexerExpression e) {}
159 protected override void GenerateIterationStatement (CodeIterationStatement s) {}
160 protected override void GenerateLabeledStatement (CodeLabeledStatement statement) {}
161 protected override void GenerateLinePragmaStart (CodeLinePragma p) {}
162 protected override void GenerateLinePragmaEnd (CodeLinePragma p) {}
163 protected override void GenerateMethod (CodeMemberMethod m, CodeTypeDeclaration d) {}
164 protected override void GenerateMethodInvokeExpression (CodeMethodInvokeExpression e) {}
165 protected override void GenerateMethodReferenceExpression (CodeMethodReferenceExpression e) {}
166 protected override void GenerateMethodReturnStatement (CodeMethodReturnStatement e) {}
167 protected override void GenerateNamespaceStart (CodeNamespace ns) {}
168 protected override void GenerateNamespaceEnd (CodeNamespace ns) {}
169 protected override void GenerateObjectCreateExpression (CodeObjectCreateExpression e) {}
170 protected override void GenerateProperty (CodeMemberProperty p, CodeTypeDeclaration d) {}
171 protected override void GeneratePropertyReferenceExpression (CodePropertyReferenceExpression e) {}
172 protected override void GeneratePropertySetValueReferenceExpression (CodePropertySetValueReferenceExpression e) {}
173 protected override void GenerateRemoveEventStatement (CodeRemoveEventStatement statement) {}
174 protected override void GenerateSnippetExpression (CodeSnippetExpression e) {}
175 protected override void GenerateSnippetMember (CodeSnippetTypeMember m) {}
176 protected override void GenerateThisReferenceExpression (CodeThisReferenceExpression e) {}
177 protected override void GenerateThrowExceptionStatement (CodeThrowExceptionStatement s) {}
178 protected override void GenerateTryCatchFinallyStatement (CodeTryCatchFinallyStatement s) {}
179 protected override void GenerateTypeEnd (CodeTypeDeclaration declaration) {}
180 protected override void GenerateTypeConstructor (CodeTypeConstructor constructor) {}
181 protected override void GenerateTypeStart (CodeTypeDeclaration declaration) {}
182 protected override void GenerateVariableDeclarationStatement (CodeVariableDeclarationStatement e) {}
183 protected override void GenerateVariableReferenceExpression (CodeVariableReferenceExpression e) {}
184 protected override void OutputType (CodeTypeReference t) {}
185 protected override string QuoteSnippetString (string value) { return string.Empty; }
186 protected override string CreateEscapedIdentifier (string value) { return string.Empty; }
187 protected override string CreateValidIdentifier (string value) { return string.Empty; }
188 protected override string GetTypeOutput (CodeTypeReference type) { return string.Empty; }
189 protected override bool IsValidIdentifier (string value) { return false; }
190 protected override bool Supports (GeneratorSupport supports) { return false; }