Skip to content

Commit 46ed4b9

Browse files
author
Anh Thi Dao
committed
added the code and tests for analyzer in issue #35815
1 parent 8cb31a4 commit 46ed4b9

File tree

4 files changed

+219
-61
lines changed

4 files changed

+219
-61
lines changed

src/Framework/AspNetCoreAnalyzers/src/Analyzers/DiagnosticDescriptors.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,14 @@ internal static class DiagnosticDescriptors
7979
DiagnosticSeverity.Error,
8080
isEnabledByDefault: true,
8181
helpLinkUri: "https://aka.ms/aspnet/analyzers");
82+
83+
internal static readonly DiagnosticDescriptor DisallowConfigureAppConfigureHostBuilder = new(
84+
"ASP0013",
85+
"Do not use builder.Host.ConfigureAppConfiguration or builder.Host.ConfigureHostConfiguration",
86+
"Replace with builder.Configuration",
87+
"Usage",
88+
DiagnosticSeverity.Error,
89+
isEnabledByDefault: true,
90+
helpLinkUri: "https://aka.ms/aspnet/analyzers");
91+
8292
}

src/Framework/AspNetCoreAnalyzers/src/Analyzers/WebApplicationBuilder/WebApplicationBuilderAnalyzer.cs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public class WebApplicationBuilderAnalyzer : DiagnosticAnalyzer
2121
DiagnosticDescriptors.DoNotUseConfigureWebHostWithConfigureHostBuilder,
2222
DiagnosticDescriptors.DoNotUseConfigureWithConfigureWebHostBuilder,
2323
DiagnosticDescriptors.DoNotUseUseStartupWithConfigureWebHostBuilder,
24+
DiagnosticDescriptors.DisallowConfigureAppConfigureHostBuilder,
2425
});
2526

2627
public override void Initialize(AnalysisContext context)
@@ -44,6 +45,14 @@ public override void Initialize(AnalysisContext context)
4445
wellKnownTypes.HostingAbstractionsWebHostBuilderExtensions,
4546
wellKnownTypes.WebHostBuilderExtensions,
4647
};
48+
INamedTypeSymbol[] configureAppTypes =
49+
{
50+
wellKnownTypes.ConfigureHostBuilder,
51+
wellKnownTypes.ConfigureWebHostBuilder,
52+
wellKnownTypes.WebHostBuilderExtensions,
53+
wellKnownTypes.HostingHostBuilderExtensions,
54+
};
55+
INamedTypeSymbol[] configureHostTypes = { wellKnownTypes.ConfigureHostBuilder };
4756

4857
compilationStartAnalysisContext.RegisterOperationAction(operationAnalysisContext =>
4958
{
@@ -98,6 +107,54 @@ public override void Initialize(AnalysisContext context)
98107
invocation));
99108
}
100109

