Skip to content

Commit

Permalink
Add UseArrayItemAttribute option (fixes #313)
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Ganss committed Mar 21, 2022
1 parent a317132 commit 732fcd2
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 13 deletions.
3 changes: 3 additions & 0 deletions XmlSchemaClassGenerator.Console/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ static void Main(string[] args)
var netCoreSpecificCode = false;
var nullableReferenceAttributes = false;
var generateCommandLineArgs = true;
var useArrayItemAttribute = true;

var options = new OptionSet {
{ "h|help", "show this message and exit", v => showHelp = v != null },
Expand Down Expand Up @@ -129,6 +130,7 @@ A file name may be given by appending a pipe sign (|) followed by a file name (l
{ "gc|generatedCodeAttribute", "add version information to GeneratedCodeAttribute (default is true)", v => createGeneratedCodeAttributeVersion = v != null },
{ "nc|netCore", "generate .NET Core specific code that might not work with .NET Framework (default is false)", v => netCoreSpecificCode = v != null },
{ "nr|nullableReferenceAttributes", "generate attributes for nullable reference types (default is false)", v => nullableReferenceAttributes = v != null },
{ "ar|useArrayItemAttribute", "use ArrayItemAttribute for sequences with single elements (default is true)", v => useArrayItemAttribute = v != null },
{ "ca|commandArgs", "generate a comment with the exact command line arguments that were used to generate the source code (default is true)", v => generateCommandLineArgs = v != null },
};

Expand Down Expand Up @@ -207,6 +209,7 @@ A file name may be given by appending a pipe sign (|) followed by a file name (l
NetCoreSpecificCode = netCoreSpecificCode,
EnableNullableReferenceAttributes = nullableReferenceAttributes,
GenerateCommandLineArgumentsComment = generateCommandLineArgs,
UseArrayItemAttribute = useArrayItemAttribute,
};

generator.CommentLanguages.AddRange(commentLanguages);
Expand Down
3 changes: 2 additions & 1 deletion XmlSchemaClassGenerator.Tests/Compiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@ public static Assembly GenerateFiles(string name, IEnumerable<string> files, Gen
CreateGeneratedCodeAttributeVersion = generatorPrototype.CreateGeneratedCodeAttributeVersion,
NetCoreSpecificCode = generatorPrototype.NetCoreSpecificCode,
EnableNullableReferenceAttributes = generatorPrototype.EnableNullableReferenceAttributes,
NamingScheme = generatorPrototype.NamingScheme
NamingScheme = generatorPrototype.NamingScheme,
UseArrayItemAttribute = generatorPrototype.UseArrayItemAttribute,
};

gen.CommentLanguages.Clear();
Expand Down
58 changes: 54 additions & 4 deletions XmlSchemaClassGenerator.Tests/XmlTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ private static IEnumerable<string> ConvertXml(string name, IEnumerable<string> x
CollectionType = generatorPrototype.CollectionType,
CollectionImplementationType = generatorPrototype.CollectionImplementationType,
CollectionSettersMode = generatorPrototype.CollectionSettersMode,
UseArrayItemAttribute = generatorPrototype.UseArrayItemAttribute,
};

gen.CommentLanguages.Clear();
Expand Down Expand Up @@ -2371,20 +2372,20 @@ void UnknownAttributeHandler(object sender, XmlAttributeEventArgs e)

[Fact, TestPriority(1)]
[UseCulture("en-US")]
public void TestNullableReferenceAttributes()
public void TestNullableReferenceAttributes()
{
var files = Glob.ExpandNames(NullableReferenceAttributesPattern).OrderByDescending(f => f);
var generator = new Generator
var generator = new Generator
{
EnableNullableReferenceAttributes = true,
UseShouldSerializePattern = true,
NamespaceProvider = new NamespaceProvider
NamespaceProvider = new NamespaceProvider
{
GenerateNamespace = key => "Test"
}
};
var assembly = Compiler.Generate(nameof(TestNullableReferenceAttributes), NullableReferenceAttributesPattern, generator);
void assertNullable(string typename, bool nullable)
void assertNullable(string typename, bool nullable)
{
Type c = assembly.GetType(typename);
var property = c.GetProperty("Text");
Expand Down Expand Up @@ -2528,5 +2529,54 @@ public partial class Elem
}}
", csharp);
}

[Fact]
public void TestArrayItemAttribute()
{
// see https://github.com/mganss/XmlSchemaClassGenerator/issues/313

var xsd =
@"<?xml version=""1.0"" encoding=""UTF-8""?>
<xs:schema xmlns:xs=""http://www.w3.org/2001/XMLSchema""
xmlns=""test_generation_namespace/common.xsd""
xmlns:ct=""test_generation_namespace/commontypes.xsd""
targetNamespace=""test_generation_namespace/common.xsd""
version=""1.1""
elementFormDefault=""qualified""
attributeFormDefault=""unqualified"">
<xs:import namespace=""test_generation_namespace/commontypes.xsd"" schemaLocation=""TheCommonTypes.xsd""/>
<xs:complexType name=""T_NameValue"">
<xs:sequence>
<xs:element name=""Name"" type=""xs:string""/>
<xs:element name=""Value"" type=""xs:string"" minOccurs=""0""/>
</xs:sequence>
</xs:complexType>
<xs:complexType name=""T_OptionList"">
<xs:sequence>
<xs:element name=""Option"" type=""T_NameValue"" minOccurs=""0"" maxOccurs=""unbounded""/>
</xs:sequence>
</xs:complexType>
<xs:complexType name=""T_Application"">
<xs:sequence>
<xs:element name=""OptionList"" type=""T_OptionList"" minOccurs=""0""/>
</xs:sequence>
</xs:complexType>
</xs:schema>";
var generator = new Generator
{
IntegerDataType = typeof(int),
GenerateNullables = true,
CollectionType = typeof(System.Array),
CollectionSettersMode = CollectionSettersMode.Public,
UseArrayItemAttribute = false
};
var contents = ConvertXml(nameof(TestArrayItemAttribute), new[] { xsd }, generator).ToArray();
var assembly = Compiler.Compile(nameof(TestArrayItemAttribute), contents);
var applicationType = assembly.GetType("Test_Generation_Namespace.T_Application");
Assert.NotNull(applicationType);
var optionList = applicationType.GetProperty("OptionList");
Assert.Equal("Test_Generation_Namespace.T_OptionList", optionList.PropertyType.FullName);
}
}
}
2 changes: 1 addition & 1 deletion XmlSchemaClassGenerator/CodeUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ public static string GetUniqueTypeName(this NamespaceModel model, string name)
var n = name;
var i = 2;

