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