Skip to content

Commit a8ab402

Browse files
committed
Add ServiceMethodPrepareAsyncAnalyzer
Fixes #15
1 parent 21251cf commit a8ab402

3 files changed

Lines changed: 76 additions & 0 deletions

File tree

OpenStackNetAnalyzers/OpenStackNetAnalyzers/OpenStackNetAnalyzers.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
<Compile Include="PlaceholderDocumentationCodeFix.cs" />
5050
<Compile Include="Properties\AssemblyInfo.cs" />
5151
<Compile Include="SdkTypeSymbolExtensions.cs" />
52+
<Compile Include="ServiceMethodPrepareAsyncAnalyzer.cs" />
5253
<Compile Include="SpacingExtensions.cs" />
5354
<Compile Include="TypeSymbolExtensions.cs" />
5455
<Compile Include="XmlSyntaxFactory.cs" />

OpenStackNetAnalyzers/OpenStackNetAnalyzers/SdkTypeSymbolExtensions.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ internal static class SdkTypeSymbolExtensions
99

1010
private const string FullyQualifiedDelegatingHttpApiCallT = "global::OpenStack.Net.DelegatingHttpApiCall<T>";
1111

12+
private const string FullyQualifiedIHttpService = "global::OpenStack.Services.IHttpService";
13+
1214
public static bool IsExtensibleJsonObject(this INamedTypeSymbol symbol)
1315
{
1416
while (symbol != null && symbol.SpecialType != SpecialType.System_Object)
@@ -39,5 +41,19 @@ public static bool IsDelegatingHttpApiCall(this INamedTypeSymbol symbol)
3941

4042
return false;
4143
}
44+
45+
public static bool IsHttpServiceInterface(this INamedTypeSymbol symbol)
46+
{
47+
if (symbol == null || symbol.TypeKind != TypeKind.Interface)
48+
return false;
49+
50+
foreach (INamedTypeSymbol interfaceType in symbol.AllInterfaces)
51+
{
52+
if (string.Equals(FullyQualifiedIHttpService, interfaceType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)))
53+
return true;
54+
}
55+
56+
return false;
57+
}
4258
}
4359
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
namespace OpenStackNetAnalyzers
2+
{
3+
using System;
4+
using System.Collections.Immutable;
5+
using System.Linq;
6+
using Microsoft.CodeAnalysis;
7+
using Microsoft.CodeAnalysis.Diagnostics;
8+
9+
[DiagnosticAnalyzer(LanguageNames.CSharp)]
10+
public class ServiceMethodPrepareAsyncAnalyzer : DiagnosticAnalyzer
11+
{
12+
public const string DiagnosticId = "ServiceMethodPrepareAsync";
13+
internal const string Title = "Service methods should be named Prepare{Name}Async";
14+
internal const string MessageFormat = "Service methods should be named Prepare{Name}Async";
15+
internal const string Category = "OpenStack.Maintainability";
16+
internal const string Description = "Service methods should be named Prepare{Name}Async";
17+
18+
private static DiagnosticDescriptor Descriptor =
19+
new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, Category, DiagnosticSeverity.Warning, isEnabledByDefault: true, description: Description);
20+
21+
private static readonly ImmutableArray<DiagnosticDescriptor> _supportedDiagnostics =
22+
ImmutableArray.Create(Descriptor);
23+
24+
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
25+
{
26+
get
27+
{
28+
return _supportedDiagnostics;
29+
}
30+
}
31+
32+
public override void Initialize(AnalysisContext context)
33+
{
34+
context.RegisterSymbolAction(HandleNamedType, SymbolKind.NamedType);
35+
}
36+
37+
private void HandleNamedType(SymbolAnalysisContext context)
38+
{
39+
INamedTypeSymbol symbol = (INamedTypeSymbol)context.Symbol;
40+
if (!symbol.IsHttpServiceInterface())
41+
return;
42+
43+
foreach (IMethodSymbol method in symbol.GetMembers().OfType<IMethodSymbol>())
44+
{
45+
if (string.IsNullOrEmpty(method.Name))
46+
continue;
47+
48+
if (method.Name.StartsWith("Prepare", StringComparison.Ordinal) && method.Name.EndsWith("Async", StringComparison.Ordinal))
49+
{
50+
// TODO check letter following 'Prepare'
51+
continue;
52+
}
53+
54+
ImmutableArray<Location> locations = method.Locations;
55+
context.ReportDiagnostic(Diagnostic.Create(Descriptor, locations.FirstOrDefault(), locations.Skip(1)));
56+
}
57+
}
58+
}
59+
}

0 commit comments

Comments
 (0)