Skip to content

Commit

Permalink
Add Dapr.Pubsub.Analyzers and related tests
Browse files Browse the repository at this point in the history
- Introduced new projects for `Dapr.Pubsub.Analyzers` and `Dapr.Pubsub.Analyzers.Test` in the solution.
- Updated solution configuration to include new analyzers for Debug and Release builds.
- Added analyzer rule DAPR2001 to enforce calling `MapSubscribeHandler` for Dapr subscriptions.
- Implemented `MapSubscribeHandlerCodeFixProvider` for automatic code fixes.
- Developed `SubscriptionAnalyzer` to validate subscription method usage.
- Added unit tests for the new analyzer and code fix provider.
- Updated test utilities and configurations to support new functionality.

Signed-off-by: Nils Gruson <[email protected]>
  • Loading branch information
ngruson committed Jan 16, 2025
1 parent 3019a29 commit 31c88ef
Show file tree
Hide file tree
Showing 13 changed files with 720 additions and 38 deletions.
90 changes: 52 additions & 38 deletions all.sln
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapr.Workflow.Analyzers", "
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapr.Workflow.Analyzers.Test", "test\Dapr.Workflow.Analyzers.Test\Dapr.Workflow.Analyzers.Test.csproj", "{CE0D5FEB-F6DB-4EB8-B8A9-6A4A32944539}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapr.Pubsub.Analyzers", "src\Dapr.Pubsub.Analyzers\Dapr.Pubsub.Analyzers.csproj", "{984BBCC6-C827-430A-8796-C4EB55E7D979}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapr.Pubsub.Analyzers.Test", "test\Dapr.Pubsub.Analyzers.Test\Dapr.Pubsub.Analyzers.Test.csproj", "{A716C2AB-1B38-4284-AC94-2C3D9B758534}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -415,6 +419,14 @@ Global
{CE0D5FEB-F6DB-4EB8-B8A9-6A4A32944539}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CE0D5FEB-F6DB-4EB8-B8A9-6A4A32944539}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CE0D5FEB-F6DB-4EB8-B8A9-6A4A32944539}.Release|Any CPU.Build.0 = Release|Any CPU
{984BBCC6-C827-430A-8796-C4EB55E7D979}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{984BBCC6-C827-430A-8796-C4EB55E7D979}.Debug|Any CPU.Build.0 = Debug|Any CPU
{984BBCC6-C827-430A-8796-C4EB55E7D979}.Release|Any CPU.ActiveCfg = Release|Any CPU
{984BBCC6-C827-430A-8796-C4EB55E7D979}.Release|Any CPU.Build.0 = Release|Any CPU
{A716C2AB-1B38-4284-AC94-2C3D9B758534}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A716C2AB-1B38-4284-AC94-2C3D9B758534}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A716C2AB-1B38-4284-AC94-2C3D9B758534}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A716C2AB-1B38-4284-AC94-2C3D9B758534}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -435,62 +447,64 @@ Global
{78FC19B2-396C-4ED2-BFD9-6C5667C61666} = {DD020B34-460F-455F-8D17-CF4A949F100B}
{B615B353-476C-43B9-A776-B193B0DBD256} = {27C5D71D-0721-4221-9286-B94AB07B58CF}
{A11DC259-D1DB-4686-AD28-A427D0BABA83} = {D687DDC4-66C5-4667-9E3A-FD8B78ECAA78}
{2EC50C79-782D-4985-ABB1-AD07F35D1621} = {A11DC259-D1DB-4686-AD28-A427D0BABA83}
{2EC50C79-782D-4985-ABB1-AD07F35D1621} = {D687DDC4-66C5-4667-9E3A-FD8B78ECAA78}
{15A16323-2CCA-472E-BE79-07259DAD5F6F} = {A11DC259-D1DB-4686-AD28-A427D0BABA83}
{5BACBA51-03FE-4CE1-B0F5-9E9C2A132FAB} = {A11DC259-D1DB-4686-AD28-A427D0BABA83}
{3160CC92-1D6E-42CB-AE89-9401C8CEC5CB} = {A11DC259-D1DB-4686-AD28-A427D0BABA83}
{02374BD0-BF0B-40F8-A04A-C4C4D61D4992} = {D687DDC4-66C5-4667-9E3A-FD8B78ECAA78}
{7957E852-1291-4FAA-9034-FB66CE817FF1} = {02374BD0-BF0B-40F8-A04A-C4C4D61D4992}
{626D74DD-4F37-4F74-87A3-5A6888684F5E} = {02374BD0-BF0B-40F8-A04A-C4C4D61D4992}
{7957E852-1291-4FAA-9034-FB66CE817FF1} = {A11DC259-D1DB-4686-AD28-A427D0BABA83}
{626D74DD-4F37-4F74-87A3-5A6888684F5E} = {D687DDC4-66C5-4667-9E3A-FD8B78ECAA78}
{CC0A5C98-ACDE-4139-BA2F-2995A9B8E18C} = {02374BD0-BF0B-40F8-A04A-C4C4D61D4992}
{A7F41094-8648-446B-AECD-DCC2CC871F73} = {D687DDC4-66C5-4667-9E3A-FD8B78ECAA78}
{F70AC78E-8925-4770-832A-2FC67A620EB2} = {A7F41094-8648-446B-AECD-DCC2CC871F73}
{8B570E70-0E73-4042-A4B6-1CC3CC782A65} = {A7F41094-8648-446B-AECD-DCC2CC871F73}
{4AA9E7B7-36BF-4AAE-BFA3-C9CE8740F4A0} = {DD020B34-460F-455F-8D17-CF4A949F100B}
{345FC3FB-D1E9-4AE8-9052-17D20AB01FA2} = {DD020B34-460F-455F-8D17-CF4A949F100B}
{2AED1542-A8ED-488D-B6D0-E16AB5D6EF6C} = {DD020B34-460F-455F-8D17-CF4A949F100B}
{F70AC78E-8925-4770-832A-2FC67A620EB2} = {02374BD0-BF0B-40F8-A04A-C4C4D61D4992}
{8B570E70-0E73-4042-A4B6-1CC3CC782A65} = {02374BD0-BF0B-40F8-A04A-C4C4D61D4992}
{4AA9E7B7-36BF-4AAE-BFA3-C9CE8740F4A0} = {D687DDC4-66C5-4667-9E3A-FD8B78ECAA78}
{345FC3FB-D1E9-4AE8-9052-17D20AB01FA2} = {A7F41094-8648-446B-AECD-DCC2CC871F73}
{2AED1542-A8ED-488D-B6D0-E16AB5D6EF6C} = {A7F41094-8648-446B-AECD-DCC2CC871F73}
{E8212911-344B-4638-ADC3-B215BCDCAFD1} = {DD020B34-460F-455F-8D17-CF4A949F100B}
{F80F837E-D2FC-4FFC-B68F-3CF0EC015F66} = {A7F41094-8648-446B-AECD-DCC2CC871F73}
{F80F837E-D2FC-4FFC-B68F-3CF0EC015F66} = {DD020B34-460F-455F-8D17-CF4A949F100B}
{5BE7F505-7D77-4C3A-ABFD-54088774DAA7} = {DD020B34-460F-455F-8D17-CF4A949F100B}
{35031EDB-C0DE-453A-8335-D2EBEA2FC640} = {A7F41094-8648-446B-AECD-DCC2CC871F73}
{35031EDB-C0DE-453A-8335-D2EBEA2FC640} = {DD020B34-460F-455F-8D17-CF4A949F100B}
{07578B6C-9B96-4B3D-BA2E-7800EFCA7F99} = {27C5D71D-0721-4221-9286-B94AB07B58CF}
{BF3ED6BF-ADF3-4D25-8E89-02FB8D945CA9} = {D687DDC4-66C5-4667-9E3A-FD8B78ECAA78}
{5C61ABED-7623-4C28-A5C9-C5972A0F669C} = {BF3ED6BF-ADF3-4D25-8E89-02FB8D945CA9}
{5C61ABED-7623-4C28-A5C9-C5972A0F669C} = {A7F41094-8648-446B-AECD-DCC2CC871F73}
{0EF6EA64-D7C3-420D-9890-EAE8D54A57E6} = {A7F41094-8648-446B-AECD-DCC2CC871F73}
{4A175C27-EAFE-47E7-90F6-873B37863656} = {0EF6EA64-D7C3-420D-9890-EAE8D54A57E6}
{DDC41278-FB60-403A-B969-2AEBD7C2D83C} = {0EF6EA64-D7C3-420D-9890-EAE8D54A57E6}
{8CA09061-2BEF-4506-A763-07062D2BD6AC} = {BF3ED6BF-ADF3-4D25-8E89-02FB8D945CA9}
{4A175C27-EAFE-47E7-90F6-873B37863656} = {DD020B34-460F-455F-8D17-CF4A949F100B}
{DDC41278-FB60-403A-B969-2AEBD7C2D83C} = {A7F41094-8648-446B-AECD-DCC2CC871F73}
{8CA09061-2BEF-4506-A763-07062D2BD6AC} = {D687DDC4-66C5-4667-9E3A-FD8B78ECAA78}
{7592AFA4-426B-42F3-AE82-957C86814482} = {D687DDC4-66C5-4667-9E3A-FD8B78ECAA78}
{61C24126-F39D-4BEA-96DC-FC87BA730554} = {7592AFA4-426B-42F3-AE82-957C86814482}
{CB903D21-4869-42EF-BDD6-5B1CFF674337} = {7592AFA4-426B-42F3-AE82-957C86814482}
{980B5FD8-0107-41F7-8FAD-E4E8BAE8A625} = {27C5D71D-0721-4221-9286-B94AB07B58CF}
{7C06FE2D-6C62-48F5-A505-F0D715C554DE} = {7592AFA4-426B-42F3-AE82-957C86814482}
{AF89083D-4715-42E6-93E9-38497D12A8A6} = {DD020B34-460F-455F-8D17-CF4A949F100B}
{B5CDB0DC-B26D-48F1-B934-FE5C1C991940} = {DD020B34-460F-455F-8D17-CF4A949F100B}
{C74FBA78-13E8-407F-A173-4555AEE41FF3} = {A7F41094-8648-446B-AECD-DCC2CC871F73}
{DFBABB04-50E9-42F6-B470-310E1B545638} = {27C5D71D-0721-4221-9286-B94AB07B58CF}
{61C24126-F39D-4BEA-96DC-FC87BA730554} = {BF3ED6BF-ADF3-4D25-8E89-02FB8D945CA9}
{CB903D21-4869-42EF-BDD6-5B1CFF674337} = {A7F41094-8648-446B-AECD-DCC2CC871F73}
{980B5FD8-0107-41F7-8FAD-E4E8BAE8A625} = {0EF6EA64-D7C3-420D-9890-EAE8D54A57E6}
{7C06FE2D-6C62-48F5-A505-F0D715C554DE} = {0EF6EA64-D7C3-420D-9890-EAE8D54A57E6}
{AF89083D-4715-42E6-93E9-38497D12A8A6} = {BF3ED6BF-ADF3-4D25-8E89-02FB8D945CA9}
{B5CDB0DC-B26D-48F1-B934-FE5C1C991940} = {D687DDC4-66C5-4667-9E3A-FD8B78ECAA78}
{C74FBA78-13E8-407F-A173-4555AEE41FF3} = {7592AFA4-426B-42F3-AE82-957C86814482}
{DFBABB04-50E9-42F6-B470-310E1B545638} = {7592AFA4-426B-42F3-AE82-957C86814482}
{B445B19C-A925-4873-8CB7-8317898B6970} = {27C5D71D-0721-4221-9286-B94AB07B58CF}
{CDB47863-BEBD-4841-A807-46D868962521} = {DD020B34-460F-455F-8D17-CF4A949F100B}
{273F2527-1658-4CCF-8DC6-600E921188C5} = {27C5D71D-0721-4221-9286-B94AB07B58CF}
{CDB47863-BEBD-4841-A807-46D868962521} = {7592AFA4-426B-42F3-AE82-957C86814482}
{273F2527-1658-4CCF-8DC6-600E921188C5} = {DD020B34-460F-455F-8D17-CF4A949F100B}
{2F3700EF-1CDA-4C15-AC88-360230000ECD} = {DD020B34-460F-455F-8D17-CF4A949F100B}
{3046DBF4-C2FF-4F3A-9176-E1C01E0A90E5} = {D687DDC4-66C5-4667-9E3A-FD8B78ECAA78}
{11011FF8-77EA-4B25-96C0-29D4D486EF1C} = {3046DBF4-C2FF-4F3A-9176-E1C01E0A90E5}
{43CB06A9-7E88-4C5F-BFB8-947E072CBC9F} = {BF3ED6BF-ADF3-4D25-8E89-02FB8D945CA9}
{7F73A3D8-FFC2-4E31-AA3D-A4840316A8C6} = {BF3ED6BF-ADF3-4D25-8E89-02FB8D945CA9}
{945DD3B7-94E5-435E-B3CB-796C20A652C7} = {BF3ED6BF-ADF3-4D25-8E89-02FB8D945CA9}
{FD3E9371-3134-4235-8E80-32226DFB4B1F} = {BF3ED6BF-ADF3-4D25-8E89-02FB8D945CA9}
{D83B27F3-4401-42F5-843E-147566B4999A} = {BF3ED6BF-ADF3-4D25-8E89-02FB8D945CA9}
{00359961-0C50-4BB1-A794-8B06DE991639} = {BF3ED6BF-ADF3-4D25-8E89-02FB8D945CA9}
{4E04EB35-7FD2-4FDB-B09A-F75CE24053B9} = {DD020B34-460F-455F-8D17-CF4A949F100B}
{0EAE36A1-B578-4F13-A113-7A477ECA1BDA} = {27C5D71D-0721-4221-9286-B94AB07B58CF}
{290D1278-F613-4DF3-9DF5-F37E38CDC363} = {0EF6EA64-D7C3-420D-9890-EAE8D54A57E6}
{C8BB6A85-A7EA-40C0-893D-F36F317829B3} = {27C5D71D-0721-4221-9286-B94AB07B58CF}
{BF9828E9-5597-4D42-AA6E-6E6C12214204} = {DD020B34-460F-455F-8D17-CF4A949F100B}
{11011FF8-77EA-4B25-96C0-29D4D486EF1C} = {A7F41094-8648-446B-AECD-DCC2CC871F73}
{43CB06A9-7E88-4C5F-BFB8-947E072CBC9F} = {27C5D71D-0721-4221-9286-B94AB07B58CF}
{7F73A3D8-FFC2-4E31-AA3D-A4840316A8C6} = {27C5D71D-0721-4221-9286-B94AB07B58CF}
{945DD3B7-94E5-435E-B3CB-796C20A652C7} = {DD020B34-460F-455F-8D17-CF4A949F100B}
{FD3E9371-3134-4235-8E80-32226DFB4B1F} = {27C5D71D-0721-4221-9286-B94AB07B58CF}
{D83B27F3-4401-42F5-843E-147566B4999A} = {DD020B34-460F-455F-8D17-CF4A949F100B}
{00359961-0C50-4BB1-A794-8B06DE991639} = {D687DDC4-66C5-4667-9E3A-FD8B78ECAA78}
{4E04EB35-7FD2-4FDB-B09A-F75CE24053B9} = {3046DBF4-C2FF-4F3A-9176-E1C01E0A90E5}
{0EAE36A1-B578-4F13-A113-7A477ECA1BDA} = {BF3ED6BF-ADF3-4D25-8E89-02FB8D945CA9}
{290D1278-F613-4DF3-9DF5-F37E38CDC363} = {BF3ED6BF-ADF3-4D25-8E89-02FB8D945CA9}
{C8BB6A85-A7EA-40C0-893D-F36F317829B3} = {BF3ED6BF-ADF3-4D25-8E89-02FB8D945CA9}
{BF9828E9-5597-4D42-AA6E-6E6C12214204} = {BF3ED6BF-ADF3-4D25-8E89-02FB8D945CA9}
{D9697361-232F-465D-A136-4561E0E88488} = {D687DDC4-66C5-4667-9E3A-FD8B78ECAA78}
{9CAF360E-5AD3-4C4F-89A0-327EEB70D673} = {D9697361-232F-465D-A136-4561E0E88488}
{E90114C6-86FC-43B8-AE5C-D9273CF21FE4} = {DD020B34-460F-455F-8D17-CF4A949F100B}
{9CAF360E-5AD3-4C4F-89A0-327EEB70D673} = {BF3ED6BF-ADF3-4D25-8E89-02FB8D945CA9}
{E90114C6-86FC-43B8-AE5C-D9273CF21FE4} = {BF3ED6BF-ADF3-4D25-8E89-02FB8D945CA9}
{55A7D436-CC8C-47E6-B43A-DFE32E0FE38C} = {27C5D71D-0721-4221-9286-B94AB07B58CF}
{CE0D5FEB-F6DB-4EB8-B8A9-6A4A32944539} = {DD020B34-460F-455F-8D17-CF4A949F100B}
{984BBCC6-C827-430A-8796-C4EB55E7D979} = {27C5D71D-0721-4221-9286-B94AB07B58CF}
{A716C2AB-1B38-4284-AC94-2C3D9B758534} = {DD020B34-460F-455F-8D17-CF4A949F100B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {65220BF2-EAE1-4CB2-AA58-EBE80768CB40}
Expand Down
1 change: 1 addition & 0 deletions src/Dapr.AspNetCore/Dapr.AspNetCore.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<ItemGroup>
<ProjectReference Include="..\Dapr.Client\Dapr.Client.csproj" />
<ProjectReference Include="..\Dapr.Common\Dapr.Common.csproj" />
<ProjectReference Include="..\Dapr.Pubsub.Analyzers\Dapr.Pubsub.Analyzers.csproj" />
</ItemGroup>

</Project>
7 changes: 7 additions & 0 deletions src/Dapr.Pubsub.Analyzers/AnalyzerReleases.Shipped.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## Release 1.16

### New Rules

Rule ID | Category | Severity | Notes
--------|----------|----------|--------------------
DAPR2001| Usage | Warning | Call MapSubscribeHandler
2 changes: 2 additions & 0 deletions src/Dapr.Pubsub.Analyzers/AnalyzerReleases.Unshipped.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
; Unshipped analyzer release
; https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md
38 changes: 38 additions & 0 deletions src/Dapr.Pubsub.Analyzers/Dapr.Pubsub.Analyzers.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFrameworks></TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
</PropertyGroup>

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

<PropertyGroup>
<!-- Suppress false-positive error NU5128 when packing analyzers with no lib/ref files. -->
<SuppressDependenciesWhenPacking>true</SuppressDependenciesWhenPacking>

<!-- Suppress generation of symbol package (.snupkg). -->
<IncludeSymbols>false</IncludeSymbols>

<!-- Do not include the generator as a lib dependency -->
<IncludeBuildOutput>false</IncludeBuildOutput>

<!-- Additional NuGet package properties. -->
<Description>This package contains Roslyn analyzers for actors.</Description>
<PackageTags>$(PackageTags)</PackageTags>
</PropertyGroup>

<ItemGroup>
<None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
</ItemGroup>

<ItemGroup>
<InternalsVisibleTo Include="$(AssemblyName).Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b1f597635c44597fcecb493e2b1327033b29b1a98ac956a1a538664b68f87d45fbaada0438a15a6265e62864947cc067d8da3a7d93c5eb2fcbb850e396c8684dba74ea477d82a1bbb18932c0efb30b64ff1677f85ae833818707ac8b49ad8062ca01d2c89d8ab1843ae73e8ba9649cd28666b539444dcdee3639f95e2a099bb2" />
</ItemGroup>

</Project>
114 changes: 114 additions & 0 deletions src/Dapr.Pubsub.Analyzers/MapSubscribeHandlerCodeFixProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace Dapr.Pubsub.Analyzers;

/// <summary>
/// Provides a code fix for the DAPR2001 diagnostic.
/// </summary>
public class MapSubscribeHandlerCodeFixProvider : CodeFixProvider
{
/// <summary>
/// Gets the diagnostic IDs that this provider can fix.
/// </summary>
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create("DAPR2001");

/// <summary>
/// Gets the FixAllProvider for this code fix provider.
/// </summary>
/// <returns>The FixAllProvider.</returns>
public override FixAllProvider? GetFixAllProvider()
{
return WellKnownFixAllProviders.BatchFixer;
}

/// <summary>
/// Registers code fixes for the specified diagnostics.
/// </summary>
/// <param name="context">A <see cref="CodeFixContext"/> containing the context in which the code fix is being applied.</param>
public override Task RegisterCodeFixesAsync(CodeFixContext context)
{
var title = "Call MapSubscribeHandler";
context.RegisterCodeFix(
CodeAction.Create(
title,
createChangedDocument: c => AddMapSubscribeHandlerAsync(context.Document, context.Diagnostics.First(), c),
equivalenceKey: title),
context.Diagnostics);
return Task.CompletedTask;
}

private async Task<Document> AddMapSubscribeHandlerAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken)
{
var root = await document.GetSyntaxRootAsync(cancellationToken);
var invocationExpressions = root!.DescendantNodes().OfType<InvocationExpressionSyntax>();

var createBuilderInvocation = invocationExpressions
.FirstOrDefault(invocation =>
{
return invocation.Expression is MemberAccessExpressionSyntax memberAccess &&
memberAccess.Name.Identifier.Text == "CreateBuilder" &&
memberAccess.Expression is IdentifierNameSyntax identifier &&
identifier.Identifier.Text == "WebApplication";
});

var variableDeclarator = createBuilderInvocation
.AncestorsAndSelf()
.OfType<VariableDeclaratorSyntax>()
.FirstOrDefault();

var variableName = variableDeclarator.Identifier.Text;

var buildInvocation = invocationExpressions
.FirstOrDefault(invocation =>
{
return invocation.Expression is MemberAccessExpressionSyntax memberAccess &&
memberAccess.Name.Identifier.Text == "Build" &&
memberAccess.Expression is IdentifierNameSyntax identifier &&
identifier.Identifier.Text == variableName;
});

var buildVariableDeclarator = buildInvocation
.AncestorsAndSelf()
.OfType<VariableDeclaratorSyntax>()
.FirstOrDefault();

var buildVariableName = buildVariableDeclarator.Identifier.Text;

var mapSubscribeHandlerInvocation = SyntaxFactory.ExpressionStatement(
SyntaxFactory.InvocationExpression(
SyntaxFactory.MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression,
SyntaxFactory.IdentifierName(buildVariableName),
SyntaxFactory.IdentifierName("MapSubscribeHandler"))));

if (buildInvocation?.Ancestors().OfType<MethodDeclarationSyntax>().FirstOrDefault() is SyntaxNode parentBlock)
{
var localDeclaration = buildInvocation
.AncestorsAndSelf()
.OfType<LocalDeclarationStatementSyntax>()
.FirstOrDefault();

var newParentBlock = parentBlock.InsertNodesAfter(localDeclaration, new[] { mapSubscribeHandlerInvocation });
root = root.ReplaceNode(parentBlock, newParentBlock);
}
else
{
var buildInvocationGlobalStatement = buildInvocation?
.AncestorsAndSelf()
.OfType<GlobalStatementSyntax>()
.FirstOrDefault();

var compilationUnitSyntax = createBuilderInvocation.Ancestors().OfType<CompilationUnitSyntax>().FirstOrDefault();
var newCompilationUnitSyntax = compilationUnitSyntax.InsertNodesAfter(buildInvocationGlobalStatement!,
new[] { SyntaxFactory.GlobalStatement(mapSubscribeHandlerInvocation) });
root = root.ReplaceNode(compilationUnitSyntax, newCompilationUnitSyntax);
}

return document.WithSyntaxRoot(root);
}
}
Loading

0 comments on commit 31c88ef

Please sign in to comment.