public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { if (!Settings.IsAnyCodeFixEnabled( CodeFixIdentifiers.UseYieldReturnInsteadOfReturn, CodeFixIdentifiers.RemoveReturnKeyword, CodeFixIdentifiers.RemoveReturnExpression)) { return; } SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); ReturnStatementSyntax returnStatement = root .FindNode(context.Span, getInnermostNodeForTie: true)? .FirstAncestorOrSelf <ReturnStatementSyntax>(); Debug.Assert(returnStatement != null, $"{nameof(returnStatement)} is null"); if (returnStatement == null) { return; } foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case CompilerDiagnosticIdentifiers.CannotReturnValueFromIterator: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.UseYieldReturnInsteadOfReturn)) { break; } ExpressionSyntax expression = returnStatement.Expression; if (expression != null) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ISymbol containingSymbol = semanticModel.GetEnclosingSymbol(returnStatement.SpanStart, context.CancellationToken); if (containingSymbol?.IsKind(SymbolKind.Method) == true) { var methodSymbol = (IMethodSymbol)containingSymbol; ITypeSymbol returnType = methodSymbol.ReturnType; var replacementKind = SyntaxKind.None; if (returnType.SpecialType == SpecialType.System_Collections_IEnumerable) { if (semanticModel .GetTypeSymbol(expression, context.CancellationToken) .IsIEnumerableOrConstructedFromIEnumerableOfT()) { replacementKind = SyntaxKind.ForEachStatement; } else { replacementKind = SyntaxKind.YieldReturnStatement; } } else if (returnType.IsNamedType()) { var namedTypeSymbol = (INamedTypeSymbol)returnType; if (namedTypeSymbol.IsConstructedFromIEnumerableOfT()) { if (semanticModel.IsImplicitConversion(expression, namedTypeSymbol.TypeArguments[0])) { replacementKind = SyntaxKind.YieldReturnStatement; } else { replacementKind = SyntaxKind.ForEachStatement; } } } if (replacementKind == SyntaxKind.YieldReturnStatement || (replacementKind == SyntaxKind.ForEachStatement && !returnStatement.SpanContainsDirectives())) { CodeAction codeAction = CodeAction.Create( "Use yield return instead of return", cancellationToken => UseYieldReturnInsteadOfReturnRefactoring.RefactorAsync(context.Document, returnStatement, replacementKind, semanticModel, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } } } break; } case CompilerDiagnosticIdentifiers.SinceMethodReturnsVoidReturnKeywordMustNotBeFollowedByObjectExpression: case CompilerDiagnosticIdentifiers.SinceMethodIsAsyncMethodThatReturnsTaskReturnKeywordMustNotBeFollowedByObjectExpression: { if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveReturnExpression)) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ISymbol symbol = semanticModel.GetEnclosingSymbol(returnStatement.SpanStart, context.CancellationToken); if (symbol?.IsMethod() == true) { var methodSymbol = (IMethodSymbol)symbol; if (methodSymbol.ReturnsVoid || methodSymbol.ReturnType.Equals(semanticModel.GetTypeByMetadataName(MetadataNames.System_Threading_Tasks_Task))) { CodeAction codeAction = CodeAction.Create( "Remove return expression", cancellationToken => { ReturnStatementSyntax newNode = returnStatement .WithExpression(null) .WithFormatterAnnotation(); return(context.Document.ReplaceNodeAsync(returnStatement, newNode, cancellationToken)); }, GetEquivalenceKey(diagnostic, CodeFixIdentifiers.RemoveReturnExpression)); context.RegisterCodeFix(codeAction, diagnostic); } } } if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveReturnKeyword)) { ExpressionSyntax expression = returnStatement.Expression; if (expression.IsKind( SyntaxKind.InvocationExpression, SyntaxKind.ObjectCreationExpression, SyntaxKind.PreDecrementExpression, SyntaxKind.PreIncrementExpression, SyntaxKind.PostDecrementExpression, SyntaxKind.PostIncrementExpression) || expression is AssignmentExpressionSyntax) { CodeAction codeAction = CodeAction.Create( "Remove 'return'", cancellationToken => { SyntaxTriviaList leadingTrivia = returnStatement .GetLeadingTrivia() .AddRange(returnStatement.ReturnKeyword.TrailingTrivia.EmptyIfWhitespace()) .AddRange(expression.GetLeadingTrivia().EmptyIfWhitespace()); ExpressionStatementSyntax newNode = SyntaxFactory.ExpressionStatement( expression.WithLeadingTrivia(leadingTrivia), returnStatement.SemicolonToken); return(context.Document.ReplaceNodeAsync(returnStatement, newNode, cancellationToken)); }, GetEquivalenceKey(diagnostic, CodeFixIdentifiers.RemoveReturnKeyword)); context.RegisterCodeFix(codeAction, diagnostic); } } break; } } } }