Skip to content

Commit

Permalink
Use DataType for date types (see #465)
Browse files Browse the repository at this point in the history
Apply VS code suggestions
  • Loading branch information
mganss committed Apr 19, 2024
1 parent 4ce4394 commit a1c63e4
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 35 deletions.
2 changes: 2 additions & 0 deletions XmlSampleGenerator/XmlSampleGenerator.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,7 @@
<PropertyGroup>
<SonarQubeExclude>true</SonarQubeExclude>
<RunCodeAnalysis>false</RunCodeAnalysis>
<RunAnalyzersDuringLiveAnalysis>False</RunAnalyzersDuringLiveAnalysis>
<RunAnalyzersDuringBuild>False</RunAnalyzersDuringBuild>
</PropertyGroup>
</Project>
28 changes: 28 additions & 0 deletions XmlSchemaClassGenerator.Tests/DateTimeTypeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,34 @@ public void WhenDateTimeOffsetIsNotUsed_DataTypePropertyIsPresent()
Assert.Contains(expectedXmlSerializationAttribute, generatedProperty);
}

[Fact]
public void WhenDateTimeOffsetIsNotUsed_DataTypePropertyIsPresent2()
{
var xsd = @$"<?xml version=""1.0"" encoding=""UTF-8""?>
<xs:schema elementFormDefault=""qualified"" xmlns:xs=""http://www.w3.org/2001/XMLSchema"">
<xs:complexType name=""document"">
<xs:sequence>
<xs:element name=""someDate"" type=""xs:date"" />
</xs:sequence>
</xs:complexType>
</xs:schema>";

var generatedType = ConvertXml(
xsd, new()
{
NamespaceProvider = new()
{
GenerateNamespace = _ => "Test"
},
DateTimeWithTimeZone = true
});

var expectedXmlSerializationAttribute = "[System.Xml.Serialization.XmlElementAttribute(\"someDate\", DataType=\"date\")]";
var generatedProperty = generatedType.First();

Assert.Contains(expectedXmlSerializationAttribute, generatedProperty);
}

[Theory]
[InlineData(false, "System.DateTime")]
[InlineData(true, "System.DateTimeOffset")]
Expand Down
5 changes: 3 additions & 2 deletions XmlSchemaClassGenerator/CodeUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,11 @@ public static string ToCamelCase(this string s) => string.IsNullOrEmpty(s) ? s
public static string ToBackingField(this string propertyName, string privateFieldPrefix)
=> string.Concat(privateFieldPrefix, propertyName.ToCamelCase());

public static bool? IsDataTypeAttributeAllowed(this XmlSchemaDatatype type) => type.TypeCode switch
public static bool? IsDataTypeAttributeAllowed(this XmlSchemaDatatype type, GeneratorConfiguration configuration) => type.TypeCode switch
{
XmlTypeCode.AnyAtomicType => false,// union
XmlTypeCode.DateTime or XmlTypeCode.Time or XmlTypeCode.Date or XmlTypeCode.Base64Binary or XmlTypeCode.HexBinary => true,
XmlTypeCode.DateTime or XmlTypeCode.Time => !configuration.DateTimeWithTimeZone,
XmlTypeCode.Date or XmlTypeCode.Base64Binary or XmlTypeCode.HexBinary => true,
_ => false,
};

Expand Down
48 changes: 19 additions & 29 deletions XmlSchemaClassGenerator/ModelBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ internal class ModelBuilder
private const string ElementName = "Element";
private readonly GeneratorConfiguration _configuration;
private readonly XmlSchemaSet _set;
private readonly Dictionary<XmlQualifiedName, HashSet<XmlSchemaAttributeGroup>> AttributeGroups = new();
private readonly Dictionary<XmlQualifiedName, HashSet<XmlSchemaGroup>> Groups = new();
private readonly Dictionary<NamespaceKey, NamespaceModel> Namespaces = new();
private readonly Dictionary<string, TypeModel> Types = new();
private readonly Dictionary<XmlQualifiedName, HashSet<Substitute>> SubstitutionGroups = new();
private readonly Dictionary<XmlQualifiedName, HashSet<XmlSchemaAttributeGroup>> AttributeGroups = [];
private readonly Dictionary<XmlQualifiedName, HashSet<XmlSchemaGroup>> Groups = [];
private readonly Dictionary<NamespaceKey, NamespaceModel> Namespaces = [];
private readonly Dictionary<string, TypeModel> Types = [];
private readonly Dictionary<XmlQualifiedName, HashSet<Substitute>> SubstitutionGroups = [];

