Codewars C# code generator

For the past couple weeks I’ve been trying to sharpen my C# skills by using Codewars. Now, we all know that one of the best ways to learn a programing language is to dive right in and try to tackle some Codewars problems, but it’s also very good for deliberate practice.

In other blogs, I’ve stated the importance of continuously using the IDE that you use as your daily driver. It helps you to learn keyboard shortcuts, navigation and develop speed. You won’t catch me writing my solution in the Codewars editor unless it’s a simple 8Kyu that I can handle with a quick one-liner Linq query. That’s not to say there isn’t benefit in writing solutions without an IDE, but that’s a different blog altogether.

The main issue I come across when coding these problems in my own editor is the boilerplate involved, creating the class, naming, method building, response/argument types and inconsistency with other solutions. To combat this I created a handy code generator written in and for C# projects. The basic premise of the generator is to minimise the boilerplate I have to manually type, allowing me to jump straight into solving the problem without the faff.

  1. You simply select the difficulty — so it’ll be placed in the correct main folder
  2. Select the name, which will be converted to PascalCase for the class
  3. Select the method name
  4. Select the return types
  5. Select the arguments

This will create a class:

using System;

namespace CSharpCodeWars.Kyu6.ConvertToCamel;

public class ConvertToCamel
{
    public string Convert(List<string> arg1)
    {
         return "";
    }
}

And a test project:

using NUnit.Framework;
using FluentAssertions;

namespace CSharpCodeWars.Kyu6.ConvertToCamel;

public class ConvertToCamelTests
{
      private ConvertToCamel _sut;
      
      [SetUp]
      public void Setup()
      {
          _sut = new ConvertToCamel();
      }

      [Test]
      public void Test1()
      {
          
      }
}

Placing them in the same folder for speed. From there, it’s just a case of copying across any tests and you’re good to go.

The generator code is pretty simple. I’m finding the parent folder and then creating a new folder based on the parent, difficulty and the name of the Kata. Then I’m creating a new .cs file with the boiler-plate code plugged in.

var parent = Directory.GetParent(Directory.GetCurrentDirectory().Replace("\\CodeWarsCodeGen\\bin\\Debug", ""));

var newFolder = $"{parent}\\CSharpCodeWars\\Kyu{difficulty}\\{kataName}";

Console.WriteLine($"new folder {newFolder}");
Directory.CreateDirectory(newFolder);

var filePath = $"{newFolder}\\{kataName}.cs";
using (StreamWriter writer = new StreamWriter(filePath))
{
    writer.WriteLine("using System;");
    writer.WriteLine("");
    writer.WriteLine($"namespace CSharpCodeWars.Kyu{difficulty}.{kataName};");
    writer.WriteLine("");
    writer.WriteLine($"public class {kataName}");
    writer.WriteLine("{");
    writer.WriteLine($"    public {returnType} {methodName}({GetArgumentValue()})");
    writer.WriteLine("    {");
    writer.WriteLine(GetReturnValue());
    writer.WriteLine("    }");
    writer.WriteLine("}");
}

The return value I’m defaulting to is a funny one, it’s an ever-growing list. At the time you’re reading this blog I suspect this would have grown — and neatened up if future me isn’t so lazy:

string GetReturnValue()
{
    var output = "";

    if (returnType == "string")
        output += "\"\"";
    else if (returnType is "int" or "long")
        output += "0";
    else if (returnType == "double")
        output += "0.0";
    else if (returnType == "bool")
        output += "true";
    else if (returnType.StartsWith("IEnumerable"))
    {
        var type = returnType[(returnType.IndexOf("<") + 1)..^1];
        output += $"Enumerable.Empty<{type}>()";
    }
    else if (returnType.EndsWith("[]"))
    {
        var type = returnType.Split("[");
        output += $"Array.Empty<{type[0]}>()";
    }

    return $"         return {output};";
}

This little code generator has come in really handy for me over the last week so maybe some of you could benefit from it too. If you want to give it a go, I’d recommend cloning the project and then deleting the folders with my solutions in them, if there seems to be demand for it I’ll shift it into its own repo.

And that’s pretty much all there is to it, if you liked this blog then please sign up for my newsletter and join an awesome community!

Leave a Reply