I've implemented a TimeProvider within a large C# application, so that there is centralized control over the application time. I want to make sure in the future that no one is using DateTime.Now/Today/UtcNow
as this would circumvent the previous mentioned implementation. Instead, I want an analyzer to suggest to use my TimeProviderService
, so that it is not missed in e.g a code review.
I want to solve this with an analyzer, so therefore my question is: How do I do this?
Below is one of my attemps; however, this one seems to trigger some sort of legacy issue with FxCop:
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class Analyzer : DiagnosticAnalyzer
{
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(AnalyzeSymbol, SyntaxKind.IdentifierName);
}
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; }
public static string DiagnosticId = "1337";
private static void AnalyzeSymbol(SyntaxNodeAnalysisContext context)
{
var token = context.Node.GetFirstToken();
if (token.ToString().Equals("DateTime"))
{
var nextToken = token.GetNextToken();
if (nextToken.IsKind(SyntaxKind.DotToken))
{
var dateTimeProperty = nextToken.GetNextToken();
var descripter = new DiagnosticDescriptor(DiagnosticId, "DateTime.Today: Use the TimeProvider.Today instead", "", "Noitso best practise", DiagnosticSeverity.Error, isEnabledByDefault: true);
if (dateTimeProperty.ToString().Equals("Now"))
{
context.ReportDiagnostic(Diagnostic.Create(descripter, context.Node.GetLocation(), "DateTime.Now: Use the TimeProvider.Now instead"));
}
else if (dateTimeProperty.ToString().Equals("Today"))
{
context.ReportDiagnostic(Diagnostic.Create(descripter, context.Node.GetLocation()));
}
else if (dateTimeProperty.ToString().Equals("UtcNow"))
{
context.ReportDiagnostic(Diagnostic.Create(descripter, context.Node.GetLocation(), "DateTime.UtcNow: Use the TimeProvider.UtcNow instead"));
}
}
}
}
}