Skip to content

Commit a211ce3

Browse files
committed
feat: Implement analyzer for deprecated WasmHttpHandler
1 parent d26dc5b commit a211ce3

File tree

4 files changed

+156
-15
lines changed

4 files changed

+156
-15
lines changed

src/Uno.Analyzers.Tests/Uno.Analyzers.Tests.csproj

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
<IsPackable>false</IsPackable>
55
<NoWarn>1998</NoWarn>
66
<OutputPath>..\Build\Tests\bin\$(Configuration)_$(Platform)\</OutputPath>
7+
8+
<CodeAnalysisVersionForAnalyzersTests>3.8.0</CodeAnalysisVersionForAnalyzersTests>
79
</PropertyGroup>
810

911
<ItemGroup>
@@ -13,21 +15,13 @@
1315
<PackageReference Include="MSTest.TestFramework">
1416
<Version>2.1.2</Version>
1517
</PackageReference>
16-
<PackageReference Include="Microsoft.CodeAnalysis">
17-
<Version>3.3.1</Version>
18-
</PackageReference>
19-
<PackageReference Include="Microsoft.CodeAnalysis.Common">
20-
<Version>3.3.1</Version>
21-
</PackageReference>
22-
<PackageReference Include="Microsoft.CodeAnalysis.CSharp">
23-
<Version>3.3.1</Version>
24-
</PackageReference>
25-
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces">
26-
<Version>3.3.1</Version>
27-
</PackageReference>
28-
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common">
29-
<Version>3.3.1</Version>
30-
</PackageReference>
18+
19+
<PackageReference Include="Microsoft.CodeAnalysis" Version="$(CodeAnalysisVersionForAnalyzersTests)" />
20+
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="$(CodeAnalysisVersionForAnalyzersTests)" />
21+
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="$(CodeAnalysisVersionForAnalyzersTests)" />
22+
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="$(CodeAnalysisVersionForAnalyzersTests)" />
23+
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="$(CodeAnalysisVersionForAnalyzersTests)" />
24+
3125
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.CodeFix.Testing.MSTest">
3226
<Version>1.1.1</Version>
3327
</PackageReference>
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
using Microsoft.VisualStudio.TestTools.UnitTesting;
2+
using Microsoft.CodeAnalysis.Testing;
3+
using Uno.Analyzers.Tests.Verifiers;
4+
using System.Threading.Tasks;
5+
6+
namespace Uno.Analyzers.Tests
7+
{
8+
using Verify = CSharpCodeFixVerifier<WasmHttpHandlerDeprecatedAnalyzer, EmptyCodeFixProvider>;
9+
10+
[TestClass]
11+
public class WasmHttpHandlerDeprecatedTests
12+
{
13+
private static string Stub = @"
14+
namespace Uno.UI.Wasm
15+
{
16+
public class WasmHttpHandler
17+
{
18+
public void M() { }
19+
}
20+
}
21+
";
22+
23+
[TestMethod]
24+
public async Task When_Method_Is_Invoked()
25+
{
26+
var test = @"
27+
using Uno.UI.Wasm;
28+
29+
public class C
30+
{
31+
public void M(WasmHttpHandler handler) => [|handler.M()|];
32+
}
33+
" + Stub;
34+
35+
await Verify.VerifyAnalyzerAsync(test);
36+
}
37+
38+
[TestMethod]
39+
public async Task When_Object_Is_Instantiated()
40+
{
41+
var test = @"
42+
using Uno.UI.Wasm;
43+
44+
public class C
45+
{
46+
public void M1() => _ = [|new WasmHttpHandler()|];
47+
public void M2() { WasmHttpHandler handler = [|new()|]; }
48+
}
49+
" + Stub;
50+
51+
await Verify.VerifyAnalyzerAsync(test);
52+
}
53+
54+
[TestMethod]
55+
public async Task When_Inherited()
56+
{
57+
var test = @"
58+
using Uno.UI.Wasm;
59+
60+
public class [|C|] : WasmHttpHandler
61+
{
62+
}
63+
" + Stub;
64+
65+
await Verify.VerifyAnalyzerAsync(test);
66+
}
67+
}
68+
}

