Ejemplo n.º 1
0
        public static List <string> GetPreprocessorSymbols(CompilerOptions flags)
        {
            var preprocessorSymbols = new List <string>();

            if (flags.HasFlag(CompilerOptions.UseDebug))
            {
                preprocessorSymbols.Add("DEBUG");
            }
            if (flags.HasFlag(CompilerOptions.Optimize))
            {
                preprocessorSymbols.Add("OPT");
            }
            if (flags.HasFlag(CompilerOptions.UseRoslyn))
            {
                preprocessorSymbols.Add("ROSLYN");
                preprocessorSymbols.Add("CS60");
                preprocessorSymbols.Add("CS70");
                preprocessorSymbols.Add("CS71");
                preprocessorSymbols.Add("CS72");
                preprocessorSymbols.Add("CS73");
                preprocessorSymbols.Add("VB11");
                preprocessorSymbols.Add("VB14");
                preprocessorSymbols.Add("VB15");
            }
            else if (flags.HasFlag(CompilerOptions.UseMcs))
            {
                preprocessorSymbols.Add("MCS");
            }
            else
            {
                preprocessorSymbols.Add("LEGACY_CSC");
                preprocessorSymbols.Add("LEGACY_VBC");
            }
            return(preprocessorSymbols);
        }
Ejemplo n.º 2
0
 public void CheckedUnchecked([ValueSource("defaultOptions")] CompilerOptions cscOptions)
 {
     if (cscOptions.HasFlag(CompilerOptions.UseRoslyn) && cscOptions.HasFlag(CompilerOptions.Optimize))
     {
         Assert.Ignore("Roslyn opt replaces locals with stack slots, resulting in S_* variable names.");
     }
     Run(cscOptions: cscOptions);
 }
Ejemplo n.º 3
0
        public async Task StringInterpolation([ValueSource(nameof(roslynOnlyWithNet40Options))] CompilerOptions cscOptions)
        {
            if (!cscOptions.HasFlag(CompilerOptions.TargetNet40) && cscOptions.HasFlag(CompilerOptions.UseRoslynLatest))
            {
                Assert.Ignore("DefaultInterpolatedStringHandler is not yet supported!");
                return;
            }

            await Run(cscOptions : cscOptions);
        }
Ejemplo n.º 4
0
 public ExpressionClosureResolver(LambdaExpression lambda, ModuleBuilder module, bool dynamic, CompilerOptions options)
 {
     lambda = (LambdaExpression) new LambdaPreparer().Visit(new RuntimeVariablesInliner().Visit(lambda));
     if (!dynamic)
     {
         lambda = (LambdaExpression) new ExpressionPrivateMembersAccessor().Visit(new ExpressionAnonymousTypeReplacer(module).Visit(lambda));
     }
     constantsBuilder = options.HasFlag(CompilerOptions.CreateDynamicClosure)
                            ? new DynamicClosureBuilder(module)
                            : (IClosureBuilder) new StaticClosureBuilder();
     closureBuilder = options.HasFlag(CompilerOptions.CreateDynamicClosure)
                          ? new DynamicClosureBuilder(module)
                          : (IClosureBuilder) new StaticClosureBuilder();
     parsedLambda = new ExpressionClosureBuilder(lambda, closureBuilder, constantsBuilder).Build(dynamic);
 }
