Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@
<PackageVersion Include="coverlet.collector" Version="6.0.2" />
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="8.0.1" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="5.0.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="5.0.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
<PackageVersion Include="ScenarioTests.XUnit" Version="1.0.1" />
<PackageVersion Include="Verify.Xunit" Version="22.5.0" />
<PackageVersion Include="xunit" Version="2.9.2" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" />
Expand Down
98 changes: 98 additions & 0 deletions EntityFrameworkCore.Projectables.sln
Original file line number Diff line number Diff line change
Expand Up @@ -53,44 +53,140 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{
.github\workflows\release.yml = .github\workflows\release.yml
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EntityFrameworkCore.Projectables.CodeFixes", "src\EntityFrameworkCore.Projectables.CodeFixes\EntityFrameworkCore.Projectables.CodeFixes.csproj", "{1890C6AF-37A4-40B0-BD0C-7FB18357891A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EntityFrameworkCore.Projectables.CodeFixes.Tests", "tests\EntityFrameworkCore.Projectables.CodeFixes.Tests\EntityFrameworkCore.Projectables.CodeFixes.Tests.csproj", "{C62B59E5-A32F-4CB5-ADB1-B3D03BBC8476}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{698E3EEC-64F9-4F96-B700-D61D04FD0704}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{698E3EEC-64F9-4F96-B700-D61D04FD0704}.Debug|Any CPU.Build.0 = Debug|Any CPU
{698E3EEC-64F9-4F96-B700-D61D04FD0704}.Debug|x64.ActiveCfg = Debug|Any CPU
{698E3EEC-64F9-4F96-B700-D61D04FD0704}.Debug|x64.Build.0 = Debug|Any CPU
{698E3EEC-64F9-4F96-B700-D61D04FD0704}.Debug|x86.ActiveCfg = Debug|Any CPU
{698E3EEC-64F9-4F96-B700-D61D04FD0704}.Debug|x86.Build.0 = Debug|Any CPU
{698E3EEC-64F9-4F96-B700-D61D04FD0704}.Release|Any CPU.ActiveCfg = Release|Any CPU
{698E3EEC-64F9-4F96-B700-D61D04FD0704}.Release|Any CPU.Build.0 = Release|Any CPU
{698E3EEC-64F9-4F96-B700-D61D04FD0704}.Release|x64.ActiveCfg = Release|Any CPU
{698E3EEC-64F9-4F96-B700-D61D04FD0704}.Release|x64.Build.0 = Release|Any CPU
{698E3EEC-64F9-4F96-B700-D61D04FD0704}.Release|x86.ActiveCfg = Release|Any CPU
{698E3EEC-64F9-4F96-B700-D61D04FD0704}.Release|x86.Build.0 = Release|Any CPU
{20F85652-2923-4211-9262-C64BA8C9ED89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{20F85652-2923-4211-9262-C64BA8C9ED89}.Debug|Any CPU.Build.0 = Debug|Any CPU
{20F85652-2923-4211-9262-C64BA8C9ED89}.Debug|x64.ActiveCfg = Debug|Any CPU
{20F85652-2923-4211-9262-C64BA8C9ED89}.Debug|x64.Build.0 = Debug|Any CPU
{20F85652-2923-4211-9262-C64BA8C9ED89}.Debug|x86.ActiveCfg = Debug|Any CPU
{20F85652-2923-4211-9262-C64BA8C9ED89}.Debug|x86.Build.0 = Debug|Any CPU
{20F85652-2923-4211-9262-C64BA8C9ED89}.Release|Any CPU.ActiveCfg = Release|Any CPU
{20F85652-2923-4211-9262-C64BA8C9ED89}.Release|Any CPU.Build.0 = Release|Any CPU
{20F85652-2923-4211-9262-C64BA8C9ED89}.Release|x64.ActiveCfg = Release|Any CPU
{20F85652-2923-4211-9262-C64BA8C9ED89}.Release|x64.Build.0 = Release|Any CPU
{20F85652-2923-4211-9262-C64BA8C9ED89}.Release|x86.ActiveCfg = Release|Any CPU
{20F85652-2923-4211-9262-C64BA8C9ED89}.Release|x86.Build.0 = Release|Any CPU
{EE4D6CC1-78DE-4279-A567-C3D360C479F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EE4D6CC1-78DE-4279-A567-C3D360C479F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EE4D6CC1-78DE-4279-A567-C3D360C479F8}.Debug|x64.ActiveCfg = Debug|Any CPU
{EE4D6CC1-78DE-4279-A567-C3D360C479F8}.Debug|x64.Build.0 = Debug|Any CPU
{EE4D6CC1-78DE-4279-A567-C3D360C479F8}.Debug|x86.ActiveCfg = Debug|Any CPU
{EE4D6CC1-78DE-4279-A567-C3D360C479F8}.Debug|x86.Build.0 = Debug|Any CPU
{EE4D6CC1-78DE-4279-A567-C3D360C479F8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EE4D6CC1-78DE-4279-A567-C3D360C479F8}.Release|Any CPU.Build.0 = Release|Any CPU
{EE4D6CC1-78DE-4279-A567-C3D360C479F8}.Release|x64.ActiveCfg = Release|Any CPU
{EE4D6CC1-78DE-4279-A567-C3D360C479F8}.Release|x64.Build.0 = Release|Any CPU
{EE4D6CC1-78DE-4279-A567-C3D360C479F8}.Release|x86.ActiveCfg = Release|Any CPU
{EE4D6CC1-78DE-4279-A567-C3D360C479F8}.Release|x86.Build.0 = Release|Any CPU
{C8038180-36F8-4077-922B-91F428EAC7D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C8038180-36F8-4077-922B-91F428EAC7D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C8038180-36F8-4077-922B-91F428EAC7D9}.Debug|x64.ActiveCfg = Debug|Any CPU
{C8038180-36F8-4077-922B-91F428EAC7D9}.Debug|x64.Build.0 = Debug|Any CPU
{C8038180-36F8-4077-922B-91F428EAC7D9}.Debug|x86.ActiveCfg = Debug|Any CPU
{C8038180-36F8-4077-922B-91F428EAC7D9}.Debug|x86.Build.0 = Debug|Any CPU
{C8038180-36F8-4077-922B-91F428EAC7D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C8038180-36F8-4077-922B-91F428EAC7D9}.Release|Any CPU.Build.0 = Release|Any CPU
{C8038180-36F8-4077-922B-91F428EAC7D9}.Release|x64.ActiveCfg = Release|Any CPU
{C8038180-36F8-4077-922B-91F428EAC7D9}.Release|x64.Build.0 = Release|Any CPU
{C8038180-36F8-4077-922B-91F428EAC7D9}.Release|x86.ActiveCfg = Release|Any CPU
{C8038180-36F8-4077-922B-91F428EAC7D9}.Release|x86.Build.0 = Release|Any CPU
{2F0DD7D7-867F-4478-9E22-45C114B61C46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2F0DD7D7-867F-4478-9E22-45C114B61C46}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2F0DD7D7-867F-4478-9E22-45C114B61C46}.Debug|x64.ActiveCfg = Debug|Any CPU
{2F0DD7D7-867F-4478-9E22-45C114B61C46}.Debug|x64.Build.0 = Debug|Any CPU
{2F0DD7D7-867F-4478-9E22-45C114B61C46}.Debug|x86.ActiveCfg = Debug|Any CPU
{2F0DD7D7-867F-4478-9E22-45C114B61C46}.Debug|x86.Build.0 = Debug|Any CPU
{2F0DD7D7-867F-4478-9E22-45C114B61C46}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2F0DD7D7-867F-4478-9E22-45C114B61C46}.Release|Any CPU.Build.0 = Release|Any CPU
{2F0DD7D7-867F-4478-9E22-45C114B61C46}.Release|x64.ActiveCfg = Release|Any CPU
{2F0DD7D7-867F-4478-9E22-45C114B61C46}.Release|x64.Build.0 = Release|Any CPU
{2F0DD7D7-867F-4478-9E22-45C114B61C46}.Release|x86.ActiveCfg = Release|Any CPU
{2F0DD7D7-867F-4478-9E22-45C114B61C46}.Release|x86.Build.0 = Release|Any CPU
{A36F5471-0C16-4453-811B-818326931313}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A36F5471-0C16-4453-811B-818326931313}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A36F5471-0C16-4453-811B-818326931313}.Debug|x64.ActiveCfg = Debug|Any CPU
{A36F5471-0C16-4453-811B-818326931313}.Debug|x64.Build.0 = Debug|Any CPU
{A36F5471-0C16-4453-811B-818326931313}.Debug|x86.ActiveCfg = Debug|Any CPU
{A36F5471-0C16-4453-811B-818326931313}.Debug|x86.Build.0 = Debug|Any CPU
{A36F5471-0C16-4453-811B-818326931313}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A36F5471-0C16-4453-811B-818326931313}.Release|Any CPU.Build.0 = Release|Any CPU
{A36F5471-0C16-4453-811B-818326931313}.Release|x64.ActiveCfg = Release|Any CPU
{A36F5471-0C16-4453-811B-818326931313}.Release|x64.Build.0 = Release|Any CPU
{A36F5471-0C16-4453-811B-818326931313}.Release|x86.ActiveCfg = Release|Any CPU
{A36F5471-0C16-4453-811B-818326931313}.Release|x86.Build.0 = Release|Any CPU
{6F63E04C-9267-4211-8AC7-290C60331D60}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6F63E04C-9267-4211-8AC7-290C60331D60}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6F63E04C-9267-4211-8AC7-290C60331D60}.Debug|x64.ActiveCfg = Debug|Any CPU
{6F63E04C-9267-4211-8AC7-290C60331D60}.Debug|x64.Build.0 = Debug|Any CPU
{6F63E04C-9267-4211-8AC7-290C60331D60}.Debug|x86.ActiveCfg = Debug|Any CPU
{6F63E04C-9267-4211-8AC7-290C60331D60}.Debug|x86.Build.0 = Debug|Any CPU
{6F63E04C-9267-4211-8AC7-290C60331D60}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6F63E04C-9267-4211-8AC7-290C60331D60}.Release|Any CPU.Build.0 = Release|Any CPU
{6F63E04C-9267-4211-8AC7-290C60331D60}.Release|x64.ActiveCfg = Release|Any CPU
{6F63E04C-9267-4211-8AC7-290C60331D60}.Release|x64.Build.0 = Release|Any CPU
{6F63E04C-9267-4211-8AC7-290C60331D60}.Release|x86.ActiveCfg = Release|Any CPU
{6F63E04C-9267-4211-8AC7-290C60331D60}.Release|x86.Build.0 = Release|Any CPU
{F2F01B61-5FB8-4F96-A6DE-824C9756B365}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F2F01B61-5FB8-4F96-A6DE-824C9756B365}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F2F01B61-5FB8-4F96-A6DE-824C9756B365}.Debug|x64.ActiveCfg = Debug|Any CPU
{F2F01B61-5FB8-4F96-A6DE-824C9756B365}.Debug|x64.Build.0 = Debug|Any CPU
{F2F01B61-5FB8-4F96-A6DE-824C9756B365}.Debug|x86.ActiveCfg = Debug|Any CPU
{F2F01B61-5FB8-4F96-A6DE-824C9756B365}.Debug|x86.Build.0 = Debug|Any CPU
{F2F01B61-5FB8-4F96-A6DE-824C9756B365}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F2F01B61-5FB8-4F96-A6DE-824C9756B365}.Release|Any CPU.Build.0 = Release|Any CPU
{F2F01B61-5FB8-4F96-A6DE-824C9756B365}.Release|x64.ActiveCfg = Release|Any CPU
{F2F01B61-5FB8-4F96-A6DE-824C9756B365}.Release|x64.Build.0 = Release|Any CPU
{F2F01B61-5FB8-4F96-A6DE-824C9756B365}.Release|x86.ActiveCfg = Release|Any CPU
{F2F01B61-5FB8-4F96-A6DE-824C9756B365}.Release|x86.Build.0 = Release|Any CPU
{1890C6AF-37A4-40B0-BD0C-7FB18357891A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1890C6AF-37A4-40B0-BD0C-7FB18357891A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1890C6AF-37A4-40B0-BD0C-7FB18357891A}.Debug|x64.ActiveCfg = Debug|Any CPU
{1890C6AF-37A4-40B0-BD0C-7FB18357891A}.Debug|x64.Build.0 = Debug|Any CPU
{1890C6AF-37A4-40B0-BD0C-7FB18357891A}.Debug|x86.ActiveCfg = Debug|Any CPU
{1890C6AF-37A4-40B0-BD0C-7FB18357891A}.Debug|x86.Build.0 = Debug|Any CPU
{1890C6AF-37A4-40B0-BD0C-7FB18357891A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1890C6AF-37A4-40B0-BD0C-7FB18357891A}.Release|Any CPU.Build.0 = Release|Any CPU
{1890C6AF-37A4-40B0-BD0C-7FB18357891A}.Release|x64.ActiveCfg = Release|Any CPU
{1890C6AF-37A4-40B0-BD0C-7FB18357891A}.Release|x64.Build.0 = Release|Any CPU
{1890C6AF-37A4-40B0-BD0C-7FB18357891A}.Release|x86.ActiveCfg = Release|Any CPU
{1890C6AF-37A4-40B0-BD0C-7FB18357891A}.Release|x86.Build.0 = Release|Any CPU
{C62B59E5-A32F-4CB5-ADB1-B3D03BBC8476}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C62B59E5-A32F-4CB5-ADB1-B3D03BBC8476}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C62B59E5-A32F-4CB5-ADB1-B3D03BBC8476}.Debug|x64.ActiveCfg = Debug|Any CPU
{C62B59E5-A32F-4CB5-ADB1-B3D03BBC8476}.Debug|x64.Build.0 = Debug|Any CPU
{C62B59E5-A32F-4CB5-ADB1-B3D03BBC8476}.Debug|x86.ActiveCfg = Debug|Any CPU
{C62B59E5-A32F-4CB5-ADB1-B3D03BBC8476}.Debug|x86.Build.0 = Debug|Any CPU
{C62B59E5-A32F-4CB5-ADB1-B3D03BBC8476}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C62B59E5-A32F-4CB5-ADB1-B3D03BBC8476}.Release|Any CPU.Build.0 = Release|Any CPU
{C62B59E5-A32F-4CB5-ADB1-B3D03BBC8476}.Release|x64.ActiveCfg = Release|Any CPU
{C62B59E5-A32F-4CB5-ADB1-B3D03BBC8476}.Release|x64.Build.0 = Release|Any CPU
{C62B59E5-A32F-4CB5-ADB1-B3D03BBC8476}.Release|x86.ActiveCfg = Release|Any CPU
{C62B59E5-A32F-4CB5-ADB1-B3D03BBC8476}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -105,6 +201,8 @@ Global
{6F63E04C-9267-4211-8AC7-290C60331D60} = {07584D01-2D30-404B-B0D1-32080C0CC18A}
{F2F01B61-5FB8-4F96-A6DE-824C9756B365} = {D1DB50EE-D639-46B0-8966-D0AA5F569620}
{31596010-788E-434F-BF00-4EBC6E232822} = {C95A2C5D-4A3B-440C-A703-2D5892ABA7FE}
{1890C6AF-37A4-40B0-BD0C-7FB18357891A} = {A43F1828-D9B6-40F7-82B6-CA0070843E2F}
{C62B59E5-A32F-4CB5-ADB1-B3D03BBC8476} = {F5E4436F-87F2-46AB-A9EB-59B4BF21BF7A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D17BD356-592C-4628-9D81-A04E24FF02F3}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,17 @@
<OutputItemType>Content</OutputItemType>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</ProjectReference>
<ProjectReference Include="..\EntityFrameworkCore.Projectables.CodeFixes\EntityFrameworkCore.Projectables.CodeFixes.csproj" Pack="false">
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<OutputItemType>Content</OutputItemType>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</ProjectReference>
</ItemGroup>

