diff --git a/XmlSchemaClassGenerator.Console/Program.cs b/XmlSchemaClassGenerator.Console/Program.cs index acc28cf3..5417cadf 100644 --- a/XmlSchemaClassGenerator.Console/Program.cs +++ b/XmlSchemaClassGenerator.Console/Program.cs @@ -89,29 +89,19 @@ A file name may be given by appending a pipe sign (|) followed by a file name (l { "u|enableUpaCheck", "should XmlSchemaSet check for Unique Particle Attribution (UPA) (default is enabled)", v => enableUpaCheck = v != null }, { "ct|collectionType=", "collection type to use (default is " + typeof(Collection<>).FullName + ")", v => collectionType = v == null ? typeof(Collection<>) : Type.GetType(v, true) }, { "cit|collectionImplementationType=", "the default collection type implementation to use (default is null)", v => collectionImplementationType = v == null ? null : Type.GetType(v, true) }, - { "csm|collectionSettersMode=", @"generate a private, public or public setters + { "csm|collectionSettersMode=", @"generate a private, public or public setters without backing field initialization for collections (default is Private; can be: {Private, Public, PublicWithoutConstructorInitialization})", v => { - switch (v) + collectionSettersMode = v switch { - case "pr": - case "Private": - collectionSettersMode = CollectionSettersMode.Private; - break; - case "pu": - case "Public": - collectionSettersMode = CollectionSettersMode.Public; - break; - case "puwci": - case "PublicWithoutConstructorInitialization": - collectionSettersMode = CollectionSettersMode.PublicWithoutConstructorInitialization; - break; - default: - collectionSettersMode = CollectionSettersMode.Private; - break; - } + "pr" or "Private" => CollectionSettersMode.Private, + "pu" or "Public" => CollectionSettersMode.Public, + "puwci" or "PublicWithoutConstructorInitialization" => + CollectionSettersMode.PublicWithoutConstructorInitialization, + _ => CollectionSettersMode.Private + }; }}, { "ctro|codeTypeReferenceOptions=", "the default CodeTypeReferenceOptions Flags to use (default is unset; can be: {GlobalReference, GenericTypeParameter})", v => codeTypeReferenceOptions = v == null ? default : (CodeTypeReferenceOptions)Enum.Parse(typeof(CodeTypeReferenceOptions), v, false) }, { "tvpn|textValuePropertyName=", "the name of the property that holds the text value of an element (default is Value)", v => textValuePropertyName = v }, diff --git a/XmlSchemaClassGenerator.Console/XmlSchemaClassGenerator.Console.csproj b/XmlSchemaClassGenerator.Console/XmlSchemaClassGenerator.Console.csproj index f5af7ea4..52cd5bf6 100644 --- a/XmlSchemaClassGenerator.Console/XmlSchemaClassGenerator.Console.csproj +++ b/XmlSchemaClassGenerator.Console/XmlSchemaClassGenerator.Console.csproj @@ -23,6 +23,7 @@ true true snupkg + latest diff --git a/XmlSchemaClassGenerator.Tests/XmlSchemaClassGenerator.Tests.csproj b/XmlSchemaClassGenerator.Tests/XmlSchemaClassGenerator.Tests.csproj index 078be04c..471ed9f9 100644 --- a/XmlSchemaClassGenerator.Tests/XmlSchemaClassGenerator.Tests.csproj +++ b/XmlSchemaClassGenerator.Tests/XmlSchemaClassGenerator.Tests.csproj @@ -1,6 +1,6 @@  - netcoreapp2.2 + net5.0 2.0.0 XmlSchemaClassGenerator.Tests XmlSchemaClassGenerator.Tests @@ -873,6 +873,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/XmlSchemaClassGenerator.Tests/xsd/simple/default.xsd b/XmlSchemaClassGenerator.Tests/xsd/simple/default.xsd new file mode 100644 index 00000000..f9b4d5af --- /dev/null +++ b/XmlSchemaClassGenerator.Tests/xsd/simple/default.xsd @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/XmlSchemaClassGenerator/ModelBuilder.cs b/XmlSchemaClassGenerator/ModelBuilder.cs index c5259b06..1df50ad7 100644 --- a/XmlSchemaClassGenerator/ModelBuilder.cs +++ b/XmlSchemaClassGenerator/ModelBuilder.cs @@ -77,29 +77,42 @@ public ModelBuilder(GeneratorConfiguration configuration, XmlSchemaSet set) private void CreateSubstitutes() { - var properties = Types.Values.OfType().SelectMany(c => c.Properties).Where(p => p.XmlSchemaName != null).ToList(); + var classesProps = Types.Values.OfType().Select(c => c.Properties.Where(p => p.XmlSchemaName != null).ToList()).ToList(); - foreach (var prop in properties) + foreach (var classProps in classesProps) { - var substitutes = GetSubstitutedElements(prop.XmlSchemaName).ToList(); + var order = 0; - if (_configuration.SeparateSubstitutes) + foreach (var prop in classProps) { - var elems = GetElements(prop.XmlParticle, prop.XmlParent); + if (_configuration.EmitOrder) + { + prop.Order = order; + order++; + } + + var substitutes = GetSubstitutedElements(prop.XmlSchemaName).ToList(); - foreach (var substitute in substitutes) + if (_configuration.SeparateSubstitutes) { - var cls = (ClassModel)prop.OwningType; - var schema = substitute.Element.GetSchema(); - var source = CodeUtilities.CreateUri(schema.SourceUri); - var props = CreatePropertiesForElements(source, cls, prop.XmlParticle, elems, substitute); + var elems = GetElements(prop.XmlParticle, prop.XmlParent); + + foreach (var substitute in substitutes) + { + var cls = (ClassModel)prop.OwningType; + var schema = substitute.Element.GetSchema(); + var source = CodeUtilities.CreateUri(schema.SourceUri); + var props = CreatePropertiesForElements(source, cls, prop.XmlParticle, elems, substitute, order); + + cls.Properties.AddRange(props); - cls.Properties.AddRange(props); + order += props.Count(); + } + } + else + { + prop.Substitutes = substitutes; } - } - else - { - prop.Substitutes = substitutes; } } } @@ -404,7 +417,7 @@ private TypeModel CreateTypeModel(Uri source, XmlSchemaComplexType complexType, IsAbstract = complexType.IsAbstract, IsAnonymous = string.IsNullOrEmpty(complexType.QualifiedName.Name), IsMixed = complexType.IsMixed, - IsSubstitution = complexType.Parent is XmlSchemaElement && !((XmlSchemaElement)complexType.Parent).SubstitutionGroup.IsEmpty + IsSubstitution = complexType.Parent is XmlSchemaElement parent && !parent.SubstitutionGroup.IsEmpty }; classModel.Documentation.AddRange(docs); diff --git a/XmlSchemaClassGenerator/TypeModel.cs b/XmlSchemaClassGenerator/TypeModel.cs index 67ca38fb..130056cf 100644 --- a/XmlSchemaClassGenerator/TypeModel.cs +++ b/XmlSchemaClassGenerator/TypeModel.cs @@ -152,7 +152,7 @@ protected void GenerateTypeAttribute(CodeTypeDeclaration typeDeclaration) var typeAttribute = new CodeAttributeDeclaration(new CodeTypeReference(typeof(XmlTypeAttribute), Configuration.CodeTypeReferenceOptions), new CodeAttributeArgument(new CodePrimitiveExpression(XmlSchemaName.Name)), new CodeAttributeArgument("Namespace", new CodePrimitiveExpression(XmlSchemaName.Namespace))); - if (IsAnonymous && (!(this is ClassModel classModel) || classModel.BaseClass == null)) + if (IsAnonymous && (this is not ClassModel classModel || classModel.BaseClass == null)) { // don't generate AnonymousType if it's derived class, otherwise XmlSerializer will // complain with "InvalidOperationException: Cannot include anonymous type '...'" @@ -865,7 +865,7 @@ public void AddMembersTo(CodeTypeDeclaration typeDeclaration, bool withDataBindi typeDeclaration.Members.Add(backingField); } - if (DefaultValue == null) + if (DefaultValue == null || ((IsCollection || isArray || (IsList && IsAttribute)) && IsNullable)) { var propertyName = Name; diff --git a/appveyor.yml b/appveyor.yml index dd9adbcc..29daaf32 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -22,7 +22,7 @@ test_script: - ps: | if (-not $env:APPVEYOR_PULL_REQUEST_NUMBER) { dotnet tool install --global dotnet-sonarscanner - dotnet sonarscanner begin /k:"mganss_XmlSchemaClassGenerator" /v:$env:APPVEYOR_BUILD_VERSION /o:"mganss-github" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.login="$env:sonar_token" /d:sonar.cs.opencover.reportsPaths="$($env:APPVEYOR_BUILD_FOLDER)\coverage.netcoreapp2.2.xml" /d:sonar.coverage.exclusions="**/Program.cs" + dotnet sonarscanner begin /k:"mganss_XmlSchemaClassGenerator" /v:$env:APPVEYOR_BUILD_VERSION /o:"mganss-github" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.login="$env:sonar_token" /d:sonar.cs.opencover.reportsPaths="$($env:APPVEYOR_BUILD_FOLDER)\coverage.net5.0.xml" /d:sonar.coverage.exclusions="**/Program.cs" dotnet build } - dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:CoverletOutput="..\coverage.xml" XmlSchemaClassGenerator.Tests\XmlSchemaClassGenerator.Tests.csproj /p:Include="[XmlSchemaClassGenerator]*" @@ -31,7 +31,7 @@ test_script: dotnet sonarscanner end /d:sonar.login="$env:sonar_token" } - pip install codecov - - codecov -f "coverage.netcoreapp2.2.xml" + - codecov -f "coverage.net5.0.xml" artifacts: - path: 'XmlSchemaClassGenerator\**\*.*nupkg' - path: 'XmlSchemaClassGenerator.Console\**\*.*nupkg' diff --git a/xscgen-proj/xscgen-proj.csproj b/xscgen-proj/xscgen-proj.csproj index 9b5fb90f..f71fc8fd 100644 --- a/xscgen-proj/xscgen-proj.csproj +++ b/xscgen-proj/xscgen-proj.csproj @@ -24,6 +24,7 @@ true true snupkg + latest diff --git a/xscgen/xscgen.csproj b/xscgen/xscgen.csproj index 56f22b57..55faa4c2 100644 --- a/xscgen/xscgen.csproj +++ b/xscgen/xscgen.csproj @@ -25,6 +25,7 @@ true true snupkg + latest