Ejemplo n.º 5
0
        void Run([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None, CompilerOptions cscOptions = CompilerOptions.None, DecompilerSettings decompilerSettings = null)
        {
            var ilFile = Path.Combine(TestCasePath, testName) + Tester.GetSuffix(cscOptions) + ".il";
            var csFile = Path.Combine(TestCasePath, testName + ".cs");

            if (!File.Exists(ilFile))
            {
                // re-create .il file if necessary
                CompilerResults output = null;
                try {
                    string outputFile = Path.ChangeExtension(ilFile,
                                                             cscOptions.HasFlag(CompilerOptions.Library) ? ".dll" : ".exe");
                    output = Tester.CompileCSharp(csFile, cscOptions, outputFile);
                    Tester.Disassemble(output.PathToAssembly, ilFile, asmOptions);
                } finally {
                    if (output != null)
                    {
                        output.TempFiles.Delete();
                    }
                }
            }

            var executable = Tester.AssembleIL(ilFile, asmOptions);
            var decompiled = Tester.DecompileCSharp(executable, decompilerSettings ?? Tester.GetSettings(cscOptions));

            CodeAssert.FilesAreEqual(csFile, decompiled, Tester.GetPreprocessorSymbols(cscOptions).ToArray());
        }
Ejemplo n.º 6
0
        void Run([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None, CompilerOptions cscOptions = CompilerOptions.None, DecompilerSettings decompilerSettings = null)
        {
            var csFile  = Path.Combine(TestCasePath, testName + ".cs");
            var exeFile = Path.Combine(TestCasePath, testName) + Tester.GetSuffix(cscOptions) + ".exe";

            if (cscOptions.HasFlag(CompilerOptions.Library))
            {
                exeFile = Path.ChangeExtension(exeFile, ".dll");
            }

            // 1. Compile
            CompilerResults output = null;

            try {
                output = Tester.CompileCSharp(csFile, cscOptions, exeFile);
            } finally {
                if (output != null)
                {
                    output.TempFiles.Delete();
                }
            }

            // 2. Decompile
            var decompiled = Tester.DecompileCSharp(exeFile, decompilerSettings ?? Tester.GetSettings(cscOptions));

            // 3. Compile
            CodeAssert.FilesAreEqual(csFile, decompiled, Tester.GetPreprocessorSymbols(cscOptions).ToArray());
        }
Ejemplo n.º 7
0
 internal static DecompilerSettings GetSettings(CompilerOptions cscOptions)
 {
     if ((cscOptions & CompilerOptions.UseRoslynMask) != 0)
     {
         var langVersion = (cscOptions & CompilerOptions.UseRoslynMask) switch {
             CompilerOptions.UseRoslyn1_3_2 => CSharp.LanguageVersion.CSharp6,
             CompilerOptions.UseRoslyn2_10_0 => CSharp.LanguageVersion.CSharp7_3,
             CompilerOptions.UseRoslyn3_11_0 => CSharp.LanguageVersion.CSharp9_0,
             _ => cscOptions.HasFlag(CompilerOptions.Preview) ? CSharp.LanguageVersion.Latest : CSharp.LanguageVersion.CSharp10_0,
         };
         return(new DecompilerSettings(langVersion)
         {
             // Never use file-scoped namespaces
             FileScopedNamespaces = false
         });
     }
     else
     {
         var settings = new DecompilerSettings(CSharp.LanguageVersion.CSharp5);
         if ((cscOptions & CompilerOptions.UseMcsMask) != 0)
         {
             // we don't recompile with mcs but with roslyn, so we can use ref locals
             settings.UseRefLocalsForAccurateOrderOfEvaluation = true;
         }
         return(settings);
     }
 }
Ejemplo n.º 8
0
        void Run([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None, CompilerOptions cscOptions = CompilerOptions.None)
        {
            var ilFile = Path.Combine(TestCasePath, testName) + Tester.GetSuffix(cscOptions) + ".il";
            var csFile = Path.Combine(TestCasePath, testName + ".cs");

            if (!File.Exists(ilFile))
            {
                // re-create .il file if necessary
                CompilerResults output = null;
                try {
                    output = Tester.CompileCSharp(csFile, cscOptions | CompilerOptions.Library);
                    Tester.Disassemble(output.PathToAssembly, ilFile, asmOptions);
                } finally {
                    if (output != null)
                    {
                        output.TempFiles.Delete();
                    }
                }
            }

            var executable = Tester.AssembleIL(ilFile, asmOptions | AssemblerOptions.Library);
            var decompiled = Tester.DecompileCSharp(executable);

            CodeAssert.FilesAreEqual(csFile, decompiled, cscOptions.HasFlag(CompilerOptions.UseRoslyn) ? null : new[] { "LEGACY_CSC" });
        }
Ejemplo n.º 9
0
 public async Task IndexRangeTest([ValueSource(nameof(roslyn3OrNewerOptions))] CompilerOptions cscOptions)
 {
     if (cscOptions.HasFlag(CompilerOptions.UseRoslynLatest))
     {
         Assert.Ignore("See https://github.com/icsharpcode/ILSpy/issues/2540");
     }
     await RunForLibrary(cscOptions : cscOptions);
 }
Ejemplo n.º 10
0
 public async Task MiniJSON([ValueSource(nameof(defaultOptions))] CompilerOptions options)
 {
     if (options.HasFlag(CompilerOptions.UseMcs2_6_4))
     {
         Assert.Ignore("Decompiler bug with mono!");
     }
     await RunCS(options : options);
 }
Ejemplo n.º 11
0
 public void YieldReturn([ValueSource(nameof(defaultOptions))] CompilerOptions options)
 {
     if (options.HasFlag(CompilerOptions.UseMcs))
     {
         Assert.Ignore("Decompiler bug with mono!");
     }
     RunCS(options: options);
 }
Ejemplo n.º 12
0
 public void UnsafeCode([ValueSource(nameof(defaultOptions))] CompilerOptions options)
 {
     if (options.HasFlag(CompilerOptions.UseMcs2_6_4))
     {
         Assert.Ignore("Decompiler bug with mono!");
     }
     RunCS(options: options);
 }
Ejemplo n.º 13
0
 public void IndexRangeTest([ValueSource(nameof(dotnetCoreOnlyOptions))] CompilerOptions cscOptions)
 {
     if (cscOptions.HasFlag(CompilerOptions.UseRoslynLatest))
     {
         Assert.Ignore("See https://github.com/icsharpcode/ILSpy/issues/2540");
     }
     RunForLibrary(cscOptions: cscOptions);
 }
Ejemplo n.º 14
0
 public void MiniJSON([ValueSource("defaultOptions")] CompilerOptions options)
 {
     if (options.HasFlag(CompilerOptions.UseMcs))
     {
         Assert.Ignore("Decompiler bug with mono!");
     }
     RunCS(options: options);
 }
Ejemplo n.º 15
0
 internal static DecompilerSettings GetSettings(CompilerOptions cscOptions)
 {
     if (cscOptions.HasFlag(CompilerOptions.UseRoslyn))
     {
         if (cscOptions.HasFlag(CompilerOptions.Preview))
         {
             return(new DecompilerSettings(CSharp.LanguageVersion.Latest));
         }
         else
         {
             return(new DecompilerSettings(CSharp.LanguageVersion.CSharp8_0));
         }
     }
     else
     {
         return(new DecompilerSettings(CSharp.LanguageVersion.CSharp5));
     }
 }
Ejemplo n.º 16
0
 public async Task CustomAttributes([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
 {
     if (cscOptions.HasFlag(CompilerOptions.UseRoslynLatest))
     {
         // Test C# 11 generic attributes
         cscOptions |= CompilerOptions.Preview;
     }
     await RunForLibrary(cscOptions : cscOptions);
 }
Ejemplo n.º 17
0
        public static List <string> GetPreprocessorSymbols(CompilerOptions flags)
        {
            var preprocessorSymbols = new List <string>();

            if (flags.HasFlag(CompilerOptions.UseDebug))
            {
                preprocessorSymbols.Add("DEBUG");
            }
            if (flags.HasFlag(CompilerOptions.Optimize))
            {
                preprocessorSymbols.Add("OPT");
            }
            if (flags.HasFlag(CompilerOptions.ReferenceCore))
            {
                preprocessorSymbols.Add("NETCORE");
            }
            if ((flags & CompilerOptions.UseRoslynMask) != 0)
            {
                preprocessorSymbols.Add("ROSLYN");
                preprocessorSymbols.Add("CS60");
                preprocessorSymbols.Add("VB11");
                preprocessorSymbols.Add("VB14");
                if (flags.HasFlag(CompilerOptions.UseRoslyn2_10_0) ||
                    flags.HasFlag(CompilerOptions.UseRoslynLatest))
                {
                    preprocessorSymbols.Add("ROSLYN2");
                    preprocessorSymbols.Add("CS70");
                    preprocessorSymbols.Add("CS71");
                    preprocessorSymbols.Add("CS72");
                    preprocessorSymbols.Add("VB15");
                }
                if (flags.HasFlag(CompilerOptions.UseRoslynLatest))
                {
                    preprocessorSymbols.Add("ROSLYN3");
                    preprocessorSymbols.Add("CS73");
                    preprocessorSymbols.Add("CS80");
                    preprocessorSymbols.Add("VB16");
                    if (flags.HasFlag(CompilerOptions.Preview))
                    {
                        preprocessorSymbols.Add("CS90");
                    }
                }
            }
            else if (flags.HasFlag(CompilerOptions.UseMcs))
            {
                preprocessorSymbols.Add("MCS");
            }
            else
            {
                preprocessorSymbols.Add("LEGACY_CSC");
                preprocessorSymbols.Add("LEGACY_VBC");
            }
            return(preprocessorSymbols);
        }
Ejemplo n.º 18
0
        public static CompiledFunction Compile(
            ControlFlowGraph cfg,
            OperandType[]    argTypes,
            OperandType retType,
            CompilerOptions options)
        {
            CompilerContext cctx = new(cfg, argTypes, retType, options);

            if (options.HasFlag(CompilerOptions.Optimize))
            {
                Logger.StartPass(PassName.TailMerge);

                TailMerge.RunPass(cctx);

                Logger.EndPass(PassName.TailMerge, cfg);
            }

            if (options.HasFlag(CompilerOptions.SsaForm))
            {
                Logger.StartPass(PassName.Dominance);

                Dominance.FindDominators(cfg);
                Dominance.FindDominanceFrontiers(cfg);

                Logger.EndPass(PassName.Dominance);

                Logger.StartPass(PassName.SsaConstruction);

                Ssa.Construct(cfg);

                Logger.EndPass(PassName.SsaConstruction, cfg);
            }
            else
            {
                Logger.StartPass(PassName.RegisterToLocal);

                RegisterToLocal.Rename(cfg);

                Logger.EndPass(PassName.RegisterToLocal, cfg);
            }

            return(CodeGenerator.Generate(cctx));
        }
Ejemplo n.º 19
0
 DecompilerSettings GetSettings(CompilerOptions options)
 {
     if (!options.HasFlag(CompilerOptions.UseRoslyn))
     {
         return(new DecompilerSettings {
             StringInterpolation = false
         });
     }
     return(new DecompilerSettings());
 }
Ejemplo n.º 20
0
        public async Task TupleTests([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
        {
            if (cscOptions.HasFlag(CompilerOptions.UseRoslynLatest))
            {
                Assert.Ignore("DefaultInterpolatedStringHandler is not yet supported!");
                return;
            }

            await RunForLibrary(cscOptions : cscOptions);
        }
Ejemplo n.º 21
0
        public static List <string> GetPreprocessorSymbols(CompilerOptions flags)
        {
            var preprocessorSymbols = new List <string>();

            if (flags.HasFlag(CompilerOptions.UseDebug))
            {
                preprocessorSymbols.Add("DEBUG");
            }
            if (flags.HasFlag(CompilerOptions.Optimize))
            {
                preprocessorSymbols.Add("OPT");
            }
            if (flags.HasFlag(CompilerOptions.UseRoslyn))
            {
                preprocessorSymbols.Add("ROSLYN");
            }
            else
            {
                preprocessorSymbols.Add("LEGACY_CSC");
            }
            return(preprocessorSymbols);
        }
Ejemplo n.º 22
0
 internal static DecompilerSettings GetSettings(CompilerOptions cscOptions)
 {
     if (cscOptions.HasFlag(CompilerOptions.UseRoslyn))
     {
         if (cscOptions.HasFlag(CompilerOptions.Preview))
         {
             return(new DecompilerSettings(CSharp.LanguageVersion.Latest));
         }
         else
         {
             return(new DecompilerSettings(CSharp.LanguageVersion.CSharp8_0));
         }
     }
     else
     {
         var settings = new DecompilerSettings(CSharp.LanguageVersion.CSharp5);
         if (cscOptions.HasFlag(CompilerOptions.UseMcs))
         {
             // we don't recompile with mcs but with roslyn, so we can use ref locals
             settings.UseRefLocalsForAccurateOrderOfEvaluation = true;
         }
         return(settings);
     }
 }
Ejemplo n.º 23
0
        void Run([CallerMemberName] string testName = null, CompilerOptions options = CompilerOptions.UseDebug, DecompilerSettings settings = null)
        {
            var vbFile  = Path.Combine(TestCasePath, testName + ".vb");
            var csFile  = Path.Combine(TestCasePath, testName + ".cs");
            var exeFile = Path.Combine(TestCasePath, testName) + Tester.GetSuffix(options) + ".exe";

            if (options.HasFlag(CompilerOptions.Library))
            {
                exeFile = Path.ChangeExtension(exeFile, ".dll");
            }

            var executable = Tester.CompileVB(vbFile, options | CompilerOptions.ReferenceVisualBasic, exeFile);
            var decompiled = Tester.DecompileCSharp(executable.PathToAssembly, settings);

            CodeAssert.FilesAreEqual(csFile, decompiled);
        }
Ejemplo n.º 24
0
        async Task Run([CallerMemberName] string testName = null, CompilerOptions options = CompilerOptions.UseDebug, DecompilerSettings settings = null)
        {
            var vbFile  = Path.Combine(TestCasePath, testName + ".vb");
            var csFile  = Path.Combine(TestCasePath, testName + ".cs");
            var exeFile = Path.Combine(TestCasePath, testName) + Tester.GetSuffix(options) + ".exe";

            if (options.HasFlag(CompilerOptions.Library))
            {
                exeFile = Path.ChangeExtension(exeFile, ".dll");
            }

            var executable = await Tester.CompileVB(vbFile, options | CompilerOptions.ReferenceVisualBasic, exeFile).ConfigureAwait(false);

            var decompiled = await Tester.DecompileCSharp(executable.PathToAssembly, settings).ConfigureAwait(false);

            CodeAssert.FilesAreEqual(csFile, decompiled, Tester.GetPreprocessorSymbols(options).ToArray());
        }
Ejemplo n.º 25
0
        void RunCS([CallerMemberName] string testName = null, CompilerOptions options = CompilerOptions.UseDebug)
        {
            string          testFileName = testName + ".cs";
            string          testOutputFileName = testName + Tester.GetSuffix(options) + ".exe";
            CompilerResults outputFile = null, decompiledOutputFile = null;

            try
            {
                outputFile = Tester.CompileCSharp(Path.Combine(TestCasePath, testFileName), options,
                                                  outputFileName: Path.Combine(TestCasePath, testOutputFileName));
                string decompiledCodeFile = Tester.DecompileCSharp(outputFile.PathToAssembly, Tester.GetSettings(options));
                if (options.HasFlag(CompilerOptions.UseMcs))
                {
                    // For second pass, use roslyn instead of mcs.
                    // mcs has some compiler bugs that cause it to not accept ILSpy-generated code,
                    // for example when there's unreachable code due to other compiler bugs in the first mcs run.
                    options &= ~CompilerOptions.UseMcs;
                    options |= CompilerOptions.UseRoslynLatest;
                    // Also, add an .exe.config so that we consistently use the .NET 4.x runtime.
                    File.WriteAllText(outputFile.PathToAssembly + ".config", @"<?xml version=""1.0"" encoding=""utf-8""?>
<configuration>
	<startup>
		<supportedRuntime version=""v4.0"" sku="".NETFramework,Version=v4.0,Profile=Client"" />
	</startup>
</configuration>");
                }
                decompiledOutputFile = Tester.CompileCSharp(decompiledCodeFile, options);

                Tester.RunAndCompareOutput(testFileName, outputFile.PathToAssembly, decompiledOutputFile.PathToAssembly, decompiledCodeFile);

                Tester.RepeatOnIOError(() => File.Delete(decompiledCodeFile));
                Tester.RepeatOnIOError(() => File.Delete(decompiledOutputFile.PathToAssembly));
            }
            finally
            {
                if (outputFile != null)
                {
                    outputFile.TempFiles.Delete();
                }
                if (decompiledOutputFile != null)
                {
                    decompiledOutputFile.TempFiles.Delete();
                }
            }
        }
Ejemplo n.º 26
0
        public static CompilerResults CompileVB(string sourceFileName, CompilerOptions flags = CompilerOptions.UseDebug, string outputFileName = null)
        {
            List <string> sourceFileNames = new List <string> {
                sourceFileName
            };

            foreach (Match match in Regex.Matches(File.ReadAllText(sourceFileName), @"#include ""([\w\d./]+)"""))
            {
                sourceFileNames.Add(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(sourceFileName), match.Groups[1].Value)));
            }

            var preprocessorSymbols = GetPreprocessorSymbols(flags).Select(symbol => new KeyValuePair <string, object>(symbol, 1)).ToList();

            if (flags.HasFlag(CompilerOptions.UseRoslyn))
            {
                var parseOptions = new VisualBasicParseOptions(preprocessorSymbols: preprocessorSymbols, languageVersion: LanguageVersion.Latest);
                var syntaxTrees  = sourceFileNames.Select(f => SyntaxFactory.ParseSyntaxTree(File.ReadAllText(f), parseOptions, path: f));
                var references   = defaultReferences.Value;
                if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic))
                {
                    references = references.Concat(visualBasic.Value);
                }
                var compilation = VisualBasicCompilation.Create(Path.GetFileNameWithoutExtension(sourceFileName),
                                                                syntaxTrees, references,
                                                                new VisualBasicCompilationOptions(
                                                                    flags.HasFlag(CompilerOptions.Library) ? OutputKind.DynamicallyLinkedLibrary : OutputKind.ConsoleApplication,
                                                                    platform: flags.HasFlag(CompilerOptions.Force32Bit) ? Platform.X86 : Platform.AnyCpu,
                                                                    optimizationLevel: flags.HasFlag(CompilerOptions.Optimize) ? OptimizationLevel.Release : OptimizationLevel.Debug,
                                                                    deterministic: true
                                                                    ));
                CompilerResults results = new CompilerResults(new TempFileCollection());
                results.PathToAssembly = outputFileName ?? Path.GetTempFileName();
                var emitResult = compilation.Emit(results.PathToAssembly);
                if (!emitResult.Success)
                {
                    StringBuilder b = new StringBuilder("Compiler error:");
                    foreach (var diag in emitResult.Diagnostics)
                    {
                        b.AppendLine(diag.ToString());
                    }
                    throw new Exception(b.ToString());
                }
                return(results);
            }
            else if (flags.HasFlag(CompilerOptions.UseMcs))
            {
                throw new NotSupportedException("Cannot use mcs for VB");
            }
            else
            {
                var provider = new VBCodeProvider(new Dictionary <string, string> {
                    { "CompilerVersion", "v4.0" }
                });
                CompilerParameters options = new CompilerParameters();
                options.GenerateExecutable = !flags.HasFlag(CompilerOptions.Library);
                options.CompilerOptions    = "/optimize" + (flags.HasFlag(CompilerOptions.Optimize) ? "+" : "-");
                options.CompilerOptions   += (flags.HasFlag(CompilerOptions.UseDebug) ? " /debug" : "");
                options.CompilerOptions   += (flags.HasFlag(CompilerOptions.Force32Bit) ? " /platform:anycpu32bitpreferred" : "");
                options.CompilerOptions   += " /optioninfer+ /optionexplicit+";
                if (preprocessorSymbols.Count > 0)
                {
                    options.CompilerOptions += " /d:" + string.Join(",", preprocessorSymbols.Select(p => $"{p.Key}={p.Value}"));
                }
                if (outputFileName != null)
                {
                    options.OutputAssembly = outputFileName;
                }

                options.ReferencedAssemblies.Add("System.dll");
                options.ReferencedAssemblies.Add("System.Core.dll");
                options.ReferencedAssemblies.Add("System.Xml.dll");
                if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic))
                {
                    options.ReferencedAssemblies.Add("Microsoft.VisualBasic.dll");
                }
                CompilerResults results = provider.CompileAssemblyFromFile(options, sourceFileNames.ToArray());
                if (results.Errors.Cast <CompilerError>().Any(e => !e.IsWarning))
                {
                    StringBuilder b = new StringBuilder("Compiler error:");
                    foreach (var error in results.Errors)
                    {
                        b.AppendLine(error.ToString());
                    }
                    throw new Exception(b.ToString());
                }
                return(results);
            }
        }
Ejemplo n.º 27
0
        public static CompilerResults CompileCSharp(string sourceFileName, CompilerOptions flags = CompilerOptions.UseDebug, string outputFileName = null)
        {
            List <string> sourceFileNames = new List <string> {
                sourceFileName
            };

            foreach (Match match in Regex.Matches(File.ReadAllText(sourceFileName), @"#include ""([\w\d./]+)"""))
            {
                sourceFileNames.Add(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(sourceFileName), match.Groups[1].Value)));
            }
            if (flags.HasFlag(CompilerOptions.ReferenceCore))
            {
                sourceFileNames.Add(targetFrameworkAttributeSnippetFile.Value);
            }

            var preprocessorSymbols = GetPreprocessorSymbols(flags);

            if ((flags & CompilerOptions.UseMcsMask) == 0)
            {
                CompilerResults results = new CompilerResults(new TempFileCollection());
                results.PathToAssembly = outputFileName ?? Path.GetTempFileName();

                var(roslynVersion, languageVersion) = (flags & CompilerOptions.UseRoslynMask) switch {
                    0 => ("legacy", "5"),
                    CompilerOptions.UseRoslyn1_3_2 => ("1.3.2", "6"),
                    CompilerOptions.UseRoslyn2_10_0 => ("2.10.0", "latest"),
                    CompilerOptions.UseRoslyn3_11_0 => ("3.11.0", "latest"),
                    _ => (RoslynLatestVersion, flags.HasFlag(CompilerOptions.Preview) ? "preview" : "latest")
                };

                var cscPath = roslynToolset.GetCSharpCompiler(roslynVersion);

                IEnumerable <string> references;
                if ((flags & CompilerOptions.UseRoslynMask) != 0)
                {
                    if (flags.HasFlag(CompilerOptions.ReferenceCore))
                    {
                        references = coreDefaultReferences.Value.Select(r => "-r:\"" + r + "\"");
                    }
                    else
                    {
                        references = roslynDefaultReferences.Value.Select(r => "-r:\"" + r + "\"");
                    }
                }
                else
                {
                    references = defaultReferences.Value.Select(r => "-r:\"" + r + "\"");
                }
                if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic))
                {
                    if ((flags & CompilerOptions.UseRoslynMask) != 0)
                    {
                        references = references.Concat(visualBasic.Value.Select(r => "-r:\"" + r + "\""));
                    }
                    else
                    {
                        references = references.Concat(new[] { "-r:\"Microsoft.VisualBasic.dll\"" });
                    }
                }
                string otherOptions = $"-noconfig " +
                                      $"-langversion:{languageVersion} " +
                                      $"-unsafe -o{(flags.HasFlag(CompilerOptions.Optimize) ? "+ " : "- ")}";

                // note: the /shared switch is undocumented. It allows us to use the VBCSCompiler.exe compiler
                // server to speed up testing
                if (roslynVersion != "legacy")
                {
                    otherOptions += "/shared ";
                }

                if (flags.HasFlag(CompilerOptions.Library))
                {
                    otherOptions += "-t:library ";
                }
                else
                {
                    otherOptions += "-t:exe ";
                }

                if (flags.HasFlag(CompilerOptions.GeneratePdb))
                {
                    otherOptions += "-debug:full ";
                }
                else
                {
                    otherOptions += "-debug- ";
                }

                if (flags.HasFlag(CompilerOptions.Force32Bit))
                {
                    otherOptions += "-platform:x86 ";
                }
                else
                {
                    otherOptions += "-platform:anycpu ";
                }
                if (preprocessorSymbols.Count > 0)
                {
                    otherOptions += " \"-d:" + string.Join(";", preprocessorSymbols) + "\" ";
                }

                ProcessStartInfo info = new ProcessStartInfo(cscPath);
                info.Arguments              = $"{otherOptions}{string.Join(" ", references)} -out:\"{Path.GetFullPath(results.PathToAssembly)}\" {string.Join(" ", sourceFileNames.Select(fn => '"' + Path.GetFullPath(fn) + '"'))}";
                info.RedirectStandardError  = true;
                info.RedirectStandardOutput = true;
                info.UseShellExecute        = false;

                Console.WriteLine($"\"{info.FileName}\" {info.Arguments}");

                Process process = Process.Start(info);

                var outputTask = process.StandardOutput.ReadToEndAsync();
                var errorTask  = process.StandardError.ReadToEndAsync();

                Task.WaitAll(outputTask, errorTask);
                process.WaitForExit();

                Console.WriteLine("output: " + outputTask.Result);
                Console.WriteLine("errors: " + errorTask.Result);
                Assert.AreEqual(0, process.ExitCode, "csc failed");
                return(results);
            }
            else
            {
                CompilerResults results = new CompilerResults(new TempFileCollection());
                results.PathToAssembly = outputFileName ?? Path.GetTempFileName();
                string testBasePath = RoundtripAssembly.TestDir;
                if (!Directory.Exists(testBasePath))
                {
                    Assert.Ignore($"Compilation with mcs ignored: test directory '{testBasePath}' needs to be checked out separately." + Environment.NewLine +
                                  $"git clone https://github.com/icsharpcode/ILSpy-tests \"{testBasePath}\"");
                }
                string mcsPath = (flags & CompilerOptions.UseMcsMask) switch {
                    CompilerOptions.UseMcs5_23 => Path.Combine(testBasePath, @"mcs\5.23\bin\mcs.bat"),
                    _ => Path.Combine(testBasePath, @"mcs\2.6.4\bin\gmcs.bat")
                };
                string otherOptions = " -unsafe -o" + (flags.HasFlag(CompilerOptions.Optimize) ? "+ " : "- ");

                if (flags.HasFlag(CompilerOptions.Library))
                {
                    otherOptions += "-t:library ";
                }
                else
                {
                    otherOptions += "-t:exe ";
                }

                if (flags.HasFlag(CompilerOptions.UseDebug))
                {
                    otherOptions += "-g ";
                }

                if (flags.HasFlag(CompilerOptions.Force32Bit))
                {
                    otherOptions += "-platform:x86 ";
                }
                else
                {
                    otherOptions += "-platform:anycpu ";
                }
                if (preprocessorSymbols.Count > 0)
                {
                    otherOptions += " \"-d:" + string.Join(";", preprocessorSymbols) + "\" ";
                }

                ProcessStartInfo info = new ProcessStartInfo(mcsPath);
                info.Arguments              = $"{otherOptions}-out:\"{Path.GetFullPath(results.PathToAssembly)}\" {string.Join(" ", sourceFileNames.Select(fn => '"' + Path.GetFullPath(fn) + '"'))}";
                info.RedirectStandardError  = true;
                info.RedirectStandardOutput = true;
                info.UseShellExecute        = false;

                Console.WriteLine($"\"{info.FileName}\" {info.Arguments}");

                Process process = Process.Start(info);

                var outputTask = process.StandardOutput.ReadToEndAsync();
                var errorTask  = process.StandardError.ReadToEndAsync();

                Task.WaitAll(outputTask, errorTask);
                process.WaitForExit();

                Console.WriteLine("output: " + outputTask.Result);
                Console.WriteLine("errors: " + errorTask.Result);
                Assert.AreEqual(0, process.ExitCode, "mcs failed");
                return(results);
            }
        }
