Example #1
0
        public CSharp_FastCompiler()
        {
            DebugMode             = false;				        // set to true to see details about each AstCreation and Compilation stage
            FinishedCompilingCode = new ManualResetEvent(true);

            CompilerOptions       = new CSharp_FastCompiler_CompilerOptions ();
            ExecutionOptions      = new CSharp_FastCompiler_ExecutionOptions();
            CompilerArtifacts     = new CSharp_FastCompiler_CompilerArtifacts();
            Events                = new CSharp_FastCompiler_Events           ();
        }
        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 string ast_CSharp_CreateCompilableClass(this BlockStatement blockStatement, SnippetParser snippetParser, string codeSnippet)
        {
            if (blockStatement.isNull() || snippetParser.isNull() || codeSnippet.notValid())
                return null;

            var compilerOptions   = new CSharp_FastCompiler_CompilerOptions  ();
            var compilerArtifacts = new CSharp_FastCompiler_CompilerArtifacts();
            var executionOptions  = new CSharp_FastCompiler_ExecutionOptions ();
            var csharpCode        = blockStatement.ast_CSharp_CreateCompilableClass(snippetParser, codeSnippet,
                compilerOptions, compilerArtifacts, executionOptions);
            return csharpCode;
        }
        public static Ast_CSharp mapCodeO2References(this Ast_CSharp astCSharp, CSharp_FastCompiler_CompilerOptions compilerOptions)
        {
            compilerOptions.ExtraSourceCodeFilesToCompile = new List <string>();
            var compilationUnit = astCSharp.CompilationUnit;

            compilerOptions.ReferencedAssemblies   = new List <string>();               // this should be cleared in a more global location
            compilerOptions.Extra_Using_Statements = new List <string>();               // same here

            var filesToDownload = new List <string>();

            var currentUsingDeclarations = new List <string>();

            foreach (var usingDeclaration in astCSharp.AstDetails.UsingDeclarations)
            {
                currentUsingDeclarations.Add(usingDeclaration.Text);
            }

            compilerOptions.mapOptionsDefinedInsideComments(astCSharp.AstDetails.comments())
            .mapNuGetReferences()
            .Extra_Using_Statements.forEach(value => astCSharp.CompilationUnit.add_Using(value));

            //resolve location of ExtraSourceCodeFilesToCompile
            astCSharp.resolveFileLocationsOfExtraSourceCodeFilesToCompile(compilerOptions);

            CompileEngine.handleReferencedAssembliesInstallRequirements(astCSharp.AstDetails.CSharpCode);

            //use the same technique to download files that are needed for this script (for example *.zip files or other unmanaged/support files)
            CompileEngine.tryToResolveReferencesForCompilation(filesToDownload, compilerOptions.WorkOffline);


            if (compilerOptions.onlyAddReferencedAssemblies.isFalse())
            {
                foreach (var defaultRefAssembly in CompileEngine.DefaultReferencedAssemblies)
                {
                    if (compilerOptions.ReferencedAssemblies.Contains(defaultRefAssembly).isFalse())
                    {
                        compilerOptions.ReferencedAssemblies.add(defaultRefAssembly);
                    }
                }
                foreach (var usingStatement in CompileEngine.DefaultUsingStatements)
                {
                    if (false == currentUsingDeclarations.Contains(usingStatement))
                    {
                        compilationUnit.add_Using(usingStatement);
                    }
                }
            }

            //make sure the referenced assemblies are in the current execution directory
            CompileEngine.tryToResolveReferencesForCompilation(compilerOptions.ReferencedAssemblies, compilerOptions.WorkOffline);
            return(astCSharp);
        }
        public static string ast_CSharp_CreateCompilableClass(this BlockStatement blockStatement, SnippetParser snippetParser, string codeSnippet)
        {
            if (blockStatement.isNull() || snippetParser.isNull() || codeSnippet.notValid())
            {
                return(null);
            }

            var compilerOptions   = new CSharp_FastCompiler_CompilerOptions();
            var compilerArtifacts = new CSharp_FastCompiler_CompilerArtifacts();
            var executionOptions  = new CSharp_FastCompiler_ExecutionOptions();
            var csharpCode        = blockStatement.ast_CSharp_CreateCompilableClass(snippetParser, codeSnippet,
                                                                                    compilerOptions, compilerArtifacts, executionOptions);

            return(csharpCode);
        }
 public static CSharp_FastCompiler_CompilerOptions mapNuGetReferences(this CSharp_FastCompiler_CompilerOptions compilerOptions, API_NuGet nuGet)
 {
     foreach (var nugetReference  in compilerOptions.NuGet_References)
     {
         if (nuGet.does_Not_Have_Package(nugetReference))
         {
             nuGet.install(nugetReference);
         }
         var assemmbliesInsideNugetPackage = nuGet.path_Package(nugetReference).files(true, "*.exe", "*.dll");
         if (assemmbliesInsideNugetPackage.empty())
         {
             "[CSharp_FastCompiler_CompilerOptions][mapNuGetReferences] no assemblies found for Nuget package: {0}".error(nugetReference);
         }
         compilerOptions.ReferencedAssemblies.add(assemmbliesInsideNugetPackage);
     }
     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;
        }
        public void mapNuGetReferences()
        {
            var targetPackage = "FluentSharp.HtmlAgilityPack";
            var nuGet = new API_NuGet("_temp_Packages_Folder".temp_Dir());

            new API_NuGet().setup().NuGet_Exe.file_CopyToFolder(nuGet.Packages_Folder);         // do this so that the nuget.exe file is not downloaded every time this unit test runs
            nuGet.NuGet_Exe.assert_File_Exists();
            nuGet.path_Package(targetPackage).assert_Null();

            nuGet.path_Package(targetPackage);
            var compilerOptions = new CSharp_FastCompiler_CompilerOptions();
            compilerOptions.ReferencedAssemblies.assert_Not_Empty();
            compilerOptions.NuGet_References.add(targetPackage);

            compilerOptions.mapNuGetReferences(nuGet);

            nuGet.path_Package(targetPackage).assert_Not_Null();
            compilerOptions.ReferencedAssemblies.contains(targetPackage);
            Files.delete_Folder_Recursively(nuGet.Packages_Folder)
                 .assert_True();
        }
 public static CSharp_FastCompiler_CompilerOptions mapNuGetReferences(this CSharp_FastCompiler_CompilerOptions compilerOptions)
 {
     return(compilerOptions.mapNuGetReferences(new API_NuGet()));
 }
        public static Ast_CSharp resolveFileLocationsOfExtraSourceCodeFilesToCompile(this Ast_CSharp astCSharp, CSharp_FastCompiler_CompilerOptions compilerOptions)
        {
            if (compilerOptions.ExtraSourceCodeFilesToCompile.size() > 0)
            {
                // try to resolve local file references
                try
                {
                    if (compilerOptions.SourceCodeFile.isNull())           // in case this is not set  (note: this should not be done here, better to do it on the REPL code)
                    {
                        compilerOptions.SourceCodeFile = PublicDI.CurrentScript;
                    }
                    for (int i = 0; i < compilerOptions.ExtraSourceCodeFilesToCompile.size(); i++)
                    {
                        var fileToResolve = compilerOptions.ExtraSourceCodeFilesToCompile[i].trim();

                        var resolved = false;
                        // try using SourceCodeFile.directoryName()
                        if (fileToResolve.fileExists().isFalse())
                        {
                            if (compilerOptions.SourceCodeFile.valid() && compilerOptions.SourceCodeFile.isFile())
                            {
                                var resolvedFile = compilerOptions.SourceCodeFile.directoryName().pathCombine(fileToResolve);
                                if (resolvedFile.fileExists())
                                {
                                    compilerOptions.ExtraSourceCodeFilesToCompile[i] = resolvedFile;
                                    resolved = true;
                                }
                            }
                        }
                        // try using the localscripts folders
                        var localMapping = fileToResolve.local();
                        if (localMapping.valid())
                        {
                            compilerOptions.ExtraSourceCodeFilesToCompile[i] = localMapping;
                            resolved = true;
                        }

                        if (resolved.isFalse() && fileToResolve.fileExists().isFalse())
                        {
                            compilerOptions.ExtraSourceCodeFilesToCompile[i] = compilerOptions.ExtraSourceCodeFilesToCompile[i].fullPath();
                        }
                    }
                }
                catch (Exception ex)
                {
                    ex.log("in compileExtraSourceCodeReferencesAndUpdateReferencedAssemblies while resolving ExtraSourceCodeFilesToCompile");
                }
            }
            return(astCSharp);
        }
        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 Ast_CSharp resolveFileLocationsOfExtraSourceCodeFilesToCompile(this Ast_CSharp astCSharp , CSharp_FastCompiler_CompilerOptions compilerOptions)
        {
            if (compilerOptions.ExtraSourceCodeFilesToCompile.size() > 0)
            {
                // try to resolve local file references
                try
                {
                    if (compilerOptions.SourceCodeFile.isNull())           // in case this is not set  (note: this should not be done here, better to do it on the REPL code)
                        compilerOptions.SourceCodeFile = PublicDI.CurrentScript;
                    for (int i = 0; i < compilerOptions.ExtraSourceCodeFilesToCompile.size(); i++)
                    {
                        var fileToResolve = compilerOptions.ExtraSourceCodeFilesToCompile[i].trim();

                        var resolved = false;
                        // try using SourceCodeFile.directoryName()
                        if (fileToResolve.fileExists().isFalse())
                            if (compilerOptions.SourceCodeFile.valid() && compilerOptions.SourceCodeFile.isFile())
                            {
                                var resolvedFile = compilerOptions.SourceCodeFile.directoryName().pathCombine(fileToResolve);
                                if (resolvedFile.fileExists())
                                {
                                    compilerOptions.ExtraSourceCodeFilesToCompile[i] = resolvedFile;
                                    resolved = true;
                                }
                            }
                        // try using the localscripts folders
                        var localMapping = fileToResolve.local();
                        if (localMapping.valid())
                        {
                            compilerOptions.ExtraSourceCodeFilesToCompile[i] = localMapping;
                            resolved = true;
                        }

                        if (resolved.isFalse() && fileToResolve.fileExists().isFalse())
                            compilerOptions.ExtraSourceCodeFilesToCompile[i] = compilerOptions.ExtraSourceCodeFilesToCompile[i].fullPath();
                    }
                }
                catch (Exception ex)
                {
                    ex.log("in compileExtraSourceCodeReferencesAndUpdateReferencedAssemblies while resolving ExtraSourceCodeFilesToCompile");
                }
            }
            return astCSharp;
        }
        public static Ast_CSharp mapCodeO2References(this Ast_CSharp astCSharp, CSharp_FastCompiler_CompilerOptions compilerOptions)
        {
            compilerOptions.ExtraSourceCodeFilesToCompile = new List<string>();
            var compilationUnit = astCSharp.CompilationUnit;
            compilerOptions.ReferencedAssemblies = new List<string>();                  // this should be cleared in a more global location
            compilerOptions.Extra_Using_Statements = new List<string>();                // same here

            var filesToDownload = new List<string>();

            var currentUsingDeclarations = new List<string>();
            foreach(var usingDeclaration in astCSharp.AstDetails.UsingDeclarations)
                currentUsingDeclarations.Add(usingDeclaration.Text);

            compilerOptions.mapOptionsDefinedInsideComments(astCSharp.AstDetails.comments())
                           .mapNuGetReferences()
                           .Extra_Using_Statements.forEach (value => astCSharp.CompilationUnit.add_Using(value));

            //resolve location of ExtraSourceCodeFilesToCompile
            astCSharp.resolveFileLocationsOfExtraSourceCodeFilesToCompile(compilerOptions);

            CompileEngine.handleReferencedAssembliesInstallRequirements(astCSharp.AstDetails.CSharpCode);

            //use the same technique to download files that are needed for this script (for example *.zip files or other unmanaged/support files)
            CompileEngine.tryToResolveReferencesForCompilation(filesToDownload, compilerOptions.WorkOffline);

            if (compilerOptions.onlyAddReferencedAssemblies.isFalse())
            {
                foreach (var defaultRefAssembly in CompileEngine.DefaultReferencedAssemblies)
                    if (compilerOptions.ReferencedAssemblies.Contains(defaultRefAssembly).isFalse())
                        compilerOptions.ReferencedAssemblies.add(defaultRefAssembly);
                foreach (var usingStatement in CompileEngine.DefaultUsingStatements)
                    if (false == currentUsingDeclarations.Contains(usingStatement))
                        compilationUnit.add_Using(usingStatement);
            }

            //make sure the referenced assemblies are in the current execution directory
            CompileEngine.tryToResolveReferencesForCompilation(compilerOptions.ReferencedAssemblies, compilerOptions.WorkOffline);
            return astCSharp;
        }
        public void mapOptionsDefinedInsideComments()
        {
            var compilerOptions = new CSharp_FastCompiler_CompilerOptions();

            var comments = new List<string>();

            compilerOptions.mapOptionsDefinedInsideComments(comments)
                           .toXml().assert_Equal(new CSharp_FastCompiler_CompilerOptions().toXml(), "Empty comments should make no changes to compilerOptions");
            comments.add("This is a random content");

            compilerOptions.mapOptionsDefinedInsideComments(comments)
                           .toXml().assert_Equal(new CSharp_FastCompiler_CompilerOptions().toXml(), "Non relevant comments should make no changes to compilerOptions");

            //O2Tag_OnlyAddReferencedAssemblies
            compilerOptions.onlyAddReferencedAssemblies.assert_False();
            compilerOptions.mapOptionsDefinedInsideComments(comments.add("O2Tag_OnlyAddReferencedAssemblies"))
                           .onlyAddReferencedAssemblies.assert_True();

            //generateDebugSymbols
            compilerOptions.generateDebugSymbols.assert_False();
            compilerOptions.mapOptionsDefinedInsideComments(comments.add("generateDebugSymbols"))
                           .generateDebugSymbols.assert_True();

            //SetInvocationParametersToDynamic
            compilerOptions.ResolveInvocationParametersType.assert_True();
            compilerOptions.mapOptionsDefinedInsideComments(comments.add("SetInvocationParametersToDynamic"))
                           .ResolveInvocationParametersType.assert_False();

            //DontSetInvocationParametersToDynamic
            compilerOptions.ResolveInvocationParametersType.assert_False();
            compilerOptions.mapOptionsDefinedInsideComments(comments.add("DontSetInvocationParametersToDynamic"))
                           .ResolveInvocationParametersType.assert_True();

            //StaThread
            compilerOptions.ExecuteInStaThread.assert_False();
            compilerOptions.mapOptionsDefinedInsideComments(comments.add("StaThread"))
                           .ExecuteInStaThread.assert_True();

            //MtaThread
            compilerOptions.ExecuteInMtaThread.assert_False();
            compilerOptions.mapOptionsDefinedInsideComments(comments.add("MtaThread"))
                           .ExecuteInMtaThread.assert_True();

            //WorkOffline
            compilerOptions.WorkOffline.assert_False();
            compilerOptions.mapOptionsDefinedInsideComments(comments.add("WorkOffline"))
                           .WorkOffline.assert_True();

            //using
            compilerOptions.Extra_Using_Statements.assert_Empty();
            compilerOptions.mapOptionsDefinedInsideComments(comments.add("using ABC"))
                           .Extra_Using_Statements.assert_Not_Empty()
                                                  .first().assert_Is("ABC");
            //O2Ref
            compilerOptions.ReferencedAssemblies.assert_Not_Contains("ABC");
            compilerOptions.mapOptionsDefinedInsideComments(comments.add("O2Ref:ABC"))
                           .ReferencedAssemblies.assert_Contains("ABC");

            //O2Download
            compilerOptions.FilesToDownload.assert_Empty();
            compilerOptions.mapOptionsDefinedInsideComments(comments.add("O2Download:ABC"))
                           .FilesToDownload.assert_Not_Empty()
                                                  .first().assert_Is("ABC");

            //O2File
            compilerOptions.ExtraSourceCodeFilesToCompile.assert_Empty();
            compilerOptions.mapOptionsDefinedInsideComments(comments.add("O2File:ABC"))
                           .ExtraSourceCodeFilesToCompile.assert_Not_Empty()
                                                         .first().assert_Is("ABC");

            //O2Dir

            var tempDir = "_DirToInclude".temp_Dir();
            var file    = tempDir.folder_Create_File("tempFile.cs", "some code");
            compilerOptions.ExtraSourceCodeFilesToCompile.assert_Not_Contains(file);
            compilerOptions.mapOptionsDefinedInsideComments(comments.add("O2Dir:".append(tempDir)))
                           .ExtraSourceCodeFilesToCompile.assert_Contains(file);

            tempDir.assert_Folder_Deleted();

            //NuGet
            compilerOptions.NuGet_References.assert_Empty();
            compilerOptions.mapOptionsDefinedInsideComments(comments.add("NuGet:ABC"))
                           .NuGet_References.assert_Not_Empty()
                                            .first().assert_Is("ABC");
        }