diff --git a/XmlSchemaClassGenerator.Tests/XmlTests.cs b/XmlSchemaClassGenerator.Tests/XmlTests.cs index b830e08d..b32f931a 100644 --- a/XmlSchemaClassGenerator.Tests/XmlTests.cs +++ b/XmlSchemaClassGenerator.Tests/XmlTests.cs @@ -53,7 +53,7 @@ private IEnumerable ConvertXml(string name, string xsd, Generator genera { var schema = XmlSchema.Read(stringReader, (s, e) => { - throw new InvalidOperationException(); + throw new InvalidOperationException($"{e.Severity}: {e.Message}",e.Exception); }); set.Add(schema); @@ -632,7 +632,7 @@ public void ChoiceMembersAreNullable() } [Fact] - public void AssemblyVisibleIsInternal() + public void AssemblyVisibleIsInternalClass() { // We test to see whether choices which are part of a larger ComplexType are marked as nullable. // Because nullability isn't directly exposed in the generated C#, we use "XXXSpecified" on a value type @@ -675,13 +675,103 @@ public void AssemblyVisibleIsInternal() Assert.Contains("internal partial class Root", content); } + [Fact] + public void AssemblyVisibleIsInternalEnum() + { + // We test to see whether choices which are part of a larger ComplexType are marked as nullable. + // Because nullability isn't directly exposed in the generated C#, we use "XXXSpecified" on a value type + // as a proxy. + + const string xsd = @" + + + + + + + + +"; + + var generator = new Generator + { + NamespaceProvider = new NamespaceProvider + { + GenerateNamespace = key => "Test" + }, + AssemblyVisible = true + }; + var contents = ConvertXml(nameof(ComplexTypeWithAttributeGroupExtension), xsd, generator); + var content = Assert.Single(contents); + + Assert.Contains("internal enum Answer", content); + } + + [Fact] + public void AssemblyVisibleIsInternalInterface() + { + // We test to see whether choices which are part of a larger ComplexType are marked as nullable. + // Because nullability isn't directly exposed in the generated C#, we use "XXXSpecified" on a value type + // as a proxy. + + const string xsd = @" + + + + + + + +"; + + var generator = new Generator + { + NamespaceProvider = new NamespaceProvider + { + GenerateNamespace = key => "Test" + }, + GenerateInterfaces = true, + AssemblyVisible = true + }; + var contents = ConvertXml(nameof(ComplexTypeWithAttributeGroupExtension), xsd, generator); + var content = Assert.Single(contents); + + Assert.Contains("internal partial interface INamedElement", content); + } + + [Fact] + public void DecimalSeparatorTest() + { + // see https://github.com/mganss/XmlSchemaClassGenerator/issues/101 + + const string xsd = @" + + + + +"; + + var generator = new Generator + { + NamespaceProvider = new NamespaceProvider + { + GenerateNamespace = key => "Test", + }, + GenerateInterfaces = true, + AssemblyVisible = true + }; + var contents = ConvertXml(nameof(ComplexTypeWithAttributeGroupExtension), xsd, generator); + var content = Assert.Single(contents); + + Assert.Contains("private decimal _someAttr = 1.5m;", content); + } + private static void CompareOutput(string expected, string actual) { string Normalize(string input) => Regex.Replace(input, @"[ \t]*\r\n", "\n"); Assert.Equal(Normalize(expected), Normalize(actual)); } - [Theory] [InlineData(typeof(decimal), "decimal")] [InlineData(typeof(long), "long")] diff --git a/XmlSchemaClassGenerator.sln b/XmlSchemaClassGenerator.sln index 4eeb8618..a0b92761 100644 --- a/XmlSchemaClassGenerator.sln +++ b/XmlSchemaClassGenerator.sln @@ -18,6 +18,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution README.md = README.md EndProjectSection EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "xscgen-proj", "xscgen-proj\xscgen-proj.csproj", "{2F20FF02-12AB-448B-BC78-DD76DD4C9E66}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -44,6 +46,10 @@ Global {C5C1FF7F-31AD-4D4F-81F3-C9F54516D9D0}.Debug|Any CPU.Build.0 = Debug|Any CPU {C5C1FF7F-31AD-4D4F-81F3-C9F54516D9D0}.Release|Any CPU.ActiveCfg = Release|Any CPU {C5C1FF7F-31AD-4D4F-81F3-C9F54516D9D0}.Release|Any CPU.Build.0 = Release|Any CPU + {2F20FF02-12AB-448B-BC78-DD76DD4C9E66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2F20FF02-12AB-448B-BC78-DD76DD4C9E66}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2F20FF02-12AB-448B-BC78-DD76DD4C9E66}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2F20FF02-12AB-448B-BC78-DD76DD4C9E66}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/XmlSchemaClassGenerator/CodeUtilities.cs b/XmlSchemaClassGenerator/CodeUtilities.cs index fc7d515b..8b4886c8 100644 --- a/XmlSchemaClassGenerator/CodeUtilities.cs +++ b/XmlSchemaClassGenerator/CodeUtilities.cs @@ -295,5 +295,7 @@ internal static string NormalizeNewlines(string text) "using", "using static", "virtual", "void", "volatile", "while" }; + + internal static Uri CreateUri(string uri) => string.IsNullOrEmpty(uri) ? null : new Uri(uri); } } \ No newline at end of file diff --git a/XmlSchemaClassGenerator/ModelBuilder.cs b/XmlSchemaClassGenerator/ModelBuilder.cs index 81347c5e..dc58ac3a 100644 --- a/XmlSchemaClassGenerator/ModelBuilder.cs +++ b/XmlSchemaClassGenerator/ModelBuilder.cs @@ -47,14 +47,14 @@ public ModelBuilder(GeneratorConfiguration configuration, XmlSchemaSet set) foreach (var globalType in set.GlobalTypes.Values.Cast()) { var schema = globalType.GetSchema(); - var source = string.IsNullOrEmpty(schema?.SourceUri) ? null : new Uri(schema.SourceUri); + var source = CodeUtilities.CreateUri(schema?.SourceUri); CreateTypeModel(source, globalType, globalType.QualifiedName); } foreach (var rootElement in set.GlobalElements.Values.Cast()) { var rootSchema = rootElement.GetSchema(); - var source = !string.IsNullOrEmpty(rootSchema.SourceUri) ? new Uri(rootElement.GetSchema().SourceUri) : default(Uri); + var source = CodeUtilities.CreateUri(rootSchema.SourceUri); var qualifiedName = rootElement.ElementSchemaType.QualifiedName; if (qualifiedName.IsEmpty) { qualifiedName = rootElement.QualifiedName; } var type = CreateTypeModel(source, rootElement.ElementSchemaType, qualifiedName); @@ -165,7 +165,7 @@ private TypeModel CreateTypeModel(Uri source, XmlSchemaGroup group, NamespaceMod var properties = CreatePropertiesForElements(source, interfaceModel, particle, items.Where(i => !(i.XmlParticle is XmlSchemaGroupRef))); interfaceModel.Properties.AddRange(properties); var interfaces = items.Select(i => i.XmlParticle).OfType() - .Select(i => (InterfaceModel)CreateTypeModel(new Uri(i.SourceUri), Groups[i.RefName], i.RefName)); + .Select(i => (InterfaceModel)CreateTypeModel(CodeUtilities.CreateUri(i.SourceUri), Groups[i.RefName], i.RefName)); interfaceModel.Interfaces.AddRange(interfaces); return interfaceModel; @@ -192,7 +192,7 @@ private TypeModel CreateTypeModel(Uri source, XmlSchemaAttributeGroup attributeG var properties = CreatePropertiesForAttributes(source, interfaceModel, items.OfType()); interfaceModel.Properties.AddRange(properties); var interfaces = items.OfType() - .Select(a => (InterfaceModel)CreateTypeModel(new Uri(a.SourceUri), AttributeGroups[a.RefName], a.RefName)); + .Select(a => (InterfaceModel)CreateTypeModel(CodeUtilities.CreateUri(a.SourceUri), AttributeGroups[a.RefName], a.RefName)); interfaceModel.Interfaces.AddRange(interfaces); return interfaceModel; @@ -254,7 +254,7 @@ private TypeModel CreateTypeModel(Uri source, XmlSchemaComplexType complexType, if (_configuration.GenerateInterfaces) { var interfaces = items.Select(i => i.XmlParticle).OfType() - .Select(i => (InterfaceModel)CreateTypeModel(new Uri(i.SourceUri), Groups[i.RefName], i.RefName)); + .Select(i => (InterfaceModel)CreateTypeModel(CodeUtilities.CreateUri(i.SourceUri), Groups[i.RefName], i.RefName)); classModel.Interfaces.AddRange(interfaces); } @@ -283,7 +283,7 @@ private TypeModel CreateTypeModel(Uri source, XmlSchemaComplexType complexType, if (_configuration.GenerateInterfaces) { var attributeInterfaces = attributes.OfType() - .Select(i => (InterfaceModel)CreateTypeModel(new Uri(i.SourceUri), AttributeGroups[i.RefName], i.RefName)); + .Select(i => (InterfaceModel)CreateTypeModel(CodeUtilities.CreateUri(i.SourceUri), AttributeGroups[i.RefName], i.RefName)); classModel.Interfaces.AddRange(attributeInterfaces); } } @@ -463,7 +463,7 @@ private IEnumerable CreatePropertiesForAttributes(Uri source, Typ { if (_configuration.GenerateInterfaces) { - CreateTypeModel(new Uri(attributeGroupRef.SourceUri), AttributeGroups[attributeGroupRef.RefName], attributeGroupRef.RefName); + CreateTypeModel(CodeUtilities.CreateUri(attributeGroupRef.SourceUri), AttributeGroups[attributeGroupRef.RefName], attributeGroupRef.RefName); } var groupItems = AttributeGroups[attributeGroupRef.RefName].Attributes; @@ -552,7 +552,7 @@ private IEnumerable CreatePropertiesForElements(Uri source, TypeM { if (_configuration.GenerateInterfaces) { - CreateTypeModel(new Uri(groupRef.SourceUri), Groups[groupRef.RefName], groupRef.RefName); + CreateTypeModel(CodeUtilities.CreateUri(groupRef.SourceUri), Groups[groupRef.RefName], groupRef.RefName); } var groupItems = GetElements(groupRef.Particle); diff --git a/XmlSchemaClassGenerator/TypeModel.cs b/XmlSchemaClassGenerator/TypeModel.cs index 24363181..6028dca3 100644 --- a/XmlSchemaClassGenerator/TypeModel.cs +++ b/XmlSchemaClassGenerator/TypeModel.cs @@ -6,6 +6,7 @@ using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Diagnostics; +using System.Globalization; using System.Linq; using System.Text.RegularExpressions; using System.Xml; @@ -209,6 +210,11 @@ public override CodeTypeDeclaration Generate() interfaceDeclaration.IsInterface = true; interfaceDeclaration.IsPartial = true; + if (Configuration.AssemblyVisible) + { + interfaceDeclaration.TypeAttributes = (interfaceDeclaration.TypeAttributes & ~System.Reflection.TypeAttributes.VisibilityMask) | System.Reflection.TypeAttributes.NestedAssembly; + } + foreach (var property in Properties) property.AddInterfaceMembersTo(interfaceDeclaration); @@ -1126,6 +1132,10 @@ public override CodeTypeDeclaration Generate() GenerateTypeAttribute(enumDeclaration); enumDeclaration.IsEnum = true; + if (Configuration.AssemblyVisible) + { + enumDeclaration.TypeAttributes = (enumDeclaration.TypeAttributes & ~System.Reflection.TypeAttributes.VisibilityMask) | System.Reflection.TypeAttributes.NestedAssembly; + } foreach (var val in Values) { @@ -1277,7 +1287,7 @@ public override CodeExpression GetDefaultValueFor(string defaultString, bool att } - return new CodePrimitiveExpression(Convert.ChangeType(defaultString, ValueType)); + return new CodePrimitiveExpression(Convert.ChangeType(defaultString, ValueType, CultureInfo.InvariantCulture)); } public IEnumerable GetRestrictionAttributes() diff --git a/XmlSchemaClassGenerator/XmlSchemaClassGenerator.csproj b/XmlSchemaClassGenerator/XmlSchemaClassGenerator.csproj index 1cdd7f36..5a4f2c18 100644 --- a/XmlSchemaClassGenerator/XmlSchemaClassGenerator.csproj +++ b/XmlSchemaClassGenerator/XmlSchemaClassGenerator.csproj @@ -6,7 +6,7 @@ XmlSchemaClassGenerator 1.0.0-VERSION Michael Ganss - net45;netstandard2.0 + netstandard2.0;net45 XmlSchemaClassGenerator XmlSchemaClassGenerator-beta xsd diff --git a/appveyor.yml b/appveyor.yml index e4b37b8c..f7d0eb75 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -12,6 +12,7 @@ build_script: - ps: (Get-Content XmlSchemaClassGenerator\XmlSchemaClassGenerator.csproj).Replace("1.0.0-VERSION", $env:APPVEYOR_BUILD_VERSION) | Set-Content XmlSchemaClassGenerator\XmlSchemaClassGenerator.csproj - ps: (Get-Content XmlSchemaClassGenerator.Console\XmlSchemaClassGenerator.Console.csproj).Replace("1.0.0-VERSION", $env:APPVEYOR_BUILD_VERSION) | Set-Content XmlSchemaClassGenerator.Console\XmlSchemaClassGenerator.Console.csproj - ps: (Get-Content xscgen\xscgen.csproj).Replace("1.0.0-VERSION", $env:APPVEYOR_BUILD_VERSION) | Set-Content xscgen\xscgen.csproj + - ps: (Get-Content xscgen-proj\xscgen-proj.csproj).Replace("1.0.0-VERSION", $env:APPVEYOR_BUILD_VERSION) | Set-Content xscgen-proj\xscgen-proj.csproj - dotnet --info - dotnet restore - dotnet build -c Release @@ -19,6 +20,7 @@ build_script: - dotnet pack --include-symbols --include-source -c Release XmlSchemaClassGenerator - dotnet pack --include-symbols --include-source -c Release XmlSchemaClassGenerator.Console - dotnet pack --include-symbols --include-source -c Release xscgen + - dotnet pack --include-symbols --include-source -c Release xscgen-proj - 7z a -mx=9 XmlSchemaClassGenerator.%APPVEYOR_BUILD_VERSION%.zip ".\XmlSchemaClassGenerator.Console\bin\Release\net45\publish\*" test_script: - ps: | @@ -38,6 +40,7 @@ artifacts: - path: 'XmlSchemaClassGenerator\**\*.nupkg' - path: 'XmlSchemaClassGenerator.Console\**\*.nupkg' - path: 'xscgen\**\*.nupkg' + - path: 'xscgen-proj\**\*.nupkg' - path: XmlSchemaClassGenerator.%APPVEYOR_BUILD_VERSION%.zip on_success: - ps: | diff --git a/xscgen-proj/xscgen-proj.csproj b/xscgen-proj/xscgen-proj.csproj new file mode 100644 index 00000000..e25da27d --- /dev/null +++ b/xscgen-proj/xscgen-proj.csproj @@ -0,0 +1,34 @@ + + + Exe + netcoreapp2.1 + A .NET Core CLI tool to generate XmlSerializer compatible C# classes from XML Schema files. + Copyright 2013-2018 Michael Ganss + xscgen + 1.0.0-VERSION + dotnet-xscgen + XmlSchemaClassGenerator.Console + Michael Ganss + dotnet-xscgen-proj + xsd xmlschema generator + https://github.com/mganss/XmlSchemaClassGenerator + https://github.com/mganss/XmlSchemaClassGenerator/blob/master/LICENSE + git + git://github.com/mganss/XmlSchemaClassGenerator + dotnet-xscgen + $(DefineConstants);NETSTANDARD + + + + + + + + + + + + + true + +