Skip to content

Commit 1741be0

Browse files
committed
Provide a codefix for legacy service usage and add tests
The codefix should be helpful in migrating larger codebases that used the previous approach (since we allow batch fixing in an entire solution). The added project also means we need a separate packaging project (can't reference the codefix project from the analyzer one because that can cause the analyzer to not load in the reduced scope of the compiler). The codefix project is only intended by consumption by an editor that can apply fixes. We now have a standalone packaging project that contains the eula and readme plus references to the other two.
1 parent 6495d3b commit 1741be0

24 files changed

+213
-19
lines changed

DependencyInjection.slnx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
<Solution>
22
<Project Path="src/Attributed/Attributed.msbuildproj" Type="13b669be-bb05-4ddf-9536-439f39a36129" />
33
<Project Path="src/CodeAnalysis.Tests/CodeAnalysis.Tests.csproj" />
4+
<Project Path="src/DependencyInjection.CodeFixes/DependencyInjection.CodeFixes.csproj" Id="2dbf1d6d-2147-407b-9e3a-8caf0eda549c" />
45
<Project Path="src/DependencyInjection.Tests/DependencyInjection.Tests.csproj" />
5-
<Project Path="src/DependencyInjection/DependencyInjection.csproj" />
6+
<Project Path="src/DependencyInjection.CodeAnalysis/DependencyInjection.CodeAnalysis.csproj" />
67
<Project Path="src/NoAddServices/NoAddServices.csproj" />
8+
<Project Path="src/Package/DependencyInjection.Package.msbuildproj" Type="13b669be-bb05-4ddf-9536-439f39a36129" />
79
</Solution>

src/CodeAnalysis.Tests/CodeAnalysis.Tests.csproj

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,17 @@
1414
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.14.0" />
1515
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Analyzer.Testing" Version="1.1.2" />
1616
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.SourceGenerators.Testing" Version="1.1.2" />
17+
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.CodeFix.Testing" Version="1.1.2" />
1718
<PackageReference Include="ThisAssembly.Resources" Version="2.1.2" PrivateAssets="all" />
1819
</ItemGroup>
1920

2021
<ItemGroup>
21-
<ProjectReference Include="..\DependencyInjection\DependencyInjection.csproj" AdditionalProperties="ILRepack=true" />
22+
<ProjectReference Include="..\DependencyInjection.CodeFixes\DependencyInjection.CodeFixes.csproj" />
23+
<ProjectReference Include="..\DependencyInjection.CodeAnalysis\DependencyInjection.CodeAnalysis.csproj" AdditionalProperties="ILRepack=true" />
2224
</ItemGroup>
2325

2426
<ItemGroup>
25-
<EmbeddedCode Include="..\DependencyInjection\compile\*.cs" />
27+
<EmbeddedCode Include="..\DependencyInjection.CodeAnalysis\compile\*.cs" />
2628
</ItemGroup>
2729

2830
</Project>
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Collections.Immutable;
4+
using System.IO;
5+
using System.Linq;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using Devlooped.Extensions.DependencyInjection;
9+
using Microsoft.CodeAnalysis;
10+
using Microsoft.CodeAnalysis.CSharp;
11+
using Microsoft.CodeAnalysis.CSharp.Testing;
12+
using Microsoft.CodeAnalysis.Diagnostics;
13+
using Microsoft.CodeAnalysis.Testing;
14+
using Xunit;
15+
using Xunit.Abstractions;
16+
using AnalyzerTest = Microsoft.CodeAnalysis.CSharp.Testing.CSharpAnalyzerTest<Devlooped.Extensions.DependencyInjection.LegacyServiceAttributeAnalyzer, Microsoft.CodeAnalysis.Testing.DefaultVerifier>;
17+
using Verifier = Microsoft.CodeAnalysis.CSharp.Testing.CSharpAnalyzerVerifier<Devlooped.Extensions.DependencyInjection.LegacyServiceAttributeAnalyzer, Microsoft.CodeAnalysis.Testing.DefaultVerifier>;
18+
19+
namespace Tests.CodeAnalysis;
20+
21+
public class LegacyServiceAttributeTests(ITestOutputHelper Output)
22+
{
23+
[Fact]
24+
public async Task ErrorIfTKeyMatchesStringConstant()
25+
{
26+
var test = new AnalyzerTest
27+
{
28+
TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck,
29+
TestCode =
30+
"""
31+
using System;
32+
using Microsoft.Extensions.DependencyInjection;
33+
34+
[{|#0:Service<string>("my")|}]
35+
public class MyService { }
36+
"""
37+
}.WithTestState();
38+
39+
var expected = Verifier.Diagnostic(LegacyServiceAttributeAnalyzer.ServiceTypeNotKeyType).WithLocation(0);
40+
test.ExpectedDiagnostics.Add(expected);
41+
42+
await test.RunAsync();
43+
}
44+
45+
[Fact]
46+
public async Task ExecuteSyncWithAsyncCommand()
47+
{
48+
var test = new CSharpCodeFixTest<LegacyServiceAttributeAnalyzer, LegacyServiceAttributeFixer, DefaultVerifier>
49+
{
50+
TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck,
51+
TestCode =
52+
"""
53+
using System;
54+
using Microsoft.Extensions.DependencyInjection;
55+
56+
[{|#0:Service<string>("my")|}]
57+
public class MyService { }
58+
""",
59+
FixedCode =
60+
"""
61+
using System;
62+
using Microsoft.Extensions.DependencyInjection;
63+
64+
[Service("my")]
65+
public class MyService { }
66+
""",
67+
}.WithTestState();
68+
69+
test.ExpectedDiagnostics.Add(new DiagnosticResult(LegacyServiceAttributeAnalyzer.ServiceTypeNotKeyType).WithLocation(0));
70+
test.FixedState.Sources.AddStaticFiles();
71+
72+
await test.RunAsync();
73+
}
74+
}

src/CodeAnalysis.Tests/TestExtensions.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Collections.Immutable;
4+
using System.IO;
35
using System.Linq;
46
using System.Text;
57
using System.Threading.Tasks;
68
using Microsoft.CodeAnalysis.CSharp;
79
using Microsoft.CodeAnalysis.Testing;
10+
using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.Resources;
811

912
namespace Tests.CodeAnalysis;
1013

@@ -31,4 +34,26 @@ public static TAnalyzerTest WithPreprocessorSymbols<TAnalyzerTest>(this TAnalyze
3134

3235
return test;
3336
}
37+
38+
public static TAnalyzerTest WithTestState<TAnalyzerTest>(this TAnalyzerTest test)
39+
where TAnalyzerTest : AnalyzerTest<DefaultVerifier>
40+
{
41+
test.TestState.Sources.AddStaticFiles();
42+
test.TestState.ReferenceAssemblies = new ReferenceAssemblies(
43+
"net8.0",
44+
new PackageIdentity(
45+
"Microsoft.NETCore.App.Ref", "8.0.0"),
46+
Path.Combine("ref", "net8.0"))
47+
.AddPackages(ImmutableArray.Create(
48+
new PackageIdentity("Microsoft.Extensions.DependencyInjection", "8.0.0")));
49+
50+
return test;
51+
}
52+
53+
public static void AddStaticFiles(this SourceFileList sources)
54+
{
55+
sources.Add(ThisAssembly.Resources.AddServicesNoReflectionExtension.Text);
56+
sources.Add(ThisAssembly.Resources.ServiceAttribute.Text);
57+
sources.Add(ThisAssembly.Resources.ServiceAttribute_1.Text);
58+
}
3459
}
File renamed without changes.

