/// <summary> Apply mutations to an <see cref="InvocationExpressionSyntax"/> </summary> public override IEnumerable <Mutation> ApplyMutations(InvocationExpressionSyntax parent) { if (parent.Expression is MemberAccessExpressionSyntax node) { if (Enum.TryParse(node.Name.Identifier.ValueText, out LinqExpression expression) && KindsToMutate.TryGetValue(expression, out var replacementExpression)) { var replacement = SyntaxFactory.IdentifierName(replacementExpression.ToString()); var displayName = $"Linq method mutation ({node.Name.Identifier.ValueText}() to {replacement}())"; if (RequireArguments.Contains(replacementExpression) && parent.ArgumentList.Arguments.Count == 0) { yield break; } yield return(new Mutation { DisplayName = displayName, OriginalNode = parent, ReplacementNode = parent.ReplaceNode(node.Name, replacement), Type = Mutator.Linq }); } } }
/// <summary> Apply mutations to an <see cref="InvocationExpressionSyntax"/> </summary> public override IEnumerable <Mutation> ApplyMutations(ExpressionSyntax expr) { var original = expr; if (expr.Parent is ConditionalAccessExpressionSyntax) { yield break; } while (expr is ConditionalAccessExpressionSyntax conditional) { expr = conditional.WhenNotNull; } if (!(expr is InvocationExpressionSyntax invocationExpression)) { yield break; } string memberName; SyntaxNode toReplace; switch (invocationExpression.Expression) { case MemberAccessExpressionSyntax node: toReplace = node.Name; memberName = node.Name.Identifier.ValueText; break; case MemberBindingExpressionSyntax binding: toReplace = binding.Name; memberName = binding.Name.Identifier.ValueText; break; default: yield break; } if (!Enum.TryParse(memberName, out LinqExpression expression) || !KindsToMutate.TryGetValue(expression, out var replacementExpression)) { yield break; } var replacement = SyntaxFactory.IdentifierName(replacementExpression.ToString()); var displayName = $"Linq method mutation ({memberName}() to {replacement}())"; if (RequireArguments.Contains(replacementExpression) && invocationExpression.ArgumentList.Arguments.Count == 0) { yield break; } yield return(new Mutation { DisplayName = displayName, OriginalNode = original, ReplacementNode = original.ReplaceNode(toReplace, replacement), Type = Mutator.Linq }); }
private static IEnumerable <Mutation> FindMutableMethodCalls(ExpressionSyntax node, ExpressionSyntax original) { while (node is ConditionalAccessExpressionSyntax conditional) { foreach (var subMutants in FindMutableMethodCalls(conditional.Expression, original)) { yield return(subMutants); } node = conditional.WhenNotNull; } for (; ;) { ExpressionSyntax next = null; if (!(node is InvocationExpressionSyntax invocationExpression)) { yield break; } string memberName; SyntaxNode toReplace; switch (invocationExpression.Expression) { case MemberAccessExpressionSyntax memberAccessExpression: toReplace = memberAccessExpression.Name; memberName = memberAccessExpression.Name.Identifier.ValueText; next = memberAccessExpression.Expression; break; case MemberBindingExpressionSyntax memberBindingExpression: toReplace = memberBindingExpression.Name; memberName = memberBindingExpression.Name.Identifier.ValueText; break; default: yield break; } if (Enum.TryParse(memberName, out LinqExpression expression) && KindsToMutate.TryGetValue(expression, out var replacementExpression)) { if (RequireArguments.Contains(replacementExpression) && invocationExpression.ArgumentList.Arguments.Count == 0) { yield break; } yield return(new Mutation { DisplayName = $"Linq method mutation ({memberName}() to {SyntaxFactory.IdentifierName(replacementExpression.ToString())}())", OriginalNode = original, ReplacementNode = original.ReplaceNode(toReplace, SyntaxFactory.IdentifierName(replacementExpression.ToString())), Type = Mutator.Linq }); } node = next; } }