/// <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); }