Skip to content

Commit 77a9fa6

Browse files
author
fabien.menager
committed
Merge branch 'master' into feature/docs-website
2 parents 72a5e87 + a97ee28 commit 77a9fa6

273 files changed

Lines changed: 312 additions & 359 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.devcontainer/devcontainer.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
2+
// README at: https://github.com/devcontainers/templates/tree/main/src/dotnet
3+
{
4+
"name": "C# (.NET)",
5+
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
6+
"image": "mcr.microsoft.com/devcontainers/dotnet:2-10.0-noble",
7+
"customizations": {
8+
"vscode": {
9+
"extensions": [
10+
"ms-dotnettools.csdevkit"
11+
]
12+
}
13+
},
14+
"postCreateCommand": "dotnet restore"
15+
}

.github/copilot-instructions.md

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,16 @@ samples/ # Readme sample project
2323

2424
## Build & SDK
2525

26-
| Setting | Value |
27-
|---|---|
28-
| .NET SDK | 10.0.x (`global.json`, `rollForward: latestMinor`) |
29-
| Target frameworks | `net8.0` + `net10.0` (library); `net8.0;net9.0;net10.0` (functional tests) |
30-
| C# language version | `12.0` on `net8.0`, `14.0` on `net10.0` |
31-
| Nullable | `enable` |
32-
| Implicit usings | `enable` |
33-
| Warnings as errors | `TreatWarningsAsErrors = true`**zero warnings allowed** |
34-
| Suppressed warning | `CS1591` (missing XML doc) |
35-
| Assembly signing | `Key.snk` (src projects only) |
26+
| Setting | Value |
27+
|---------------------|----------------------------------------------------------------------------|
28+
| .NET SDK | 10.0.x (`global.json`, `rollForward: latestMinor`) |
29+
| Target frameworks | `net8.0` + `net10.0` (library); `net8.0;net9.0;net10.0` (functional tests) |
30+
| C# language version | `12.0` on `net8.0`, `14.0` on `net10.0` |
31+
| Nullable | `enable` |
32+
| Implicit usings | `enable` |
33+
| Warnings as errors | `TreatWarningsAsErrors = true`**zero warnings allowed** |
34+
| Suppressed warning | `CS1591` (missing XML doc) |
35+
| Assembly signing | `Key.snk` (src projects only) |
3636

3737
The generator project targets `netstandard2.0` only (Roslyn analyzers requirement).
3838

@@ -98,18 +98,18 @@ Use file-scoped namespaces (`namespace Foo;`) in all new files **except** when t
9898
## Testing Guidelines
9999

100100
### Test projects and frameworks
101-
| Project | Framework | Library |
102-
|---|---|---|
103-
| `Generator.Tests` | xUnit 2 | `Verify.Xunit` snapshot testing |
104-
| `FunctionalTests` | xUnit 2 + ScenarioTests | `Verify.Xunit` + `Microsoft.EntityFrameworkCore.SqlServer` |
105-
| `Tests` | xUnit 2 | plain assertions |
101+
| Project | Framework | Library |
102+
|-------------------|--------------------------|--------------------------------------------------------------|
103+
| `Generator.Tests` | xUnit v3 | `Verify.XunitV3` snapshot testing for the code generator |
104+
| `CodeFixer.Tests` | xUnit v3 | `Verify.XunitV3` snapshot testing for the code fixes |
105+
| `FunctionalTests` | xUnit v3 + ScenarioTests | `Verify.XunitV3` + `Microsoft.EntityFrameworkCore.SqlServer` |
106+
| `Tests` | xUnit v3 | plain assertions |
106107

107-
### Verify.Xunit — snapshot testing
108+
### Verify.XunitV3 — snapshot testing
108109

109110
**Every test that calls `Verifier.Verify(...)` must:**
110111
1. Return `Task` (not `void`)
111-
2. Have `[UsesVerify]` on the class
112-
3. Have a corresponding `.verified.txt` file committed alongside the test file
112+
2. Have a corresponding `.verified.txt` file committed alongside the test file
113113

114114
**Naming convention for verified files:**
115115
`{ClassName}.{MethodName}.verified.txt`
@@ -223,17 +223,17 @@ $env:VERIFY_AUTO_APPROVE = "true"; dotnet test
223223

224224
### Key files in `EntityFrameworkCore.Projectables.Generator`
225225

