public static string ast_CSharp_CreateCompilableClass(this BlockStatement blockStatement, SnippetParser snippetParser, string codeSnippet,
                                                              CSharp_FastCompiler_CompilerOptions compilerOptions,
                                                              CSharp_FastCompiler_CompilerArtifacts compilerArtifacts,
                                                              CSharp_FastCompiler_ExecutionOptions executionOptions)
        {
            if (blockStatement.isNull() || compilerOptions.isNull())
            {
                return(null);
            }

            var compilationUnit = compilerArtifacts.CompilationUnit = new CompilationUnit();

            compilationUnit.add_Type(compilerOptions.default_TypeName)
            .add_Method(compilerOptions.default_MethodName, executionOptions.InvocationParameters,
                        compilerOptions.ResolveInvocationParametersType, blockStatement);

            // remove comments from parsed code
            var astCSharp = compilerArtifacts.AstCSharp = new Ast_CSharp(compilerArtifacts.CompilationUnit, snippetParser.Specials);

            // add references included in the original source code file
            compilerArtifacts.AstCSharp.mapCodeO2References(compilerOptions);

            astCSharp.mapAstDetails();

            astCSharp.ExtraSpecials.Clear();
            var method     = compilationUnit.method(compilerOptions.default_MethodName);
            var returntype = method.returnType();
            var type       = compilationUnit.type(compilerOptions.default_TypeName);

            type.Children.Clear();
            var tempBlockStatement = new BlockStatement();

            tempBlockStatement.add_Variable("a", 0);
            method.Body = tempBlockStatement;
            var newMethod = type.add_Method(compilerOptions.default_MethodName, executionOptions.InvocationParameters,
                                            compilerOptions.ResolveInvocationParametersType, tempBlockStatement);

            newMethod.TypeReference = returntype;


            if (blockStatement.returnStatements().size() > 1)
            {
                astCSharp.methodDeclarations().first().remove_LastReturnStatement();
            }

            astCSharp.mapAstDetails();

            var codeToReplace = "Int32 a = 0;";
            var csharpCode    = astCSharp.AstDetails.CSharpCode
                                .replace("\t\t{0}".format(codeToReplace), codeToReplace) // remove tabs
                                .replace("Int32 a = 0;", codeSnippet);                   // put the actual code (this should be done via AST, but it was affectting code complete)

            return(csharpCode);
        }
        public static CSharp_FastCompiler_CompilerOptions mapOptionsDefinedInsideComments(this CSharp_FastCompiler_CompilerOptions compilerOptions, List <string> comments)
        {
            if (compilerOptions.isNull() || comments.empty())
            {
                return(compilerOptions);
            }

            foreach (var comment in comments)
            {
                switch (comment)
                {
                case "O2Tag_OnlyAddReferencedAssemblies": compilerOptions.onlyAddReferencedAssemblies = true; continue;

                case "generateDebugSymbols": compilerOptions.generateDebugSymbols = true; continue;

                case "SetInvocationParametersToDynamic": compilerOptions.ResolveInvocationParametersType = false; continue;

                case "DontSetInvocationParametersToDynamic": compilerOptions.ResolveInvocationParametersType = true; continue;

                case "StaThread": compilerOptions.ExecuteInStaThread = true; continue;

                case "MtaThread": compilerOptions.ExecuteInMtaThread = true; continue;

                case "WorkOffline":  compilerOptions.WorkOffline = true; continue;
                }
                if (comment.starts("using "))
                {
                    compilerOptions.Extra_Using_Statements.add(comment.subString_After("using "));
                }
                else
                {
                    switch (comment.split(":").first())
                    {
                    case "O2Ref": compilerOptions.ReferencedAssemblies.add(comment.subString_After("O2Ref:")); continue;

                    case "O2Download": compilerOptions.FilesToDownload.add(comment.subString_After("O2Download:")); continue;

                    case "O2File": compilerOptions.ExtraSourceCodeFilesToCompile.add(comment.subString_After("O2File:")); continue;

                    case "O2Dir": compilerOptions.ExtraSourceCodeFilesToCompile.add(comment.subString_After("O2Dir:").files("*.cs", true)); continue;

                    case "NuGet": compilerOptions.NuGet_References.add(comment.subString_After("NuGet:")); continue;
                    }
                }
            }
            return(compilerOptions);
        }
        public static string ast_CSharp_CreateCompilableClass(this BlockStatement blockStatement, SnippetParser snippetParser, string codeSnippet,
            CSharp_FastCompiler_CompilerOptions   compilerOptions,
            CSharp_FastCompiler_CompilerArtifacts compilerArtifacts,
            CSharp_FastCompiler_ExecutionOptions  executionOptions)
        {
            if (blockStatement.isNull() || compilerOptions.isNull())
                return null;

            var compilationUnit= compilerArtifacts.CompilationUnit = new CompilationUnit();

            compilationUnit.add_Type(compilerOptions.default_TypeName)
                .add_Method(compilerOptions.default_MethodName, executionOptions.InvocationParameters,
                    compilerOptions.ResolveInvocationParametersType, blockStatement);

            // remove comments from parsed code
            var astCSharp = compilerArtifacts.AstCSharp = new Ast_CSharp(compilerArtifacts.CompilationUnit, snippetParser.Specials);

            // add references included in the original source code file
            compilerArtifacts.AstCSharp.mapCodeO2References(compilerOptions);

            astCSharp.mapAstDetails();

            astCSharp.ExtraSpecials.Clear();
            var method     = compilationUnit.method(compilerOptions.default_MethodName);
            var returntype = method.returnType();
            var type       = compilationUnit.type(compilerOptions.default_TypeName);

            type.Children.Clear();
            var tempBlockStatement = new BlockStatement();
            tempBlockStatement.add_Variable("a", 0);
            method.Body = tempBlockStatement;
            var newMethod = type.add_Method(compilerOptions.default_MethodName, executionOptions.InvocationParameters,
                compilerOptions.ResolveInvocationParametersType, tempBlockStatement);
            newMethod.TypeReference = returntype;

            if(blockStatement.returnStatements().size() >1)
                astCSharp.methodDeclarations().first().remove_LastReturnStatement();

            astCSharp.mapAstDetails();

            var codeToReplace = "Int32 a = 0;";
            var csharpCode = astCSharp.AstDetails.CSharpCode
                .replace("\t\t{0}".format(codeToReplace), codeToReplace)    // remove tabs
                .replace("Int32 a = 0;", codeSnippet);                      // put the actual code (this should be done via AST, but it was affectting code complete)
            return csharpCode;
        }