src/Uno.Analyzers/Uno.Analyzers.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
<ItemGroup>
6161
<Compile Include="UnoNotImplementedAnalyzer.cs" />
6262
<Compile Include="Properties\AssemblyInfo.cs" />
63+
<Compile Include="WasmHttpHandlerDeprecatedAnalyzer.cs" />
6364
</ItemGroup>
6465
<ItemGroup>
6566
</ItemGroup>
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#nullable enable
2+
3+
using System;
4+
using System.Collections.Immutable;
5+
using System.Linq;
6+
using Microsoft.CodeAnalysis;
7+
using Microsoft.CodeAnalysis.Diagnostics;
8+
using Microsoft.CodeAnalysis.Operations;
9+
10+
namespace Uno.Analyzers
11+
{
12+
[DiagnosticAnalyzer(LanguageNames.CSharp)]
13+
public class WasmHttpHandlerDeprecatedAnalyzer : DiagnosticAnalyzer
14+
{
15+
internal const string Title = "'WasmHttpHandler' is deprecated";
16+
internal const string MessageFormat = "'WasmHttpHandler' is deprecated";
17+
internal const string Category = "Usage";
18+
19+
internal static DiagnosticDescriptor Rule = new(
20+
"Uno0002",
21+
Title,
22+
MessageFormat,
23+
Category,
24+
DiagnosticSeverity.Warning,
25+
isEnabledByDefault: true
26+
);
27+
28+
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create(Rule);
29+
30+
public override void Initialize(AnalysisContext context)
31+
{
32+
context.EnableConcurrentExecution();
33+
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
34+
35+
context.RegisterCompilationStartAction(context =>
36+
{
37+
var wasmHttpHandlerSymbol = context.Compilation.GetTypeByMetadataName("Uno.UI.Wasm.WasmHttpHandler");
38+
if (wasmHttpHandlerSymbol is null)
39+
{
40+
return;
41+
}
42+
43+
context.RegisterOperationAction(c => AnalyzeOperation(c, wasmHttpHandlerSymbol), OperationKind.Invocation, OperationKind.ObjectCreation);
44+
context.RegisterSymbolAction(c => AnalyzeNamedType(c, wasmHttpHandlerSymbol), SymbolKind.NamedType);
45+
});
46+
}
47+
48+
private void AnalyzeNamedType(SymbolAnalysisContext context, INamedTypeSymbol wasmHttpHandlerSymbol)
49+
{
50+
var namedType = (INamedTypeSymbol)context.Symbol;
51+
if (wasmHttpHandlerSymbol.Equals(namedType.BaseType))
52+
{
53+
context.ReportDiagnostic(Diagnostic.Create(Rule, context.Symbol.Locations.First()));
54+
}
55+
}
56+
57+
private void AnalyzeOperation(OperationAnalysisContext context, INamedTypeSymbol wasmHttpHandlerSymbol)
58+
{
59+
var symbol = GetTypeSymbolFromOperation(context.Operation);
60+
if (wasmHttpHandlerSymbol.Equals(symbol, SymbolEqualityComparer.Default))
61+
{
62+
context.ReportDiagnostic(Diagnostic.Create(Rule, context.Operation.Syntax.GetLocation()));
63+
}
64+
}
65+
66+
private INamedTypeSymbol? GetTypeSymbolFromOperation(IOperation operation)
67+
{
68+
return operation switch
69+
{
70+
IInvocationOperation invocationOperation => invocationOperation.TargetMethod.ContainingType,
71+
IObjectCreationOperation objectCreation => objectCreation.Constructor.ContainingType,
72+
IFieldReferenceOperation fieldReferenceOperation => fieldReferenceOperation.Field.ContainingType,
73+
IPropertyReferenceOperation propertyReferenceOperation => propertyReferenceOperation.Property.ContainingType,
74+
_ => throw new InvalidOperationException("This code path is unreachable.")
75+
};
76+
}
77+
}
78+
}

0 commit comments

Comments
 (0)