<ItemGroup>
<!-- Package the generator in the analyzer directory of the nuget package -->
<!-- Package the generator and the code fix provider in the analyzer directory of the nuget package -->
<None Include="..\EntityFrameworkCore.Projectables.Generator\bin\$(Configuration)\netstandard2.0\EntityFrameworkCore.Projectables.Generator.dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
<None Include="..\EntityFrameworkCore.Projectables.CodeFixes\bin\$(Configuration)\netstandard2.0\EntityFrameworkCore.Projectables.CodeFixes.dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@


Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using System.Collections.Immutable;
using System.Composition;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace EntityFrameworkCore.Projectables.CodeFixes;

/// <summary>
/// Code fix provider for EFP0001 (Block-bodied member support is experimental).
/// Adds <c>AllowBlockBody = true</c> to the <c>[Projectable]</c> attribute.
/// </summary>
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(BlockBodyExperimentalCodeFixProvider))]
[Shared]
public sealed class BlockBodyExperimentalCodeFixProvider : CodeFixProvider
{
public override ImmutableArray<string> FixableDiagnosticIds => ["EFP0001"];

public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer;

public override async Task RegisterCodeFixesAsync(CodeFixContext context)
{
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
if (root is null)
{
return;
}

var diagnostic = context.Diagnostics[0];
var node = root.FindNode(diagnostic.Location.SourceSpan);
var member = node.AncestorsAndSelf().OfType<MemberDeclarationSyntax>().FirstOrDefault();
if (member is null)
{
return;
}

if (!ProjectableCodeFixHelper.TryFindProjectableAttribute(member, out _))
{
return;
}

context.RegisterCodeFix(
CodeAction.Create(
title: "Add AllowBlockBody = true to [Projectable]",
createChangedDocument: ct =>
ProjectableCodeFixHelper.AddOrReplaceNamedArgumentInProjectableAttributeAsync(
context.Document,
member,
"AllowBlockBody",
SyntaxFactory.LiteralExpression(SyntaxKind.TrueLiteralExpression),
ct),
equivalenceKey: "EFP0001_AddAllowBlockBody"),
diagnostic);
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<!-- Override TargetFrameworks with an "s" from Directory.Build.props settings as needed -->
<TargetFrameworks>netstandard2.0;</TargetFrameworks>
<NoWarn>$(NoWarn);NU5128</NoWarn>
<IsPackable>false</IsPackable>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" PrivateAssets="all" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
using System.Collections.Immutable;
using System.Composition;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Formatting;

namespace EntityFrameworkCore.Projectables.CodeFixes;

/// <summary>
/// Code fix provider for EFP0008 (Target class is missing a parameterless constructor).
/// Inserts a <c>public ClassName() { }</c> constructor into the class that carries the
/// <c>[Projectable]</c> constructor, satisfying the object-initializer requirement of the
/// generated expression tree.
/// </summary>
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(MissingParameterlessConstructorCodeFixProvider))]
[Shared]
public sealed class MissingParameterlessConstructorCodeFixProvider : CodeFixProvider
{
public override ImmutableArray<string> FixableDiagnosticIds => ["EFP0008"];

public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer;

public override async Task RegisterCodeFixesAsync(CodeFixContext context)
{
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
if (root is null)
{
return;
}

var diagnostic = context.Diagnostics[0];
var node = root.FindNode(diagnostic.Location.SourceSpan);

// The diagnostic is reported on the [Projectable] constructor declaration.
// Walk up to find the containing type.
var typeDecl = node.AncestorsAndSelf().OfType<TypeDeclarationSyntax>().FirstOrDefault();
if (typeDecl is null)
{
return;
}

var typeName = typeDecl.Identifier.Text;

context.RegisterCodeFix(
CodeAction.Create(
title: $"Add parameterless constructor to '{typeName}'",
createChangedDocument: ct => AddParameterlessConstructorAsync(context.Document, typeDecl, ct),
equivalenceKey: "EFP0008_AddParameterlessConstructor"),
diagnostic);
}

private async static Task<Document> AddParameterlessConstructorAsync(
Document document,
TypeDeclarationSyntax typeDecl,
CancellationToken cancellationToken)
{
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
if (root is null)
{
return document;
}

var parameterlessCtor = SyntaxFactory
.ConstructorDeclaration(typeDecl.Identifier.WithoutTrivia())
.WithModifiers(SyntaxFactory.TokenList(
SyntaxFactory.Token(SyntaxKind.PublicKeyword)
.WithTrailingTrivia(SyntaxFactory.Space)))
.WithParameterList(SyntaxFactory.ParameterList())
.WithBody(SyntaxFactory.Block())
.WithAdditionalAnnotations(Formatter.Annotation)
.WithLeadingTrivia(SyntaxFactory.ElasticCarriageReturnLineFeed);

// Insert before the first existing member so it appears at the top of the class body.
var newTypeDecl = typeDecl.WithMembers(
typeDecl.Members.Insert(0, parameterlessCtor));

var newRoot = root.ReplaceNode(typeDecl, newTypeDecl);
return document.WithSyntaxRoot(newRoot);
}
}

Loading
Loading