public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); var diagnostic = context.Diagnostics.First(); var diagnosticSpan = diagnostic.Location.SourceSpan; var identifierNode = root.FindNode(diagnosticSpan); SemanticModel semanticModel = await context.Document.GetSemanticModelAsync(); var durableVersion = SyntaxNodeUtils.GetDurableVersion(semanticModel); if (durableVersion.Equals(DurableVersion.V1)) { context.RegisterCodeFix( CodeAction.Create(FixDurableOrchestrationClient.ToString(), cancellationToken => ReplaceWithIdentifierAsync(context.Document, identifierNode, cancellationToken, "DurableOrchestrationClient"), nameof(ClientCodeFixProvider) + nameof(FixDurableOrchestrationClient)), diagnostic); } else if (durableVersion.Equals(DurableVersion.V2)) { context.RegisterCodeFix( CodeAction.Create(FixIDurableClient.ToString(), cancellationToken => ReplaceWithIdentifierAsync(context.Document, identifierNode, cancellationToken, "IDurableClient"), nameof(ClientCodeFixProvider) + nameof(FixIDurableClient)), diagnostic); context.RegisterCodeFix( CodeAction.Create(FixIDurableEntityClient.ToString(), cancellationToken => ReplaceWithIdentifierAsync(context.Document, identifierNode, cancellationToken, "IDurableEntityClient"), nameof(ClientCodeFixProvider) + nameof(FixIDurableEntityClient)), diagnostic); context.RegisterCodeFix( CodeAction.Create(FixIDurableOrchestrationClient.ToString(), cancellationToken => ReplaceWithIdentifierAsync(context.Document, identifierNode, cancellationToken, "IDurableOrchestrationClient"), nameof(ClientCodeFixProvider) + nameof(FixIDurableOrchestrationClient)), diagnostic); } }
public void FindEntityTriggers(SyntaxNodeAnalysisContext context) { var attribute = context.Node as AttributeSyntax; var semanticModel = context.SemanticModel; version = SyntaxNodeUtils.GetDurableVersion(semanticModel); if (AttributeMatchesVersionClientBinding(attribute)) { if (SyntaxNodeUtils.TryGetParameterNodeNextToAttribute(attribute, context, out SyntaxNode parameterNode)) { var paramTypeName = parameterNode.ToString(); if (!ParameterTypeIsCorrectDurableType(parameterNode)) { if (TryGetRuleFromVersion(out DiagnosticDescriptor rule)) { var diagnostic = Diagnostic.Create(rule, parameterNode.GetLocation(), parameterNode); context.ReportDiagnostic(diagnostic); } } } } }
private static bool AnalyzeIdentifierThread(SyntaxNode method, CompilationAnalysisContext context, SemanticModel semanticModel) { var diagnosedIssue = false; foreach (SyntaxNode descendant in method.DescendantNodes()) { if (descendant is IdentifierNameSyntax identifierName) { version = SyntaxNodeUtils.GetDurableVersion(semanticModel); var identifierText = identifierName.Identifier.ValueText; if (identifierText == "Sleep") { var memberAccessExpression = identifierName.Parent; var memberSymbol = SyntaxNodeUtils.GetSyntaxTreeSemanticModel(semanticModel, memberAccessExpression).GetSymbolInfo(memberAccessExpression).Symbol; if (memberSymbol != null && memberSymbol.ToString().StartsWith("System.Threading.Thread")) { if (TryGetRuleFromVersion(out DiagnosticDescriptor rule)) { var expression = GetAwaitOrInvocationExpression(memberAccessExpression); var diagnostic = Diagnostic.Create(rule, expression.GetLocation(), expression); context.ReportDiagnostic(diagnostic); diagnosedIssue = true; } } } } } return(diagnosedIssue); }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); var diagnostic = context.Diagnostics.First(); var diagnosticSpan = diagnostic.Location.SourceSpan; var expression = root.FindNode(diagnosticSpan, false, true); if (!TryGetInvocationExpression(expression, out SyntaxNode invocationExpression)) { return; } SemanticModel semanticModel = await context.Document.GetSemanticModelAsync(); var durableVersion = SyntaxNodeUtils.GetDurableVersion(semanticModel); if (SyntaxNodeUtils.IsInsideOrchestrator(invocationExpression) && durableVersion.Equals(DurableVersion.V2)) { if (TryGetDurableOrchestrationContextVariableName(invocationExpression, out string variableName)) { var newExpression = ""; if (TryGetMillisecondsParameter(invocationExpression, out string milliseconds)) { if (TryGetCancellationTokenParameter(invocationExpression, semanticModel, out string cancellationToken)) { newExpression = "await " + variableName + ".CreateTimer(" + variableName + ".CurrentUtcDateTime.AddMilliseconds(" + milliseconds + "), " + cancellationToken + ")"; } else { newExpression = "await " + variableName + ".CreateTimer(" + variableName + ".CurrentUtcDateTime.AddMilliseconds(" + milliseconds + "), CancellationToken.None)"; } } else if (TryGetTimespanParameter(invocationExpression, semanticModel, out string timeSpan)) { if (TryGetCancellationTokenParameter(invocationExpression, semanticModel, out string cancellationToken)) { newExpression = "await " + variableName + ".CreateTimer(" + variableName + ".CurrentUtcDateTime.Add(" + timeSpan + "), " + cancellationToken + ")"; } else { newExpression = "await " + variableName + ".CreateTimer(" + variableName + ".CurrentUtcDateTime.Add(" + timeSpan + "), CancellationToken.None)"; } } context.RegisterCodeFix( CodeAction.Create(FixTimerInOrchestrator.ToString(), c => ReplaceWithIdentifierAsync(context.Document, expression, c, newExpression), nameof(TimerCodeFixProvider)), diagnostic); } } else if (SyntaxNodeUtils.IsMarkedDeterministic(invocationExpression)) { context.RegisterCodeFix( CodeAction.Create(FixDeterministicAttribute.ToString(), c => RemoveDeterministicAttributeAsync(context.Document, expression, c), nameof(TimerCodeFixProvider)), diagnostic); } }
public void FindOrchestrationTriggers(SyntaxNodeAnalysisContext context) { if (SyntaxNodeUtils.IsInsideFunction(context.SemanticModel, context.Node) && context.Node is AttributeSyntax attribute) { var semanticModel = context.SemanticModel; version = SyntaxNodeUtils.GetDurableVersion(semanticModel); if (string.Equals(attribute.ToString(), "OrchestrationTrigger")) { if (SyntaxNodeUtils.TryGetParameterNodeNextToAttribute(attribute, out SyntaxNode parameterNode)) { if (!ParameterTypeIsCorrectDurableType(parameterNode)) { if (TryGetRuleFromVersion(out DiagnosticDescriptor rule)) { var diagnostic = Diagnostic.Create(rule, parameterNode.GetLocation(), parameterNode); context.ReportDiagnostic(diagnostic); } } } } } }
private static void AnalyzeIdentifierThread(SyntaxNodeAnalysisContext context) { var identifierName = context.Node as IdentifierNameSyntax; if (identifierName != null) { var semanticModel = context.SemanticModel; version = SyntaxNodeUtils.GetDurableVersion(semanticModel); var identifierText = identifierName.Identifier.ValueText; if (identifierText == "Sleep") { var memberAccessExpression = identifierName.Parent; var memberSymbol = context.SemanticModel.GetSymbolInfo(memberAccessExpression).Symbol; if (memberSymbol == null || !memberSymbol.ToString().StartsWith("System.Threading.Thread")) { return; } if (!SyntaxNodeUtils.IsInsideOrchestrator(identifierName) && !SyntaxNodeUtils.IsMarkedDeterministic(identifierName)) { return; } if (TryGetRuleFromVersion(out DiagnosticDescriptor rule)) { var expression = GetAwaitOrInvocationExpression(memberAccessExpression); var diagnostic = Diagnostic.Create(rule, expression.GetLocation(), expression); context.ReportDiagnostic(diagnostic); } } } }