public void CanCompileAsyncTaskGenericMethod() { UsingFiles(() => { File.WriteAllText(Path.GetFullPath("File1.cs"), @" using System.Threading.Tasks; public class C1 { public async Task<int> M() { var t = new Task(() => {}); await t; return 0; } }"); var options = new CompilerOptions { References = { new Reference(Common.MscorlibPath) }, SourceFiles = { Path.GetFullPath("File1.cs") }, OutputAssemblyPath = Path.GetFullPath("Test.dll"), OutputScriptPath = Path.GetFullPath("Test.js") }; var er = new MockErrorReporter(); var driver = new CompilerDriver(er); var result = driver.Compile(options, false); Assert.That(result, Is.True); Assert.That(File.Exists(Path.GetFullPath("Test.dll")), Is.True, "Assembly should be written"); Assert.That(File.Exists(Path.GetFullPath("Test.js")), Is.True, "Script should be written"); }, "File1.cs", "Test.dll", "Test.js"); }
/// <param name="options">Compile options</param> /// <param name="runInSeparateAppDomain">Should be set to true for production code, but there are issues with NUnit, so tests need to set this to false.</param> public bool Compile(CompilerOptions options, bool runInSeparateAppDomain) { try { AppDomain ad = null; var actualOut = Console.Out; try { Console.SetOut(new StringWriter()); // I don't trust the third-party libs to not generate spurious random messages, so make sure that any of those messages are suppressed. var er = new ErrorReporterWrapper(_errorReporter, actualOut); Executor executor; if (runInSeparateAppDomain) { var setup = new AppDomainSetup { ApplicationBase = Path.GetDirectoryName(typeof(Executor).Assembly.Location) }; ad = AppDomain.CreateDomain("SCTask", null, setup); executor = (Executor)ad.CreateInstanceAndUnwrap(typeof(Executor).Assembly.FullName, typeof(Executor).FullName); } else { executor = new Executor(); } return executor.Compile(options, er); } finally { if (ad != null) { AppDomain.Unload(ad); } if (actualOut != null) { Console.SetOut(actualOut); } } } catch (Exception ex) { _errorReporter.InternalError(ex, null, TextLocation.Empty); return false; } }
public void ChangingTheWarningLevelWorks() { UsingFiles(() => { File.WriteAllText(Path.GetFullPath("File.cs"), @"public class C1 { public void M() { var x = 0l; } }"); var options = new CompilerOptions { References = { new Reference(Common.MscorlibPath) }, SourceFiles = { Path.GetFullPath("File.cs") }, OutputAssemblyPath = Path.GetFullPath("Test.dll"), OutputScriptPath = Path.GetFullPath("Test.js"), }; var er = new MockErrorReporter(); var driver = new CompilerDriver(er); var result = driver.Compile(options, false); Assert.That(result, Is.True); Assert.That(er.AllMessages.Select(m => m.Code).ToList(), Is.EquivalentTo(new[] { 219, 78 })); }, "File.cs", "Test.dll", "Test.js"); UsingFiles(() => { File.WriteAllText(Path.GetFullPath("File.cs"), @"public class C1 { public void M() { var x = 0l; } }"); var options = new CompilerOptions { References = { new Reference(Common.MscorlibPath) }, SourceFiles = { Path.GetFullPath("File.cs") }, OutputAssemblyPath = Path.GetFullPath("Test.dll"), OutputScriptPath = Path.GetFullPath("Test.js"), WarningLevel = 3, }; var er = new MockErrorReporter(); var driver = new CompilerDriver(er); var result = driver.Compile(options, false); Assert.That(result, Is.True); Assert.That(er.AllMessages.Select(m => m.Code), Is.EqualTo(new[] { 219 })); }, "File.cs", "Test.dll", "Test.js"); }
private static string GetAssemblyName(CompilerOptions options) { if (options.OutputAssemblyPath != null) return Path.GetFileNameWithoutExtension(options.OutputAssemblyPath); else if (options.SourceFiles.Count > 0) return Path.GetFileNameWithoutExtension(options.SourceFiles[0]); else return null; }
private static void HandleReferences(CompilerOptions options, string value) { foreach (var reference in value.Split(new[] { ',' }).Select(s => s.Trim()).Where(s => s != "")) { int i = reference.IndexOf('='); if (i >= 0) options.References.Add(new Reference(reference.Substring(i + 1), reference.Substring(0, i))); else options.References.Add(new Reference(reference)); } }
private static CompilerSettings MapSettings(CompilerOptions options, string outputAssemblyPath, string outputDocFilePath, IErrorReporter er) { var allPaths = options.AdditionalLibPaths.Concat(new[] { Environment.CurrentDirectory }).ToList(); var result = new CompilerSettings { Target = (options.HasEntryPoint ? Target.Exe : Target.Library), Platform = Platform.AnyCPU, TargetExt = (options.HasEntryPoint ? ".exe" : ".dll"), MainClass = options.EntryPointClass, VerifyClsCompliance = false, Optimize = false, Version = LanguageVersion.V_5, EnhancedWarnings = false, LoadDefaultReferences = false, TabSize = 1, WarningsAreErrors = options.TreatWarningsAsErrors, FatalCounter = 100, WarningLevel = options.WarningLevel, Encoding = Encoding.UTF8, DocumentationFile = !string.IsNullOrEmpty(options.DocumentationFile) ? outputDocFilePath : null, OutputFile = outputAssemblyPath, AssemblyName = GetAssemblyName(options), StdLib = false, StdLibRuntimeVersion = RuntimeVersion.v4, StrongNameKeyContainer = options.KeyContainer, StrongNameKeyFile = options.KeyFile, }; result.SourceFiles.AddRange(options.SourceFiles.Select((f, i) => new SourceFile(f, f, i + 1))); foreach (var r in options.References) { string resolvedPath = ResolveReference(r.Filename, allPaths, er); if (r.Alias == null) { if (!result.AssemblyReferences.Contains(resolvedPath)) result.AssemblyReferences.Add(resolvedPath); } else result.AssemblyReferencesAliases.Add(Tuple.Create(r.Alias, resolvedPath)); } foreach (var c in options.DefineConstants) result.AddConditionalSymbol(c); foreach (var w in options.DisabledWarnings) result.SetIgnoreWarning(w); foreach (var w in options.WarningsAsErrors) result.AddWarningAsError(w); foreach (var w in options.WarningsNotAsErrors) result.AddWarningOnly(w); if (options.EmbeddedResources.Count > 0) result.Resources = options.EmbeddedResources.Select(r => new AssemblyResource(r.Filename, r.ResourceName, isPrivate: !r.IsPublic) { IsEmbeded = true }).ToList(); if (result.AssemblyReferencesAliases.Count > 0) { // NRefactory does currently not support reference aliases, this check will hopefully go away in the future. er.Region = DomRegion.Empty; er.Message(Messages._7998, "aliased reference"); } return result; }
public void CanInitializeListWithCollectionInitializer() { UsingFiles(() => { File.WriteAllText(Path.GetFullPath("Test.cs"), @"using System.Collections.Generic; public class C1 { public void M() { var l = new List<int> { 1 }; } }"); var options = new CompilerOptions { References = { new Reference(Common.MscorlibPath) }, SourceFiles = { Path.GetFullPath("Test.cs") }, OutputAssemblyPath = Path.GetFullPath("Test.dll"), OutputScriptPath = Path.GetFullPath("Test.js") }; var er = new MockErrorReporter(); var driver = new CompilerDriver(er); var result = driver.Compile(options, false); Assert.That(result, Is.True, "Compilation failed with " + string.Join(Environment.NewLine, er.AllMessagesText)); }, "File1.cs", "Test.dll", "Test.js"); }
private static void HandleWarningsAsErrors(CompilerOptions options, string value) { string param; if (value != null && (value[0] == '-' || value[0] == '/')) { var colon = value.IndexOf(':'); param = colon >= 0 ? value.Substring(colon + 1) : null; } else { param = value; } if (param != null) { HandleIntegerList(options.WarningsAsErrors, param, "warnaserror"); } else { options.TreatWarningsAsErrors = true; } }
public void SimpleCompilationWorks() { UsingFiles(() => { File.WriteAllText(Path.GetFullPath("File1.cs"), @"using System.Collections; public class C1 { public JsDictionary M() { return null; } }"); File.WriteAllText(Path.GetFullPath("File2.cs"), @"using System.Collections; public class C2 { public JsDictionary M() { return null; } }"); var options = new CompilerOptions { References = { new Reference(Common.MscorlibPath) }, SourceFiles = { Path.GetFullPath("File1.cs"), Path.GetFullPath("File2.cs") }, OutputAssemblyPath = Path.GetFullPath("Test.dll"), OutputScriptPath = Path.GetFullPath("Test.js") }; var driver = new CompilerDriver(new MockErrorReporter()); var result = driver.Compile(options, null); Assert.That(result, Is.True); Assert.That(File.Exists(Path.GetFullPath("Test.dll")), Is.True, "Assembly should be written"); Assert.That(File.Exists(Path.GetFullPath("Test.js")), Is.True, "Script should be written"); }, "File1.cs", "File2.cs", "Test.dll", "Test.js"); }
public void AssemblyNameIsCorrectInTheGeneratedScript() { UsingFiles(() => { File.WriteAllText(Path.GetFullPath("File1.cs"), @"using System.Collections; public class C1 { public JsDictionary M() { return null; } }"); File.WriteAllText(Path.GetFullPath("File2.cs"), @"using System.Collections; public class C2 { public JsDictionary M() { return null; } }"); var options = new CompilerOptions { References = { new Reference(Common.MscorlibPath) }, SourceFiles = { Path.GetFullPath("File1.cs"), Path.GetFullPath("File2.cs") }, OutputAssemblyPath = Path.GetFullPath("Test.Assembly.dll"), OutputScriptPath = Path.GetFullPath("Test.js") }; var driver = new CompilerDriver(new MockErrorReporter()); var result = driver.Compile(options); Assert.That(result, Is.True); var text = File.ReadAllText(Path.GetFullPath("Test.js")); Assert.That(text.Contains("ss.initAssembly($asm, 'Test.Assembly')")); // Verify that the symbol was passed to the script compiler. }, "File1.cs", "File2.cs", "Test.Assembly.dll", "Test.js"); }
public void CanCompileLockStatement() { UsingFiles(() => { File.WriteAllText(Path.GetFullPath("File1.cs"), @"using System.Collections.Generic; public class C1 { public void M() { lock (new object()) {} } }"); var options = new CompilerOptions { References = { new Reference(Common.MscorlibPath) }, SourceFiles = { Path.GetFullPath("File1.cs") }, OutputAssemblyPath = Path.GetFullPath("Test.dll"), OutputScriptPath = Path.GetFullPath("Test.js") }; var driver = new CompilerDriver(new MockErrorReporter()); var result = driver.Compile(options, false); Assert.That(result, Is.True); Assert.That(File.Exists(Path.GetFullPath("Test.dll")), Is.True, "Assembly should be written"); Assert.That(File.Exists(Path.GetFullPath("Test.js")), Is.True, "Script should be written"); }, "File1.cs", "Test.dll", "Test.js"); }
public void CompileErrorsAreReportedAndCauseFilesNotToBeGenerated() { UsingFiles(() => { File.WriteAllText(Path.GetFullPath("File.cs"), @"public class C1 { public void M() { var x = y; } }"); var options = new CompilerOptions { References = { new Reference(Common.MscorlibPath) }, SourceFiles = { Path.GetFullPath("File.cs") }, OutputAssemblyPath = Path.GetFullPath("Test.dll"), OutputScriptPath = Path.GetFullPath("Test.js") }; var er = new MockErrorReporter(); var driver = new CompilerDriver(er); var result = driver.Compile(options, null); Assert.That(result, Is.False); Assert.That(er.AllMessages.Any(m => m.Severity == MessageSeverity.Error && m.Code == 103 && m.Region.FileName == Path.GetFullPath("File.cs") && m.Region.Begin == new TextLocation(1, 45) && m.Format != null && m.Args.Length == 0)); Assert.That(File.Exists(Path.GetFullPath("Test.dll")), Is.False, "Assembly should not be written"); Assert.That(File.Exists(Path.GetFullPath("Test.js")), Is.False, "Script should not be written"); }, "File.cs", "Test.dll", "Test.js"); }
public void AssemblyThatCanNotBeLocatedCausesError7997() { UsingFiles(() => { File.WriteAllText(Path.GetFullPath("File.cs"), @"class Class1 { public void M() {} }"); var options = new CompilerOptions { References = { new Reference(Common.MscorlibPath), new Reference("MyNonexistentAssembly") }, SourceFiles = { Path.GetFullPath("File.cs") }, OutputAssemblyPath = Path.GetFullPath("Test.dll"), OutputScriptPath = Path.GetFullPath("Test.js"), MinimizeScript = false, }; var er = new MockErrorReporter(); var driver = new CompilerDriver(er); var result = driver.Compile(options, false); Assert.That(er.AllMessages, Has.Count.EqualTo(1)); Assert.That(er.AllMessages.Any(m => m.Code == 7997 && (string)m.Args[0] == "MyNonexistentAssembly")); Assert.That(result, Is.False); Assert.That(File.Exists(Path.GetFullPath("Test.dll")), Is.False); }, "File.cs", "Test.dll", "Test.js"); }
private CompilerOptions ReadProject(string filename, string solutionDir = null) { var basePath = Path.GetDirectoryName(filename); var opts = new CompilerOptions(); string content = File.ReadAllText(filename); content = content.Replace("$(SolutionDir)", solutionDir + "\\"); var project = XDocument.Parse(content); var nsm = new XmlNamespaceManager(new NameTable()); nsm.AddNamespace("msb", "http://schemas.microsoft.com/developer/msbuild/2003"); var projectReferences = project.XPathSelectElements("msb:Project/msb:ItemGroup/msb:ProjectReference", nsm) .Select(n => n.Attribute("Include").Value).ToList() .Select(f => Path.GetFullPath(Path.Combine(basePath, Path.GetDirectoryName(f), "bin", "Debug", Path.GetFileNameWithoutExtension(f) + ".dll"))).ToList(); opts.SourceFiles.AddRange(project.XPathSelectElements("msb:Project/msb:ItemGroup/msb:Compile", nsm).Select(item => Path.GetFullPath(Path.Combine(basePath, item.Attributes("Include").Single().Value)))); opts.References.AddRange(project.XPathSelectElements("msb:Project/msb:ItemGroup/msb:Reference/msb:HintPath", nsm).Select(item => new Reference(Path.GetFullPath(Path.Combine(basePath, item.Value))))); opts.References.AddRange(projectReferences.Select(item => new Reference(item))); opts.OutputAssemblyPath = Path.GetFullPath("output.dll"); opts.OutputScriptPath = Path.GetFullPath("output.js"); return opts; }
public void SpecificWarningsNotAsErrorsWorks() { UsingFiles(() => { File.WriteAllText(Path.GetFullPath("File.cs"), @"public class C1 { public void M() { var x = 0; } }"); var options = new CompilerOptions { References = { new Reference(Common.MscorlibPath) }, SourceFiles = { Path.GetFullPath("File.cs") }, OutputAssemblyPath = Path.GetFullPath("Test.dll"), OutputScriptPath = Path.GetFullPath("Test.js"), TreatWarningsAsErrors = true, WarningsNotAsErrors = { 219 } }; var er = new MockErrorReporter(); var driver = new CompilerDriver(er); var result = driver.Compile(options, false); Assert.That(result, Is.True); Assert.That(er.AllMessages.Any(m => m.Severity == MessageSeverity.Warning && m.Code == 219 && m.Region.FileName == Path.GetFullPath("File.cs") && m.Region.Begin == new TextLocation(1, 41) && m.Format != null && m.Args.Length == 0)); Assert.That(File.Exists(Path.GetFullPath("Test.dll")), Is.True, "Assembly should be written"); Assert.That(File.Exists(Path.GetFullPath("Test.js")), Is.True, "Script should be written"); }, "File.cs", "Test.dll", "Test.js"); }
public void TheAssemblyNameIsCorrect() { UsingFiles(() => { File.WriteAllText(Path.GetFullPath("File.cs"), @"class Class1 { public void M() {} }"); var options = new CompilerOptions { References = { new Reference(Common.MscorlibPath) }, SourceFiles = { Path.GetFullPath("File.cs") }, OutputAssemblyPath = Path.GetFullPath("MyOutputAssembly.dll"), OutputScriptPath = Path.GetFullPath("Test.js"), DocumentationFile = Path.GetFullPath("Test.xml"), MinimizeScript = false, }; var er = new MockErrorReporter(); var driver = new CompilerDriver(er); var result = driver.Compile(options, false); Assert.That(result, Is.True); Assert.That(File.Exists(Path.GetFullPath("Test.xml")), Is.True); string doc = File.ReadAllText(Path.GetFullPath("Test.xml")); Assert.That(XDocument.Parse(doc).XPathSelectElement("/doc/assembly/name").Value, Is.EqualTo("MyOutputAssembly")); var asm = AssemblyDefinition.ReadAssembly(Path.GetFullPath("MyOutputAssembly.dll")); Assert.That(asm.Name.Name, Is.EqualTo("MyOutputAssembly")); }, "File.cs", "MyOutputAssembly.dll", "Test.js", "Test.xml"); }
public void ReferenceWithoutExtensionTheCurrentDirectoryCanBeResolved() { UsingFiles(() => { File.WriteAllText(Path.GetFullPath("File.cs"), @"class Class1 { public void M() {} }"); File.Copy(Common.MscorlibPath, "mscorlib.dll"); var options = new CompilerOptions { References = { new Reference("mscorlib") }, SourceFiles = { Path.GetFullPath("File.cs") }, OutputAssemblyPath = Path.GetFullPath("Test.dll"), OutputScriptPath = Path.GetFullPath("Test.js"), MinimizeScript = false, }; var er = new MockErrorReporter(); var driver = new CompilerDriver(er); var result = driver.Compile(options, false); Assert.That(result, Is.True); Assert.That(File.Exists(Path.GetFullPath("Test.dll")), Is.True); }, "File.cs", "Test.dll", "Test.js", "mscorlib.dll"); }
public void SigningWorks() { string key = "0702000000240000525341320004000001000100BF8CF25A8FAE18A956C58C7F0484E846B1DAF18C64DDC3C04B668894E90AFB7C796F86B2926EB59548DDF82097805AE0A981C553A639A0669B39BECD22C1026A3F8E0F90E01BF6993EA18F8E2EA60F4F1B1563FDBB9F8D501A0E0736C3ACCD6BA86B6B2002D20AE83A5E62218BC2ADA819FF0B1521E56801684FA07726EB6DAAC9DF138633A3495C1687045E1B98ECAC630F4BB278AEFF7D6276A88DFFFF02D556562579E144591166595656519A0620F272E8FE1F29DC6EAB1D14319A77EDEB479C09294F0970F1293273AA6E5A8DB32DB6C156E070672F7EEA2C1111E040FB8B992329CD8572D48D9BB256A5EE0329B69ABAFB227BBEEEF402F7383DE4EDB83947AF3B87F9ED7B2A3F3F4572F871020606778C0CEF86C77ECF6F9E8A5112A5B06FA33255A1D8AF6F2401DFA6AC3220181B1BB99D79C931B416E06926DA0E21B79DA68D3ED95CBBFE513990B3BFB4419A390206B48AC93BC397183CD608E0ECA794B66AEC94521E655559B7A098711D2FFD531BED25FF797B8320E415E99F70995777243C3940AF6672976EF37D851D93F765EC0F35FE641279F14400E227A1627CDDCCE09F6B3543681544A169DC78B6AF734AFDAF2C50015E6B932E6BD913619BA04FB5BE03428EAB072C64F7743E1E9DDDADE9DCA6A1E47C648BE01D9133F7D227FAE72337E662459B6A0CA11410FA0179F22312A534B5CABE611742A11A890B1893CD0402CE01778EDC921F0D27CBC96AEE75ECB4D4E083301A843E9716BBB0AD689FDEE275321EA915FD44F696883DAF4E3CAB3D0229283ED43FB12747"; byte[] keyBytes = Enumerable.Range(0, key.Length / 2).Select(i => Convert.ToByte(key.Substring(i * 2, 2), 16)).ToArray(); UsingFiles(() => { var er = new MockErrorReporter(); var driver = new CompilerDriver(er); File.WriteAllBytes(Path.GetFullPath("Key.snk"), keyBytes); File.WriteAllText(Path.GetFullPath("File.cs"), @"public class Class1 { public void M() {} }"); var options = new CompilerOptions { References = { new Reference(Common.MscorlibPath) }, SourceFiles = { Path.GetFullPath("File.cs") }, OutputAssemblyPath = Path.GetFullPath("File.dll"), OutputScriptPath = Path.GetFullPath("File.js"), KeyFile = Path.GetFullPath("Key.snk"), }; bool result = driver.Compile(options, false); Assert.That(result, Is.True); Assert.That(er.AllMessages, Is.Empty); var asm = AssemblyDefinition.ReadAssembly("File.dll"); Assert.That(asm.Name.PublicKeyToken, Is.EqualTo(new[] { 0xf5, 0xa5, 0x6d, 0x86, 0x8e, 0xa6, 0xbd, 0x2e })); }, "Key.snk", "File.cs", "File.dll", "File.js"); }
public void NotSpecifyingAnyFilesToCompileIsAnError() { UsingFiles(() => { var options = new CompilerOptions { References = { new Reference(Common.MscorlibPath) }, SourceFiles = {}, OutputAssemblyPath = Path.GetFullPath("Test.dll"), OutputScriptPath = Path.GetFullPath("Test.js"), }; var er = new MockErrorReporter(); var driver = new CompilerDriver(er); var result = driver.Compile(options, false); Assert.That(result, Is.False); Assert.That(er.AllMessages.Where(m => m.Severity == MessageSeverity.Error), Is.Not.Empty); }, "Test.dll", "Test.js"); }
public void ReferenceInAdditionalLibPathCanBeLocated() { UsingFiles(() => { Directory.CreateDirectory("MyAdditionalReferencePath"); var er = new MockErrorReporter(); var driver = new CompilerDriver(er); File.WriteAllText(Path.GetFullPath("MyAdditionalReferencePath\\Ref.cs"), @"public class Class1 { public void M() {} }"); var options = new CompilerOptions { References = { new Reference(Common.MscorlibPath) }, SourceFiles = { Path.GetFullPath("MyAdditionalReferencePath\\Ref.cs") }, OutputAssemblyPath = Path.GetFullPath("MyAdditionalReferencePath\\Ref.dll"), OutputScriptPath = Path.GetFullPath("MyAdditionalReferencePath\\Ref.js"), }; bool result = driver.Compile(options, false); Assert.That(result, Is.True); Assert.That(er.AllMessages, Is.Empty); File.WriteAllText(Path.GetFullPath("Out.cs"), @"class Class2 : Class1 { public void M2() {} }"); options = new CompilerOptions { References = { new Reference(Common.MscorlibPath), new Reference("Ref.dll") }, SourceFiles = { Path.GetFullPath("Out.cs") }, OutputAssemblyPath = Path.GetFullPath("Out.dll"), OutputScriptPath = Path.GetFullPath("Out.js"), AdditionalLibPaths = { Path.GetFullPath("MyAdditionalReferencePath") }, }; result = driver.Compile(options, false); Assert.That(result, Is.True); Assert.That(File.Exists(Path.GetFullPath("Out.dll")), Is.True); }, "MyAdditionalReferencePath", "Out.cs", "Out.dll", "Out.js"); }
public void MinimizeScriptWorks() { UsingFiles(() => { File.WriteAllText(Path.GetFullPath("File.cs"), @"class Class1 { public void M(int someVariable) {} }"); var options = new CompilerOptions { References = { new Reference(Common.MscorlibPath) }, SourceFiles = { Path.GetFullPath("File.cs") }, OutputAssemblyPath = Path.GetFullPath("Test.dll"), OutputScriptPath = Path.GetFullPath("Test.js"), MinimizeScript = false, }; var er = new MockErrorReporter(); var driver = new CompilerDriver(er); var result = driver.Compile(options, false); Assert.That(result, Is.True); Assert.That(File.ReadAllText(Path.GetFullPath("Test.js")).Contains("Class1"), Is.True); Assert.That(File.ReadAllText(Path.GetFullPath("Test.js")).Contains("someVariable"), Is.True); Assert.That(File.ReadAllText(Path.GetFullPath("Test.js")).Contains(" "), Is.True); }, "File.cs", "Test.dll", "Test.js"); UsingFiles(() => { File.WriteAllText(Path.GetFullPath("File.cs"), @"class Class1 { public void M(int someVariable) {} }"); var options = new CompilerOptions { References = { new Reference(Common.MscorlibPath) }, SourceFiles = { Path.GetFullPath("File.cs") }, OutputAssemblyPath = Path.GetFullPath("Test.dll"), OutputScriptPath = Path.GetFullPath("Test.js"), MinimizeScript = true, }; var er = new MockErrorReporter(); var driver = new CompilerDriver(er); var result = driver.Compile(options, false); Assert.That(result, Is.True); var content = File.ReadAllText(Path.GetFullPath("Test.js")); Assert.That(content.Contains("Class1"), Is.False); Assert.That(content.Contains("someVariable"), Is.False); Assert.That(new System.Text.RegularExpressions.Regex("(?<!var) ").IsMatch(content), Is.False); }, "File.cs", "Test.dll", "Test.js"); }
public void NonExistentSourceFilesAreHandledGracefully() { UsingFiles(() => { File.WriteAllText(Path.GetFullPath("ExistentFile.cs"), @"class C1 { public void M() {} }"); var options = new CompilerOptions { References = { new Reference(Common.MscorlibPath) }, SourceFiles = { Path.GetFullPath("NonExistentFile.cs") }, OutputAssemblyPath = Path.GetFullPath("Test.dll"), OutputScriptPath = Path.GetFullPath("Test.js"), }; var er = new MockErrorReporter(); var driver = new CompilerDriver(er); var result = driver.Compile(options, false); Assert.That(result, Is.False); Assert.That(er.AllMessages.Where(m => m.Severity == MessageSeverity.Error && m.Format.Contains("NonExistentFile.cs")), Is.Not.Empty); }, "ExistentFile.cs", "Test.dll", "Test.js"); }
public void GeneratingDocumentationFileWorks() { UsingFiles(() => { File.WriteAllText(Path.GetFullPath("File.cs"), @"/** <summary>$$$$$$$$$$$$$$$</summary>*/ class Class1 { public void M() {} }"); var options = new CompilerOptions { References = { new Reference(Common.MscorlibPath) }, SourceFiles = { Path.GetFullPath("File.cs") }, OutputAssemblyPath = Path.GetFullPath("Test.dll"), OutputScriptPath = Path.GetFullPath("Test.js"), DocumentationFile = Path.GetFullPath("Test.xml"), MinimizeScript = false, }; var er = new MockErrorReporter(); var driver = new CompilerDriver(er); var result = driver.Compile(options, false); Assert.That(result, Is.True); Assert.That(File.Exists(Path.GetFullPath("Test.xml")), Is.True); string doc = File.ReadAllText(Path.GetFullPath("Test.xml")); Assert.That(doc, Is.StringContaining("$$$$$$$$$$$$$$$")); }, "File.cs", "Test.dll", "Test.js", "Test.xml"); }
public bool Compile(CompilerOptions options) { string intermediateAssemblyFile = Path.GetTempFileName(), intermediateDocFile = Path.GetTempFileName(); var actualOut = Console.Out; var er = new ErrorReporterWrapper(_errorReporter, actualOut); try { Console.SetOut(new StringWriter()); // I don't trust the third-party libs to not generate spurious random messages, so make sure that any of those messages are suppressed. var settings = MapSettings(options, intermediateAssemblyFile, intermediateDocFile, er); if (er.HasErrors) { return(false); } if (!options.AlreadyCompiled) { // Compile the assembly var ctx = new CompilerContext(settings, new ConvertingReportPrinter(er)); var d = new Mono.CSharp.Driver(ctx); d.Compile(); if (er.HasErrors) { return(false); } } var references = LoadReferences(settings.AssemblyReferences, er); if (references == null) { return(false); } PreparedCompilation compilation = PreparedCompilation.CreateCompilation(settings.AssemblyName, options.SourceFiles.Select(f => new SimpleSourceFile(f, settings.Encoding)), references.Select(r => r.Item1), options.DefineConstants, LoadResources(options.EmbeddedResources)); IMethod entryPoint = FindEntryPoint(options, er, compilation); var container = new WindsorContainer(); foreach (var plugin in TopologicalSortPlugins(references).Reverse()) { RegisterPlugin(container, plugin); } var attributeStore = new AttributeStore(compilation.Compilation, er); container.Register(Component.For <IErrorReporter>().Instance(er), Component.For <CompilerOptions>().Instance(options), Component.For <IAttributeStore>().Instance(attributeStore), Component.For <ICompilation>().Instance(compilation.Compilation), Component.For <ICompiler>().ImplementedBy <Compiler.Compiler>() ); InitializeAttributeStore(attributeStore, container, compilation.Compilation); container.Resolve <IMetadataImporter>().Prepare(compilation.Compilation.GetAllTypeDefinitions()); var compiledTypes = container.Resolve <ICompiler>().Compile(compilation); foreach (var rewriter in container.ResolveAll <IJSTypeSystemRewriter>()) { compiledTypes = rewriter.Rewrite(compiledTypes); } var invoker = new OOPEmulatorInvoker(container.Resolve <IOOPEmulator>(), container.Resolve <IMetadataImporter>(), container.Resolve <IErrorReporter>()); var js = invoker.Process(compiledTypes.ToList(), entryPoint); js = container.Resolve <ILinker>().Process(js); if (er.HasErrors) { return(false); } string outputAssemblyPath = !string.IsNullOrEmpty(options.OutputAssemblyPath) ? options.OutputAssemblyPath : Path.ChangeExtension(options.SourceFiles[0], ".dll"); string outputScriptPath = !string.IsNullOrEmpty(options.OutputScriptPath) ? options.OutputScriptPath : Path.ChangeExtension(options.SourceFiles[0], ".js"); if (!options.AlreadyCompiled) { try { File.Copy(intermediateAssemblyFile, outputAssemblyPath, true); } catch (IOException ex) { er.Region = DomRegion.Empty; er.Message(Messages._7950, ex.Message); return(false); } if (!string.IsNullOrEmpty(options.DocumentationFile)) { try { File.Copy(intermediateDocFile, options.DocumentationFile, true); } catch (IOException ex) { er.Region = DomRegion.Empty; er.Message(Messages._7952, ex.Message); return(false); } } } if (options.MinimizeScript) { js = ((JsBlockStatement)Minifier.Process(JsStatement.Block(js))).Statements; } string script = options.MinimizeScript ? OutputFormatter.FormatMinified(js) : OutputFormatter.Format(js); try { File.WriteAllText(outputScriptPath, script, settings.Encoding); } catch (IOException ex) { er.Region = DomRegion.Empty; er.Message(Messages._7951, ex.Message); return(false); } return(true); } catch (Exception ex) { er.Region = DomRegion.Empty; er.InternalError(ex.ToString()); return(false); } finally { if (!options.AlreadyCompiled) { try { File.Delete(intermediateAssemblyFile); } catch {} try { File.Delete(intermediateDocFile); } catch {} } if (actualOut != null) { Console.SetOut(actualOut); } } }
private static CompilerSettings MapSettings(CompilerOptions options, string outputAssemblyPath, string outputDocFilePath, IErrorReporter er) { var allPaths = options.AdditionalLibPaths.Concat(new[] { Environment.CurrentDirectory }).ToList(); var result = new CompilerSettings(); result.Target = Target.Library; result.Platform = Platform.AnyCPU; result.TargetExt = ".dll"; result.VerifyClsCompliance = false; result.Optimize = false; result.Version = LanguageVersion.V_5; result.EnhancedWarnings = false; result.LoadDefaultReferences = false; result.TabSize = 1; result.WarningsAreErrors = options.TreatWarningsAsErrors; result.FatalCounter = 100; result.WarningLevel = options.WarningLevel; result.AssemblyReferences = options.References.Where(r => r.Alias == null).Select(r => ResolveReference(r.Filename, allPaths, er)).ToList(); result.AssemblyReferencesAliases = options.References.Where(r => r.Alias != null).Select(r => Tuple.Create(r.Alias, ResolveReference(r.Filename, allPaths, er))).ToList(); result.Encoding = Encoding.UTF8; result.DocumentationFile = !string.IsNullOrEmpty(options.DocumentationFile) ? outputDocFilePath : null; result.OutputFile = outputAssemblyPath; result.AssemblyName = GetAssemblyName(options); result.StdLib = false; result.StdLibRuntimeVersion = RuntimeVersion.v4; result.StrongNameKeyContainer = options.KeyContainer; result.StrongNameKeyFile = options.KeyFile; result.SourceFiles.AddRange(options.SourceFiles.Select((f, i) => new SourceFile(f, f, i + 1))); foreach (var c in options.DefineConstants) result.AddConditionalSymbol(c); foreach (var w in options.DisabledWarnings) result.SetIgnoreWarning(w); result.SetIgnoreWarning(660); // 660 and 661: class defines operator == or operator != but does not override Equals / GetHashCode. These warnings don't really apply, since we have no Equals / GetHashCode methods to override. result.SetIgnoreWarning(661); foreach (var w in options.WarningsAsErrors) result.AddWarningAsError(w); foreach (var w in options.WarningsNotAsErrors) result.AddWarningOnly(w); if (result.AssemblyReferencesAliases.Count > 0) { // NRefactory does currently not support reference aliases, this check will hopefully go away in the future. er.Region = DomRegion.Empty; er.Message(7998, "aliased reference"); } return result; }
private Tuple<bool, List<Message>> Compile(string source, string baseName, params string[] references) { var er = new MockErrorReporter(); var driver = new CompilerDriver(er); File.WriteAllText(Path.GetFullPath(baseName + ".cs"), source); var options = new CompilerOptions { References = { new Reference(Common.MscorlibPath) }, SourceFiles = { Path.GetFullPath(baseName + ".cs") }, OutputAssemblyPath = Path.GetFullPath(baseName + ".dll"), OutputScriptPath = Path.GetFullPath(baseName + ".js"), }; foreach (var r in references) options.References.Add(new Reference(Path.GetFullPath(r + ".dll"))); bool result = driver.Compile(options, false); return Tuple.Create(result, er.AllMessages); }
public void TheOutputFileNamesAreTakenFromTheFirstSourceFileIfNotSpecified() { UsingFiles(() => { File.WriteAllText(Path.GetFullPath("FirstFile.cs"), @"class C1 { public void M() {} }"); File.WriteAllText(Path.GetFullPath("SecondFile.cs"), @"class C2 { public void M() {} }"); var options = new CompilerOptions { References = { new Reference(Common.MscorlibPath) }, SourceFiles = { Path.GetFullPath("FirstFile.cs"), Path.GetFullPath("SecondFile.cs") }, }; var er = new MockErrorReporter(); var driver = new CompilerDriver(er); var result = driver.Compile(options, false); Assert.That(result, Is.True); Assert.That(File.Exists(Path.GetFullPath("FirstFile.dll")), Is.True); Assert.That(File.Exists(Path.GetFullPath("FirstFile.js")), Is.True); var asm = AssemblyDefinition.ReadAssembly(Path.GetFullPath("FirstFile.dll")); Assert.That(asm.Name.Name, Is.EqualTo("FirstFile")); }, "FirstFile.cs", "SecondFile.cs", "FirstFile.dll", "FirstFile.js"); }
public void UsingAliasedReferenceCausesError7998() { UsingFiles(() => { var er = new MockErrorReporter(); var driver = new CompilerDriver(er); File.WriteAllText(Path.GetFullPath("Ref.cs"), @"public class Class1 { public void M() {} }"); var options = new CompilerOptions { References = { new Reference(Common.MscorlibPath) }, SourceFiles = { Path.GetFullPath("Ref.cs") }, OutputAssemblyPath = Path.GetFullPath("Ref.dll"), OutputScriptPath = Path.GetFullPath("Ref.js"), }; bool result = driver.Compile(options, false); Assert.That(result, Is.True); Assert.That(er.AllMessages, Is.Empty); File.WriteAllText(Path.GetFullPath("Out.cs"), @"extern alias myalias; class Class2 : myalias::Class1 { public void M2() {} }"); options = new CompilerOptions { References = { new Reference(Common.MscorlibPath), new Reference(Path.GetFullPath("Ref.dll"), alias: "myalias") }, SourceFiles = { Path.GetFullPath("Out.cs") }, OutputAssemblyPath = Path.GetFullPath("Out.dll"), OutputScriptPath = Path.GetFullPath("Out.js"), }; result = driver.Compile(options, false); Assert.That(result, Is.False); Assert.That(er.AllMessages.Single().Code, Is.EqualTo(7998)); Assert.That(er.AllMessages.Single().Args[0], Is.EqualTo("aliased reference")); }, "Ref.cs", "Ref.dll", "Ref.js", "Out.cs", "Out.dll", "Out.js"); }
public void EntryPointCanBeSpecified() { UsingFiles(() => { var er = new MockErrorReporter(); var driver = new CompilerDriver(er); File.WriteAllText(Path.GetFullPath("File1.cs"), @"namespace MyNamespace { public class SomeClass { public static void Main() {} } } public class OtherClass { public static void Main() {} }"); var options = new CompilerOptions { References = { new Reference(Common.MscorlibPath) }, SourceFiles = { Path.GetFullPath("File1.cs") }, HasEntryPoint = true, EntryPointClass = "MyNamespace.SomeClass", DisabledWarnings = { 28 }, OutputAssemblyPath = Path.GetFullPath("Test.dll"), OutputScriptPath = Path.GetFullPath("Test.js") }; bool result = driver.Compile(options, false); Assert.That(result, Is.True); Assert.That(er.AllMessages, Is.Empty); var content = File.ReadAllText(Path.GetFullPath("Test.js")); Assert.That(content.Replace("\r\n", "\n").EndsWith("$MyNamespace_SomeClass.main();\n"), Is.True); }, "File1.cs", "Test.dll", "Test.js"); }
public bool Compile(CompilerOptions options, ErrorReporterWrapper er) { string intermediateAssemblyFile = Path.GetTempFileName(), intermediateDocFile = Path.GetTempFileName(); try { // Compile the assembly var settings = MapSettings(options, intermediateAssemblyFile, intermediateDocFile, er); if (er.HasErrors) { return(false); } if (!options.AlreadyCompiled) { // Compile the assembly var ctx = new CompilerContext(settings, new ConvertingReportPrinter(er)); var d = new Mono.CSharp.Driver(ctx); d.Compile(); if (er.HasErrors) { return(false); } } // Compile the script var md = new MetadataImporter.ScriptSharpMetadataImporter(options.MinimizeScript); var n = new DefaultNamer(); PreparedCompilation compilation = null; var rtl = new ScriptSharpRuntimeLibrary(md, er, n.GetTypeParameterName, tr => new JsTypeReferenceExpression(tr.Resolve(compilation.Compilation).GetDefinition())); var compiler = new Compiler.Compiler(md, n, rtl, er, allowUserDefinedStructs: options.References.Count == 0 /* We allow user-defined structs in mscorlib only, which can be identified by the fact that it has no references*/); var references = LoadReferences(settings.AssemblyReferences, er); if (references == null) { return(false); } compilation = compiler.CreateCompilation(options.SourceFiles.Select(f => new SimpleSourceFile(f, settings.Encoding)), references, options.DefineConstants); var compiledTypes = compiler.Compile(compilation); IMethod entryPoint = null; if (options.HasEntryPoint) { List <IMethod> candidates; if (!string.IsNullOrEmpty(options.EntryPointClass)) { var t = compilation.Compilation.MainAssembly.GetTypeDefinition(new FullTypeName(options.EntryPointClass)); if (t == null) { er.Region = DomRegion.Empty; er.Message(7950, "Could not find the entry point class " + options.EntryPointClass + "."); return(false); } candidates = t.Methods.Where(IsEntryPointCandidate).ToList(); } else { candidates = compilation.Compilation.MainAssembly.GetAllTypeDefinitions().SelectMany(t => t.Methods).Where(IsEntryPointCandidate).ToList(); } if (candidates.Count != 1) { er.Region = DomRegion.Empty; er.Message(7950, "Could not find a unique entry point."); return(false); } entryPoint = candidates[0]; } var js = new ScriptSharpOOPEmulator(compilation.Compilation, md, rtl, n, er).Process(compiledTypes, compilation.Compilation, entryPoint); js = new DefaultLinker(md, n).Process(js, compilation.Compilation.MainAssembly); if (er.HasErrors) { return(false); } string outputAssemblyPath = !string.IsNullOrEmpty(options.OutputAssemblyPath) ? options.OutputAssemblyPath : Path.ChangeExtension(options.SourceFiles[0], ".dll"); string outputScriptPath = !string.IsNullOrEmpty(options.OutputScriptPath) ? options.OutputScriptPath : Path.ChangeExtension(options.SourceFiles[0], ".js"); if (!options.AlreadyCompiled) { try { File.Copy(intermediateAssemblyFile, outputAssemblyPath, true); } catch (IOException ex) { er.Region = DomRegion.Empty; er.Message(7950, ex.Message); return(false); } if (!string.IsNullOrEmpty(options.DocumentationFile)) { try { File.Copy(intermediateDocFile, options.DocumentationFile, true); } catch (IOException ex) { er.Region = DomRegion.Empty; er.Message(7952, ex.Message); return(false); } } } if (options.MinimizeScript) { js = ((JsBlockStatement)Minifier.Process(new JsBlockStatement(js))).Statements; } string script = string.Join("", js.Select(s => options.MinimizeScript ? OutputFormatter.FormatMinified(s) : OutputFormatter.Format(s))); try { File.WriteAllText(outputScriptPath, script, settings.Encoding); } catch (IOException ex) { er.Region = DomRegion.Empty; er.Message(7951, ex.Message); return(false); } return(true); } catch (Exception ex) { er.Region = DomRegion.Empty; er.InternalError(ex.ToString()); return(false); } finally { if (!options.AlreadyCompiled) { try { File.Delete(intermediateAssemblyFile); } catch {} try { File.Delete(intermediateDocFile); } catch {} } } }
public void ErrorWritingTheOutputScriptGivesCS7951() { UsingFiles(() => { File.WriteAllText(Path.GetFullPath("File.cs"), @"class Class1 { public void M() {} }"); var options = new CompilerOptions { References = { new Reference(Common.MscorlibPath) }, SourceFiles = { Path.GetFullPath("File.cs") }, OutputAssemblyPath = Path.GetFullPath("MyOutputFile.dll"), OutputScriptPath = Path.GetFullPath("MyOutputFile.js"), DocumentationFile = Path.GetFullPath("MyOutputFile.xml"), }; var er = new MockErrorReporter(); var driver = new CompilerDriver(er); bool result; using (File.Open(Path.GetFullPath("MyOutputFile.js"), FileMode.Create)) { result = driver.Compile(options, false); } Assert.That(result, Is.False); Assert.That(er.AllMessages.Any(m => m.Code == 7951 && m.Args.Length == 1)); }, "File.cs", "MyOutputFile.dll", "MyOutputFile.js", "MyOutputFile.xml"); }
public bool Compile(CompilerOptions options, ErrorReporterWrapper er) { string intermediateAssemblyFile = Path.GetTempFileName(), intermediateDocFile = Path.GetTempFileName(); try { // Compile the assembly var settings = MapSettings(options, intermediateAssemblyFile, intermediateDocFile, er); if (er.HasErrors) return false; if (!options.AlreadyCompiled) { // Compile the assembly var ctx = new CompilerContext(settings, new ConvertingReportPrinter(er)); var d = new Mono.CSharp.Driver(ctx); d.Compile(); if (er.HasErrors) return false; } // Compile the script var md = new MetadataImporter.ScriptSharpMetadataImporter(options.MinimizeScript); var n = new DefaultNamer(); PreparedCompilation compilation = null; var rtl = new ScriptSharpRuntimeLibrary(md, er, n.GetTypeParameterName, tr => { var t = tr.Resolve(compilation.Compilation).GetDefinition(); return new JsTypeReferenceExpression(t.ParentAssembly, md.GetTypeSemantics(t).Name); }); var compiler = new Compiler.Compiler(md, n, rtl, er, allowUserDefinedStructs: options.References.Count == 0 /* We allow user-defined structs in mscorlib only, which can be identified by the fact that it has no references*/); var references = LoadReferences(settings.AssemblyReferences, er); if (references == null) return false; compilation = compiler.CreateCompilation(options.SourceFiles.Select(f => new SimpleSourceFile(f, settings.Encoding)), references, options.DefineConstants); var compiledTypes = compiler.Compile(compilation); var js = new ScriptSharpOOPEmulator(compilation.Compilation, md, rtl, er).Rewrite(compiledTypes, compilation.Compilation); js = new GlobalNamespaceReferenceImporter().ImportReferences(js); if (er.HasErrors) return false; string outputAssemblyPath = !string.IsNullOrEmpty(options.OutputAssemblyPath) ? options.OutputAssemblyPath : Path.ChangeExtension(options.SourceFiles[0], ".dll"); string outputScriptPath = !string.IsNullOrEmpty(options.OutputScriptPath) ? options.OutputScriptPath : Path.ChangeExtension(options.SourceFiles[0], ".js"); if (!options.AlreadyCompiled) { try { File.Copy(intermediateAssemblyFile, outputAssemblyPath, true); } catch (IOException ex) { er.Region = DomRegion.Empty; er.Message(7950, ex.Message); return false; } if (!string.IsNullOrEmpty(options.DocumentationFile)) { try { File.Copy(intermediateDocFile, options.DocumentationFile, true); } catch (IOException ex) { er.Region = DomRegion.Empty; er.Message(7952, ex.Message); return false; } } } string script = string.Join("", js.Select(s => options.MinimizeScript ? OutputFormatter.FormatMinified(Minifier.Process(s)) : OutputFormatter.Format(s))); try { File.WriteAllText(outputScriptPath, script, settings.Encoding); } catch (IOException ex) { er.Region = DomRegion.Empty; er.Message(7951, ex.Message); return false; } return true; } catch (Exception ex) { er.Region = DomRegion.Empty; er.InternalError(ex.ToString()); return false; } finally { if (!options.AlreadyCompiled) { try { File.Delete(intermediateAssemblyFile); } catch {} try { File.Delete(intermediateDocFile); } catch {} } } }
private static CompilerSettings MapSettings(CompilerOptions options, string outputAssemblyPath, string outputDocFilePath, IErrorReporter er) { var allPaths = options.AdditionalLibPaths.Concat(new[] { Environment.CurrentDirectory }).ToList(); var result = new CompilerSettings { Target = (options.HasEntryPoint ? Target.Exe : Target.Library), Platform = Platform.AnyCPU, TargetExt = (options.HasEntryPoint ? ".exe" : ".dll"), MainClass = options.EntryPointClass, VerifyClsCompliance = false, Optimize = false, Version = LanguageVersion.V_5, EnhancedWarnings = false, LoadDefaultReferences = false, TabSize = 1, WarningsAreErrors = options.TreatWarningsAsErrors, FatalCounter = 100, WarningLevel = options.WarningLevel, Encoding = Encoding.UTF8, DocumentationFile = !string.IsNullOrEmpty(options.DocumentationFile) ? outputDocFilePath : null, OutputFile = outputAssemblyPath, AssemblyName = GetAssemblyName(options), StdLib = false, StdLibRuntimeVersion = RuntimeVersion.v4, StrongNameKeyContainer = options.KeyContainer, StrongNameKeyFile = options.KeyFile, }; result.SourceFiles.AddRange(options.SourceFiles.Select((f, i) => new SourceFile(f, f, i + 1))); foreach (var r in options.References) { string resolvedPath = ResolveReference(r.Filename, allPaths, er); if (r.Alias == null) { result.AssemblyReferences.Add(resolvedPath); } else { result.AssemblyReferencesAliases.Add(Tuple.Create(r.Alias, resolvedPath)); } } foreach (var c in options.DefineConstants) { result.AddConditionalSymbol(c); } foreach (var w in options.DisabledWarnings) { result.SetIgnoreWarning(w); } foreach (var w in options.WarningsAsErrors) { result.AddWarningAsError(w); } foreach (var w in options.WarningsNotAsErrors) { result.AddWarningOnly(w); } if (options.EmbeddedResources.Count > 0) { result.Resources = options.EmbeddedResources.Select(r => new AssemblyResource(r.Filename, r.ResourceName, isPrivate: !r.IsPublic) { IsEmbeded = true }).ToList(); } if (result.AssemblyReferencesAliases.Count > 0) // NRefactory does currently not support reference aliases, this check will hopefully go away in the future. { er.Region = DomRegion.Empty; er.Message(Messages._7998, "aliased reference"); } return(result); }