private SyntaxNode MutateStaticConstructor(ConstructorDeclarationSyntax constructorDeclaration, MutationContext context) { var trackedConstructor = constructorDeclaration.TrackNodes((SyntaxNode)constructorDeclaration.Body ?? constructorDeclaration.ExpressionBody); if (constructorDeclaration.ExpressionBody != null) { var bodyBlock = SyntaxFactory.Block(SyntaxFactory.ExpressionStatement(constructorDeclaration.ExpressionBody.Expression)); var markedBlock = MutantPlacer.PlaceStaticContextMarker((BlockSyntax)Mutate(bodyBlock, context)); trackedConstructor = trackedConstructor.Update( trackedConstructor.AttributeLists, trackedConstructor.Modifiers, trackedConstructor.Identifier, trackedConstructor.ParameterList, trackedConstructor.Initializer, markedBlock, null, SyntaxFactory.Token(SyntaxKind.None)); } else if (constructorDeclaration.Body != null) { var markedBlock = MutantPlacer.PlaceStaticContextMarker((BlockSyntax)Mutate(constructorDeclaration.Body, context)); trackedConstructor = trackedConstructor.ReplaceNode(trackedConstructor.GetCurrentNode(constructorDeclaration.Body), markedBlock); } return(trackedConstructor); }
private SyntaxNode MutateStaticConstructor(ConstructorDeclarationSyntax constructorDeclaration, MutationContext context) { var trackedConstructor = constructorDeclaration.TrackNodes(constructorDeclaration.Body); var mutatedBlock = (BlockSyntax)Mutate(constructorDeclaration.Body, context); var markedBlock = MutantPlacer.PlaceStaticContextMarker(mutatedBlock); return(trackedConstructor.ReplaceNode(trackedConstructor.Body, markedBlock)); }
private ExpressionSyntax MutateSubExpressionWithConditional(ExpressionSyntax originalNode, ExpressionSyntax currentNode, MutationContext context) { var expressionAst = currentNode; foreach (var mutant in FindMutants(originalNode, context)) { expressionAst = MutantPlacer.PlaceWithConditionalExpression(expressionAst, ApplyMutant(originalNode, mutant), mutant.Id); } return(expressionAst); }
private StatementSyntax MutateSubExpressionWithIfStatements(StatementSyntax originalNode, StatementSyntax nodeToReplace, SyntaxNode subExpression, MutationContext context) { var ast = nodeToReplace; // The mutations should be placed using an IfStatement foreach (var mutant in FindMutants(subExpression, context)) { var mutatedNode = ApplyMutant(originalNode, mutant); ast = MutantPlacer.PlaceWithIfStatement(ast, mutatedNode, mutant.Id); } return(ast); }
private SyntaxNode MutateWithConditionalExpressions(ExpressionSyntax currentNode) { var expressionAst = currentNode; foreach (var mutant in FindMutantsRecursive(currentNode)) { _mutants.Add(mutant); var mutatedNode = ApplyMutant(currentNode, mutant); expressionAst = MutantPlacer.PlaceWithConditionalExpression(expressionAst, mutatedNode, mutant.Id); } return(expressionAst); }
public static SyntaxNode RemoveMutant(SyntaxNode nodeToRemove) { // remove the mutated node using its MutantPlacer remove method and update the tree if (nodeToRemove is IfStatementSyntax ifStatement) { return(MutantPlacer.RemoveByIfStatement(ifStatement)); } else if (nodeToRemove is ParenthesizedExpressionSyntax parenthesizedExpression) { return(MutantPlacer.RemoveByConditionalExpression(parenthesizedExpression)); } // this is not one of our structure return(nodeToRemove); }
/// <summary> /// Recursively mutates a single SyntaxNode /// </summary> /// <param name="currentNode">The current root node</param> /// <returns>Mutated node</returns> public SyntaxNode Mutate(SyntaxNode currentNode) { if (GetExpressionSyntax(currentNode) is var expressionSyntax && expressionSyntax != null) { // The mutations should be placed using a ConditionalExpression ExpressionSyntax expressionAst = expressionSyntax; foreach (var mutant in FindMutants(expressionSyntax)) { _mutants.Add(mutant); ExpressionSyntax mutatedNode = ApplyMutant(expressionSyntax, mutant); expressionAst = MutantPlacer.PlaceWithConditionalExpression(expressionAst, mutatedNode, mutant.Id); } return(currentNode.ReplaceNode(expressionSyntax, expressionAst)); }
private SyntaxNode MutateWithConditionalExpressions(ExpressionSyntax currentNode) { var expressionAst = currentNode.TrackNodes(currentNode.ChildNodes().Append(currentNode)); foreach (var childNode in currentNode.ChildNodes()) { var mutatedChild = Mutate(childNode); if (mutatedChild != childNode) { expressionAst = expressionAst.ReplaceNode(expressionAst.GetCurrentNode(childNode), mutatedChild); } } foreach (var mutant in FindMutants(currentNode)) { var mutatedNode = ApplyMutant(currentNode, mutant); expressionAst = MutantPlacer.PlaceWithConditionalExpression(expressionAst, mutatedNode, mutant.Id); } return(expressionAst); }
private SyntaxNode MutateStaticAccessor(PropertyDeclarationSyntax accessorDeclaration, MutationContext context) { var trackedNode = accessorDeclaration.TrackNodes(accessorDeclaration.AccessorList.Accessors.Select(x => (SyntaxNode)x.Body ?? x.ExpressionBody).Where(x => x != null)); foreach (var accessor in accessorDeclaration.AccessorList.Accessors) { if (accessor.ExpressionBody != null) { var markedBlock = Mutate(accessor.ExpressionBody, context); trackedNode = trackedNode.ReplaceNode(trackedNode.GetCurrentNode(accessor.ExpressionBody), markedBlock); } else if (accessor.Body != null) { var markedBlock = MutantPlacer.PlaceStaticContextMarker((BlockSyntax)Mutate(accessor.Body, context)); trackedNode = trackedNode.ReplaceNode(trackedNode.GetCurrentNode(accessor.Body), markedBlock); } } return(trackedNode); }
/// <summary> /// Add return default to the end of the method to prevent "not all code paths return a value" error as a result of mutations /// </summary> private SyntaxNode AddReturnDefault(SyntaxNode currentNode) { // If it's not a method or the method has no body skip the node if (!(currentNode is MethodDeclarationSyntax methodNode) || methodNode.Body == null) { return(currentNode); } // If method return type is void skip the node if (methodNode.ReturnType is PredefinedTypeSyntax predefinedType && predefinedType.Keyword.IsKind(SyntaxKind.VoidKeyword)) { return(currentNode); } TypeSyntax returnType = methodNode.ReturnType; // the GenericNameSyntax node can be encapsulated by QualifiedNameSyntax nodes var genericReturn = returnType.DescendantNodesAndSelf().OfType <GenericNameSyntax>().FirstOrDefault(); if (methodNode.Modifiers.Any(x => x.IsKind(SyntaxKind.AsyncKeyword))) { if (genericReturn != null) { // if the method is async and returns a generic task, make the return default return the underlying type returnType = genericReturn.TypeArgumentList.Arguments.First(); } else { // if the method is async but returns a non-generic task, don't add the return default return(currentNode); } } var newBody = methodNode.Body.AddStatements(MutantPlacer.AnnotateHelper(SyntaxFactory.ReturnStatement(SyntaxFactory.DefaultExpression(returnType)))); currentNode = currentNode.ReplaceNode(methodNode.Body, newBody); return(currentNode); }
private ExpressionSyntax MutateSubExpressionWithConditional(ExpressionSyntax originalNode, ExpressionSyntax currentNode, MutationContext context) { return(FindMutants(originalNode, context).Aggregate(currentNode, (current, mutant) => MutantPlacer.PlaceWithConditionalExpression(current, ApplyMutant(originalNode, mutant), mutant.Id))); }
private SyntaxNode MutateExpressions(SyntaxNode currentNode) { if (currentNode is ExpressionStatementSyntax expressionStatement) { // The subExpression of a ExpressionStatement cannot be mutated directly var mutant = Mutate(expressionStatement.Expression); return(currentNode.ReplaceNode(expressionStatement.Expression, mutant)); } if (currentNode is InvocationExpressionSyntax invocationExpression && invocationExpression.ArgumentList.Arguments.Count == 0) { var mutant = FindMutants(invocationExpression).FirstOrDefault(); if (mutant != null) { _mutants.Add(mutant); return(MutantPlacer.PlaceWithConditionalExpression(invocationExpression, mutant.Mutation.ReplacementNode as ExpressionSyntax, mutant.Id)); } } var expressions = GetExpressionSyntax(currentNode).Where(x => x != null); if (expressions.Any()) { var currentNodeCopy = currentNode.TrackNodes(expressions); foreach (var expressionSyntax in expressions) { var currentExpressionSyntax = currentNodeCopy.GetCurrentNode(expressionSyntax); if (expressionSyntax is InvocationExpressionSyntax) { // chained invocations, we will recurse var mutant = Mutate(expressionSyntax); currentNodeCopy = currentNodeCopy.ReplaceNode(currentExpressionSyntax, mutant); continue; } SyntaxNode mutationCandidate = null; if (expressionSyntax is ParenthesizedLambdaExpressionSyntax lambda) { mutationCandidate = lambda.Body; } else if (expressionSyntax is MemberAccessExpressionSyntax memberAccess) { mutationCandidate = memberAccess.Expression; } else if (expressionSyntax is AnonymousFunctionExpressionSyntax anonymousFunction) { mutationCandidate = anonymousFunction.Body; } if (mutationCandidate != null) { // we can mutate a part of expression var subNodeCopy = expressionSyntax.TrackNodes(mutationCandidate); var sub = subNodeCopy.ReplaceNode(subNodeCopy.GetCurrentNode(mutationCandidate), Mutate(mutationCandidate)); currentNodeCopy = currentNodeCopy.ReplaceNode(currentExpressionSyntax, sub); } else { // attempts to mutate the expression as a whole currentNodeCopy = currentNodeCopy.ReplaceNode(currentExpressionSyntax, MutateWithConditionalExpressions(expressionSyntax)); } } return(currentNodeCopy); } return(null); }