Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,43 @@
# Changelog

## v1.7.0

Closes three AutoMapper-parity gaps surfaced by the Duende.IdentityServer.Admin migration analysis (#125, #126, #127).

### New Features

- **Per-property LINQ projection (`SelectProperty`)** (#136) — New `ForgePropertyAttribute.SelectProperty` named property emits `source.Src?.Select(x => x.<member>).To<TDest>()` for the targeted property, eliminating the `[ForgeFrom]` boilerplate previously required for join-table-entity → primitive-collection mappings (e.g., `List<ApiResourceClaim>` → `List<string>`). Composes with v1.5 collection coercion and v1.6 string↔enum / built-in coercions on the projected element. Mutually exclusive with `ConvertWith`/`ConvertWithType` and `[ForgeFrom]`/`[ForgeWith]`. Adds FM0055–FM0059, FM0072, FM0073, and FM0075.

- **Conditional property assignment (`Condition` / `SkipWhen`)** (#137) — `ForgePropertyAttribute.Condition` and `SkipWhen` accept a predicate method name (`bool Predicate(TSource)` or `bool Predicate(TSource, TDestination)`) that gates whether the destination property is assigned. `SkipWhen` is the inverse of `Condition`; the two are mutually exclusive. Emits an `if` guard around the assignment so the destination retains its existing value when the predicate fails — ideal for nullable update DTOs that should not overwrite populated fields. Not supported on init-only or constructor-bound members. Adds FM0060–FM0064.

- **Entity↔primitive mapping (`[ExtractProperty]` / `[WrapProperty]`)** (#138) — Two new method-level attributes generate single-element projections between entity types and their primitive payloads. `[ExtractProperty(nameof(Source.Member))]` emits `source?.Member` (or value-type equivalent under the active `NullPropertyHandling`); `[WrapProperty(nameof(Dest.Member))]` emits `new TDest { Member = source }` with required-members validation. Complements `SelectProperty` for the single-element case. Mutually exclusive with `[ForgeFrom]`/`[ForgeWith]`/`[ConvertWith]` on the same method. Adds FM0065–FM0071 and FM0074.
Comment thread
superyyrrzz marked this conversation as resolved.
Outdated

### New Diagnostics

| Rule ID | Severity | Description |
|---------|----------|-------------|
| FM0055 | Error | `SelectProperty` source is not enumerable |
| FM0056 | Error | `SelectProperty` member not found on source element type |
| FM0057 | Error | `SelectProperty` element type incompatible with destination element type |
| FM0058 | Error | `SelectProperty` conflicts with `ConvertWith`/`ConvertWithType` |
| FM0059 | Disabled | `SelectProperty` projection applied |
| FM0060 | Error | `Condition` and `SkipWhen` cannot both be set |
| FM0061 | Error | Conditional predicate method invalid (not found / wrong signature / not bool-returning) |
| FM0062 | Error | Conditional assignment not supported on init-only or constructor-bound members |
| FM0063 | Error | Conditional assignment conflicts with `[ForgeFrom]`/`[ForgeWith]` |
| FM0064 | Disabled | Conditional assignment applied |
| FM0065 | Error | `[ExtractProperty]`/`[WrapProperty]` conflicts with `[ForgeFrom]`/`[ForgeWith]`/`[ConvertWith]` |
| FM0066 | Error | `[ExtractProperty]` member not found on source |
| FM0067 | Error | `[ExtractProperty]` member type incompatible with method return type |
| FM0068 | Error | `[WrapProperty]` member not found on destination |
| FM0069 | Error | `[WrapProperty]` member type incompatible with method parameter type |
| FM0070 | Error | `[ExtractProperty]`/`[WrapProperty]` invalid method signature |
| FM0071 | Error | `[WrapProperty]` destination has unsatisfied required members |
| FM0072 | Error | `SelectProperty` conflicts with `[ForgeFrom]`/`[ForgeWith]` |
| FM0073 | Error | `SelectProperty` destination is not enumerable |
| FM0074 | Disabled | `[ExtractProperty]`/`[WrapProperty]` value-type return under `ReturnNull` |
| FM0075 | Warning | `SelectProperty` not supported on `ForgeInto` methods |

## v1.6.0

### New Features
Expand Down
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<Copyright>Copyright (c) ForgeMap Contributors</Copyright>

<!-- Versioning -->
<VersionPrefix>1.6.0</VersionPrefix>
<VersionPrefix>1.7.0</VersionPrefix>

<!-- SourceLink & deterministic builds -->
<PublishRepositoryUrl>true</PublishRepositoryUrl>
Expand Down
28 changes: 28 additions & 0 deletions src/ForgeMap.Generator/AnalyzerReleases.Shipped.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,34 @@
; Shipped analyzer releases
; https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md

## Release 1.7.0

### New Rules

Rule ID | Category | Severity | Notes
--------|----------|----------|-------
FM0055 | ForgeMap | Error | SelectPropertySourceNotEnumerable
FM0056 | ForgeMap | Error | SelectPropertyMemberNotFound
FM0057 | ForgeMap | Error | SelectPropertyElementTypeIncompatible
FM0058 | ForgeMap | Error | SelectPropertyConflictsWithConverter
FM0059 | ForgeMap | Disabled | SelectPropertyApplied
FM0060 | ForgeMap | Error | ConditionAndSkipWhenBothSet
FM0061 | ForgeMap | Error | ConditionalPredicateInvalid
FM0062 | ForgeMap | Error | ConditionalNotSupportedOnInitOrCtor
FM0063 | ForgeMap | Error | ConditionalConflictsWithForgeFromOrWith
FM0064 | ForgeMap | Disabled | ConditionalAssignmentApplied
FM0065 | ForgeMap | Error | ExtractWrapConflictsWithMethodAttributes
FM0066 | ForgeMap | Error | ExtractPropertyNotFound
FM0067 | ForgeMap | Error | ExtractPropertyTypeIncompatible
FM0068 | ForgeMap | Error | WrapPropertyNotFound
FM0069 | ForgeMap | Error | WrapPropertyTypeIncompatible
FM0070 | ForgeMap | Error | ExtractWrapInvalidSignature
FM0071 | ForgeMap | Error | WrapPropertyRequiredMembersUnsatisfied
FM0072 | ForgeMap | Error | SelectPropertyConflictsWithForgeFromOrWith
FM0073 | ForgeMap | Error | SelectPropertyDestinationNotEnumerable
FM0074 | ForgeMap | Disabled | ExtractWrapValueTypeReturnUnderReturnNull
FM0075 | ForgeMap | Warning | SelectPropertyNotSupportedOnForgeInto

## Release 1.6.0

### New Rules
Expand Down
26 changes: 0 additions & 26 deletions src/ForgeMap.Generator/AnalyzerReleases.Unshipped.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,2 @@
; Unshipped analyzer releases
; https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md

### New Rules

Rule ID | Category | Severity | Notes
--------|----------|----------|-------
FM0055 | ForgeMap | Error | SelectPropertySourceNotEnumerable
FM0056 | ForgeMap | Error | SelectPropertyMemberNotFound
FM0057 | ForgeMap | Error | SelectPropertyElementTypeIncompatible
FM0058 | ForgeMap | Error | SelectPropertyConflictsWithConverter
FM0059 | ForgeMap | Disabled | SelectPropertyApplied
FM0060 | ForgeMap | Error | ConditionAndSkipWhenBothSet
FM0061 | ForgeMap | Error | ConditionalPredicateInvalid
FM0062 | ForgeMap | Error | ConditionalNotSupportedOnInitOrCtor
FM0063 | ForgeMap | Error | ConditionalConflictsWithForgeFromOrWith
FM0064 | ForgeMap | Disabled | ConditionalAssignmentApplied
FM0065 | ForgeMap | Error | ExtractWrapConflictsWithMethodAttributes
FM0066 | ForgeMap | Error | ExtractPropertyNotFound
FM0067 | ForgeMap | Error | ExtractPropertyTypeIncompatible
FM0068 | ForgeMap | Error | WrapPropertyNotFound
FM0069 | ForgeMap | Error | WrapPropertyTypeIncompatible
FM0070 | ForgeMap | Error | ExtractWrapInvalidSignature
FM0071 | ForgeMap | Error | WrapPropertyRequiredMembersUnsatisfied
FM0072 | ForgeMap | Error | SelectPropertyConflictsWithForgeFromOrWith
FM0073 | ForgeMap | Error | SelectPropertyDestinationNotEnumerable
FM0074 | ForgeMap | Disabled | ExtractWrapValueTypeReturnUnderReturnNull
FM0075 | ForgeMap | Warning | SelectPropertyNotSupportedOnForgeInto
Loading