226-
| File | Responsibility |
227-
|---|---|
228-
| `ProjectionExpressionGenerator.cs` | `IIncrementalGenerator` entry point — wires up the pipeline |
229-
| `ProjectableInterpreter.cs` (+ partials) | Converts a `MemberDeclarationSyntax` into a `ProjectableDescriptor` |
230-
| `ExpressionSyntaxRewriter.cs` (+ partials) | Rewrites expressions: null-conditionals, enum expansions, switch expressions |
231-
| `DeclarationSyntaxRewriter.cs` | Rewrites declarations (fully-qualified names, etc.) |
232-
| `BlockStatementConverter.cs` | Converts block-bodied methods to expression trees |
233-
| `ProjectableDescriptor.cs` | Pure data record describing a projectable member |
234-
| `ProjectableAttributeData.cs` | Serializable snapshot of `[Projectable]` attribute values (no live Roslyn objects) |
235-
| `ProjectionRegistryEmitter.cs` | Emits `ProjectionRegistry.g.cs` |
236-
| `Diagnostics.cs` | All `DiagnosticDescriptor` constants (EFP0001–EFP0009) |
226+
| File | Responsibility |
227+
|--------------------------------------------|------------------------------------------------------------------------------------|
228+
| `ProjectionExpressionGenerator.cs` | `IIncrementalGenerator` entry point — wires up the pipeline |
229+
| `ProjectableInterpreter.cs` (+ partials) | Converts a `MemberDeclarationSyntax` into a `ProjectableDescriptor` |
230+
| `ExpressionSyntaxRewriter.cs` (+ partials) | Rewrites expressions: null-conditionals, enum expansions, switch expressions |
231+
| `DeclarationSyntaxRewriter.cs` | Rewrites declarations (fully-qualified names, etc.) |
232+
| `BlockStatementConverter.cs` | Converts block-bodied methods to expression trees |
233+
| `ProjectableDescriptor.cs` | Pure data record describing a projectable member |
234+
| `ProjectableAttributeData.cs` | Serializable snapshot of `[Projectable]` attribute values (no live Roslyn objects) |
235+
| `ProjectionRegistryEmitter.cs` | Emits `ProjectionRegistry.g.cs` |
236+
| `Diagnostics.cs` | All `DiagnosticDescriptor` constants (EFP0001–EFP0009) |
237237

238238
### Incremental generator rules
239239
- **Never capture live Roslyn objects** (`ISymbol`, `SemanticModel`, `Compilation`, `AttributeData`) in the incremental pipeline transforms — they break caching. Use `ProjectableAttributeData` (a plain struct) instead.
@@ -243,15 +243,15 @@ $env:VERIFY_AUTO_APPROVE = "true"; dotnet test
243243

244244
## Diagnostics Reference
245245

246-
| ID | Severity | Title |
247-
|---|---|---|
248-
| EFP0001 | Warning | Block-bodied member support is experimental |
249-
| EFP0002 | Error | Null-conditional expression unsupported |
250-
| EFP0003 | Warning | Unsupported statement in block-bodied method |
251-
| EFP0004 | Error | Statement with side effects in block-bodied method |
252-
| EFP0005 | Warning | Potential side effect in block-bodied method |
253-
| EFP0006 | Error | Method/property should expose a body definition |
254-
| EFP0007 | Warning | Non-projectable method call in block body |
246+
| ID | Severity | Title |
247+
|---------|----------|----------------------------------------------------|
248+
| EFP0001 | Warning | Block-bodied member support is experimental |
249+
| EFP0002 | Error | Null-conditional expression unsupported |
250+
| EFP0003 | Warning | Unsupported statement in block-bodied method |
251+
| EFP0004 | Error | Statement with side effects in block-bodied method |
252+
| EFP0005 | Warning | Potential side effect in block-bodied method |
253+
| EFP0006 | Error | Method/property should expose a body definition |
254+
| EFP0007 | Warning | Non-projectable method call in block body |
255255

256256
---
257257

.github/workflows/build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ env:
1313
# Disable sending usage data to Microsoft
1414
DOTNET_CLI_TELEMETRY_OPTOUT: true
1515
# GitHub Packages Feed settings
16-
GITHUB_FEED: https://nuget.pkg.github.com/koenbeuk/
17-
GITHUB_USER: koenbeuk
16+
GITHUB_FEED: https://nuget.pkg.github.com/EFNext/
17+
GITHUB_USER: EFNext
1818
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1919

2020
jobs:

.github/workflows/release.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ env:
1111
# Disable sending usage data to Microsoft
1212
DOTNET_CLI_TELEMETRY_OPTOUT: true
1313
# GitHub Packages Feed settings
14-
GITHUB_FEED: https://nuget.pkg.github.com/koenbeuk/
15-
GITHUB_USER: koenbeuk
14+
GITHUB_FEED: https://nuget.pkg.github.com/EFNext/
15+
GITHUB_USER: EFNext
1616
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1717
# Official NuGet Feed settings
1818
NUGET_FEED: https://api.nuget.org/v3/index.json

