Skip to content

Commit

Permalink
Add compact type names
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Ganss committed Dec 23, 2020
1 parent b106724 commit d3e7c4a
Show file tree
Hide file tree
Showing 10 changed files with 153 additions and 136 deletions.
7 changes: 5 additions & 2 deletions XmlSchemaClassGenerator.Console/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ static void Main(string[] args)
var separateSubstitutes = false;
var collectionSettersMode = CollectionSettersMode.Private;
var doNotForceIsNullable = false;
var compactTypeNames = false;

var options = new OptionSet {
{ "h|help", "show this message and exit", v => showHelp = v != null },
Expand Down Expand Up @@ -113,7 +114,8 @@ A file name may be given by appending a pipe sign (|) followed by a file name (l
{ "s|useShouldSerialize", "use ShouldSerialize pattern instead of Specified pattern (default is false)", v => useShouldSerialize = v != null },
{ "sf|separateFiles", "generate a separate file for each class (default is false)", v => separateClasses = v != null },
{ "sg|separateSubstitutes", "generate a separate property for each element of a substitution group (default is false)", v => separateSubstitutes = v != null },
{ "dnfin|doNotForceIsNullable", "do not force generator to emit IsNullable = true in XmlElement annotation for nillable elements when element is nullable (minOccurs < 1 or parent element is choice) (default is false)", v => doNotForceIsNullable = v != null }
{ "dnfin|doNotForceIsNullable", "do not force generator to emit IsNullable = true in XmlElement annotation for nillable elements when element is nullable (minOccurs < 1 or parent element is choice) (default is false)", v => doNotForceIsNullable = v != null },
{ "cn|compactTypeNames", "use type names without namespace qualifier for types in the using list (default is false)", v => compactTypeNames = v != null }
};

var globsAndUris = options.Parse(args);
Expand Down Expand Up @@ -184,7 +186,8 @@ A file name may be given by appending a pipe sign (|) followed by a file name (l
SeparateClasses = separateClasses,
CollectionSettersMode = collectionSettersMode,
DoNotForceIsNullable = doNotForceIsNullable,
SeparateSubstitutes = separateSubstitutes
SeparateSubstitutes = separateSubstitutes,
CompactTypeNames = compactTypeNames
};

if (pclCompatible)
Expand Down
3 changes: 2 additions & 1 deletion XmlSchemaClassGenerator.Tests/Compiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@ public static Assembly GenerateFiles(string name, IEnumerable<string> files, Gen
SeparateClasses = generatorPrototype.SeparateClasses,
CollectionType = generatorPrototype.CollectionType,
CollectionImplementationType = generatorPrototype.CollectionImplementationType,
SeparateSubstitutes = generatorPrototype.SeparateSubstitutes
SeparateSubstitutes = generatorPrototype.SeparateSubstitutes,
CompactTypeNames = generatorPrototype.CompactTypeNames
};

output.Configuration = gen.Configuration;
Expand Down
39 changes: 24 additions & 15 deletions XmlSchemaClassGenerator.Tests/XmlTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public XmlTests(ITestOutputHelper output)
Output = output;
}

