Skip to content

Conversation

@smaillet
Copy link
Member

@smaillet smaillet commented Jan 9, 2026

Updates in prep for code gen

Important

Some of these changes are breaking changes that require a major version bump.

General repository updates

  • Moved editorconfig and global.json to same folder as the solution.
    • Despite what is implied in the docs, these are only recognized when they exist at the same level of the directory structure as the solution it applies to.
  • Added GeneratePathProperty to all packagereferences so that is automatic now.
    • It appears that it is the default whether that is set or not. The default behavior in the project system might handle explicitly setting it to false. This makes it consistently on even if the default is normally off.
  • Updated NuGet.config to leverage source mapping and force all generated packages to come from the build output location and never from nuget.org or any other source.

Ubiquity.NET.CodeAnalysis.Utils

  • [Potentially Breaking Change] Added reference from Ubiquity.NET.CodeAnalysis.Utils to Ubiquity.NET.Extensions

  • Added AttributeDataExtensions to provide common usage extensions for AttributeData

  • Cleaned up implementation of BaseTypeDeclarationSyntaxExtensions.GetNestedClassName

  • Added DebugAssert extension to validate the size of a struct is within the recommended limits.

    • If a struct is too large there's a very good chance that it has more overhead than if it was a class.
  • [Breaking change] Updated DiagnosticInfo to use an ImmutableArray as the member and apply structural equality on it.

    • This ensures that two instances that have the same contents are considered equal. Previously it was only a shallow compare so two diagnostics with the same contents for Params ended up comparing as not equal even though they were equal.
  • [Breaking Change] Added Structural equality behavior to EquatableArray.

    • Also clarified docs that use of this type is rather limited. It's primary goal is to add structural equatability as the behavior behind IEquatable<T> which is normally just a shallow equality or reference equality. When an array is captured as a member of something else, than an ImmutableArray<T> should be used directly. The primary reason this isn't obsolete is for a top level array that is a direct result of a parse/analysis. Capturing it into EquatableArray<T> ensures correct caching behavior.
  • Added EquatableAttributeData to capture attribute data in the analysis phase.

  • Added EquatableAttributeDataCollection

    • This is essentially a KeyedCollection<EquatableAttributeData> that uses the EquatableAttributeData.Name as the key AND supports structural equality.
  • Added EquatableDictionary<TKey,TValue> that is a struct to wrap a Dictionary<TKey,TValue> with structural equality. This is a simple struct that consume no size beyond that of the managed ref to the wrapped dictionary. It is only providing alternate behavior.

  • Added NamespaceQualifiedNameFormatter as a general type to handle custom formatting of NamespaceWualifiedName.

    • This type is generalized to allow language specific implementations with only the global prefix and alias maps as unique per language.
    • Added static CSharp, using singleton pattern for the language as only one actual instance is needed.
  • [Breaking Change] Added Structural Equality support to NestedClassName

  • [Breaking Change] Changed type of Result<T>.Diagnostics to ImmutableArray<DiagnosticInfo>

  • Added StructurallyEquatableTypedConstant

    • This is a simple wrapper around TypedConstant to provide structural equality for array constants. These are most likely used in the constructor or named arguments of an Attribute.
  • Added StructuralTypedConstantComparer to perform structural comparisons of TypedConstant values.

  • Added SymbolExtensions utility class to host extension methods for an ISymbol. Particularly around finding/capturing attribute data attached to a symbol.

  • Added TypedConstantExtensions utility class to host extension methods for TypedConstant.

    • Specifically to test if a given constant is a non-null array.
  • Added TypeSymbolExtensions utility class to host extensions for a ITypeSymbol.

    • Specifically to gather or determine the name elements.
    • Reverse walk of the hierarchy is NOT performed until the sequence of namespace names is enumerated. This helps reduce the cost until it is needed.

Ubiquity.NET.CommandLine

  • [Breaking Change] Changed the name of CmdLineSettings to CommandLineSettings for consistency.
  • [Breaking Change] Split ICommandLineOptions<T> into two distinct interfaces.
    • ICommandBinder provides binding support of the results of a parse
    • IRootCommandBuilder provides support for building the application root command.
    • This paves the way for generators and, in particular, that every sub-command is NOT a root command. That is, a sub-command, when supported,
      does not implement IRooCommandBuilder as it isn't a root command.
  • Obsoleted the ArgsParsing.TryParse<T> as the use of this with it's odd return code behavior was sub-optimal leading to confusion and incorrect use that was difficult to understand. Callers should use the RootCommandExtensions.ParseAndInvokeResult overloads instead.

Ubiquity.NET.Extensions

  • Added ICustomFormatter<T> interface to the extensions support.
    • This provides an explicit type formatter that custom formatting can query of an IFormatter instance to know that a particular type format is available
  • Added ImmutableArrayExtensions utility class to host extension to ImmutableArray<T>

Ubiquity.NET.SrcGeneration

  • Added AsLiteral methods to the CSharpLanguage type to allow formatting a string or bool as a literal appropriate for the language.

>[!IMPORTANT]
> Some of these changes are breaking changes that require a major version bump.

## General repository updates
* Moved editorconfig and global.json to same folder as the solution.
    - Despite what is implied in the docs, these are only recognized when they exist at the same level of the directory structure as the solution it applies to.
* Added `GeneratePathProperty` to all packagereferences so that is automatic now.
    - It appears that it is the default whether that is set or not. The default behavior in the project system might handle explicitly setting it to `false`. This makes it consistently on even if the default is normally off.
