Skip to content

Conversation

@mamift
Copy link
Owner

@mamift mamift commented Dec 9, 2025

Updated to version 3.4.12

  • updated SDK to .NET 10;
  • added gitHub/agent instructions
  • Fixes a bug in the CLI tool occurring when a directory with trailling quotes (' or ") is provided for the gen -a path\ command.
  • Added more substantial tests for testing code gen regressions.
  • The LinqToXsd CLI tool now runs on .NET 7,8,9 and 10. Still supports .NET core 3.1, 5 and 6 and .NET Framework 4.7.2.
  • Anonymous union type code generation — a new code gen feature. When an XSD attribute declares an inline union like <xs:union memberTypes="xs:date xs:dateTime"/>, the generator now produces a named nested validator class (e.g. simpleUnionTypeOfDateAndDateTime) so the C# setter can validate values at runtime. Previously this produced broken references.
  • CodeDOM parent tracking — supporting infrastructure. CodeDOM objects now track their parent namespace via UserData, enabling the generator to search for sibling types during code generation.
  • Adds a new foundational classes and methods for future implementation like, IWarnableObserver interface to provides structured warnings during generation.
  • Also updates some tests accordingly to new functionality.

Also addresses #67


Open with Devin

mamift and others added 26 commits October 30, 2025 16:21
… is provided for the `gen -a path\` command.
…lass TypeEnumValidator is no longer being generated!
….System.DateTimeOnly and System.Memory nuget.

<PropertyGroup>
<TargetFrameworks>net6.0;net5.0;netcoreapp3.1;netframework472</TargetFrameworks>
<TargetFrameworks>net10.0;net9.0;net8.0;net7.0;net6.0;net5.0;netcoreapp3.1;netframework472</TargetFrameworks>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mamift I don't think this is needed?
Normally you can run tools targeting earlier frameworks without issue on newer one?

Listing a framework explicitly should only be required if you intend on using a new framework-specific feature.

Having many targets needs more build passes (so longer) and bloats IDE memory, which tries to juggle available apis for all requested target framework.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is only for the LinqToXsd tool project; XObjectsCore and XObjectsCodeGen still target just 2 framework monikers.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is different about LinqToXsd tool? If it's built for net5.0 I can run it on my machine that has .net10.0, can't I?

Another drawback of this long list of target frameworks is that anyone who works on LinqToXsd source needs to have all these targeting packs installed.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another drawback of this long list of target frameworks is that anyone who works on LinqToXsd source needs to have all these targeting packs installed

No they don't. I've only got .NET 6, 8, and 10 SDK installed. Only .NET 8 and 10 runtimes and am able to build it all fine. Also the build server I use only uses the .NET 10 SDK and runtime and it's able to produce assets for all TFMs without issue.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not SDKs, targeting packs.
You can have just .NET 10 SDK and build for all targets listed here, but you need targeting packs.
At least for .net framework versions... now that I look into it, targeting packs don't seem to exists for .net core, makes me wonder how it works.

But I still don't get why so many targets are needed? If you target net5.0 (and build with .net 10 SDK), it should run just fine on a machine that has .net 10 runtime?

Copy link

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 3 new potential issues.

View 14 additional findings in Devin Review.

Open in Devin Review

Comment on lines +250 to +253
return type != null && !(
type.IsGlobal() &&
type.IsBuiltInSimpleType()
);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 IsAnonymous uses AND instead of OR, misclassifying global named types as anonymous

The IsAnonymous extension method uses && (AND) inside a negation where it should use || (OR), causing global user-defined named simple types to be incorrectly classified as anonymous.

Root Cause and Impact

At XObjectsCode/Extensions/XmlSchemaExtensions.cs:250-253, the logic is:

return type != null && !(
    type.IsGlobal() &&
    type.IsBuiltInSimpleType()
);

By De Morgan's law, !(A && B) equals (!A || !B). So this returns true whenever a type is either not global or not built-in. A global user-defined named type (e.g., <xs:simpleType name="ShortString">) would have IsGlobal()=true and IsBuiltInSimpleType()=false, yielding !(true && false) = true — incorrectly marking a named global type as anonymous.

The correct intent is: a type is anonymous when it is neither global nor built-in, which requires || instead of && inside the negation:

return type != null && !(
    type.IsGlobal() ||
    type.IsBuiltInSimpleType()
);

In practice, callers like IsOfAnonymousType(XmlSchemaAttribute) pass attr.SchemaType which is null for referenced types, partly masking this bug. But the IsForAnonymousXsdType property at XObjectsCode/Src/ClrTypeReference.cs:337 casts schemaObject directly, where this logic error can produce incorrect results.

Suggested change
return type != null && !(
type.IsGlobal() &&
type.IsBuiltInSimpleType()
);
return type != null && !(
type.IsGlobal() ||
type.IsBuiltInSimpleType()
);
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

View 17 additional findings in Devin Review.

Open in Devin Review

Comment on lines +216 to +218
var excludeV11Xsds = dictOfSchemasAndTheirConfigs
.Where(filePairs => filePairs.xsdFile.Exists && filePairs.xsdFile.GetXmlSchemaVersion() != XmlSchemaVersion.Version1_1)
.ToList();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Generate method no longer filters out XSD files without config files, contradicting documented behavior

In the auto-config Generate method, the filtering condition was changed from checking whether the config file exists to checking whether the XSD file exists, silently changing behavior.

Detailed Explanation

The old code at XObjectsCode/Src/XObjectsCoreGenerator.cs filtered with kvp.Value.Exists where kvp.Value was the FileInfo for the .config file — meaning XSD files without a companion config were skipped.

The new code at line 217 filters with filePairs.xsdFile.Exists — checking whether the XSD file itself exists, which is almost always true since the user provided the path. The config file existence is no longer checked.

As a result, Generate(pair.xsdFile.FullName, pair.configFile.FullName) at line 227 passes a potentially non-existent config path to Generate(string, string?). While LoadLinqToXsdSettings now has a File.Exists guard (line 29), the behavior still changes: XSDs that previously were skipped are now processed with default settings.

The method's doc comment (line 198-202) still says "Will skip over XSDs that have no accompanying .config file," which is now incorrect. This behavioral change can lead to unexpected code generation output when users have a mix of configured and unconfigured XSD files.

Suggested change
var excludeV11Xsds = dictOfSchemasAndTheirConfigs
.Where(filePairs => filePairs.xsdFile.Exists && filePairs.xsdFile.GetXmlSchemaVersion() != XmlSchemaVersion.Version1_1)
.ToList();
var excludeV11Xsds = dictOfSchemasAndTheirConfigs
.Where(filePairs => filePairs.xsdFile.Exists && filePairs.configFile.Exists && filePairs.xsdFile.GetXmlSchemaVersion() != XmlSchemaVersion.Version1_1)
.ToList();
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants