private static void WriteUsings(StringBuilder builder, TestGenerationContext context)
        {
            List <string> namespaces = new List <string>();

            namespaces.AddRange(MockFrameworkAbstraction.GetUsings(context.MockFramework));
            namespaces.Add(TestFrameworkAbstraction.GetUsing(context.TestFramework));
            namespaces.Add(context.ClassNamespace);

            foreach (InjectableType injectedType in context.InjectedTypes)
            {
                namespaces.AddRange(injectedType.TypeNamespaces);
            }

            namespaces = namespaces.Distinct().ToList();
            namespaces.Sort(StringComparer.Ordinal);

            for (int i = 0; i < namespaces.Count; i++)
            {
                builder.Append($"using {namespaces[i]};");

                if (i < namespaces.Count - 1)
                {
                    builder.AppendLine();
                }
            }
        }
        private string GenerateUnitTestContents(
            string unitTestNamespace,
            string className,
            string classNamespace,
            IList <InjectableProperty> properties,
            IList <InjectableType> constructorTypes)
        {
            TestFramework testFramework = Utilities.FindTestFramework(this.SelectedProject.Project);
            MockFramework mockFramework = Utilities.FindMockFramework(this.SelectedProject.Project);

            if (mockFramework == MockFramework.Unknown)
            {
                mockFramework = MockFramework.Moq;
            }

            string pascalCaseShortClassName = null;

            foreach (string suffix in ClassSuffixes)
            {
                if (className.EndsWith(suffix))
                {
                    pascalCaseShortClassName = suffix;
                    break;
                }
            }

            if (pascalCaseShortClassName == null)
            {
                pascalCaseShortClassName = className;
            }

            string classVariableName = pascalCaseShortClassName.Substring(0, 1).ToLowerInvariant() + pascalCaseShortClassName.Substring(1);

            List <InjectableType> injectedTypes = new List <InjectableType>(properties);

            injectedTypes.AddRange(constructorTypes);

            var mockFields = new List <MockField>();

            foreach (InjectableType injectedType in injectedTypes)
            {
                mockFields.Add(
                    new MockField(
                        mockFramework == MockFramework.SimpleStubs ? "stub" + injectedType.TypeBaseName : "mock" + injectedType.TypeBaseName,
                        mockFramework == MockFramework.SimpleStubs ? "Stub" + injectedType.TypeName : injectedType.TypeName));
            }

            List <string> namespaces = new List <string>();

            namespaces.AddRange(MockFrameworkAbstraction.GetUsings(mockFramework));
            namespaces.Add(TestFrameworkAbstraction.GetUsing(testFramework));
            namespaces.Add(classNamespace);
            namespaces.AddRange(injectedTypes.Select(t => t.TypeNamespace));
            namespaces = namespaces.Distinct().ToList();
            namespaces.Sort(StringComparer.Ordinal);

            StringBuilder builder = new StringBuilder();

            foreach (string ns in namespaces)
            {
                builder.AppendLine($"using {ns};");
            }

            builder.Append(
                Environment.NewLine +
                "namespace ");

            builder.Append(unitTestNamespace);
            builder.Append(
                Environment.NewLine +
                "{" + Environment.NewLine +
                $"    [{TestFrameworkAbstraction.GetTestClassAttribute(testFramework)}]" + Environment.NewLine +
                "    public class ");
            builder.Append(className);
            builder.Append(
                "Tests" + Environment.NewLine +
                "    {" + Environment.NewLine);
            if (mockFramework == MockFramework.Moq)
            {
                builder.Append("        private MockRepository mockRepository;" + Environment.NewLine);

                if (mockFields.Count > 0)
                {
                    builder.AppendLine();
                }
            }

            foreach (MockField field in mockFields)
            {
                if (mockFramework == MockFramework.SimpleStubs)
                {
                    builder.AppendLine($"        private {field.TypeName} {field.Name};");
                }
                else
                {
                    builder.AppendLine($"        private Mock<{field.TypeName}> {field.Name};");
                }
            }

            builder.Append(
                Environment.NewLine +
                $"        [{TestFrameworkAbstraction.GetTestInitializeAttribute(testFramework)}]" + Environment.NewLine +
                "        public void TestInitialize()" + Environment.NewLine +
                "        {" + Environment.NewLine);

            if (mockFramework == MockFramework.Moq)
            {
                builder.AppendLine("            this.mockRepository = new MockRepository(MockBehavior.Strict);");

                if (mockFields.Count > 0)
                {
                    builder.AppendLine();
                }
            }

            foreach (MockField field in mockFields)
            {
                string fieldCreationStatement;

                if (mockFramework == MockFramework.SimpleStubs)
                {
                    fieldCreationStatement = $"new {field.TypeName}()";
                }
                else
                {
                    fieldCreationStatement = $"this.mockRepository.Create<{field.TypeName}>()";
                }

                builder.AppendLine($"            this.{field.Name} = {fieldCreationStatement};");
            }

            builder.Append(
                "        }" + Environment.NewLine +
                Environment.NewLine);

            if (mockFramework == MockFramework.Moq)
            {
                builder.Append(
                    $"        [{TestFrameworkAbstraction.GetTestCleanupAttribute(testFramework)}]" + Environment.NewLine +
                    "        public void TestCleanup()" + Environment.NewLine +
                    "        {" + Environment.NewLine +
                    "            this.mockRepository.VerifyAll();" + Environment.NewLine +
                    "        }" + Environment.NewLine +
                    Environment.NewLine);
            }

            builder.Append(
                $"        [{TestFrameworkAbstraction.GetTestMethodAttribute(testFramework)}]" + Environment.NewLine +
                "        public void TestMethod1()" + Environment.NewLine +
                "        {" + Environment.NewLine +
                "            " + Environment.NewLine +
                "            " + Environment.NewLine);

            builder.AppendLine($"            {className} {classVariableName} = this.Create{pascalCaseShortClassName}();");
            builder.AppendLine("            ");
            builder.AppendLine("            ");
            builder.AppendLine("        }");
            builder.AppendLine();
            builder.AppendLine($"        private {className} Create{pascalCaseShortClassName}()");
            builder.AppendLine("        {");
            builder.Append($"            return new {className}");

            if (constructorTypes.Count > 0)
            {
                builder.AppendLine("(");

                for (int i = 0; i < constructorTypes.Count; i++)
                {
                    string mockReferenceStatement;
                    if (mockFramework == MockFramework.SimpleStubs)
                    {
                        mockReferenceStatement = $"this.stub{constructorTypes[i].TypeBaseName}";
                    }
                    else
                    {
                        mockReferenceStatement = $"this.mock{constructorTypes[i].TypeBaseName}.Object";
                    }

                    builder.Append($"                {mockReferenceStatement}");

                    if (i < constructorTypes.Count - 1)
                    {
                        builder.AppendLine(",");
                    }
                }

                builder.Append(")");
            }
            else if (properties.Count == 0)
            {
                builder.Append("()");
            }

            if (properties.Count > 0)
            {
                builder.AppendLine();
                builder.AppendLine("            {");

                foreach (InjectableProperty property in properties)
                {
                    string mockReferenceStatement;
                    if (mockFramework == MockFramework.SimpleStubs)
                    {
                        mockReferenceStatement = $"this.stub{property.TypeBaseName}";
                    }
                    else
                    {
                        mockReferenceStatement = $"this.mock{property.TypeBaseName}.Object";
                    }

                    builder.AppendLine($"                {property.Name} = {mockReferenceStatement},");
                }

                builder.Append(@"            }");
            }

            builder.AppendLine(";");
            builder.AppendLine("        }");
            builder.AppendLine("    }");
            builder.AppendLine("}");

            return(builder.ToString());
        }
        private string GenerateUnitTestContents(TestGenerationContext context)
        {
            TestFramework testFramework = context.TestFramework;
            MockFramework mockFramework = context.MockFramework;

            string pascalCaseShortClassName = null;

            foreach (string suffix in ClassSuffixes)
            {
                if (className.EndsWith(suffix))
                {
                    pascalCaseShortClassName = suffix;
                    break;
                }
            }

            if (pascalCaseShortClassName == null)
            {
                pascalCaseShortClassName = className;
            }

            string classVariableName = pascalCaseShortClassName.Substring(0, 1).ToLowerInvariant() + pascalCaseShortClassName.Substring(1);

            string fileTemplate = StaticBoilerplateSettings.GetTemplate(mockFramework, TemplateType.File);
            var    builder      = new StringBuilder();

            for (int i = 0; i < fileTemplate.Length; i++)
            {
                char c = fileTemplate[i];
                if (c == '$')
                {
                    int endIndex = -1;
                    for (int j = i + 1; j < fileTemplate.Length; j++)
                    {
                        if (fileTemplate[j] == '$')
                        {
                            endIndex = j;
                            break;
                        }
                    }

                    if (endIndex < 0)
                    {
                        // We couldn't find the end index for the replacement property name. Continue.
                        builder.Append(c);
                    }
                    else
                    {
                        // Calculate values on demand from switch statement. Some are preset values, some need a bit of calc like base name,
                        // some are dependent on the test framework (attributes), some need to pull down other templates and loop through mock fields
                        string propertyName = fileTemplate.Substring(i + 1, endIndex - i - 1);
                        switch (propertyName)
                        {
                        case "UsingStatements":
                            WriteUsings(builder, context);
                            break;

                        case "Namespace":
                            builder.Append(context.UnitTestNamespace);
                            break;

                        case "MockFieldDeclarations":
                            WriteMockFieldDeclarations(builder, context);
                            break;

                        case "MockFieldInitializations":
                            WriteMockFieldInitializations(builder, context);
                            break;

                        case "ExplicitConstructor":
                            WriteExplicitConstructor(builder, context, FindIndent(fileTemplate, i));
                            break;

                        case "ClassName":
                            builder.Append(context.ClassName);
                            break;

                        case "ClassNameShort":
                            builder.Append(GetShortClassName(context.ClassName));
                            break;

                        case "ClassNameShortLower":
                            builder.Append(GetShortClassNameLower(context.ClassName));
                            break;

                        case "TestClassAttribute":
                            builder.Append(TestFrameworkAbstraction.GetTestClassAttribute(testFramework));
                            break;

                        case "TestInitializeAttribute":
                            builder.Append(TestFrameworkAbstraction.GetTestInitializeAttribute(testFramework));
                            break;

                        case "TestCleanupAttribute":
                            builder.Append(TestFrameworkAbstraction.GetTestCleanupAttribute(testFramework));
                            break;

                        case "TestMethodAttribute":
                            builder.Append(TestFrameworkAbstraction.GetTestMethodAttribute(testFramework));
                            break;

                        default:
                            // We didn't recognize it, just pass through.
                            builder.Append($"${propertyName}$");
                            break;
                        }

                        i = endIndex;
                    }
                }
                else
                {
                    builder.Append(c);
                }
            }

            SyntaxTree tree          = CSharpSyntaxTree.ParseText(builder.ToString());
            SyntaxNode formattedNode = Formatter.Format(tree.GetRoot(), CreateUnitTestBoilerplateCommandPackage.VisualStudioWorkspace);

            return(formattedNode.ToString());
        }