* Updated `NuGet.config` to leverage source mapping and force all generated packages to come from the build output location and never from nuget.org or any other source.

## Ubiquity.NET.CodeAnalysis.Utils
* [Potentially Breaking Change] Added reference from `Ubiquity.NET.CodeAnalysis.Utils` to `Ubiquity.NET.Extensions`
* Added `AttributeDataExtensions` to provide common usage extensions for `AttributeData`
* Cleaned up implementation of `BaseTypeDeclarationSyntaxExtensions.GetNestedClassName`
* Added DebugAssert extension to validate the size of a struct is within the recommended limits.
    - If a struct is too large there's a very good chance that it has more overhead than if it was a class.
* [Breaking change] Updated `DiagnosticInfo` to use an ImmutableArray as the member and apply structural equality on it.
    - This ensures that two instances that have the same contents are considered equal. Previously it was only a shallow compare so tow diagnostics with the same contents for `Params` ended up comparing as not equal even though they were equal.
* [Breaking Change] Added Structural equality behavior to EquatableArray.
    - Also clarified docs that use of this type is rather limited. It's primary goal is to add structural equatability as the behavior behind `IEquatable<T>` which is normally just a shallow equality or reference equality. When an array is captured as a member of something else, than an `ImmutableArray<T>` should be used directly. The primary reason this isn't obsolete is for a top level array that is a direct result of a parse/analysis. Capturing it into `EquatableArray<T>` ensures correct caching behavior.
* Added EquatableAttributeData to capture attribute data in the analysis phase.
* Added `EquatableAttributeDataCollection`
    * This is essentially a `KeyedCollection<EquatableAttributeData>` that uses the `EquatableAttributeData.Name` as the key AND supports structural equality.
* Added `EquatableDictionary<TKey,TValue>` that is a struct to wrap a `Dictionary<TKey,TValue>` with structural equality. This is a simple struct that consume no size beyond that of the managed ref to the wrapped dictionary. It is only providing alternate behavior.
* Added `NamespaceQualifiedNameFormatter` as a general type to handle custom formatting of `NamespaceWualifiedName`.
    - This type is generalized to allow language specific implementations with only the global prefix and alias maps as unique per language.
    - Added static CSharp, using singleton pattern for the language as only one actual instance is needed.

* [Breaking Change] Added Structural Equality support to `NestedClassName`
* [Breaking Change] Changed type of `Result<T>.Diagnostics` to  `ImmutableArray<DiagnosticInfo>`
* Added `StructurallyEquatableTypedConstant`
    - This is a simple wrapper around `TypedConstant` to provide structural equality for array constants. These are most likely used in the constructor or named arguments of an Attribute.
* Added `StructuralTypedConstantComparer` to perform structural comparisons of `TypedConstant` values.
* Added `SymbolExtensions` utility class to host extension methods for an `ISymbol`. Particularly around finding/capturing attribute data attached to a symbol.
* Added `TypedConstantExtensions` utility class to host extension methods for `TypedConstant`.
    - Specifically to test if a given constant is a non-null array.
* Added `TypeSymbolExtensions` utility class to host extensions for a `ITypeSymbol`.
    - Specifically to gather or determine the name elements.
    - Reverse walk of the hierarchy is NOT performed until the sequence of namespace names is enumerated. This helps reduce the cost until it is needed.

## Ubiquity.NET.CommandLine
* [Breaking Change] changed the name of `CmdLineSettings` to `CommandLineSettings` for consistency.
* [Breaking Change] - Split `ICommandLineOptions<T>` into two distinct interfaces.
    - `ICommandBinder` provides binding support of the results of a parse
    - `IRootCommandBuilder` provides support for building the application root command.
    - This paves the way for generators and, in particular, that every sub-command is NOT a root command. That is, a sub-command, when supported,
does not implement IRooCommandBuilder as it isn't a root command.
* Obsoleted the `ArgsParsing.TryParse<T>` as the use of this with it's odd return code behavior was sub-optimal leading to confusion and incorrect use that was difficult to understand. Callers should use the `RootCommandExtensions.ParseAndInvokeResult` overloads instead.

## Ubiquity.NET.Extensions
* Added `ICustomFormatter<T>` interface to the extensions support.
    - This provides an explicit type formatter that custom formatting can query of an `IFormatter` instance to know that a particular type format is available
* Added `ImmutableArrayExtensions` utility class to host extension to `ImmutableArray<T>`

## Ubiquity.NET.SrcGeneration
* Added AsLiteral methods to the `CSharpLanguage` type to allow formatting a string or bool as a literal appropriate for the language.
@github-actions
Copy link

github-actions bot commented Jan 9, 2026

Test Results

  7 files  ±0    7 suites  ±0   5s ⏱️ +2s
157 tests ±0  153 ✅ ±0  4 💤 ±0  0 ❌ ±0 
288 runs  ±0  279 ✅ ±0  9 💤 ±0  0 ❌ ±0 

Results for commit 742109b. ± Comparison against base commit 1e2ed7e.

♻️ This comment has been updated with latest results.

@smaillet smaillet merged commit d063c2a into UbiquityDotNET:develop Jan 9, 2026
3 checks passed
@smaillet smaillet deleted the PrepForCodeGen branch January 9, 2026 22:11
@smaillet smaillet restored the PrepForCodeGen branch January 11, 2026 15:45
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.

1 participant