Skip to content

Commit

Permalink
Make non-generic collections and arrays work (fixes #211)
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Ganss committed Jun 9, 2020
1 parent c279eb0 commit 24d63bf
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 24 deletions.
5 changes: 4 additions & 1 deletion XmlSchemaClassGenerator.Tests/Compiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public static CompilationResult GenerateAssembly(Compilation compilation)
"System.Private.Xml",
"System.Private.Xml.Linq",
"System.Runtime",
"System.Runtime.Extensions",
"System.Xml.XDocument",
"System.Xml.XmlSerializer",
};
Expand Down Expand Up @@ -104,7 +105,9 @@ public static Assembly GenerateFiles(string name, IEnumerable<string> files, Gen
CollectionSettersMode = generatorPrototype.CollectionSettersMode,
TextValuePropertyName = generatorPrototype.TextValuePropertyName,
EmitOrder = generatorPrototype.EmitOrder,
SeparateClasses = generatorPrototype.SeparateClasses
SeparateClasses = generatorPrototype.SeparateClasses,
CollectionType = generatorPrototype.CollectionType,
CollectionImplementationType = generatorPrototype.CollectionImplementationType
};

output.Configuration = gen.Configuration;
Expand Down
24 changes: 20 additions & 4 deletions XmlSchemaClassGenerator.Tests/XmlTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -379,16 +379,32 @@ public void TestTableau()
public void TestSeparateClasses()
{
var output = new FileWatcherOutputWriter(Path.Combine("output", "Tableau.Separate"));
Compiler.Generate("Tableau.Separate", TableauPattern,
new Generator
{
OutputWriter = output,
Compiler.Generate("Tableau.Separate", TableauPattern,
new Generator
{
OutputWriter = output,
SeparateClasses = true,
EnableDataBinding = true
});
TestSamples("Tableau.Separate", TableauPattern);
}

[Fact, TestPriority(1)]
[UseCulture("en-US")]
public void TestArray()
{
var output = new FileWatcherOutputWriter(Path.Combine("output", "Tableau.Array"));
Compiler.Generate("Tableau.Array", TableauPattern,
new Generator
{
OutputWriter = output,
EnableDataBinding = true,
CollectionType = typeof(System.Array),
CollectionSettersMode = CollectionSettersMode.Public
});
TestSamples("Tableau.Array", TableauPattern);
}

[Fact, TestPriority(1)]
[UseCulture("en-US")]
public void TestDtsx()
Expand Down
60 changes: 41 additions & 19 deletions XmlSchemaClassGenerator/TypeModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -717,7 +717,7 @@ private bool IsNullableValueType
{
return DefaultValue == null
&& IsNullable && !(IsCollection || IsArray) && !IsList
&& ((PropertyType is EnumModel) || (PropertyType is SimpleModel && ((SimpleModel)PropertyType).ValueType.IsValueType));
&& ((PropertyType is EnumModel) || (PropertyType is SimpleModel model && model.ValueType.IsValueType));
}
}

Expand All @@ -727,7 +727,7 @@ private bool IsNillableValueType
{
return IsNillable
&& !(IsCollection || IsArray)
&& ((PropertyType is EnumModel) || (PropertyType is SimpleModel && ((SimpleModel)PropertyType).ValueType.IsValueType));
&& ((PropertyType is EnumModel) || (PropertyType is SimpleModel model && model.ValueType.IsValueType));
}
}

