private static async Task <Document> AddTryCatchAsync(CodeFixContext context, CancellationToken cancellationToken) { var document = context.Document; var root = await document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); var diagnostic = context.Diagnostics.First(); var diagnosticSpan = diagnostic.Location.SourceSpan; SyntaxToken invocation = root.FindToken(diagnosticSpan.Start); InvocationExpressionSyntax completeMethod = await GetInvokedMethodAsync(context, cancellationToken); SemanticModel sm = await document.GetSemanticModelAsync(); var calleeAttributes = NotHandledAnalyzer.GetAllAttributes(sm, completeMethod); var catchedAttributes = await GetCallerAttributesAsync(context, cancellationToken); var tryElement = invocation.Parent.FirstAncestorOrSelf <TryStatementSyntax>(); var oldRoot = await document.GetSyntaxRootAsync(cancellationToken); SyntaxNode newRoot = null; var catches = new List <CatchClauseSyntax>(); foreach (var attrib in calleeAttributes) { var skip = false; var typeParameter = attrib.AttributeData.ConstructorArguments.FirstOrDefault(f => f.Type.TypeKind == TypeKind.Class); if (typeParameter.Type == null) { continue; } var exceptionName = typeParameter.Value.ToString(); foreach (var catchedAttribute in catchedAttributes) { var typeOfExp = catchedAttribute.DescendantNodes().OfType <TypeOfExpressionSyntax>(); if (typeOfExp == null || !typeOfExp.Any()) { skip = true; continue; } var identifier = typeOfExp.First().DescendantNodes().OfType <IdentifierNameSyntax>(); if (identifier == null || !identifier.Any()) { skip = true; continue; } var semanticType = sm.GetTypeInfo(identifier.First()).Type; if (semanticType != null && exceptionName.Equals(semanticType.ToString())) { skip = true; break; } } if (skip) { continue; } bool createCatchPart = tryElement == null; if (!createCatchPart) { var exists = false; foreach (var f in tryElement.Catches) { if (f.Declaration != null) { foreach (var k in f.Declaration.DescendantNodes().OfType <IdentifierNameSyntax>()) { var typeInfo = sm.GetTypeInfo(k); if (typeInfo.Type == null) { continue; } if (typeInfo.Type.ToString().Equals(typeof(Exception).FullName) || typeInfo.Type.ToString().Equals(exceptionName)) { exists = true; break; } } } if (exists) { break; } } createCatchPart = !exists; } if (createCatchPart) { IdentifierNameSyntax catchTypeSyntax = SyntaxFactory.IdentifierName(exceptionName); var catchDeclaration = SyntaxFactory.CatchDeclaration(catchTypeSyntax, new SyntaxToken()); var blockSyntax = SyntaxFactory.Block(); var catchPart = SyntaxFactory.CatchClause(catchDeclaration, null, blockSyntax); catches.Add(catchPart); } } try { if (tryElement != null) { newRoot = oldRoot.InsertNodesAfter(tryElement.Catches.Last(), catches); } else { var body = completeMethod.FirstAncestorOrSelf <StatementSyntax>(); var expressionIndex = body.Parent.ChildNodesAndTokens().ToList().IndexOf(body); BlockSyntax block = SyntaxFactory.Block(body); TryStatementSyntax trySyntax = SyntaxFactory.TryStatement(block, new SyntaxList <CatchClauseSyntax>(), null); trySyntax = trySyntax.AddCatches(catches.ToArray()).NormalizeWhitespace(elasticTrivia: true); newRoot = oldRoot.ReplaceNode(body, trySyntax); } } catch (Exception ex) { Debug.WriteLine(ex); } return(document.WithSyntaxRoot(newRoot)); }
private static async Task <Document> AddAnnotationAsync(CodeFixContext context, CancellationToken cancellationToken) { var document = context.Document; var root = await document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); var diagnostic = context.Diagnostics.First(); var diagnosticSpan = diagnostic.Location.SourceSpan; SemanticModel sm = await document.GetSemanticModelAsync(); SyntaxToken invocation = root.FindToken(diagnosticSpan.Start); InvocationExpressionSyntax completeMethod = await GetInvokedMethodAsync(context, cancellationToken); MethodDeclarationSyntax callerMethodContainer = (MethodDeclarationSyntax)invocation.Parent.AncestorsAndSelf().OfType <MethodDeclarationSyntax>().FirstOrDefault(); var calleeAttributes = NotHandledAnalyzer.GetAllAttributes(sm, completeMethod); var catchedAttributes = await GetCallerAttributesAsync(context, cancellationToken); var tryElement = invocation.Parent.FirstAncestorOrSelf <TryStatementSyntax>(); var newAttributes = callerMethodContainer.AttributeLists; foreach (var attrib in calleeAttributes) { var skip = false; var typeParameter = attrib.AttributeData.ConstructorArguments.FirstOrDefault(f => f.Type.TypeKind == TypeKind.Class); if (typeParameter.Type == null) { continue; } var exceptionName = typeParameter.Value.ToString(); foreach (var catchedAttribute in catchedAttributes) { var typeOfExp = catchedAttribute.DescendantNodes().OfType <TypeOfExpressionSyntax>(); if (typeOfExp == null || !typeOfExp.Any()) { skip = true; continue; } var identifier = typeOfExp.First().DescendantNodes().OfType <IdentifierNameSyntax>(); if (identifier == null || !identifier.Any()) { skip = true; continue; } var semanticType = sm.GetTypeInfo(identifier.First()).Type; if (semanticType != null && exceptionName.Equals(semanticType.ToString())) { skip = true; break; } } if (!skip && tryElement != null) { foreach (var f in tryElement.Catches) { if (f.Declaration != null) { foreach (var k in f.Declaration.DescendantNodes().OfType <IdentifierNameSyntax>()) { var typeInfo = sm.GetTypeInfo(k); if (typeInfo.Type == null) { continue; } if (typeInfo.Type.ToString().Equals(typeof(Exception).FullName) || typeInfo.Type.ToString().Equals(exceptionName)) { skip = true; break; } } } if (skip) { break; } } } if (skip) { continue; } var attributeName = typeof(ThrowsExceptionAttribute).FullName.Substring(0, typeof(ThrowsExceptionAttribute).FullName.IndexOf("Attribute")); newAttributes = newAttributes.Add( SyntaxFactory.AttributeList( SyntaxFactory.SingletonSeparatedList <AttributeSyntax>( SyntaxFactory.Attribute( SyntaxFactory.IdentifierName(attributeName)).WithArgumentList( SyntaxFactory.AttributeArgumentList( SyntaxFactory.SingletonSeparatedList <AttributeArgumentSyntax>( SyntaxFactory.AttributeArgument( SyntaxFactory.TypeOfExpression( SyntaxFactory.IdentifierName(exceptionName))))))))); } try { return(document.WithSyntaxRoot(root.ReplaceNode(callerMethodContainer, callerMethodContainer.WithAttributeLists(newAttributes)))); } catch (Exception ex) { Debug.WriteLine(ex); return(document.WithSyntaxRoot(root)); } }