private async Task<Document> RemoveAsyncAwait(Document document, MethodDeclarationSyntax methodDecl, CancellationToken cancellationToken) { MethodDeclarationSyntax newMethodDecl; // (1) Remove async keyword var asyncModifier = methodDecl.Modifiers.First(a => a.Kind() == SyntaxKind.AsyncKeyword); newMethodDecl = asyncModifier.HasLeadingTrivia ? methodDecl.WithModifiers(methodDecl.Modifiers.Remove(asyncModifier)).WithLeadingTrivia(asyncModifier.LeadingTrivia) : methodDecl.WithModifiers(methodDecl.Modifiers.Remove(asyncModifier)); // (2) If void, convert it to Task if (newMethodDecl.ReturnsVoid()) { var newType = SyntaxFactory.ParseTypeName("System.Threading.Tasks.Task").WithAdditionalAnnotations(Simplifier.Annotation).WithTrailingTrivia(newMethodDecl.ReturnType.GetTrailingTrivia()); newMethodDecl = newMethodDecl.WithReturnType(newType); } // (3) For all await expressions, remove await and insert return if there is none. var awaitExprs = newMethodDecl.Body.DescendantNodes().OfType<AwaitExpressionSyntax>(); List<SyntaxReplacementPair> pairs = new List<SyntaxReplacementPair>(); foreach (var awaitExpr in awaitExprs) { SyntaxNode oldNode; SyntaxNode newNode; var newAwaitExpr = awaitExpr; // If there is some ConfigureAwait(false), remove it var invoc = awaitExpr.Expression as InvocationExpressionSyntax; if (invoc != null) { var expr = invoc.Expression as MemberAccessExpressionSyntax; // TODO: Check whether it is ConfigureAwait(false) or ConfigureAwait(true); if (expr != null && expr.Name.Identifier.ValueText == "ConfigureAwait") { newAwaitExpr = awaitExpr.ReplaceNode(awaitExpr.Expression, expr.Expression); } } if (awaitExpr.Parent.Kind() == SyntaxKind.ReturnStatement) { oldNode = awaitExpr; newNode = newAwaitExpr.Expression.WithAdditionalAnnotations(Simplifier.Annotation); } else { oldNode = awaitExpr.Parent; newNode = SyntaxFactory.ReturnStatement(newAwaitExpr.Expression).WithAdditionalAnnotations(Formatter.Annotation).WithTrailingTrivia(oldNode.GetTrailingTrivia()); } pairs.Add(new SyntaxReplacementPair(oldNode, newNode)); } newMethodDecl = newMethodDecl.ReplaceAll(pairs); // (4) Replace the old method with the new one. var root = await document.GetSyntaxRootAsync().ConfigureAwait(false); var newRoot = root.ReplaceNode(methodDecl, newMethodDecl); return document.WithSyntaxRoot(newRoot); }
private static void RegisterNewCodeFix(CodeFixContext context, SyntaxNode root, MethodDeclarationSyntax methodNode, SyntaxKind visibility, string description, Diagnostic diagnostic) { var publicModifier = methodNode.Modifiers.Where(_ => _.Kind() == SyntaxKind.PublicKeyword).First(); var visibilityNode = SyntaxFactory.Token(publicModifier.LeadingTrivia, visibility, publicModifier.TrailingTrivia); var modifiers = methodNode.Modifiers.Replace(publicModifier, visibilityNode); var newwMethodNode = methodNode.WithModifiers(modifiers); var newRoot = root.ReplaceNode(methodNode, newwMethodNode); context.RegisterCodeFix( CodeAction.Create(description, _ => Task.FromResult(context.Document.WithSyntaxRoot(newRoot)), description), diagnostic); }
private async Task<Document> ReplacePropertyModifierAsync(Document document, MethodDeclarationSyntax method, SyntaxKind methodModifier, CancellationToken cancellationToken) { var previousWhiteSpacesToken = SyntaxFactory.Token(method.GetLeadingTrivia(), SyntaxKind.StringLiteralToken, SyntaxTriviaList.Empty); var newProperty = method.WithModifiers(SyntaxTokenList.Create(previousWhiteSpacesToken) .Add(SyntaxFactory.Token(methodModifier)) .Add(_whitespaceToken)); if (method.Modifiers.Any(m => m.Kind() == SyntaxKind.VirtualKeyword)) { newProperty = newProperty.AddModifiers(SyntaxFactory.Token(SyntaxKind.VirtualKeyword), _whitespaceToken); } return await ReplacePropertyInDocumentAsync(document, method, newProperty, cancellationToken); }
/// <summary> /// Normalizes the <paramref name="declaration" />. /// </summary> public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax declaration) { _methodSymbol = declaration.GetMethodSymbol(SemanticModel); if (!_methodSymbol.ContainingType.IsComponent(SemanticModel) || !_methodSymbol.IsRequiredPort(SemanticModel)) return declaration; var body = CreateBindingCode(); var originalDeclaration = declaration; var index = declaration.Modifiers.IndexOf(SyntaxKind.ExternKeyword); var delegateFieldName = Syntax.LiteralExpression(GetBindingDelegateFieldName()); var infoFieldName = Syntax.LiteralExpression(GetBinderFieldName()); var defaultMethod = Syntax.LiteralExpression(GetUnboundPortAssignmentMethodName()); declaration = declaration.WithModifiers(declaration.Modifiers.RemoveAt(index)).WithSemicolonToken(default(SyntaxToken)); declaration = (MethodDeclarationSyntax)Syntax.AddAttribute<DebuggerHiddenAttribute>(declaration); declaration = (MethodDeclarationSyntax)Syntax.AddAttribute<BindingMetadataAttribute>(declaration, delegateFieldName, infoFieldName, defaultMethod); return declaration.WithBody(body).EnsureLineCount(originalDeclaration); }
public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node) { node = (MethodDeclarationSyntax)base.VisitMethodDeclaration(node); // only public methods not marked as virtual if (node.Modifiers.Any(SyntaxKind.PublicKeyword) && !node.Modifiers.Any(SyntaxKind.VirtualKeyword)) { var symbol = _compiler.GetSemanticModel(node.SyntaxTree).GetDeclaredSymbol(node); if (symbol.InheritsFrom<Controller>()) { Debug.WriteLine( "R4MVC - Marking controller method {0} as virtual from {1}", symbol.ToString(), symbol.ContainingType?.ToString()); node = node.WithModifiers(SyntaxKind.VirtualKeyword); } } return node; }
private MethodDeclarationSyntax OverrideMethod(MethodDeclarationSyntax method) { return method .WithModifiers(CSharp.TokenList(method .Modifiers .Where(modifier => modifier.Kind() != SyntaxKind.VirtualKeyword) .Union(new[] { CSharp.Token(SyntaxKind.OverrideKeyword) }) .ToArray())) .WithBody(CSharp.Block() .WithStatements(CSharp.List(new[] { contextCall.Get<StatementSyntax>(method .ParameterList .Parameters .First() .Type) }))); }
/// <summary> /// Normalizes the <paramref name="methodDeclaration" /> and adds the generated members. /// </summary> /// <param name="methodDeclaration">The method declaration that should be normalized.</param> private MethodDeclarationSyntax NormalizeExternMethod(MethodDeclarationSyntax methodDeclaration) { var originalDeclaration = methodDeclaration; var methodDelegate = CreateDelegate(methodDeclaration); var methodField = CreateField(methodDelegate); // Add the [Required] attribute if it is not already present if (!methodDeclaration.HasAttribute<RequiredAttribute>(SemanticModel)) { methodDeclaration = methodDeclaration.RemoveTrivia(); methodDeclaration = methodDeclaration.WithAttributeLists(methodDeclaration.AttributeLists.Add(_requiredAttribute.WithTrailingSpace())); } // Remove the 'extern' keyword from the method var externIndex = methodDeclaration.Modifiers.IndexOf(SyntaxKind.ExternKeyword); methodDeclaration = methodDeclaration.WithModifiers(methodDeclaration.Modifiers.RemoveAt(externIndex)); // Add the [DebuggerHidden] attribute if it is not already present if (!originalDeclaration.HasAttribute<DebuggerHiddenAttribute>(SemanticModel)) methodDeclaration = methodDeclaration.WithAttributeLists(methodDeclaration.AttributeLists.Add(_debuggerHiddenAttribute)); // Replace the method's body and ensure that we don't modify the line count of the containing type methodDeclaration = AddBackingFieldAttribute(methodDeclaration); methodDeclaration = ReplaceBodyWithDelegateInvocation(methodDeclaration); methodDeclaration = methodDeclaration.NormalizeWhitespace(); methodDeclaration = methodDeclaration.WithTrivia(originalDeclaration); ++_portCount; AddMembers(originalDeclaration.GetMethodSymbol(SemanticModel).ContainingType, methodField, methodDelegate); return methodDeclaration.EnsureLineCount(originalDeclaration); }