MethodDeclarationSyntax RewriteMethod(MethodDeclarationSyntax inMethodSyntax, SemanticModel semanticModel) { var inMethodSymbol = semanticModel.GetDeclaredSymbol(inMethodSyntax); //Log.LogMessage("Method {0}: {1}", inMethodInfo.Symbol.Name, inMethodInfo.Symbol.); var outMethodName = inMethodSyntax.Identifier.Text + "Async"; _log.Debug(" Rewriting method {0} to {1}", inMethodSymbol.Name, outMethodName); // Visit all method invocations inside the method, rewrite them to async if needed var rewriter = new MethodInvocationRewriter(_log, semanticModel, _excludedTypes); var outMethod = (MethodDeclarationSyntax)rewriter.Visit(inMethodSyntax); // Method signature outMethod = outMethod .WithIdentifier(SyntaxFactory.Identifier(outMethodName)) .WithAttributeLists(new SyntaxList<AttributeListSyntax>()) .WithModifiers(inMethodSyntax.Modifiers .Add(SyntaxFactory.Token(SyntaxKind.AsyncKeyword)) //.Remove(SyntaxFactory.Token(SyntaxKind.OverrideKeyword)) //.Remove(SyntaxFactory.Token(SyntaxKind.NewKeyword)) ); // Transform return type adding Task<> var returnType = inMethodSyntax.ReturnType.ToString(); outMethod = outMethod.WithReturnType(SyntaxFactory.ParseTypeName( returnType == "void" ? "Task" : $"Task<{returnType}>") ); // Remove the override and new attributes. Seems like the clean .Remove above doesn't work... for (var i = 0; i < outMethod.Modifiers.Count;) { var text = outMethod.Modifiers[i].Text; if (text == "override" || text == "new") { outMethod = outMethod.WithModifiers(outMethod.Modifiers.RemoveAt(i)); continue; } i++; } var attr = inMethodSymbol.GetAttributes().Single(a => a.AttributeClass.Name == "RewriteAsyncAttribute"); if (attr.ConstructorArguments.Length > 0 && (bool) attr.ConstructorArguments[0].Value) { outMethod = outMethod.AddModifiers(SyntaxFactory.Token(SyntaxKind.OverrideKeyword)); } return outMethod; }
MethodDeclarationSyntax RewriteMethod(MethodDeclarationSyntax inMethodSyntax, SemanticModel semanticModel, ITypeSymbol cancellationTokenSymbol) { var inMethodSymbol = semanticModel.GetDeclaredSymbol(inMethodSyntax); // ASYNC_TODO: Find all references //Log.LogMessage("Method {0}: {1}", inMethodInfo.Symbol.Name, inMethodInfo.Symbol.); var outMethodName = inMethodSyntax.Identifier.Text + "Async"; _log.Debug(" Rewriting method {0} to {1}", inMethodSymbol.Name, outMethodName); // Visit all method invocations inside the method, rewrite them to async if needed var rewriter = new MethodInvocationRewriter(_log, semanticModel, excludedTypesSet, cancellationTokenSymbol, GenerateConfigureAwait); var outMethod = (MethodDeclarationSyntax)rewriter.Visit(inMethodSyntax); // Method signature outMethod = outMethod .WithIdentifier(SyntaxFactory.Identifier(outMethodName)) .WithAttributeLists(new SyntaxList <AttributeListSyntax>()); if (inMethodSyntax.FirstAncestorOrSelf <TypeDeclarationSyntax>().Kind() == SyntaxKind.InterfaceDeclaration) { outMethod = outMethod .WithModifiers(inMethodSyntax.Modifiers); } else { outMethod = outMethod .WithModifiers(inMethodSyntax.Modifiers .Add(SyntaxFactory.Token(SyntaxKind.AsyncKeyword))); } //.Remove(SyntaxFactory.Token(SyntaxKind.OverrideKeyword)) //.Remove(SyntaxFactory.Token(SyntaxKind.NewKeyword)) // Insert the cancellation token into the parameter list at the right place outMethod = outMethod .WithParameterList(SyntaxFactory.ParameterList(inMethodSyntax.ParameterList.Parameters.Insert( inMethodSyntax.ParameterList.Parameters.TakeWhile(p => p.Default == null && !p.Modifiers.Any(m => m.IsKind(SyntaxKind.ParamsKeyword))).Count(), SyntaxFactory.Parameter( SyntaxFactory.List <AttributeListSyntax>(), SyntaxFactory.TokenList(), SyntaxFactory.ParseTypeName("CancellationToken"), SyntaxFactory.Identifier("cancellationToken"), null )))); // Transform return type adding Task<> var returnType = inMethodSyntax.ReturnType.ToString(); outMethod = outMethod.WithReturnType(SyntaxFactory.ParseTypeName( returnType == "void" ? "Task" : $"Task<{returnType}>") ); // Remove the override and new attributes. Seems like the clean .Remove above doesn't work... for (var i = 0; i < outMethod.Modifiers.Count;) { var text = outMethod.Modifiers[i].Text; if (text == "override" || text == "new") { outMethod = outMethod.WithModifiers(outMethod.Modifiers.RemoveAt(i)); continue; } i++; } var attr = inMethodSymbol.GetAttributes().Single(a => a.AttributeClass.Name == "RewriteAsyncAttribute"); if (attr.ConstructorArguments.Length > 0 && (bool)attr.ConstructorArguments[0].Value) { outMethod = outMethod.AddModifiers(SyntaxFactory.Token(SyntaxKind.OverrideKeyword)); } return(outMethod); }
MethodDeclarationSyntax RewriteMethodAsyncWithCancellationToken(MethodDeclarationSyntax inMethodSyntax, SemanticModel semanticModel) { var inMethodSymbol = semanticModel.GetDeclaredSymbol(inMethodSyntax); //Log.LogMessage("Method {0}: {1}", inMethodInfo.Symbol.Name, inMethodInfo.Symbol.); var outMethodName = inMethodSyntax.Identifier.Text + "Async"; _log.Info(" Rewriting method {0} to {1}", inMethodSymbol.Name, outMethodName); // Visit all method invocations inside the method, rewrite them to async if needed var rewriter = new MethodInvocationRewriter(_log, semanticModel, _excludedTypes, _cancellationTokenSymbol); var outMethod = (MethodDeclarationSyntax)rewriter.Visit(inMethodSyntax); // Method signature outMethod = outMethod .WithIdentifier(SyntaxFactory.Identifier(outMethodName)) .WithAttributeLists(new SyntaxList <AttributeListSyntax>()) .WithModifiers(inMethodSyntax.Modifiers .Add(SyntaxFactory.Token(SyntaxKind.AsyncKeyword)) //.Remove(SyntaxFactory.Token(SyntaxKind.OverrideKeyword)) //.Remove(SyntaxFactory.Token(SyntaxKind.NewKeyword)) ) // Insert the cancellation token into the parameter list at the right place .WithParameterList(SyntaxFactory.ParameterList(inMethodSyntax.ParameterList.Parameters.Insert( inMethodSyntax.ParameterList.Parameters.TakeWhile(p => p.Default == null && !p.Modifiers.Any(m => m.IsKind(SyntaxKind.ParamsKeyword))).Count(), SyntaxFactory.Parameter( SyntaxFactory.List <AttributeListSyntax>(), SyntaxFactory.TokenList(), SyntaxFactory.ParseTypeName("CancellationToken"), SyntaxFactory.Identifier("cancellationToken"), null )))); // Transform return type adding Task<> var returnType = inMethodSyntax.ReturnType.ToString(); outMethod = outMethod.WithReturnType(SyntaxFactory.ParseTypeName( returnType == "void" ? "Task" : $"Task<{returnType}>") ); var parentContainsAsyncMethod = GetAllMembers(inMethodSymbol.ReceiverType.BaseType).Any(c => c.Name == outMethodName); var parentContainsMethodWithRewriteAsync = GetAllMembers(inMethodSymbol.ReceiverType.BaseType) .Where(c => c.Name == inMethodSyntax.Identifier.Text) .Any(m => m.GetAttributes().Any(a => a.AttributeClass.Name.Contains("RewriteAsync"))); // Remove the override and new attributes. Seems like the clean .Remove above doesn't work... if (!(parentContainsAsyncMethod || parentContainsMethodWithRewriteAsync)) { for (var i = 0; i < outMethod.Modifiers.Count;) { var text = outMethod.Modifiers[i].Text; if (text == "override" || text == "new") { outMethod = outMethod.WithModifiers(outMethod.Modifiers.RemoveAt(i)); continue; } i++; } } var attr = inMethodSymbol.GetAttributes().Single(a => a.AttributeClass.Name.EndsWith("RewriteAsyncAttribute")); if (attr.ConstructorArguments.Length > 0 && (bool)attr.ConstructorArguments[0].Value) { for (var i = 0; i < outMethod.Modifiers.Count;) { var text = outMethod.Modifiers[i].Text; if (text == "public" || text == "private" || text == "protected") { outMethod = outMethod.WithModifiers(outMethod.Modifiers.RemoveAt(i)); continue; } i++; } outMethod = outMethod.WithModifiers(outMethod.Modifiers.Insert(0, SyntaxFactory.Token(SyntaxKind.PublicKeyword))); } return(outMethod); }