/// <summary> /// Recursively mutates a single SyntaxNode /// </summary> /// <param name="currentNode">The current root node</param> /// <returns>Mutated node</returns> public override SyntaxNode Mutate(SyntaxNode input) { var mutationContext = new MutationContext(this); var mutation = Mutate(input, mutationContext); return(mutation); }
private SyntaxNode MutateExpression(SyntaxNode currentNode, MutationContext context) { // Nothing to mutate, dig further var childCopy = currentNode.TrackNodes(currentNode.ChildNodes().ToList().Append(currentNode)); var mutated = false; foreach (var child in currentNode.ChildNodes().ToList()) { var mutatedChild = Mutate(child, context); if (child != mutatedChild) { var currentChild = childCopy.GetCurrentNode(child); childCopy = childCopy.ReplaceNode(currentChild, mutatedChild); mutated = true; } } if (currentNode is ExpressionSyntax expression && !expression.ContainsDeclarations()) { childCopy = MutateSubExpressionWithConditional(expression, (ExpressionSyntax)childCopy, context); mutated = true; } return(mutated ? childCopy : currentNode); }
private SyntaxNode MutateForStatement(ForStatementSyntax forStatement, MutationContext context) { // for needs special treatments for its incrementors StatementSyntax forWithMutantIncrementors = forStatement.TrackNodes(forStatement); foreach (var incrementor in forStatement.Incrementors) { forWithMutantIncrementors = MutateSubExpressionWithIfStatements(forStatement, forWithMutantIncrementors, incrementor, context); } var originalFor = forWithMutantIncrementors.GetCurrentNode(forStatement); // mutate condition, if any ForStatementSyntax mutatedFor; StatementSyntax statementPart; if (forStatement.Condition == null) { mutatedFor = forStatement; statementPart = forStatement.Statement; } else { mutatedFor = forStatement.TrackNodes(forStatement.Condition, forStatement.Statement); mutatedFor = mutatedFor.ReplaceNode(mutatedFor.GetCurrentNode(forStatement.Condition), Mutate(forStatement.Condition, context)); statementPart = mutatedFor.GetCurrentNode(forStatement.Statement); } // mutate the statement/block mutatedFor = mutatedFor.ReplaceNode(statementPart, Mutate(forStatement.Statement, context)); // and now we replace it return(forWithMutantIncrementors.ReplaceNode(originalFor, mutatedFor)); }
// recursive version public SyntaxNode Mutate(SyntaxNode currentNode, MutationContext context) { // don't mutate immutable nodes if (!SyntaxHelper.CanBeMutated(currentNode)) { return(currentNode); } // search for node specific handler var nodeHandler = _specificOrchestrator.FindHandler(currentNode); return(nodeHandler.Mutate(currentNode, context)); }
public IEnumerable <Mutant> GenerateMutationsForNode(SyntaxNode current, MutationContext context) { var mutations = new List <Mutant>(); foreach (var mutator in Mutators) { foreach (var mutation in mutator.Mutate(current, _options)) { var id = MutantCount; Logger.LogDebug("Mutant {0} created {1} -> {2} using {3}", id, mutation.OriginalNode, mutation.ReplacementNode, mutator.GetType()); var newMutant = new Mutant { Id = id, Mutation = mutation, ResultStatus = MutantStatus.NotRun, IsStaticValue = context.InStaticValue }; var duplicate = false; // check if we have a duplicate foreach (var mutant in Mutants) { if (mutant.Mutation.OriginalNode != mutation.OriginalNode || !SyntaxFactory.AreEquivalent(mutant.Mutation.ReplacementNode, newMutant.Mutation.ReplacementNode)) { continue; } Logger.LogDebug($"Mutant {id} discarded as it is a duplicate of {mutant.Id}"); duplicate = true; break; } if (duplicate) { continue; } Mutants.Add(newMutant); MutantCount++; mutations.Add(newMutant); } } return(mutations); }
/// <summary> /// Recursively mutates a single SyntaxNode /// </summary> /// <param name="currentNode">The current root node</param> /// <returns>Mutated node</returns> public override SyntaxNode Mutate(SyntaxNode input) { var mutationContext = new MutationContext(this); var mutation = Mutate(input, mutationContext); if (mutationContext.HasStatementLevelMutant && _options?.DevMode == true) { // some mutants where not injected for some reason, they should be reviewed to understand why. Logger.LogError($"Several mutants were not injected in the project : {mutationContext.BlockLevelControlledMutations.Count + mutationContext.StatementLevelControlledMutations.Count}"); } // mark remaining mutants as CompileError foreach (var mutant in mutationContext.StatementLevelControlledMutations.Union(mutationContext.BlockLevelControlledMutations)) { mutant.ResultStatus = MutantStatus.CompileError; mutant.ResultStatusReason = "Stryker was not able to inject mutation in code."; } return(mutation); }
private SyntaxNode MutateIfStatement(IfStatementSyntax ifStatement, MutationContext context) { var mutatedIf = ifStatement.Else != null ? ifStatement.TrackNodes(ifStatement.Condition, ifStatement.Statement, ifStatement.Else) : ifStatement.TrackNodes(ifStatement.Condition, ifStatement.Statement); var mutated = false; if (!ifStatement.Condition.ContainsDeclarations()) { var currentCondition = mutatedIf.GetCurrentNode(ifStatement.Condition); var mutatedCondition = Mutate(ifStatement.Condition, context); if (mutatedCondition != currentCondition) { mutatedIf = mutatedIf.ReplaceNode(currentCondition, mutatedCondition); mutated = true; } } if (ifStatement.Else != null) { var currentElse = mutatedIf.GetCurrentNode(ifStatement.Else); var mutatedElse = Mutate(ifStatement.Else, context); if (mutatedElse != currentElse) { mutatedIf = mutatedIf.ReplaceNode(currentElse, mutatedElse); mutated = true; } } var currentStatement = mutatedIf.GetCurrentNode(ifStatement.Statement); var mutatedStatement = Mutate(ifStatement.Statement, context); if (currentStatement != mutatedStatement) { mutatedIf = mutatedIf.ReplaceNode(currentStatement, mutatedStatement); mutated = true; } return(mutated ? mutatedIf : ifStatement); }
private SyntaxNode Mutate(SyntaxNode currentNode, MutationContext context) { // don't mutate immutable nodes if (!SyntaxHelper.CanBeMutated(currentNode)) { return(currentNode); } // identify static related structure switch (currentNode) { // static fields case FieldDeclarationSyntax fieldDeclaration when fieldDeclaration.Modifiers.Any(x => x.Kind() == SyntaxKind.StaticKeyword): context = new MutationContext { InStaticValue = true }; break; // static constructors case ConstructorDeclarationSyntax constructorDeclaration when constructorDeclaration.Modifiers.Any(x => x.Kind() == SyntaxKind.StaticKeyword): context = new MutationContext { InStaticValue = true }; if (MustInjectCoverageLogic) { return(MutateStaticConstructor(constructorDeclaration, context)); } break; // static properties case PropertyDeclarationSyntax propertyDeclaration when propertyDeclaration.Modifiers.Any(x => x.Kind() == SyntaxKind.StaticKeyword) && propertyDeclaration.AccessorList != null: context = new MutationContext { InStaticValue = true }; if (MustInjectCoverageLogic) { return(MutateStaticAccessor(propertyDeclaration, context)); } break; } switch (currentNode) { // apply statement specific strategies (where applicable) case ExpressionStatementSyntax tentativeAssignment when tentativeAssignment.Expression is AssignmentExpressionSyntax assign: return(MutateAssignment(tentativeAssignment, assign, context)); case ExpressionStatementSyntax tentativeAssignment when tentativeAssignment.Expression is PostfixUnaryExpressionSyntax || tentativeAssignment.Expression is PrefixUnaryExpressionSyntax: return(MutateUnaryStatement(tentativeAssignment, context)); case ExpressionStatementSyntax expressionStatement: // we must skip the expression statement part return(currentNode.ReplaceNode(expressionStatement.Expression, Mutate(expressionStatement.Expression, context))); case IfStatementSyntax ifStatement: return(MutateIfStatement(ifStatement, context)); case ForStatementSyntax forStatement: return(MutateForStatement(forStatement, context)); } var mutatedNode = MutateExpression(currentNode, context); return(AddReturnDefault(mutatedNode)); }
/// <summary> /// Mutates one single SyntaxNode using a mutator /// </summary> private IEnumerable <Mutant> ApplyMutator(SyntaxNode syntaxNode, IMutator mutator, MutationContext context) { var mutations = mutator.Mutate(syntaxNode); foreach (var mutation in mutations) { Logger.LogDebug("Mutant {0} created {1} -> {2} using {3}", MutantCount, mutation.OriginalNode, mutation.ReplacementNode, mutator.GetType()); yield return(new Mutant() { Id = MutantCount++, Mutation = mutation, ResultStatus = MutantStatus.NotRun, IsStaticValue = context.InStaticValue }); } }
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 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 IEnumerable <Mutant> FindMutants(SyntaxNode current, MutationContext context) { return(Mutators.SelectMany(mutator => ApplyMutator(current, mutator, context))); }
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 SyntaxNode MutateAssignment(ExpressionStatementSyntax tentativeAssignment, AssignmentExpressionSyntax assign, MutationContext context) { var expressionCopy = tentativeAssignment.TrackNodes(tentativeAssignment, assign, assign.Right); // mutate +=, *=, ... var result = MutateSubExpressionWithIfStatements(tentativeAssignment, expressionCopy, assign, context); // mutate the part right to the equal sign return(result.ReplaceNode(result.GetCurrentNode(assign.Right), Mutate(assign.Right, context))); }
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); }
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 MutateUnaryStatement(ExpressionStatementSyntax expressionStatement, MutationContext context) { var expressionCopy = expressionStatement.TrackNodes(expressionStatement, expressionStatement.Expression); return(MutateSubExpressionWithIfStatements(expressionStatement, expressionCopy, expressionStatement.Expression, context)); }
private MutationContext(MutationContext parent) { _ancestor = parent; _mainOrchestrator = parent._mainOrchestrator; InStaticValue = parent.InStaticValue; }