Ejemplo n.º 28
0
        public static CompilerResults CompileCSharp(string sourceFileName, CompilerOptions flags = CompilerOptions.UseDebug, string outputFileName = null)
        {
            List <string> sourceFileNames = new List <string> {
                sourceFileName
            };

            foreach (Match match in Regex.Matches(File.ReadAllText(sourceFileName), @"#include ""([\w\d./]+)"""))
            {
                sourceFileNames.Add(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(sourceFileName), match.Groups[1].Value)));
            }

            var preprocessorSymbols = new List <string>();

            if (flags.HasFlag(CompilerOptions.UseDebug))
            {
                preprocessorSymbols.Add("DEBUG");
            }

            if (flags.HasFlag(CompilerOptions.UseRoslyn))
            {
                var parseOptions = new CSharpParseOptions(preprocessorSymbols: preprocessorSymbols.ToArray());
                var syntaxTrees  = sourceFileNames.Select(f => SyntaxFactory.ParseSyntaxTree(File.ReadAllText(f), parseOptions, path: f));
                var compilation  = CSharpCompilation.Create(Path.GetFileNameWithoutExtension(sourceFileName),
                                                            syntaxTrees, defaultReferences.Value,
                                                            new CSharpCompilationOptions(
                                                                flags.HasFlag(CompilerOptions.Library) ? OutputKind.DynamicallyLinkedLibrary : OutputKind.ConsoleApplication,
                                                                platform: flags.HasFlag(CompilerOptions.Force32Bit) ? Platform.X86 : Platform.AnyCpu,
                                                                optimizationLevel: flags.HasFlag(CompilerOptions.Optimize) ? OptimizationLevel.Release : OptimizationLevel.Debug,
                                                                allowUnsafe: true,
                                                                deterministic: true
                                                                ));
                CompilerResults results = new CompilerResults(new TempFileCollection());
                results.PathToAssembly = outputFileName ?? Path.GetTempFileName();
                var emitResult = compilation.Emit(results.PathToAssembly);
                if (!emitResult.Success)
                {
                    StringBuilder b = new StringBuilder("Compiler error:");
                    foreach (var diag in emitResult.Diagnostics)
                    {
                        b.AppendLine(diag.ToString());
                    }
                    throw new Exception(b.ToString());
                }
                return(results);
            }
            else
            {
                preprocessorSymbols.Add("LEGACY_CSC");
                var provider = new CSharpCodeProvider(new Dictionary <string, string> {
                    { "CompilerVersion", "v4.0" }
                });
                CompilerParameters options = new CompilerParameters();
                options.GenerateExecutable = !flags.HasFlag(CompilerOptions.Library);
                options.CompilerOptions    = "/unsafe /o" + (flags.HasFlag(CompilerOptions.Optimize) ? "+" : "-");
                options.CompilerOptions   += (flags.HasFlag(CompilerOptions.UseDebug) ? " /debug" : "");
                options.CompilerOptions   += (flags.HasFlag(CompilerOptions.Force32Bit) ? " /platform:anycpu32bitpreferred" : "");
                if (preprocessorSymbols.Count > 0)
                {
                    options.CompilerOptions += " /d:" + string.Join(";", preprocessorSymbols);
                }
                if (outputFileName != null)
                {
                    options.OutputAssembly = outputFileName;
                }

                options.ReferencedAssemblies.Add("System.Core.dll");
                CompilerResults results = provider.CompileAssemblyFromFile(options, sourceFileNames.ToArray());
                if (results.Errors.Cast <CompilerError>().Any(e => !e.IsWarning))
                {
                    StringBuilder b = new StringBuilder("Compiler error:");
                    foreach (var error in results.Errors)
                    {
                        b.AppendLine(error.ToString());
                    }
                    throw new Exception(b.ToString());
                }
                return(results);
            }
        }
