public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var document = context.Document; if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles) { return; } var span = context.Span; if (!span.IsEmpty) { return; } var cancellationToken = context.CancellationToken; if (cancellationToken.IsCancellationRequested) { return; } var root = await document.GetSyntaxRootAsync(cancellationToken); var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (model.IsFromGeneratedCode(cancellationToken)) { return; } var node = root.FindNode(span) as BinaryExpressionSyntax; if (node == null || !node.OperatorToken.IsKind(SyntaxKind.QuestionQuestionToken)) { return; } context.RegisterRefactoring( CodeActionFactory.Create( span, DiagnosticSeverity.Info, GettextCatalog.GetString("Replace '??' operator with '?:' expression"), t2 => { var left = node.Left; var info = model.GetTypeInfo(left, t2); if (info.ConvertedType.IsNullableType()) { left = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, FlipEqualsTargetAndArgumentCodeRefactoringProvider.AddParensIfRequired(left), SyntaxFactory.IdentifierName("Value")); } var ternary = SyntaxFactory.ConditionalExpression( SyntaxFactory.BinaryExpression( SyntaxKind.NotEqualsExpression, node.Left, SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression) ), left, node.Right ).WithAdditionalAnnotations(Formatter.Annotation); return(Task.FromResult(document.WithSyntaxRoot(root.ReplaceNode((SyntaxNode)node, (ExpressionSyntax)ternary)))); } ) ); }
static Document PerformAction(Document document, SyntaxNode root, BinaryExpressionSyntax bop) { var nodeToReplace = bop.IsParentKind(SyntaxKind.ParenthesizedExpression) ? bop.Parent : bop; var castExpr = (ExpressionSyntax)SyntaxFactory.CastExpression(bop.Right as TypeSyntax, FlipEqualsTargetAndArgumentCodeRefactoringProvider.AddParensIfRequired(bop.Left.WithoutLeadingTrivia().WithoutTrailingTrivia())).WithLeadingTrivia(bop.GetLeadingTrivia()).WithTrailingTrivia(bop.GetTrailingTrivia()); var newRoot = root.ReplaceNode((SyntaxNode)nodeToReplace, castExpr); return(document.WithSyntaxRoot(newRoot)); }