private static async Task <Document> InvokeMp0101(Diagnostic diagnostic, Document document, CancellationToken cancellationToken) { // 2: add a try/catch block around RequestAsync // add block around RequestAsync call up to last // access to any variable the result is assigned to. // a: find span that would best fit the try // // b: add the catch with default code: // catch(ReceivedErrorEventException<{3rd type parameter}> ex) // { throw new NotImplementedException(ex.Message); } // 3: catch... var model = await document.GetSemanticModelAsync(cancellationToken); var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); Func <IdentifierNameSyntax, SyntaxList <StatementSyntax> > generateCatchStatements = exceptionIdentifierName => SingletonList <StatementSyntax>( ExpressionStatement( InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, AliasQualifiedName( IdentifierName( Token(SyntaxKind.GlobalKeyword) .WithLeadingTrivia(Comment("// TODO: do something with ex.ErrorEvent"), CarriageReturnLineFeed) ), IdentifierName(nameof(System))), IdentifierName(nameof(System.Diagnostics))), IdentifierName(nameof(Debug))), IdentifierName(nameof(Debug.WriteLine)))) .WithArgumentList( ArgumentList( SingletonSeparatedList( Argument( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, exceptionIdentifierName, IdentifierName(nameof(ReceivedErrorEventException <IEvent> .ErrorEvent))))))))); // Find the type declaration identified by the diagnostic. var subjectToken = root.FindToken(diagnostic.Location.SourceSpan.Start); var invocation = subjectToken.Parent.AncestorsAndSelf().OfType <InvocationExpressionSyntax>().First(); var subjectNode = root.FindNode(diagnostic.Location.SourceSpan); var requestAsyncMemberAccess = subjectNode.Parent.AncestorsAndSelf().OfType <MemberAccessExpressionSyntax>().First(); // verify invocation is the one we want // rule should detect this exists if (!(invocation.Parent is AwaitExpressionSyntax)) { throw new InvalidOperationException($"{Facts.GetCurrentMethodName()} operates on an await statement, and await statement not found."); } // assume, RequestAsync return is assigned to something (covered by other rule) // 1: get 3rd type parameter in invocation INamedTypeSymbol errorEventType, messageType, eventType; Utilities.GetRequestAsyncInfo(requestAsyncMemberAccess, model, out messageType, out eventType, out errorEventType); var generator = SyntaxGenerator.GetGenerator(document); var exceptionArgumentsInfo = new Dictionary <string, TypeSyntax> { { "ex", typeof(ReceivedErrorEventException <>).AsTypeSyntax(generator, errorEventType) } }; return (document.WithSyntaxRoot(Formatter.Format( subjectToken.GetAncestorStatement().TryCatchSafe(exceptionArgumentsInfo, generateCatchStatements, root, model), document.Project.Solution.Workspace, document.Project.Solution.Workspace.Options))); }