Ejemplo n.º 29
0
        public static CompilerResults CompileVB(string sourceFileName, CompilerOptions flags = CompilerOptions.UseDebug, string outputFileName = null)
        {
            List <string> sourceFileNames = new List <string> {
                sourceFileName
            };

            foreach (Match match in Regex.Matches(File.ReadAllText(sourceFileName), @"#include ""([\w\d./]+)"""))
            {
                sourceFileNames.Add(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(sourceFileName), match.Groups[1].Value)));
            }

            var preprocessorSymbols = GetPreprocessorSymbols(flags).Select(symbol => new KeyValuePair <string, object>(symbol, 1)).ToList();

            if (!flags.HasFlag(CompilerOptions.UseMcs))
            {
                CompilerResults results = new CompilerResults(new TempFileCollection());
                results.PathToAssembly = outputFileName ?? Path.GetTempFileName();

                var(roslynVersion, languageVersion) = (flags & CompilerOptions.UseRoslynMask) switch
                {
                    0 => ("legacy", "11"),
                    CompilerOptions.UseRoslyn1_3_2 => ("1.3.2", "14"),
                    CompilerOptions.UseRoslyn2_10_0 => ("2.10.0", "latest"),
                    _ => (RoslynLatestVersion, flags.HasFlag(CompilerOptions.Preview) ? "preview" : "latest")
                };

                var vbcPath = roslynToolset.GetVBCompiler(roslynVersion);

                IEnumerable <string> references;
                if ((flags & CompilerOptions.UseRoslynMask) != 0)
                {
                    if (flags.HasFlag(CompilerOptions.ReferenceCore))
                    {
                        references = coreDefaultReferences.Value.Select(r => "-r:\"" + r + "\"");
                    }
                    else
                    {
                        references = roslynDefaultReferences.Value.Select(r => "-r:\"" + r + "\"");
                    }
                }
                else
                {
                    references = defaultReferences.Value.Select(r => "-r:\"" + r + "\"");
                }
                if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic))
                {
                    if ((flags & CompilerOptions.UseRoslynMask) != 0)
                    {
                        references = references.Concat(visualBasic.Value.Select(r => "-r:\"" + r + "\""));
                    }
                    else
                    {
                        references = references.Concat(new[] { "-r:\"Microsoft.VisualBasic.dll\"" });
                    }
                }
                string otherOptions = $"-noconfig " +
                                      "-optioninfer+ -optionexplicit+ " +
                                      $"-langversion:{languageVersion} " +
                                      $"/optimize{(flags.HasFlag(CompilerOptions.Optimize) ? "+ " : "- ")}";

                // note: the /shared switch is undocumented. It allows us to use the VBCSCompiler.exe compiler
                // server to speed up testing
                if (roslynVersion != "legacy")
                {
                    otherOptions += "/shared ";
                }

                if (flags.HasFlag(CompilerOptions.Library))
                {
                    otherOptions += "-t:library ";
                }
                else
                {
                    otherOptions += "-t:exe ";
                }

                if (flags.HasFlag(CompilerOptions.GeneratePdb))
                {
                    otherOptions += "-debug:full ";
                }
                else
                {
                    otherOptions += "-debug- ";
                }

                if (flags.HasFlag(CompilerOptions.Force32Bit))
                {
                    otherOptions += "-platform:x86 ";
                }
                else
                {
                    otherOptions += "-platform:anycpu ";
                }
                if (preprocessorSymbols.Count > 0)
                {
                    otherOptions += " \"-d:" + string.Join(",", preprocessorSymbols.Select(kv => kv.Key + "=" + kv.Value)) + "\" ";
                }

                ProcessStartInfo info = new ProcessStartInfo(vbcPath);
                info.Arguments              = $"{otherOptions}{string.Join(" ", references)} -out:\"{Path.GetFullPath(results.PathToAssembly)}\" {string.Join(" ", sourceFileNames.Select(fn => '"' + Path.GetFullPath(fn) + '"'))}";
                info.RedirectStandardError  = true;
                info.RedirectStandardOutput = true;
                info.UseShellExecute        = false;

                Console.WriteLine($"\"{info.FileName}\" {info.Arguments}");

                Process process = Process.Start(info);

                var outputTask = process.StandardOutput.ReadToEndAsync();
                var errorTask  = process.StandardError.ReadToEndAsync();

                Task.WaitAll(outputTask, errorTask);
                process.WaitForExit();

                Console.WriteLine("output: " + outputTask.Result);
                Console.WriteLine("errors: " + errorTask.Result);
                Assert.AreEqual(0, process.ExitCode, "vbc failed");
                return(results);
            }
            else
            {
                throw new NotSupportedException("Cannot use mcs for VB");
            }
        }