Expand Down Expand Up @@ -1056,7 +1056,9 @@ public void AddMembersTo(CodeTypeDeclaration typeDeclaration, bool withDataBindi
specifiedProperty.Attributes = MemberAttributes.Public | MemberAttributes.Final;

var listReference = new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), Name);
var countReference = new CodePropertyReferenceExpression(listReference, "Count");
var collectionType = Configuration.CollectionImplementationType ?? Configuration.CollectionType;
var countProperty = collectionType == typeof(System.Array) ? "Length" : "Count";
var countReference = new CodePropertyReferenceExpression(listReference, countProperty);
var notZeroExpression = new CodeBinaryOperatorExpression(countReference, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(0));
if (Configuration.CollectionSettersMode == CollectionSettersMode.PublicWithoutConstructorInitialization)
{
Expand All @@ -1082,6 +1084,7 @@ public void AddMembersTo(CodeTypeDeclaration typeDeclaration, bool withDataBindi
if ((IsCollection || isArray || (IsList && IsAttribute)) && Configuration.CollectionSettersMode != CollectionSettersMode.PublicWithoutConstructorInitialization)
{
var constructor = typeDeclaration.Members.OfType<CodeConstructor>().FirstOrDefault();

if (constructor == null)
{
constructor = new CodeConstructor { Attributes = MemberAttributes.Public | MemberAttributes.Final };
Expand All @@ -1090,10 +1093,24 @@ public void AddMembersTo(CodeTypeDeclaration typeDeclaration, bool withDataBindi
constructor.Comments.AddRange(DocumentationModel.GetComments(constructorDocs).ToArray());
typeDeclaration.Members.Add(constructor);
}

var listReference = requiresBackingField ? (CodeExpression)new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), backingField.Name) :
new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), Name);
var initTypeReference = propertyType.GetReferenceFor(OwningType.Namespace, collection: true, forInit: true, attribute: IsAttribute);
var initExpression = new CodeObjectCreateExpression(initTypeReference);
var collectionType = Configuration.CollectionImplementationType ?? Configuration.CollectionType;

CodeExpression initExpression;

if (collectionType == typeof(System.Array))
{
var initTypeReference = propertyType.GetReferenceFor(OwningType.Namespace, collection: false, forInit: true, attribute: IsAttribute);
initExpression = new CodeArrayCreateExpression(initTypeReference);
}
else
{
var initTypeReference = propertyType.GetReferenceFor(OwningType.Namespace, collection: true, forInit: true, attribute: IsAttribute);
initExpression = new CodeObjectCreateExpression(initTypeReference);
}

constructor.Statements.Add(new CodeAssignStatement(listReference, initExpression));
}

Expand Down Expand Up @@ -1350,21 +1367,26 @@ public SimpleModel(GeneratorConfiguration configuration)

public static string GetCollectionDefinitionName(string typeName, GeneratorConfiguration configuration)
{
var typeRef = new CodeTypeReference(configuration.CollectionType, configuration.CodeTypeReferenceOptions);
return GetFullTypeName(typeName, configuration, typeRef);
var type = configuration.CollectionType;
var typeRef = new CodeTypeReference(type, configuration.CodeTypeReferenceOptions);
return GetFullTypeName(typeName, typeRef, type);
}

public static string GetCollectionImplementationName(string typeName, GeneratorConfiguration configuration)
{
var typeRef = new CodeTypeReference(configuration.CollectionImplementationType ?? configuration.CollectionType, configuration.CodeTypeReferenceOptions);
return GetFullTypeName(typeName, configuration, typeRef);
var type = configuration.CollectionImplementationType ?? configuration.CollectionType;
var typeRef = new CodeTypeReference(type, configuration.CodeTypeReferenceOptions);
return GetFullTypeName(typeName, typeRef, type);
}

private static string GetFullTypeName(string typeName, GeneratorConfiguration configuration, CodeTypeReference typeRef)
private static string GetFullTypeName(string typeName, CodeTypeReference typeRef, Type type)
{
if (configuration.CollectionType.IsGenericTypeDefinition)
{
if (type.IsGenericTypeDefinition)
typeRef.TypeArguments.Add(typeName);
else if (type == typeof(System.Array))
{
typeRef.ArrayElementType = new CodeTypeReference(typeName);
typeRef.ArrayRank = 1;
}
var typeOfExpr = new CodeTypeOfExpression(typeRef);
var writer = new System.IO.StringWriter();
Expand Down Expand Up @@ -1397,14 +1419,14 @@ public override CodeTypeReference GetReferenceFor(NamespaceModel referencingName

if (collection)
{
if (forInit)
{
type = (Configuration.CollectionImplementationType ?? Configuration.CollectionType).MakeGenericType(type);
}
var collectionType = forInit ? (Configuration.CollectionImplementationType ?? Configuration.CollectionType) : Configuration.CollectionType;

if (collectionType.IsGenericType)
type = collectionType.MakeGenericType(type);
else if (collectionType == typeof(System.Array))
type = type.MakeArrayType();
else
{
type = Configuration.CollectionType.MakeGenericType(type);
}
type = collectionType;
}

return new CodeTypeReference(type, Configuration.CodeTypeReferenceOptions);
Expand Down

0 comments on commit 24d63bf

Please sign in to comment.