private IEnumerable<string> ConvertXml(string name, IEnumerable<string> xsds, Generator generatorPrototype = null)
private static IEnumerable<string> ConvertXml(string name, IEnumerable<string> xsds, Generator generatorPrototype = null)
{
if (name is null)
{
Expand Down Expand Up @@ -75,7 +75,7 @@ private IEnumerable<string> ConvertXml(string name, IEnumerable<string> xsds, Ge
return writer.Content;
}

private IEnumerable<string> ConvertXml(string name, string xsd, Generator generatorPrototype = null)
private static IEnumerable<string> ConvertXml(string name, string xsd, Generator generatorPrototype = null)
{
return ConvertXml(name, new[] {xsd}, generatorPrototype);
}
Expand Down Expand Up @@ -325,7 +325,20 @@ public void TestArrayOrder()
[UseCulture("en-US")]
public void TestIS24RestApi()
{
Compiler.Generate("IS24RestApi", IS24Pattern);
Compiler.Generate("IS24RestApi", IS24Pattern, new Generator
{
GenerateNullables = true,
IntegerDataType = typeof(int),
DataAnnotationMode = DataAnnotationMode.All,
GenerateDesignerCategoryAttribute = false,
GenerateComplexTypesForCollections = true,
EntityFramework = false,
GenerateInterfaces = true,
NamespacePrefix = "IS24RestApi",
GenerateDescriptionAttribute = true,
TextValuePropertyName = "Value",
CompactTypeNames = true
});
TestSamples("IS24RestApi", IS24Pattern);
}

Expand Down Expand Up @@ -376,7 +389,7 @@ public void TestIS24ImmoTransfer()
[UseCulture("en-US")]
public void TestTableau()
{
Compiler.Generate("Tableau", TableauPattern, new Generator());
Compiler.Generate("Tableau", TableauPattern, new Generator { CompactTypeNames = true });
TestSamples("Tableau", TableauPattern);
}

Expand Down Expand Up @@ -440,7 +453,7 @@ private void TestSamples(string name, string pattern)

private bool HandleValidationError(string[] xmlLines, ValidationEventArgs e)
{
var line = xmlLines[e.Exception.LineNumber - 1].Substring(e.Exception.LinePosition - 1);
var line = xmlLines[e.Exception.LineNumber - 1][(e.Exception.LinePosition - 1)..];
var severity = e.Severity == XmlSeverityType.Error ? "Error" : "Warning";
Output.WriteLine($"{severity} at line {e.Exception.LineNumber}, column {e.Exception.LinePosition}: {e.Message}");
Output.WriteLine(line);
Expand Down Expand Up @@ -578,12 +591,12 @@ public void ProducesSameXmlAsXsd()
Assert.NotNull(t1);
var t2 = Assembly.GetExecutingAssembly().GetTypes().SingleOrDefault(t => t.Name == c && t.Namespace == "IS24RestApi.Xsd");
Assert.NotNull(t2);
var f = char.ToLower(c[0]) + c.Substring(1);
var f = char.ToLower(c[0]) + c[1..];
TestCompareToXsd(t1, t2, f);
}
}

void TestCompareToXsd(Type t1, Type t2, string file)
static void TestCompareToXsd(Type t1, Type t2, string file)
{
foreach (var suffix in new[] { "max", "min" })
{
Expand Down Expand Up @@ -727,7 +740,7 @@ void UnknownAttributeHandler(object sender, XmlAttributeEventArgs e)
}
}

private IDictionary<string, string> GetNamespacesFromSource(string source)
private static IDictionary<string, string> GetNamespacesFromSource(string source)
{
XPathDocument doc = new XPathDocument(new StringReader(source));
XPathNavigator namespaceNavigator = doc.CreateNavigator();
Expand All @@ -744,12 +757,12 @@ public void CanSerializeAndDeserializeAllExampleXmlFiles()
{
var t1 = assembly.GetTypes().SingleOrDefault(t => t.Name == c && t.Namespace.StartsWith("IS24RestApi.Offer.Realestates"));
Assert.NotNull(t1);
var f = char.ToLower(c[0]) + c.Substring(1);
var f = char.ToLower(c[0]) + c[1..];
TestRoundtrip(t1, f);
}
}

void TestRoundtrip(Type t, string file)
static void TestRoundtrip(Type t, string file)
{
var serializer = new XmlSerializer(t);

Expand Down Expand Up @@ -811,7 +824,7 @@ public void DontGenerateElementForEmptyCollectionInChoice()

[Theory]
[InlineData(CodeTypeReferenceOptions.GlobalReference, "[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)]")]
[InlineData((CodeTypeReferenceOptions)0, "[System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)]")]
[InlineData((CodeTypeReferenceOptions)0, "[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]")]
public void EditorBrowsableAttributeRespectsCodeTypeReferenceOptions(CodeTypeReferenceOptions codeTypeReferenceOptions, string expectedLine)
{
const string xsd = @"<?xml version=""1.0"" encoding=""UTF-8""?>
Expand Down Expand Up @@ -987,10 +1000,6 @@ public void ComplexTypeWithAttributeGroupExtension()
// This code was generated by Tests version 1.0.0.1.
namespace Test
{
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Xml.Serialization;
[System.CodeDom.Compiler.GeneratedCodeAttribute(""Tests"", ""1.0.0.1"")]
Expand Down
106 changes: 53 additions & 53 deletions XmlSchemaClassGenerator/CodeUtilities.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.CodeDom;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
Expand Down Expand Up @@ -34,24 +35,13 @@ public static string ToBackingField(this string propertyName, string privateFiel

public static bool? IsDataTypeAttributeAllowed(this XmlSchemaDatatype type)
{
bool? result;
switch (type.TypeCode)
bool? result = type.TypeCode switch
{
case XmlTypeCode.AnyAtomicType:
// union
result = false;
break;
case XmlTypeCode.DateTime:
case XmlTypeCode.Time:
case XmlTypeCode.Date:
case XmlTypeCode.Base64Binary:
case XmlTypeCode.HexBinary:
result = true;
break;
default:
result = false;
break;
}
XmlTypeCode.AnyAtomicType => false,// union
XmlTypeCode.DateTime or XmlTypeCode.Time or XmlTypeCode.Date or XmlTypeCode.Base64Binary or XmlTypeCode.HexBinary => true,
_ => false,
};

return result;
}

Expand Down Expand Up @@ -118,15 +108,15 @@ private static Type GetIntegerDerivedType(XmlSchemaDatatype type, GeneratorConfi
return result;
}

if (!(restrictions.SingleOrDefault(r => r is TotalDigitsRestrictionModel) is TotalDigitsRestrictionModel totalDigits)
if (restrictions.SingleOrDefault(r => r is TotalDigitsRestrictionModel) is not TotalDigitsRestrictionModel totalDigits
|| ((xmlTypeCode == XmlTypeCode.PositiveInteger
|| xmlTypeCode == XmlTypeCode.NonNegativeInteger) && totalDigits.Value >= 30)
|| ((xmlTypeCode == XmlTypeCode.Integer
|| xmlTypeCode == XmlTypeCode.NegativeInteger
|| xmlTypeCode == XmlTypeCode.NonPositiveInteger) && totalDigits.Value >= 29))
{
if (configuration.UseIntegerDataTypeAsFallback && configuration.IntegerDataType != null)
return configuration.IntegerDataType;
return configuration.IntegerDataType;
return typeof(string);
}

Expand Down Expand Up @@ -184,40 +174,15 @@ private static Type GetIntegerDerivedType(XmlSchemaDatatype type, GeneratorConfi

public static Type GetEffectiveType(this XmlSchemaDatatype type, GeneratorConfiguration configuration, IEnumerable<RestrictionModel> restrictions, bool attribute = false)
{
Type resultType;

switch (type.TypeCode)
var resultType = type.TypeCode switch
{
case XmlTypeCode.AnyAtomicType:
// union
resultType = typeof(string);
break;
case XmlTypeCode.AnyUri:
case XmlTypeCode.Duration:
case XmlTypeCode.GDay:
case XmlTypeCode.GMonth:
case XmlTypeCode.GMonthDay:
case XmlTypeCode.GYear:
case XmlTypeCode.GYearMonth:
resultType = typeof(string);
break;
case XmlTypeCode.Time:
resultType = typeof(DateTime);
break;
case XmlTypeCode.Idref:
resultType = typeof(string);
break;
case XmlTypeCode.Integer:
case XmlTypeCode.NegativeInteger:
case XmlTypeCode.NonNegativeInteger:
case XmlTypeCode.NonPositiveInteger:
case XmlTypeCode.PositiveInteger:
resultType = GetIntegerDerivedType(type, configuration, restrictions);
break;
default:
resultType = type.ValueType;
break;
}
XmlTypeCode.AnyAtomicType => typeof(string),// union
XmlTypeCode.AnyUri or XmlTypeCode.Duration or XmlTypeCode.GDay or XmlTypeCode.GMonth or XmlTypeCode.GMonthDay or XmlTypeCode.GYear or XmlTypeCode.GYearMonth => typeof(string),
XmlTypeCode.Time => typeof(DateTime),
XmlTypeCode.Idref => typeof(string),
XmlTypeCode.Integer or XmlTypeCode.NegativeInteger or XmlTypeCode.NonNegativeInteger or XmlTypeCode.NonPositiveInteger or XmlTypeCode.PositiveInteger => GetIntegerDerivedType(type, configuration, restrictions),
_ => type.ValueType,
};

if (type.Variety == XmlSchemaDatatypeVariety.List)
{
Expand Down Expand Up @@ -248,7 +213,7 @@ public static XmlQualifiedName GetQualifiedName(this XmlSchemaType schemaType)
public static XmlQualifiedName GetQualifiedName(this TypeModel typeModel)
{
XmlQualifiedName qualifiedName;
if (!(typeModel is SimpleModel simpleTypeModel))
if (typeModel is not SimpleModel simpleTypeModel)
{
if (typeModel.IsAnonymous)
{
Expand Down Expand Up @@ -398,5 +363,40 @@ public static KeyValuePair<NamespaceKey, string> ParseNamespace(string nsArg, st
}
return new KeyValuePair<NamespaceKey, string>(new NamespaceKey(source, xmlNs), netNs);
}

public static readonly List<(string Namespace, Func<GeneratorConfiguration,bool> Condition)> UsingNamespaces = new List<(string, Func<GeneratorConfiguration, bool>)> {
("System", c => c.CompactTypeNames),
("System.CodeDom.Compiler", c => c.CompactTypeNames),
("System.Collections.Generic", c => c.CompactTypeNames),
("System.Collections.ObjectModel", c => c.CompactTypeNames),
("System.ComponentModel", c => c.CompactTypeNames),
("System.ComponentModel.DataAnnotations", c => c.CompactTypeNames && (c.DataAnnotationMode != DataAnnotationMode.None || c.EntityFramework)),
("System.Diagnostics", c => c.CompactTypeNames && c.GenerateDebuggerStepThroughAttribute),
("System.Linq", c => c.EnableDataBinding),
("System.Xml.Serialization", c => c.CompactTypeNames)
};

public static bool IsUsingNamespace(Type t, GeneratorConfiguration conf) => UsingNamespaces.Any(n => n.Namespace == t.Namespace && n.Condition(conf));

public static CodeTypeReference CreateTypeReference(Type t, GeneratorConfiguration conf)
{
if (IsUsingNamespace(t, conf))
{
var name = t.Name;
var typeRef = new CodeTypeReference(name, conf.CodeTypeReferenceOptions);

if (t.IsConstructedGenericType)
{
var typeArgs = t.GenericTypeArguments.Select(a => CreateTypeReference(a, conf)).ToArray();
typeRef.TypeArguments.AddRange(typeArgs);
}

var generic = t.IsGenericType || t.IsGenericTypeDefinition || t.IsConstructedGenericType;

return typeRef;
}
else
return new CodeTypeReference(t, conf.CodeTypeReferenceOptions);
}
}
}
6 changes: 6 additions & 0 deletions XmlSchemaClassGenerator/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,12 @@ public bool SeparateSubstitutes
set { _configuration.SeparateSubstitutes = value; }
}

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

static Generator()
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
Expand Down
13 changes: 9 additions & 4 deletions XmlSchemaClassGenerator/GeneratorConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -240,17 +240,17 @@ public void WriteLog(string message)
/// </code>
///
/// With <code>false</code> it generates the classes:
///
///
/// <code>
/// public class books {
/// public Container&lt;componentType&gt; components {get; set;}
/// }
///
/// public class componentType {}
/// public class componentType {}
/// </code>
///
/// With <code>true</code> it generates the classes:
///
///
/// <code>
/// public class books {
/// public Container&lt;componentType&gt; components {get; set;}
Expand All @@ -260,7 +260,7 @@ public void WriteLog(string message)
/// public Container&lt;componentType&gt; components {get; set;}
/// }
///
/// public class componentType {}
/// public class componentType {}
/// </code>
/// </summary>
public bool GenerateComplexTypesForCollections { get; set; } = true;
Expand All @@ -274,5 +274,10 @@ public void WriteLog(string message)
/// Generates a separate property for each element of a substitution group
/// </summary>
public bool SeparateSubstitutes { get; set; } = false;

/// <summary>
/// Generates type names without namespace qualifiers for namespaces in using list
/// </summary>
public bool CompactTypeNames { get; set; }
}
}
2 changes: 1 addition & 1 deletion XmlSchemaClassGenerator/ModelBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1011,7 +1011,7 @@ public IEnumerable<CodeNamespace> GenerateCode()
var hierarchy = NamespaceHierarchyItem.Build(Namespaces.Values.GroupBy(x => x.Name).SelectMany(x => x))
.MarkAmbiguousNamespaceTypes();
return hierarchy.Flatten()
.Select(nhi => NamespaceModel.Generate(nhi.FullName, nhi.Models));
.Select(nhi => NamespaceModel.Generate(nhi.FullName, nhi.Models, _configuration));
}

private string BuildNamespace(Uri source, string xmlNamespace)
Expand Down
Loading

0 comments on commit d3e7c4a

Please sign in to comment.