src/DependencyInjection/CodeAnalysisExtensions.cs renamed to src/DependencyInjection.CodeAnalysis/CodeAnalysisExtensions.cs

File renamed without changes.
File renamed without changes.
File renamed without changes.

src/DependencyInjection/DependencyInjection.csproj renamed to src/DependencyInjection.CodeAnalysis/DependencyInjection.CodeAnalysis.csproj

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,12 @@
33
<PropertyGroup>
44
<LangVersion>Preview</LangVersion>
55
<TargetFramework>netstandard2.0</TargetFramework>
6-
<AssemblyName>Devlooped.Extensions.DependencyInjection</AssemblyName>
7-
<PackageId>Devlooped.Extensions.DependencyInjection</PackageId>
8-
<Title>
9-
Automatic compile-time service registrations for Microsoft.Extensions.DependencyInjection with no run-time dependencies, from conventions or attributes.
10-
</Title>
11-
<Description>$(Title)</Description>
6+
<AssemblyName>Devlooped.Extensions.DependencyInjection.CodeAnalysis</AssemblyName>
127
<PackFolder>analyzers/dotnet</PackFolder>
138
<IsRoslynComponent>true</IsRoslynComponent>
149
<DevelopmentDependency>true</DevelopmentDependency>
1510
<DefineConstants>$(DefineConstants);DDI_ADDSERVICE;DDI_ADDSERVICES</DefineConstants>
1611
<ImplicitUsings>false</ImplicitUsings>
17-
<PackageLicenseExpression></PackageLicenseExpression>
18-
<PackageLicenseFile>OSMFEULA.txt</PackageLicenseFile>
19-
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
2012
<ILRepack>true</ILRepack>
2113
</PropertyGroup>
2214

@@ -30,7 +22,6 @@
3022
</ItemGroup>
3123

3224
<ItemGroup>
33-
<None Include="..\..\osmfeula.txt" Link="osmfeula.txt" PackagePath="OSMFEULA.txt" />
3425
<None Update="Devlooped.Extensions.DependencyInjection.props" CopyToOutputDirectory="PreserveNewest" PackFolder="build\netstandard2.0" />
3526
<None Update="Devlooped.Extensions.DependencyInjection.targets" CopyToOutputDirectory="PreserveNewest" PackFolder="build\netstandard2.0" />
3627
<None Include="compile\*.cs" CopyToOutputDirectory="PreserveNewest" PackFolder="build\netstandard2.0" />

src/DependencyInjection/Devlooped.Extensions.DependencyInjection.props renamed to src/DependencyInjection.CodeAnalysis/Devlooped.Extensions.DependencyInjection.props

File renamed without changes.

0 commit comments

Comments
 (0)