Ejemplo n.º 30
0
        public static CompilerResults CompileCSharp(string sourceFileName, CompilerOptions flags = CompilerOptions.UseDebug, string outputFileName = null)
        {
            List <string> sourceFileNames = new List <string> {
                sourceFileName
            };

            foreach (Match match in Regex.Matches(File.ReadAllText(sourceFileName), @"#include ""([\w\d./]+)"""))
            {
                sourceFileNames.Add(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(sourceFileName), match.Groups[1].Value)));
            }

            var preprocessorSymbols = GetPreprocessorSymbols(flags);

            if (flags.HasFlag(CompilerOptions.UseRoslyn))
            {
                var parseOptions = new CSharpParseOptions(
                    preprocessorSymbols: preprocessorSymbols.ToArray(),
                    languageVersion: flags.HasFlag(CompilerOptions.Preview) ? Microsoft.CodeAnalysis.CSharp.LanguageVersion.Preview : Microsoft.CodeAnalysis.CSharp.LanguageVersion.CSharp8
                    );
                var syntaxTrees = sourceFileNames.Select(f => SyntaxFactory.ParseSyntaxTree(File.ReadAllText(f), parseOptions, path: f, encoding: Encoding.UTF8));
                if (flags.HasFlag(CompilerOptions.ReferenceCore))
                {
                    syntaxTrees = syntaxTrees.Concat(new[] { SyntaxFactory.ParseSyntaxTree(targetFrameworkAttributeSnippet) });
                }
                IEnumerable <MetadataReference> references;
                if (flags.HasFlag(CompilerOptions.ReferenceCore))
                {
                    references = coreDefaultReferences.Value;
                }
                else
                {
                    references = defaultReferences.Value;
                }
                if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic))
                {
                    references = references.Concat(visualBasic.Value);
                }
                var compilation = CSharpCompilation.Create(Path.GetFileNameWithoutExtension(sourceFileName),
                                                           syntaxTrees, references,
                                                           new CSharpCompilationOptions(
                                                               flags.HasFlag(CompilerOptions.Library) ? OutputKind.DynamicallyLinkedLibrary : OutputKind.ConsoleApplication,
                                                               platform: flags.HasFlag(CompilerOptions.Force32Bit) ? Platform.X86 : Platform.AnyCpu,
                                                               optimizationLevel: flags.HasFlag(CompilerOptions.Optimize) ? OptimizationLevel.Release : OptimizationLevel.Debug,
                                                               allowUnsafe: true,
                                                               deterministic: true
                                                               ));
                CompilerResults results = new CompilerResults(new TempFileCollection());
                results.PathToAssembly = outputFileName ?? Path.GetTempFileName();
                string pdbName = null;
                if (flags.HasFlag(CompilerOptions.GeneratePdb))
                {
                    pdbName = Path.ChangeExtension(outputFileName, ".pdb");
                }
                var emitResult = compilation.Emit(results.PathToAssembly, pdbName);
                if (!emitResult.Success)
                {
                    StringBuilder b = new StringBuilder("Compiler error:");
                    foreach (var diag in emitResult.Diagnostics)
                    {
                        b.AppendLine(diag.ToString());
                    }
                    throw new Exception(b.ToString());
                }
                return(results);
            }
            else if (flags.HasFlag(CompilerOptions.UseMcs))
            {
                CompilerResults results = new CompilerResults(new TempFileCollection());
                results.PathToAssembly = outputFileName ?? Path.GetTempFileName();
                string testBasePath = RoundtripAssembly.TestDir;
                if (!Directory.Exists(testBasePath))
                {
                    Assert.Ignore($"Compilation with mcs ignored: test directory '{testBasePath}' needs to be checked out separately." + Environment.NewLine +
                                  $"git clone https://github.com/icsharpcode/ILSpy-tests \"{testBasePath}\"");
                }
                string mcsPath      = Path.Combine(testBasePath, @"mcs\2.6.4\bin\gmcs.bat");
                string otherOptions = " -unsafe -o" + (flags.HasFlag(CompilerOptions.Optimize) ? "+ " : "- ");

                if (flags.HasFlag(CompilerOptions.Library))
                {
                    otherOptions += "-t:library ";
                }
                else
                {
                    otherOptions += "-t:exe ";
                }

                if (flags.HasFlag(CompilerOptions.UseDebug))
                {
                    otherOptions += "-g ";
                }

                if (flags.HasFlag(CompilerOptions.Force32Bit))
                {
                    otherOptions += "-platform:x86 ";
                }
                else
                {
                    otherOptions += "-platform:anycpu ";
                }
                if (preprocessorSymbols.Count > 0)
                {
                    otherOptions += " \"-d:" + string.Join(";", preprocessorSymbols) + "\" ";
                }

                ProcessStartInfo info = new ProcessStartInfo(mcsPath);
                info.Arguments              = $"{otherOptions}-out:\"{Path.GetFullPath(results.PathToAssembly)}\" {string.Join(" ", sourceFileNames.Select(fn => '"' + Path.GetFullPath(fn) + '"'))}";
                info.RedirectStandardError  = true;
                info.RedirectStandardOutput = true;
                info.UseShellExecute        = false;

                Console.WriteLine($"\"{info.FileName}\" {info.Arguments}");

                Process process = Process.Start(info);

                var outputTask = process.StandardOutput.ReadToEndAsync();
                var errorTask  = process.StandardError.ReadToEndAsync();

                Task.WaitAll(outputTask, errorTask);
                process.WaitForExit();

                Console.WriteLine("output: " + outputTask.Result);
                Console.WriteLine("errors: " + errorTask.Result);
                Assert.AreEqual(0, process.ExitCode, "mcs failed");
                return(results);
            }
            else
            {
                var provider = new CSharpCodeProvider(new Dictionary <string, string> {
                    { "CompilerVersion", "v4.0" }
                });
                CompilerParameters options = new CompilerParameters();
                options.GenerateExecutable = !flags.HasFlag(CompilerOptions.Library);
                options.CompilerOptions    = "/unsafe /o" + (flags.HasFlag(CompilerOptions.Optimize) ? "+" : "-");
                string debugOption = " /debug";
                if (flags.HasFlag(CompilerOptions.GeneratePdb))
                {
                    debugOption += ":full";
                    options.IncludeDebugInformation = true;
                }
                options.CompilerOptions += (flags.HasFlag(CompilerOptions.UseDebug) ? debugOption : "");
                options.CompilerOptions += (flags.HasFlag(CompilerOptions.Force32Bit) ? " /platform:anycpu32bitpreferred" : "");
                if (preprocessorSymbols.Count > 0)
                {
                    options.CompilerOptions += " /d:" + string.Join(";", preprocessorSymbols);
                }
                if (outputFileName != null)
                {
                    options.OutputAssembly = outputFileName;
                }
                options.ReferencedAssemblies.Add("System.dll");
                options.ReferencedAssemblies.Add("System.Core.dll");
                options.ReferencedAssemblies.Add("System.Xml.dll");
                options.ReferencedAssemblies.Add("Microsoft.CSharp.dll");
                if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic))
                {
                    options.ReferencedAssemblies.Add("Microsoft.VisualBasic.dll");
                }
                CompilerResults results = provider.CompileAssemblyFromFile(options, sourceFileNames.ToArray());
                if (results.Errors.Cast <CompilerError>().Any(e => !e.IsWarning))
                {
                    StringBuilder b = new StringBuilder("Compiler error:");
                    foreach (var error in results.Errors)
                    {
                        b.AppendLine(error.ToString());
                    }
                    throw new Exception(b.ToString());
                }
                return(results);
            }
        }