Directory.Build.props

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@
1414
<PropertyGroup>
1515
<Authors>Koen Bekkenutte</Authors>
1616
<PackageLicenseExpression>MIT</PackageLicenseExpression>
17-
<PackageProjectUrl>https://github.com/koenbeuk/EntityFrameworkCore.Projectables</PackageProjectUrl>
18-
<RepositoryUrl>https://github.com/koenbeuk/EntityFrameworkCore.Projectables.git</RepositoryUrl>
17+
<PackageProjectUrl>https://github.com/EFNext/EntityFrameworkCore.Projectables</PackageProjectUrl>
18+
<RepositoryUrl>https://github.com/EFNext/EntityFrameworkCore.Projectables.git</RepositoryUrl>
1919
<RepositoryType>git</RepositoryType>
20-
<PackageReleaseNotes>https://github.com/koenbeuk/EntityFrameworkCore.Projectables/releases</PackageReleaseNotes>
20+
<PackageReleaseNotes>https://github.com/EFNext/EntityFrameworkCore.Projectables/releases</PackageReleaseNotes>
2121
<Description>Project over properties and functions in your linq queries</Description>
2222
</PropertyGroup>
2323
</Project>

Directory.Packages.props

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,31 @@
66
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="8.0.0" />
77
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.0" />
88
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.0" />
9-
<PackageVersion Include="Basic.Reference.Assemblies.Net80" Version="1.8.3" />
9+
<PackageVersion Include="Basic.Reference.Assemblies.Net80" Version="1.8.4" />
1010
</ItemGroup>
1111
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
1212
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
1313
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.0" />
1414
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.0" />
15-
<PackageVersion Include="Basic.Reference.Assemblies.Net90" Version="1.8.3" />
15+
<PackageVersion Include="Basic.Reference.Assemblies.Net90" Version="1.8.4" />
1616
</ItemGroup>
1717
<ItemGroup Condition="'$(TargetFramework)' == 'net10.0'">
1818
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="10.0.0" />
1919
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.0" />
2020
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.0" />
21-
<PackageVersion Include="Basic.Reference.Assemblies.Net100" Version="1.8.3" />
21+
<PackageVersion Include="Basic.Reference.Assemblies.Net100" Version="1.8.4" />
2222
</ItemGroup>
2323
<ItemGroup>
24-
<PackageVersion Include="BenchmarkDotNet" Version="0.14.0" />
25-
<PackageVersion Include="coverlet.collector" Version="6.0.2" />
24+
<PackageVersion Include="BenchmarkDotNet" Version="0.15.8" />
25+
<PackageVersion Include="coverlet.collector" Version="8.0.1" />
2626
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="8.0.1" />
2727
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="5.0.0" />
2828
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="5.0.0" />
29-
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" />
30-
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
29+
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="5.3.0" />
30+
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
3131
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
32-
<PackageVersion Include="Verify.Xunit" Version="22.5.0" />
33-
<PackageVersion Include="xunit" Version="2.9.2" />
34-
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" />
32+
<PackageVersion Include="Verify.XunitV3" Version="31.13.5" />
33+
<PackageVersion Include="xunit.v3" Version="3.2.2" />
34+
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
3535
</ItemGroup>
3636
</Project>

benchmarks/EntityFrameworkCore.Projectables.Benchmarks/ExpressionResolverBenchmark.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ public class ExpressionResolverBenchmark
2222

2323
private static readonly MemberInfo _methodWithParamMember =
2424
typeof(TestEntity).GetMethod(nameof(TestEntity.IdPlusDelta), new[] { typeof(int) })!;
25+
26+
private static readonly MemberInfo _copyConstructorMember =
27+
typeof(TestEntity).GetConstructor(new[] { typeof(TestEntity) })!;
2528

2629
private readonly ProjectionExpressionResolver _resolver = new();
2730

@@ -39,6 +42,10 @@ public class ExpressionResolverBenchmark
3942
public LambdaExpression? ResolveMethodWithParam_Registry()
4043
=> _resolver.FindGeneratedExpression(_methodWithParamMember);
4144

45+
[Benchmark]
46+
public LambdaExpression? ResolveCopyConstructor_Registry()
47+
=> _resolver.FindGeneratedExpression(_copyConstructorMember);
48+
4249
// ── Reflection path ───────────────────────────────────────────────────
4350

