From da3a40b6a89be9e179387fba0970debbd4673650 Mon Sep 17 00:00:00 2001 From: David Maas Date: Mon, 22 Apr 2024 16:40:55 -0500 Subject: [PATCH] Allow script extensions to declare unsafe blocks. This change also improves the robustness of the `UseWindowsForms` check, only checking in appropriate locations within the project file and disregarding the case of `true` vs `True`. (The latter matters if someone uses the Visual Studio project editor, as it now uses `True` instead of `true`.) Fixes https://github.com/bonsai-rx/bonsai/issues/1727 --- Bonsai.Configuration/ScriptExtensions.cs | 18 ++++++++++++++-- .../ScriptExtensionsProvider.cs | 21 ++++++++++++++----- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/Bonsai.Configuration/ScriptExtensions.cs b/Bonsai.Configuration/ScriptExtensions.cs index 35a574ed..1806fbd2 100644 --- a/Bonsai.Configuration/ScriptExtensions.cs +++ b/Bonsai.Configuration/ScriptExtensions.cs @@ -7,6 +7,7 @@ using System.Reflection; using System.Xml; using System.Xml.Linq; +using System.Xml.XPath; namespace Bonsai.Configuration { @@ -20,6 +21,7 @@ public class ScriptExtensions : IDisposable const string PackageVersionAttribute = "Version"; const string UseWindowsFormsElement = "UseWindowsForms"; const string ItemGroupElement = "ItemGroup"; + const string AllowUnsafeBlocksElement = "AllowUnsafeBlocks"; const string ProjectFileTemplate = @" @@ -98,6 +100,12 @@ static XmlReaderSettings GetXmlReaderSettings() }; } + static XElement GetProperty(XDocument document, string key) + => document.XPathSelectElement($"/Project/PropertyGroup/{key}"); + + static bool? GetBoolProperty(XDocument document, string key) + => GetProperty(document, key)?.Value?.Equals("true", StringComparison.InvariantCultureIgnoreCase); + public IEnumerable GetAssemblyReferences() { yield return "System.dll"; @@ -114,8 +122,7 @@ public IEnumerable GetAssemblyReferences() if (!File.Exists(ProjectFileName)) yield break; using var stream = File.OpenRead(ProjectFileName); var document = LoadProjectDocument(stream); - var useWindowsForms = document.Descendants(XName.Get(UseWindowsFormsElement)).FirstOrDefault(); - if (useWindowsForms != null && useWindowsForms.Value == "true") + if (GetBoolProperty(document, UseWindowsFormsElement) ?? false) { yield return "System.Windows.Forms.dll"; } @@ -195,6 +202,13 @@ public void AddAssemblyReferences(IEnumerable assemblyReferences) File.WriteAllText(ProjectFileName, root.ToString(SaveOptions.DisableFormatting)); } + public bool GetAllowUnsafeBlocks() + { + using var stream = File.OpenRead(ProjectFileName); + var document = LoadProjectDocument(stream); + return GetBoolProperty(document, AllowUnsafeBlocksElement) ?? false; + } + public void Dispose() { assemblyFolder.Dispose(); diff --git a/Bonsai.Configuration/ScriptExtensionsProvider.cs b/Bonsai.Configuration/ScriptExtensionsProvider.cs index 48c507fd..b3ce6851 100644 --- a/Bonsai.Configuration/ScriptExtensionsProvider.cs +++ b/Bonsai.Configuration/ScriptExtensionsProvider.cs @@ -143,15 +143,26 @@ string GetAssemblyLocation(string fileName) return fileName; } - var compilerParameters = new CompilerParameters(assemblyReferences, assemblyFile); - compilerParameters.GenerateExecutable = false; - compilerParameters.GenerateInMemory = false; - compilerParameters.IncludeDebugInformation = includeDebugInformation; + var compilerParameters = new CompilerParameters(assemblyReferences, assemblyFile) + { + GenerateExecutable = false, + GenerateInMemory = false, + IncludeDebugInformation = includeDebugInformation, + CompilerOptions = "", + }; + + if (scriptEnvironment.GetAllowUnsafeBlocks()) + { + compilerParameters.CompilerOptions += " /unsafe"; + } + if (!includeDebugInformation) { - compilerParameters.CompilerOptions = "/optimize"; + compilerParameters.CompilerOptions += " /optimize"; } + compilerParameters.CompilerOptions = compilerParameters.CompilerOptions.TrimStart(); + using (var codeProvider = new CSharpCodeProvider()) { var results = codeProvider.CompileAssemblyFromFile(compilerParameters, scriptFiles);