while (model.Types.ContainsKey(n) && !(model.Types[n] is SimpleModel))
while (model.Types.ContainsKey(n) && model.Types[n] is not SimpleModel)
{
n = name + i;
i++;
Expand Down
8 changes: 7 additions & 1 deletion XmlSchemaClassGenerator/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public bool GenerateNullables
set { _configuration.GenerateNullables = value; }
}

public bool EnableNullableReferenceAttributes
public bool EnableNullableReferenceAttributes
{
get { return _configuration.EnableNullableReferenceAttributes; }
set { _configuration.EnableNullableReferenceAttributes = value; }
Expand Down Expand Up @@ -294,6 +294,12 @@ public bool NetCoreSpecificCode
set { _configuration.NetCoreSpecificCode = value; }
}

public bool UseArrayItemAttribute
{
get { return _configuration.UseArrayItemAttribute; }
set { _configuration.UseArrayItemAttribute = value;}
}

public bool GenerateCommandLineArgumentsComment
{
get { return _configuration.GenerateCommandLineArgumentsComment; }
Expand Down
6 changes: 6 additions & 0 deletions XmlSchemaClassGenerator/GeneratorConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -320,5 +320,11 @@ public void WriteLog(string message)
/// A provider to obtain the command line arguments of the tool.
/// </summary>
public CommandLineArgumentsProvider CommandLineArgumentsProvider { get; set; }

/// <summary>
/// Enables use of <see cref="System.Xml.Serialization.XmlArrayItemAttribute"/>
/// for sequences with single elements. Default is true.
/// </summary>
public bool UseArrayItemAttribute { get; set; } = true;
}
}
13 changes: 7 additions & 6 deletions XmlSchemaClassGenerator/TypeModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ public override CodeTypeDeclaration Generate()
if (IsAbstract)
classDeclaration.TypeAttributes |= System.Reflection.TypeAttributes.Abstract;

if (Configuration.EnableDataBinding && !(BaseClass is ClassModel))
if (Configuration.EnableDataBinding && BaseClass is not ClassModel)
{
var propertyChangedEvent = new CodeMemberEvent()
{
Expand Down Expand Up @@ -432,7 +432,7 @@ public override CodeTypeDeclaration Generate()
classDeclaration.BaseTypes.Add(CodeUtilities.CreateTypeReference(typeof(INotifyPropertyChanged), Configuration));
}

if (Configuration.EntityFramework && !(BaseClass is ClassModel))
if (Configuration.EntityFramework && BaseClass is not ClassModel)
{
// generate key
var keyProperty = Properties.FirstOrDefault(p => p.Name.ToLowerInvariant() == "id")
Expand Down Expand Up @@ -729,7 +729,8 @@ public bool IsArray
{
get
{
return !IsCollection && !IsAttribute && !IsList && TypeClassModel != null
return Configuration.UseArrayItemAttribute
&& !IsCollection && !IsAttribute && !IsList && TypeClassModel != null
&& TypeClassModel.BaseClass == null
&& TypeClassModel.Properties.Count == 1
&& !TypeClassModel.Properties[0].IsAttribute && !TypeClassModel.Properties[0].IsAny
Expand All @@ -752,9 +753,9 @@ private bool IsNullableValueType
}
}

private bool IsNullableReferenceType
private bool IsNullableReferenceType
{
get
get
{
return DefaultValue == null
&& IsNullable && (IsCollection || IsArray || IsList || PropertyType is ClassModel || PropertyType is SimpleModel model && !model.ValueType.IsValueType);
Expand Down Expand Up @@ -1124,7 +1125,7 @@ public void AddMembersTo(CodeTypeDeclaration typeDeclaration, bool withDataBindi
typeDeclaration.Members.Add(specifiedProperty);
}

if (isNullableReferenceType && Configuration.EnableNullableReferenceAttributes)
if (isNullableReferenceType && Configuration.EnableNullableReferenceAttributes)
{
member.CustomAttributes.Add(new CodeAttributeDeclaration("System.Diagnostics.CodeAnalysis.AllowNullAttribute"));
member.CustomAttributes.Add(new CodeAttributeDeclaration("System.Diagnostics.CodeAnalysis.MaybeNullAttribute"));
Expand Down

0 comments on commit 732fcd2

Please sign in to comment.