110+
// var builder = WebApplication.CreateBuilder();
111+
// builder.WebHost.ConfigureAppConfiguration(builder => {});
112+
if (IsDisallowedMethod(
113+
operationAnalysisContext,
114+
invocation,
115+
targetMethod,
116+
wellKnownTypes.ConfigureWebHostBuilder,
117+
"ConfigureAppConfiguration",
118+
configureAppTypes))
119+
{
120+
operationAnalysisContext.ReportDiagnostic(
121+
CreateDiagnostic(
122+
DiagnosticDescriptors.DisallowConfigureAppConfigureHostBuilder,
123+
invocation));
124+
}
125+
126+
// var builder = WebApplication.CreateBuilder();
127+
// builder.Host.ConfigureAppConfiguration(builder => {});
128+
if (IsDisallowedMethod(
129+
operationAnalysisContext,
130+
invocation,
131+
targetMethod,
132+
wellKnownTypes.ConfigureHostBuilder,
133+
"ConfigureAppConfiguration",
134+
configureAppTypes))
135+
{
136+
operationAnalysisContext.ReportDiagnostic(
137+
CreateDiagnostic(
138+
DiagnosticDescriptors.DisallowConfigureAppConfigureHostBuilder,
139+
invocation));
140+
}
141+
142+
// var builder = WebApplication.CreateBuilder();
143+
// builder.Host.ConfigureHostConfiguration(builder => {});
144+
if (IsDisallowedMethod(
145+
operationAnalysisContext,
146+
invocation,
147+
targetMethod,
148+
wellKnownTypes.ConfigureHostBuilder,
149+
"ConfigureHostConfiguration",
150+
configureHostTypes))
151+
{
152+
operationAnalysisContext.ReportDiagnostic(
153+
CreateDiagnostic(
154+
DiagnosticDescriptors.DisallowConfigureAppConfigureHostBuilder,
155+
invocation));
156+
}
157+
101158
static Diagnostic CreateDiagnostic(DiagnosticDescriptor descriptor, IInvocationOperation operation)
102159
{
103160
// Take the location for the whole invocation operation as a starting point.

src/Framework/AspNetCoreAnalyzers/src/Analyzers/WebApplicationBuilder/WellKnownTypes.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,20 @@ public static bool TryCreate(Compilation compilation, [NotNullWhen(true)] out We
4242
return false;
4343
}
4444

45+
const string HostingHostBuilderExtensions = "Microsoft.Extensions.Hosting.HostingHostBuilderExtensions";
46+
if (compilation.GetTypeByMetadataName(HostingHostBuilderExtensions) is not { } hostingHostBuilderExtensions)
47+
{
48+
return false;
49+
}
50+
4551
wellKnownTypes = new WellKnownTypes
4652
{
4753
ConfigureHostBuilder = configureHostBuilder,
4854
ConfigureWebHostBuilder = configureWebHostBuilder,
4955
GenericHostWebHostBuilderExtensions = genericHostWebHostBuilderExtensions,
5056
HostingAbstractionsWebHostBuilderExtensions = hostingAbstractionsWebHostBuilderExtensions,
5157
WebHostBuilderExtensions = webHostBuilderExtensions,
58+
HostingHostBuilderExtensions = hostingHostBuilderExtensions,
5259
};
5360

5461
return true;
@@ -59,4 +66,5 @@ public static bool TryCreate(Compilation compilation, [NotNullWhen(true)] out We
5966
public INamedTypeSymbol GenericHostWebHostBuilderExtensions { get; private init; }
6067
public INamedTypeSymbol HostingAbstractionsWebHostBuilderExtensions { get; private init; }
6168
public INamedTypeSymbol WebHostBuilderExtensions { get; private init; }
69+
public INamedTypeSymbol HostingHostBuilderExtensions { get; private init; }
6270
}
Lines changed: 144 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,127 +1,210 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
using System;
5-
using System.Collections.Generic;
6-
using System.Linq;
7-
using System.Text;
8-
using System.Threading.Tasks;
9-
using Microsoft.CodeAnalysis.Testing;
10-
using VerifyCS = Microsoft.AspNetCore.Analyzers.RouteHandlers.CSharpRouteHandlerCodeFixVerifier<
11-
Microsoft.AspNetCore.Analyzers.RouteHandlers.RouteHandlerAnalyzer,
12-
Microsoft.AspNetCore.Analyzers.RouteHandlers.Fixers.DetectMismatchedParameterOptionalityFixer>;
4+
using System.Globalization;
5+
using Microsoft.AspNetCore.Analyzer.Testing;
136

147
namespace Microsoft.AspNetCore.Analyzers.WebApplicationBuilder;
158
public partial class DisallowConfigureAppConfigureHostBuilderTest
169
{
1710
private TestDiagnosticAnalyzerRunner Runner { get; } = new(new WebApplicationBuilderAnalyzer());
18-
/**
19-
* Verify that the correct code produces no diagnostic
20-
*/
11+
2112
[Fact]
2213
public async Task ConfigurationBuilderRunsWithoutDiagnostic()
2314
{
2415
// Arrange
2516
var source = @"
2617
using Microsoft.AspNetCore.Builder;
27-
using Microsoft.Extensions.Hosting;
18+
using Microsoft.Extensions.Configuration;
2819
var builder = WebApplication.CreateBuilder(args);
29-
builder.Configuration.AddJSonFile(fileName, optional: true);
20+
builder.Configuration.AddJsonFile(""foo.json"", optional: true);
3021
";
3122
// Act
3223
var diagnostic = await Runner.GetDiagnosticsAsync(source);
3324

3425
// Assert
3526
Assert.Empty(diagnostic);
3627
}
37-
/**
38-
* Verify the fixed code and the diagnostic for builder.Host.ConfigureAppConfiguration
39-
*/
28+
4029
[Fact]
4130
public async Task ConfigureAppHostBuilderProducesDiagnostic()
4231
{
4332
// Arrange
44-
var source = @"
33+
var source = TestSource.Read(@"
4534
using Microsoft.AspNetCore.Builder;
4635
using Microsoft.Extensions.Hosting;
36+
using Microsoft.Extensions.Configuration;
4737
var builder = WebApplication.CreateBuilder(args);
48-
builder.Host.ConfigureAppConfiguration(builder =>
38+
builder.Host./*MM*/ConfigureAppConfiguration(builder =>
4939
{
50-
builder.AddJsonFile(fileName, optional: true);
40+
builder.AddJsonFile(""foo.json"", optional: true);
5141
});
52-
";
53-
var fixedSource = @"
54-
using Microsoft.AspNetCore.Builder;
55-
using Microsoft.Extensions.Hosting;
56-
var builder = WebApplication.CreateBuilder(args);
57-
builder.Configuration.AddJsonFile(fileName, optional: true);
58-
";
42+
");
43+
5944
// Act
60-
var expectedDiagnostic = new DiagnosticResult(DiagnosticDescriptors.DisallowConfigureAppConfigureHostBuilder);
45+
var diagnostics = await Runner.GetDiagnosticsAsync(source.Source);
6146

6247
// Assert
63-
await VerifyCS.VerifyCodeFixAsync(source, expectedDiagnostic, fixedSource);
48+
var diagnostic = Assert.Single(diagnostics);
49+
Assert.Same(DiagnosticDescriptors.DisallowConfigureAppConfigureHostBuilder, diagnostic.Descriptor);
50+
AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location);
51+
Assert.Equal("Replace with builder.Configuration", diagnostic.GetMessage(CultureInfo.InvariantCulture));
6452
}
6553

66-
/**
67-
* Verify the fixed code and the diagnostic for builder.Host.ConfigureHostConfiguration
68-
*/
6954
[Fact]
7055
public async Task ConfigureHostHostBuilderProducesDiagnostic()
7156
{
7257
// Arrange
73-
var source = @"
58+
var source = TestSource.Read(@"
7459
using Microsoft.AspNetCore.Builder;
75-
using Microsoft.Extensions.Hosting;
60+
using Microsoft.Extensions.Configuration;
7661
var builder = WebApplication.CreateBuilder(args);
77-
builder.Host.ConfigureHostConfiguration(builder =>
62+
builder.Host./*MM*/ConfigureHostConfiguration(builder =>
7863
{
79-
builder.AddJsonFile(fileName, optional: true);
64+
builder.AddJsonFile(""foo.json"", optional: true);
8065
});
81-
";
82-
var fixedSource = @"
83-
using Microsoft.AspNetCore.Builder;
84-
using Microsoft.Extensions.Hosting;
85-
var builder = WebApplication.CreateBuilder(args);
86-
builder.Configuration.AddJsonFile(fileName, optional: true);
87-
";
66+
");
67+
8868
// Act
89-
var expectedDiagnostic = new DiagnosticResult(DiagnosticDescriptors.DisallowConfigureAppConfigureHostBuilder);
69+
var diagnostics = await Runner.GetDiagnosticsAsync(source.Source);
9070

9171
// Assert
92-
await VerifyCS.VerifyCodeFixAsync(source, expectedDiagnostic, fixedSource);
72+
var diagnostic = Assert.Single(diagnostics);
73+
Assert.Same(DiagnosticDescriptors.DisallowConfigureAppConfigureHostBuilder, diagnostic.Descriptor);
74+
AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location);
75+
Assert.Equal("Replace with builder.Configuration", diagnostic.GetMessage(CultureInfo.InvariantCulture));
9376
}
9477

95-
/**
96-
* Verify the fixed code and the diagnostic for builder.WebHost.ConfigureAppConfiguration
97-
*/
9878
[Fact]
9979
public async Task ConfigureAppWebHostBuilderProducesDiagnostic()
10080
{
10181
// Arrange
102-
var source = @"
82+
var source = TestSource.Read(@"
10383
using Microsoft.AspNetCore.Builder;
104-
using Microsoft.Extensions.Hosting;
10584
using Microsoft.AspNetCore.Hosting;
106-
using Microsoft.Extensions.DependencyInjection;
85+
using Microsoft.Extensions.Configuration;
10786
var builder = WebApplication.CreateBuilder(args);
108-
builder.WebHost.ConfigureAppConfiguration(builder =>
87+
builder.WebHost./*MM*/ConfigureAppConfiguration(builder =>
10988
{
110-
builder.AddJsonFile(fileName, optional: true);
89+
builder.AddJsonFile(""foo.json"", optional: true);
11190
});
112-
";
113-
var fixedSource = @"
91+
");
92+
93+
// Act
94+
var diagnostics = await Runner.GetDiagnosticsAsync(source.Source);
95+
96+
// Assert
97+
var diagnostic = Assert.Single(diagnostics);
98+
Assert.Same(DiagnosticDescriptors.DisallowConfigureAppConfigureHostBuilder, diagnostic.Descriptor);
99+
AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location);
100+
Assert.Equal("Replace with builder.Configuration", diagnostic.GetMessage(CultureInfo.InvariantCulture));
101+
}
102+
103+
[Fact]
104+
public async Task ConfigureAppWebHostBuilderWithContextProducesDiagnostic()
105+
{
106+
// Arrange
107+
var source = TestSource.Read(@"
114108
using Microsoft.AspNetCore.Builder;
115-
using Microsoft.Extensions.Hosting;
116109
using Microsoft.AspNetCore.Hosting;
117-
using Microsoft.Extensions.DependencyInjection;
110+
using Microsoft.Extensions.Configuration;
118111
var builder = WebApplication.CreateBuilder(args);
119-
builder.Configuration.AddJsonFile(fileName, optional: true);
120-
";
112+
builder.WebHost./*MM*/ConfigureAppConfiguration((context, webHostBuilder) => { });
113+
");
114+
115+
// Act
116+
var diagnostics = await Runner.GetDiagnosticsAsync(source.Source);
117+
118+
// Assert
119+
var diagnostic = Assert.Single(diagnostics);
120+
Assert.Same(DiagnosticDescriptors.DisallowConfigureAppConfigureHostBuilder, diagnostic.Descriptor);
121+
AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location);
122+
Assert.Equal("Replace with builder.Configuration", diagnostic.GetMessage(CultureInfo.InvariantCulture));
123+
}
124+
[Fact]
125+
public async Task ConfigureAppWebHostBuilderProducesDiagnosticInMain()
126+
{
127+
// Arrange
128+
var source = TestSource.Read(@"
129+
using Microsoft.AspNetCore.Builder;
130+
using Microsoft.AspNetCore.Hosting;
131+
using Microsoft.Extensions.Configuration;
132+
public static class Test
133+
{
134+
public static void Main(string[]args) {
135+
var builder = WebApplication.CreateBuilder(args);
136+
builder.WebHost./*MM*/ConfigureAppConfiguration(builder => { });
137+
}
138+
}
139+
");
140+
141+
// Act
142+
var diagnostics = await Runner.GetDiagnosticsAsync(source.Source);
143+
144+
// Assert
145+
var diagnostic = Assert.Single(diagnostics);
146+
Assert.Same(DiagnosticDescriptors.DisallowConfigureAppConfigureHostBuilder, diagnostic.Descriptor);
147+
AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location);
148+
Assert.Equal("Replace with builder.Configuration", diagnostic.GetMessage(CultureInfo.InvariantCulture));
149+
}
150+
[Fact]
151+
public async Task ConfigureAppWebHostOnBuilderProducesDiagnosticInMain()
152+
{
153+
// Arrange
154+
var source = TestSource.Read(@"
155+
using Microsoft.AspNetCore.Builder;
156+
using Microsoft.AspNetCore.Hosting;
157+
using Microsoft.Extensions.Configuration;
158+
public static class Test
159+
{
160+
public static void Main(string[]args) {
161+
var builder = WebApplication.CreateBuilder(args);
162+
var webhost = builder.WebHost;
163+
webhost./*MM*/ConfigureAppConfiguration(builder => { });
164+
}
165+
}
166+
");
167+
168+
// Act
169+
var diagnostics = await Runner.GetDiagnosticsAsync(source.Source);
170+
171+
// Assert
172+
var diagnostic = Assert.Single(diagnostics);
173+
Assert.Same(DiagnosticDescriptors.DisallowConfigureAppConfigureHostBuilder, diagnostic.Descriptor);
174+
AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location);
175+
Assert.Equal("Replace with builder.Configuration", diagnostic.GetMessage(CultureInfo.InvariantCulture));
176+
}
177+
[Fact]
178+
public async Task TwoInvocationsProduceTwoDiagnostic()
179+
{
180+
// Arrange
181+
var source = TestSource.Read(@"
182+
using Microsoft.AspNetCore.Builder;
183+
using Microsoft.AspNetCore.Hosting;
184+
using Microsoft.Extensions.Configuration;
185+
var builder = WebApplication.CreateBuilder(args);
186+
builder.Host./*MM1*/ConfigureHostConfiguration(builder =>
187+
{
188+
builder.AddJsonFile(""foo.json"", optional: true);
189+
});
190+
builder.WebHost./*MM2*/ConfigureAppConfiguration(builder =>
191+
{
192+
builder.AddJsonFile(""foo.json"", optional: true);
193+
});
194+
");
195+
121196
// Act
122-
var expectedDiagnostic = new DiagnosticResult(DiagnosticDescriptors.DisallowConfigureAppConfigureHostBuilder);
197+
var diagnostics = await Runner.GetDiagnosticsAsync(source.Source);
123198

124199
// Assert
125-
await VerifyCS.VerifyCodeFixAsync(source, expectedDiagnostic, fixedSource);
200+
Assert.Equal(2, diagnostics.Length);
201+
var diagnostic1 = diagnostics[0];
202+
var diagnostic2 = diagnostics[1];
203+
Assert.Same(DiagnosticDescriptors.DisallowConfigureAppConfigureHostBuilder, diagnostic1.Descriptor);
204+
AnalyzerAssert.DiagnosticLocation(source.MarkerLocations["MM1"], diagnostic1.Location);
205+
Assert.Equal("Replace with builder.Configuration", diagnostic1.GetMessage(CultureInfo.InvariantCulture));
206+
Assert.Same(DiagnosticDescriptors.DisallowConfigureAppConfigureHostBuilder, diagnostic2.Descriptor);
207+
AnalyzerAssert.DiagnosticLocation(source.MarkerLocations["MM2"], diagnostic2.Location);
208+
Assert.Equal("Replace with builder.Configuration", diagnostic2.GetMessage(CultureInfo.InvariantCulture));
126209
}
127210
}

0 commit comments

Comments
 (0)