using System;
using System.Collections.Generic;
using CTA.Rules.Actions.ActionHelpers;
using CTA.Rules.Config;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Editing;
namespace CTA.Rules.Actions.Csharp
{
///
/// List of actions that can run on Method Declarations
///
public class MethodDeclarationActions
{
public Func GetAddCommentAction(string comment, string dontUseCTAPrefix = null)
{
MethodDeclarationSyntax AddComment(SyntaxGenerator syntaxGenerator, MethodDeclarationSyntax node)
{
return (MethodDeclarationSyntax)CommentHelper.AddCSharpComment(node, comment, dontUseCTAPrefix);
}
return AddComment;
}
public Func GetAppendExpressionAction(string expression)
{
// TODO: This will add an expression at the bottom of a method body, in the future we should add granularity for where to add the expression within a method body
Func AppendExpression = (SyntaxGenerator syntaxGenerator, MethodDeclarationSyntax node) =>
{
StatementSyntax statementExpression = SyntaxFactory.ParseStatement(expression).NormalizeWhitespace();
if(!statementExpression.FullSpan.IsEmpty)
{
BlockSyntax nodeBody = node.Body;
nodeBody = nodeBody.AddStatements(statementExpression);
node = node.WithBody(nodeBody);
}
return node;
};
return AppendExpression;
}
public Func GetChangeMethodNameAction(string newMethodName)
{
MethodDeclarationSyntax ChangeMethodName(SyntaxGenerator syntaxGenerator, MethodDeclarationSyntax node)
{
var newMethodNode = node;
newMethodNode = newMethodNode.WithIdentifier(SyntaxFactory.Identifier(newMethodName));
return newMethodNode;
}
return ChangeMethodName;
}
public Func GetChangeMethodToReturnTaskTypeAction(string newMethodName)
{
MethodDeclarationSyntax ChangeMethodToReturnTaskType(SyntaxGenerator syntaxGenerator, MethodDeclarationSyntax node)
{
TypeSyntax asyncReturnType;
if (node.ReturnType.ToFullString().Trim().Equals("void", StringComparison.OrdinalIgnoreCase))
{
asyncReturnType = SyntaxFactory.IdentifierName("Task").WithTrailingTrivia(SyntaxFactory.Space);
}
else
{
var currentTrivia = node.ReturnType.GetTrailingTrivia();
asyncReturnType = SyntaxFactory.GenericName(SyntaxFactory.Identifier("Task")).WithTypeArgumentList(SyntaxFactory.TypeArgumentList(SyntaxFactory.SingletonSeparatedList(node.ReturnType.WithoutTrailingTrivia()))).WithTrailingTrivia(currentTrivia);
}
var newMethodNode = node.WithReturnType(asyncReturnType);
return newMethodNode;
}
return ChangeMethodToReturnTaskType;
}
public Func GetRemoveMethodParametersAction()
{
MethodDeclarationSyntax RemoveMethodParametersAction(SyntaxGenerator syntaxGenerator, MethodDeclarationSyntax node)
{
List parameters = new List();
var newMethodNode = node.WithParameterList(SyntaxFactory.ParameterList(SyntaxFactory.SeparatedList(parameters)).NormalizeWhitespace());
return newMethodNode;
}
return RemoveMethodParametersAction;
}
public Func GetAddParametersToMethodAction(string types, string identifiers)
{
MethodDeclarationSyntax AddParametersToMethodAction(SyntaxGenerator syntaxGenerator, MethodDeclarationSyntax node)
{
var newMethodNode = node;
if (!string.IsNullOrWhiteSpace(identifiers) && !string.IsNullOrWhiteSpace(types))
{
var identifiersArray = identifiers.Split(',', StringSplitOptions.RemoveEmptyEntries);
var typesArray = types.Split(',', StringSplitOptions.RemoveEmptyEntries);
if (identifiersArray.Length == typesArray.Length)
{
List parameters = new List();
for (int i = 0; i < identifiersArray.Length; i++)
{
parameters.Add(SyntaxFactory.Parameter(SyntaxFactory.Identifier(identifiersArray[i])).WithType(SyntaxFactory.ParseTypeName(typesArray[i])));
}
newMethodNode = node.AddParameterListParameters(parameters.ToArray());
}
};
return newMethodNode;
}
return AddParametersToMethodAction;
}
public Func GetCommentMethodAction(string comment = null, string dontUseCTAPrefix = null)
{
MethodDeclarationSyntax CommentMethodAction(SyntaxGenerator syntaxGenerator, MethodDeclarationSyntax node)
{
var startComment = SyntaxFactory.SyntaxTrivia(SyntaxKind.MultiLineCommentTrivia, "/*");
var endComment = SyntaxFactory.SyntaxTrivia(SyntaxKind.MultiLineCommentTrivia, "*/");
var newMethodNode = node.WithLeadingTrivia(new SyntaxTriviaList(startComment)).WithTrailingTrivia(new SyntaxTriviaList(endComment));
node = node.ReplaceNode(node, newMethodNode);
if (!string.IsNullOrWhiteSpace(comment))
{
var addCommentsToMethodFunc = GetAddCommentAction(comment, dontUseCTAPrefix);
return addCommentsToMethodFunc(syntaxGenerator, node);
}
return node;
}
return CommentMethodAction;
}
public Func GetAddExpressionToMethodAction(string expression)
{
MethodDeclarationSyntax AddExpressionToMethodAction(SyntaxGenerator syntaxGenerator, MethodDeclarationSyntax node)
{
var newMethodNode = node;
StatementSyntax parsedExpression = SyntaxFactory.ParseStatement(expression).NormalizeWhitespace();
if (!parsedExpression.FullSpan.IsEmpty)
{
newMethodNode = node.AddBodyStatements(new StatementSyntax[] { parsedExpression });
}
return newMethodNode;
}
return AddExpressionToMethodAction;
}
}
}