private static readonly XmlQualifiedName AnyType = new("anyType", XmlSchema.Namespace);

Expand Down Expand Up @@ -62,7 +62,7 @@ public ModelBuilder(GeneratorConfiguration configuration, XmlSchemaSet set)
{
if (!AttributeGroups.ContainsKey(currentAttributeGroup.QualifiedName))
{
AttributeGroups.Add(currentAttributeGroup.QualifiedName, new HashSet<XmlSchemaAttributeGroup>());
AttributeGroups.Add(currentAttributeGroup.QualifiedName, []);
}

AttributeGroups[currentAttributeGroup.QualifiedName].Add(currentAttributeGroup);
Expand All @@ -75,7 +75,7 @@ public ModelBuilder(GeneratorConfiguration configuration, XmlSchemaSet set)
{
if (!Groups.ContainsKey(currentSchemaGroup.QualifiedName))
{
Groups.Add(currentSchemaGroup.QualifiedName, new HashSet<XmlSchemaGroup>());
Groups.Add(currentSchemaGroup.QualifiedName, []);
}

Groups[currentSchemaGroup.QualifiedName].Add(currentSchemaGroup);
Expand Down Expand Up @@ -314,7 +314,7 @@ private void CreateElement(XmlSchemaElement rootElement)
{
if (!SubstitutionGroups.TryGetValue(rootElement.SubstitutionGroup, out var substitutes))
{
substitutes = new HashSet<Substitute>();
substitutes = [];
SubstitutionGroups.Add(rootElement.SubstitutionGroup, substitutes);
}

Expand Down Expand Up @@ -422,24 +422,14 @@ private TypeModel CreateTypeModel(XmlQualifiedName qualifiedName, XmlSchemaAnnot
return typeModelBuilder.Create(type);
}

private sealed class TypeModelBuilder
private sealed class TypeModelBuilder(ModelBuilder builder, GeneratorConfiguration configuration, XmlQualifiedName qualifiedName, NamespaceModel namespaceModel, List<DocumentationModel> docs, Uri source)
{
private readonly ModelBuilder builder;
private readonly GeneratorConfiguration _configuration;
private readonly XmlQualifiedName qualifiedName;
private readonly NamespaceModel namespaceModel;
private readonly List<DocumentationModel> docs;
private readonly Uri source;

public TypeModelBuilder(ModelBuilder builder, GeneratorConfiguration configuration, XmlQualifiedName qualifiedName, NamespaceModel namespaceModel, List<DocumentationModel> docs, Uri source)
{
this.builder = builder;
_configuration = configuration;
this.qualifiedName = qualifiedName;
this.namespaceModel = namespaceModel;
this.docs = docs;
this.source = source;
}
private readonly ModelBuilder builder = builder;
private readonly GeneratorConfiguration _configuration = configuration;
private readonly XmlQualifiedName qualifiedName = qualifiedName;
private readonly NamespaceModel namespaceModel = namespaceModel;
private readonly List<DocumentationModel> docs = docs;
private readonly Uri source = source;

internal TypeModel Create(XmlSchemaAnnotated type) => type switch
{
Expand Down Expand Up @@ -661,7 +651,7 @@ XmlSchemaSimpleTypeUnion typeUnion when AllMembersHaveFacets(typeUnion, out base
restrictions = CodeUtilities.GetRestrictions(facets, simpleType, _configuration).Where(r => r != null).Sanitize().ToList();
}

return CreateSimpleModel(simpleType, restrictions ?? new());
return CreateSimpleModel(simpleType, restrictions ?? []);

static bool AllMembersHaveFacets(XmlSchemaSimpleTypeUnion typeUnion, out List<IEnumerable<XmlSchemaFacet>> baseFacets)
{
Expand All @@ -673,7 +663,7 @@ static bool AllMembersHaveFacets(XmlSchemaSimpleTypeUnion typeUnion, out List<IE

static List<XmlSchemaFacet> MergeRestrictions(XmlSchemaSimpleType type)
{
if (type == null) return new();
if (type == null) return [];
var baseFacets = MergeRestrictions(type.BaseXmlSchemaType as XmlSchemaSimpleType);
if (type.Content is XmlSchemaSimpleTypeRestriction typeRestriction)
{
Expand Down Expand Up @@ -908,7 +898,7 @@ private IEnumerable<PropertyModel> CreatePropertiesForElements(Uri source, TypeM
{
// ElementSchemaType must be non-null. This is not the case when maxOccurs="0".
case XmlSchemaElement element when element.ElementSchemaType != null:
property = PropertyFromElement(owningTypeModel, element, particle, item, substitute, passProperties ? properties : new List<PropertyModel>());
property = PropertyFromElement(owningTypeModel, element, particle, item, substitute, passProperties ? properties : []);
break;
case XmlSchemaAny:
SimpleModel typeModel = new(_configuration)
Expand Down Expand Up @@ -1093,7 +1083,7 @@ public IEnumerable<Particle> GetElements(XmlSchemaObject item, XmlSchemaObject p

public static List<DocumentationModel> GetDocumentation(XmlSchemaAnnotated annotated)
{
return annotated.Annotation == null ? new List<DocumentationModel>()
return annotated.Annotation == null ? []
: annotated.Annotation.Items.OfType<XmlSchemaDocumentation>()
.Where(d => d.Markup?.Length > 0)
.Select(d => d.Markup.Select(m => new DocumentationModel { Language = d.Language, Text = m.OuterXml }))
Expand Down
7 changes: 3 additions & 4 deletions XmlSchemaClassGenerator/TypeModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ public override CodeTypeDeclaration Generate()
docs.AddRange(simpleModel.Restrictions.Select(r => new DocumentationModel { Language = English, Text = r.Description }));
text.CustomAttributes.AddRange(simpleModel.GetRestrictionAttributes().ToArray());

if (BaseClass.GetQualifiedName() is { Namespace: XmlSchema.Namespace, Name: var name } && (simpleModel.XmlSchemaType.Datatype.IsDataTypeAttributeAllowed() ?? simpleModel.UseDataTypeAttribute))
if (BaseClass.GetQualifiedName() is { Namespace: XmlSchema.Namespace, Name: var name } && (simpleModel.XmlSchemaType.Datatype.IsDataTypeAttributeAllowed(Configuration) ?? simpleModel.UseDataTypeAttribute))
attribute.Arguments.Add(new CodeAttributeArgument(nameof(XmlTextAttribute.DataType), new CodePrimitiveExpression(name)));
}

Expand Down Expand Up @@ -1104,8 +1104,7 @@ private IEnumerable<CodeAttributeDeclaration> GetAttributes(bool isArray, TypeMo
{
var qualifiedName = xmlSchemaType.GetQualifiedName();

if (qualifiedName.Namespace == XmlSchema.Namespace && qualifiedName.Name != "anySimpleType" &&
!(xmlSchemaType.Datatype.ValueType == typeof(DateTime) && Configuration.DateTimeWithTimeZone))
if (qualifiedName.Namespace == XmlSchema.Namespace && qualifiedName.Name != "anySimpleType")
{
args.Add(new("DataType", new CodePrimitiveExpression(qualifiedName.Name)));
break;
Expand Down Expand Up @@ -1250,7 +1249,7 @@ public override CodeTypeReference GetReferenceFor(NamespaceModel referencingName
// XmlSerializer is inconsistent: maps xs:decimal to decimal but xs:integer to string,
// even though xs:integer is a restriction of xs:decimal
type = XmlSchemaType.Datatype.GetEffectiveType(Configuration, Restrictions, XmlSchemaType, attribute);
UseDataTypeAttribute = XmlSchemaType.Datatype.IsDataTypeAttributeAllowed() ?? UseDataTypeAttribute;
UseDataTypeAttribute = XmlSchemaType.Datatype.IsDataTypeAttributeAllowed(Configuration) ?? UseDataTypeAttribute;
}

if (collection)
Expand Down

0 comments on commit a1c63e4

Please sign in to comment.