4451
[Benchmark]
@@ -52,5 +59,9 @@ public class ExpressionResolverBenchmark
5259
[Benchmark]
5360
public LambdaExpression? ResolveMethodWithParam_Reflection()
5461
=> ProjectionExpressionResolver.FindGeneratedExpressionViaReflection(_methodWithParamMember);
62+
63+
[Benchmark]
64+
public LambdaExpression? ResolveCopyConstructor_Reflection()
65+
=> ProjectionExpressionResolver.FindGeneratedExpressionViaReflection(_copyConstructorMember);
5566
}
5667
}

benchmarks/EntityFrameworkCore.Projectables.Benchmarks/Helpers/TestEntity.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ namespace EntityFrameworkCore.Projectables.Benchmarks.Helpers
88
{
99
public class TestEntity
1010
{
11+
public TestEntity()
12+
{
13+
}
14+
1115
public int Id { get; set; }
1216

1317
[Projectable]
@@ -18,5 +22,11 @@ public class TestEntity
1822

1923
[Projectable]
2024
public int IdPlusDelta(int delta) => Id + delta;
25+
26+
[Projectable]
27+
public TestEntity(TestEntity other)
28+
{
29+
Id = other.Id;
30+
}
2131
}
2232
}

src/EntityFrameworkCore.Projectables.Generator/AnalyzerReleases.Shipped.md

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,30 @@
22

33
### New Rules
44

5-
Rule ID | Category | Severity | Notes
6-
--------|----------|----------|-------------------------------------------------------------------------
7-
EFP0003 | Design | Warning | Unsupported statement in block-bodied method
8-
EFP0004 | Design | Error | Statement with side effects in block-bodied method
9-
EFP0005 | Design | Warning | Potential side effect in block-bodied method
10-
EFP0006 | Design | Error | Method or property should expose a body definition (block or expression)
11-
EFP0007 | Design | Error | Unsupported pattern in projectable expression
12-
EFP0008 | Design | Error | Target class is missing a parameterless constructor
13-
EFP0009 | Design | Error | Delegated constructor cannot be analyzed for projection
14-
EFP0010 | Design | Error | UseMemberBody target member not found
15-
EFP0011 | Design | Error | UseMemberBody target member is incompatible
16-
EFP0012 | Design | Info | [Projectable] factory method can be converted to a constructor
5+
| Rule ID | Category | Severity | Notes |
6+
|---------|----------|----------|--------------------------------------------------------------------------|
7+
| EFP0003 | Design | Warning | Unsupported statement in block-bodied method |
8+
| EFP0004 | Design | Error | Statement with side effects in block-bodied method |
9+
| EFP0005 | Design | Warning | Potential side effect in block-bodied method |
10+
| EFP0006 | Design | Error | Method or property should expose a body definition (block or expression) |
11+
| EFP0007 | Design | Error | Unsupported pattern in projectable expression |
12+
| EFP0008 | Design | Error | Target class is missing a parameterless constructor |
13+
| EFP0009 | Design | Error | Delegated constructor cannot be analyzed for projection |
14+
| EFP0010 | Design | Error | UseMemberBody target member not found |
15+
| EFP0011 | Design | Error | UseMemberBody target member is incompatible |
16+
| EFP0012 | Design | Info | [Projectable] factory method can be converted to a constructor |
1717

1818
### Changed Rules
1919

20-
Rule ID | New Category | New Severity | Old Category | Old Severity | Notes
21-
--------|--------------|--------------|--------------|--------------|-----------------------------------------------------------------
22-
EFP0001 | Design | Warning | Design | Error | Changed to warning for experimental block-bodied members support
20+
| Rule ID | New Category | New Severity | Old Category | Old Severity | Notes |
21+
|---------|--------------|--------------|--------------|--------------|------------------------------------------------------------------|
22+
| EFP0001 | Design | Warning | Design | Error | Changed to warning for experimental block-bodied members support |
2323

2424
## Release 5.0
2525

2626
### New Rules
2727

28-
Rule ID | Category | Severity | Notes
29-
--------|----------|----------|------------------------------------------------------------------------------
30-
EFP0001 | Design | Error | Method or property should expose an expression body definition
31-
EFP0002 | Design | Error | Method or property is not configured to support null-conditional expressions
28+
| Rule ID | Category | Severity | Notes |
29+
|---------|----------|----------|------------------------------------------------------------------------------|
30+
| EFP0001 | Design | Error | Method or property should expose an expression body definition |
31+
| EFP0002 | Design | Error | Method or property is not configured to support null-conditional expressions |

0 commit comments

Comments
 (0)