From f1ab02f7a930c85169d26a0ce9d641f2542902b3 Mon Sep 17 00:00:00 2001 From: alcexhim Date: Wed, 10 Dec 2014 14:45:10 -0500 Subject: [PATCH] Various improvements to ProjectTask handling; still need to move Build launcher from SolutionExplorer to a generic Command (e.g. BuildAllProjects) --- .../Configuration/Commands.xml | 13 + ...{8891C1AE-6699-45DA-8B22-13BCEBB63364}.xml | 24 +- ...{F184B08F-C81C-45F6-A57F-5ABD9991F28F}.xml | 24 +- ...{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}.xml | 20 +- ...{AB211699-2C6A-4FCC-97FB-F629B1023277}.xml | 11 +- .../Languages/English.xml | 2 + ...{EA90755A-4A5D-4FA4-B676-F7BBD8CF0D84}.xml | 16 +- .../UEPackage/UEPackageXMLDataFormat.cs | 6 +- .../ExpandedString.cs | 254 +++++++++++++++++- .../UniversalEditor.Essential/ProjectTask.cs | 94 ++++++- .../ProjectTaskEvent.cs | 19 ++ .../UniversalEditor.Essential.csproj | 1 + 12 files changed, 395 insertions(+), 89 deletions(-) create mode 100644 CSharp/Plugins/UniversalEditor.Essential/ProjectTaskEvent.cs diff --git a/CSharp/Content/UniversalEditor.Content.PlatformIndependent/Configuration/Commands.xml b/CSharp/Content/UniversalEditor.Content.PlatformIndependent/Configuration/Commands.xml index 8cb395b3..ff06e918 100644 --- a/CSharp/Content/UniversalEditor.Content.PlatformIndependent/Configuration/Commands.xml +++ b/CSharp/Content/UniversalEditor.Content.PlatformIndependent/Configuration/Commands.xml @@ -21,12 +21,25 @@ + + + + + + + + + + + + + diff --git a/CSharp/Content/UniversalEditor.Content.PlatformIndependent/Extensions/SoftwareDeveloper/ProjectTypes/{8891C1AE-6699-45DA-8B22-13BCEBB63364}.xml b/CSharp/Content/UniversalEditor.Content.PlatformIndependent/Extensions/SoftwareDeveloper/ProjectTypes/{8891C1AE-6699-45DA-8B22-13BCEBB63364}.xml index c2be57d6..d52b49cb 100644 --- a/CSharp/Content/UniversalEditor.Content.PlatformIndependent/Extensions/SoftwareDeveloper/ProjectTypes/{8891C1AE-6699-45DA-8B22-13BCEBB63364}.xml +++ b/CSharp/Content/UniversalEditor.Content.PlatformIndependent/Extensions/SoftwareDeveloper/ProjectTypes/{8891C1AE-6699-45DA-8B22-13BCEBB63364}.xml @@ -12,21 +12,9 @@ - - - - - - - - - - - - - + - + @@ -49,7 +37,7 @@ - + @@ -57,7 +45,7 @@ - + @@ -65,10 +53,10 @@ - + - + diff --git a/CSharp/Content/UniversalEditor.Content.PlatformIndependent/Extensions/SoftwareDeveloper/ProjectTypes/{F184B08F-C81C-45F6-A57F-5ABD9991F28F}.xml b/CSharp/Content/UniversalEditor.Content.PlatformIndependent/Extensions/SoftwareDeveloper/ProjectTypes/{F184B08F-C81C-45F6-A57F-5ABD9991F28F}.xml index b449bf7a..c676a3db 100644 --- a/CSharp/Content/UniversalEditor.Content.PlatformIndependent/Extensions/SoftwareDeveloper/ProjectTypes/{F184B08F-C81C-45F6-A57F-5ABD9991F28F}.xml +++ b/CSharp/Content/UniversalEditor.Content.PlatformIndependent/Extensions/SoftwareDeveloper/ProjectTypes/{F184B08F-C81C-45F6-A57F-5ABD9991F28F}.xml @@ -9,31 +9,19 @@ - - - - - - - - - - - - - + - + - + - + - - + + diff --git a/CSharp/Content/UniversalEditor.Content.PlatformIndependent/Extensions/SoftwareDeveloper/ProjectTypes/{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}.xml b/CSharp/Content/UniversalEditor.Content.PlatformIndependent/Extensions/SoftwareDeveloper/ProjectTypes/{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}.xml index b269c2ae..ae795adf 100644 --- a/CSharp/Content/UniversalEditor.Content.PlatformIndependent/Extensions/SoftwareDeveloper/ProjectTypes/{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}.xml +++ b/CSharp/Content/UniversalEditor.Content.PlatformIndependent/Extensions/SoftwareDeveloper/ProjectTypes/{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}.xml @@ -11,25 +11,13 @@ - - - - - - - - - - - - - + - + - + - + diff --git a/CSharp/Content/UniversalEditor.Content.PlatformIndependent/Extensions/WebsiteDeveloper/ProjectTypes/{AB211699-2C6A-4FCC-97FB-F629B1023277}.xml b/CSharp/Content/UniversalEditor.Content.PlatformIndependent/Extensions/WebsiteDeveloper/ProjectTypes/{AB211699-2C6A-4FCC-97FB-F629B1023277}.xml index 401d4f00..8f75f59b 100644 --- a/CSharp/Content/UniversalEditor.Content.PlatformIndependent/Extensions/WebsiteDeveloper/ProjectTypes/{AB211699-2C6A-4FCC-97FB-F629B1023277}.xml +++ b/CSharp/Content/UniversalEditor.Content.PlatformIndependent/Extensions/WebsiteDeveloper/ProjectTypes/{AB211699-2C6A-4FCC-97FB-F629B1023277}.xml @@ -10,12 +10,11 @@ - C:\Program Files\Saxonica\bin\saxon.exe - - - - - + + + + + diff --git a/CSharp/Content/UniversalEditor.Content.PlatformIndependent/Languages/English.xml b/CSharp/Content/UniversalEditor.Content.PlatformIndependent/Languages/English.xml index 502c1bf4..be2b803f 100644 --- a/CSharp/Content/UniversalEditor.Content.PlatformIndependent/Languages/English.xml +++ b/CSharp/Content/UniversalEditor.Content.PlatformIndependent/Languages/English.xml @@ -52,6 +52,8 @@ + + diff --git a/CSharp/Content/UniversalEditor.Content.PlatformIndependent/ProjectTypes/{EA90755A-4A5D-4FA4-B676-F7BBD8CF0D84}.xml b/CSharp/Content/UniversalEditor.Content.PlatformIndependent/ProjectTypes/{EA90755A-4A5D-4FA4-B676-F7BBD8CF0D84}.xml index 65afe52b..8c380e0a 100644 --- a/CSharp/Content/UniversalEditor.Content.PlatformIndependent/ProjectTypes/{EA90755A-4A5D-4FA4-B676-F7BBD8CF0D84}.xml +++ b/CSharp/Content/UniversalEditor.Content.PlatformIndependent/ProjectTypes/{EA90755A-4A5D-4FA4-B676-F7BBD8CF0D84}.xml @@ -17,15 +17,13 @@ - $(ArduinoPath)\avr-gcc.exe - - - - - - - - + + + + + + + diff --git a/CSharp/Plugins/UniversalEditor.Essential/DataFormats/UEPackage/UEPackageXMLDataFormat.cs b/CSharp/Plugins/UniversalEditor.Essential/DataFormats/UEPackage/UEPackageXMLDataFormat.cs index d3bf8c0c..cf38a37a 100644 --- a/CSharp/Plugins/UniversalEditor.Essential/DataFormats/UEPackage/UEPackageXMLDataFormat.cs +++ b/CSharp/Plugins/UniversalEditor.Essential/DataFormats/UEPackage/UEPackageXMLDataFormat.cs @@ -430,7 +430,11 @@ namespace UniversalEditor.DataFormats.UEPackage if (attTypeID != null) { Guid id = new Guid(attTypeID.Value); - task.Actions.Add(ProjectTaskActionReference.GetByTypeID(id).Create()); + + ProjectTaskActionReference ptar = ProjectTaskActionReference.GetByTypeID(id); + ProjectTaskAction pta = ptar.Create(); + pta.LoadFromMarkup(tagAction); + task.Actions.Add(pta); } } } diff --git a/CSharp/Plugins/UniversalEditor.Essential/ExpandedString.cs b/CSharp/Plugins/UniversalEditor.Essential/ExpandedString.cs index acf81ed2..af313d9f 100644 --- a/CSharp/Plugins/UniversalEditor.Essential/ExpandedString.cs +++ b/CSharp/Plugins/UniversalEditor.Essential/ExpandedString.cs @@ -2,9 +2,63 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using UniversalEditor.ObjectModels.Markup; namespace UniversalEditor { + public class ExpandedStringVariableStore + { + + private ExpandedStringVariable.ExpandedStringVariableCollection mvarConstants = new ExpandedStringVariable.ExpandedStringVariableCollection(); + public ExpandedStringVariable.ExpandedStringVariableCollection Constants { get { return mvarConstants; } } + private ExpandedStringVariable.ExpandedStringVariableCollection mvarVariables = new ExpandedStringVariable.ExpandedStringVariableCollection(); + public ExpandedStringVariable.ExpandedStringVariableCollection Variables { get { return mvarVariables; } } + } + public class ExpandedStringVariable + { + private string mvarID = String.Empty; + public string ID { get { return mvarID; } set { mvarID = value; } } + + private object mvarValue = null; + public object Value { get { return mvarValue; } set { mvarValue = value; } } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append(mvarID); + sb.Append("="); + if (mvarValue == null) + { + sb.Append("(null)"); + } + else + { + sb.Append("\""); + sb.Append(mvarValue.ToString()); + sb.Append("\""); + } + return sb.ToString(); + } + + public class ExpandedStringVariableCollection + { + private Dictionary> variables = new Dictionary>(); + public ExpandedStringVariable this[ExpandedStringSegmentVariableScope scope, string id] + { + get + { + if (!variables.ContainsKey(scope)) variables.Add(scope, new Dictionary()); + if (!variables[scope].ContainsKey(id)) return null; + return variables[scope][id]; + } + set + { + if (!variables.ContainsKey(scope)) variables.Add(scope, new Dictionary()); + variables[scope][id] = value; + } + } + } + } public class ExpandedString { public static readonly ExpandedString Empty = new ExpandedString(); @@ -25,14 +79,76 @@ namespace UniversalEditor public ExpandedStringSegment.ExpandedStringSegmentCollection Segments { get { return mvarSegments; } } public override string ToString() + { + return mvarSegments.Count.ToString() + " segments"; + } + public string ToString(ExpandedStringVariableStore variables) { StringBuilder sb = new StringBuilder(); foreach (ExpandedStringSegment segment in mvarSegments) { - sb.Append(segment.ToString()); + sb.Append(segment.ToString(variables)); } return sb.ToString(); } + + public static ExpandedString FromMarkup(MarkupTagElement markup) + { + ExpandedString value = new ExpandedString(); + foreach (MarkupElement el in markup.Elements) + { + MarkupTagElement tag = (el as MarkupTagElement); + if (tag == null) continue; + switch (tag.FullName) + { + case "VariableReference": + case "ConstantReference": + { + MarkupAttribute attScope = tag.Attributes["Scope"]; + ExpandedStringSegmentVariableScope scope = ExpandedStringSegmentVariableScope.None; + if (attScope != null) + { + switch (attScope.Value.ToLower()) + { + case "file": scope = ExpandedStringSegmentVariableScope.File; break; + case "project": scope = ExpandedStringSegmentVariableScope.Project; break; + case "solution": scope = ExpandedStringSegmentVariableScope.Solution; break; + case "global": scope = ExpandedStringSegmentVariableScope.Global; break; + } + } + + MarkupAttribute attID = tag.Attributes["ID"]; + if (attID == null) continue; + + string separator = ";"; + MarkupAttribute attSeparator = tag.Attributes["Separator"]; + if (attSeparator != null) + { + separator = attSeparator.Value; + } + + if (tag.FullName == "VariableReference") + { + value.Segments.Add(new ExpandedStringSegmentVariable(attID.Value, scope, separator)); + } + else if (tag.FullName == "ConstantReference") + { + value.Segments.Add(new ExpandedStringSegmentConstant(attID.Value, scope, separator)); + } + break; + } + case "Literal": + { + MarkupAttribute attValue = tag.Attributes["Value"]; + if (attValue == null) continue; + + value.Segments.Add(new ExpandedStringSegmentLiteral(attValue.Value)); + break; + } + } + } + return value; + } } public abstract class ExpandedStringSegment { @@ -42,9 +158,9 @@ namespace UniversalEditor } - private static readonly Dictionary _empty = new Dictionary(); + private static readonly ExpandedStringVariableStore _empty = new ExpandedStringVariableStore(); - public abstract string ToString(Dictionary variables); + public abstract string ToString(ExpandedStringVariableStore variables); public override string ToString() { return ToString(_empty); @@ -52,14 +168,51 @@ namespace UniversalEditor } public class ExpandedStringSegmentLiteral : ExpandedStringSegment { + public ExpandedStringSegmentLiteral() + { + mvarValue = String.Empty; + } + public ExpandedStringSegmentLiteral(string value) + { + mvarValue = value; + } + private string mvarValue = String.Empty; public string Value { get { return mvarValue; } set { mvarValue = value; } } - public override string ToString(Dictionary variables) + public override string ToString(ExpandedStringVariableStore variables) { return mvarValue; } } + + /// + /// The scope of an . + /// + public enum ExpandedStringSegmentVariableScope + { + /// + /// No scope is defined for this variable. Automatically searches for the variable in this scope order: first + /// file scope, then project scope, then solution scope, and finally global scope. + /// + None = 0, + /// + /// The variable is defined at the file level. + /// + File = 1, + /// + /// The variable is defined at the project level. + /// + Project = 2, + /// + /// The variable is defined at the solution level. + /// + Solution = 3, + /// + /// The variable is defined at the global level. + /// + Global = 4 + } /// /// Represents a string segment whose value is populated by a variable. /// @@ -71,13 +224,36 @@ namespace UniversalEditor /// public string VariableName { get { return mvarVariableName; } set { mvarVariableName = value; } } + private ExpandedStringSegmentVariableScope mvarScope = ExpandedStringSegmentVariableScope.None; + /// + /// The scope of the variable to search for, or to + /// search all scopes in the order of file, project, solution, global. + /// + public ExpandedStringSegmentVariableScope Scope { get { return mvarScope; } set { mvarScope = value; } } + + private string mvarSeparator = String.Empty; + /// + /// The array separator to use when the value of the variable is an array. + /// + public string Separator { get { return mvarSeparator; } set { mvarSeparator = value; } } + /// /// Creates a new instance of with the given variable name. /// - /// The name of the variable in the variables dictionary from which to retrieve the value for this . - public ExpandedStringSegmentVariable(string variableName) + /// + /// The name of the variable in the variables dictionary from which to retrieve the value for this + /// . + /// + /// + /// The scope of the variable to search for, or to + /// search all scopes in the order of file, project, solution, global. + /// + /// The array separator to use when the value of the variable is an array. + public ExpandedStringSegmentVariable(string variableName, ExpandedStringSegmentVariableScope scope = ExpandedStringSegmentVariableScope.None, string separator = null) { mvarVariableName = variableName; + mvarScope = scope; + mvarSeparator = separator; } /// @@ -85,9 +261,71 @@ namespace UniversalEditor /// /// The variables to pass into the . /// A that contains the value of this . - public override string ToString(Dictionary variables) + public override string ToString(ExpandedStringVariableStore variables) { - return variables[mvarVariableName]; + ExpandedStringVariable varr = variables.Variables[mvarScope, mvarVariableName]; + if (varr != null && varr.Value != null) return varr.Value.ToString(); + return String.Empty; + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("Variable: \""); + sb.Append(mvarVariableName); + sb.Append("\" ("); + sb.Append(mvarScope.ToString()); + sb.Append(" scope)"); + + if (!String.IsNullOrEmpty(mvarSeparator)) + { + sb.Append(" (Array; separator=\""); + sb.Append(mvarSeparator); + sb.Append("\")"); + } + return sb.ToString(); + } + } + public class ExpandedStringSegmentConstant : ExpandedStringSegmentVariable + { + /// + /// Creates a new instance of with the given variable name. + /// + /// + /// The name of the variable in the variables dictionary from which to retrieve the value for this + /// . + /// + /// + /// The scope of the variable to search for, or to + /// search all scopes in the order of file, project, solution, global. + /// + /// The array separator to use when the value of the variable is an array. + public ExpandedStringSegmentConstant(string variableName, ExpandedStringSegmentVariableScope scope = ExpandedStringSegmentVariableScope.None, string separator = null) + : base(variableName, scope, separator) + { + } + public override string ToString(ExpandedStringVariableStore variables) + { + ExpandedStringVariable varr = variables.Constants[Scope, VariableName]; + if (varr != null && varr.Value != null) return varr.Value.ToString(); + return String.Empty; + } + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("Constant: \""); + sb.Append(VariableName); + sb.Append("\" ("); + sb.Append(Scope.ToString()); + sb.Append(" scope)"); + + if (!String.IsNullOrEmpty(Separator)) + { + sb.Append(" (Array; separator=\""); + sb.Append(Separator); + sb.Append("\")"); + } + return sb.ToString(); } } } diff --git a/CSharp/Plugins/UniversalEditor.Essential/ProjectTask.cs b/CSharp/Plugins/UniversalEditor.Essential/ProjectTask.cs index 42b575d3..e443ae3d 100644 --- a/CSharp/Plugins/UniversalEditor.Essential/ProjectTask.cs +++ b/CSharp/Plugins/UniversalEditor.Essential/ProjectTask.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using UniversalEditor.ObjectModels.Markup; namespace UniversalEditor { @@ -13,32 +14,73 @@ namespace UniversalEditor } + public event EventHandler TaskStarted; + public event ProjectTaskEventHandler TaskCompleted; + public event ProjectTaskEventHandler TaskFailed; + public event ProgressEventHandler TaskProgress; + + protected virtual void OnTaskStarted(EventArgs e) + { + if (TaskStarted != null) TaskStarted(this, e); + } + protected virtual void OnTaskCompleted(ProjectTaskEventArgs e) + { + if (TaskCompleted != null) TaskCompleted(this, e); + } + protected virtual void OnTaskFailed(ProjectTaskEventArgs e) + { + if (TaskFailed != null) TaskFailed(this, e); + } + protected virtual void OnTaskProgress(ProgressEventArgs e) + { + if (TaskProgress != null) TaskProgress(this, e); + } + private ProjectTaskAction.ProjectTaskActionCollection mvarActions = new ProjectTaskAction.ProjectTaskActionCollection(); public ProjectTaskAction.ProjectTaskActionCollection Actions { get { return mvarActions; } } private string mvarTitle = String.Empty; public string Title { get { return mvarTitle; } set { mvarTitle = value; } } - public void Execute(ProgressEventHandler progressEventHandler = null) + public void Execute() { + OnTaskStarted(EventArgs.Empty); + + ExpandedStringVariableStore variables = new ExpandedStringVariableStore(); + ExpandedStringVariable varr = new ExpandedStringVariable(); + varr.ID = "CompilerExecutablePath"; + varr.Value = @"C:\Applications\MinGW\bin\gcc.exe"; + variables.Variables[ExpandedStringSegmentVariableScope.Global, "CompilerExecutablePath"] = varr; + + varr = new ExpandedStringVariable(); + varr.ID = "OutputFileName"; + varr.Value = @"C:\Temp\ProjectOutput.exe"; + variables.Variables[ExpandedStringSegmentVariableScope.Project, "OutputFileName"] = varr; + for (int i = 0; i < mvarActions.Count; i++) { - mvarActions[i].Execute(); - if (progressEventHandler != null) + try { - progressEventHandler(this, new ProgressEventArgs(i, mvarActions.Count, mvarActions[i].Title)); + mvarActions[i].Execute(variables); } + catch (Exception ex) + { + OnTaskFailed(new ProjectTaskEventArgs(ex.Message)); + return; + } + + OnTaskProgress(new ProgressEventArgs(i, mvarActions.Count, mvarActions[i].Title)); } } } public abstract class ProjectTaskAction : References { public abstract string Title { get; } - protected abstract void ExecuteInternal(); + protected abstract void ExecuteInternal(ExpandedStringVariableStore variables); - public void Execute() + public void Execute(ExpandedStringVariableStore variables) { - ExecuteInternal(); + ExecuteInternal(variables); } public class ProjectTaskActionCollection @@ -51,6 +93,14 @@ namespace UniversalEditor { return new ProjectTaskActionReference(GetType()); } + + public void LoadFromMarkup(MarkupTagElement tag) + { + if (tag == null) return; + if (tag.FullName != "Action") return; + LoadFromMarkupInternal(tag); + } + protected abstract void LoadFromMarkupInternal(MarkupTagElement tag); } public class ProjectTaskActionReference : ReferencedBy { @@ -148,9 +198,9 @@ namespace UniversalEditor } } - protected override void ExecuteInternal() + protected override void ExecuteInternal(ExpandedStringVariableStore variables) { - string fileNameWithArguments = mvarCommandLine.ToString(); + string fileNameWithArguments = mvarCommandLine.ToString(variables); if (String.IsNullOrEmpty(fileNameWithArguments)) return; string[] fileNameArgumentsSplit = fileNameWithArguments.Split(new char[] { ' ' }, "\"", StringSplitOptions.None, 2); @@ -160,12 +210,30 @@ namespace UniversalEditor if (!System.IO.File.Exists(fileName)) throw new System.IO.FileNotFoundException(fileName); System.Diagnostics.Process p = new System.Diagnostics.Process(); - - StringBuilder sbArguments = new StringBuilder(); - // TODO: complete loading arguments - p.StartInfo = new System.Diagnostics.ProcessStartInfo(fileName, arguments); + p.StartInfo.UseShellExecute = false; + p.StartInfo.CreateNoWindow = true; + p.StartInfo.RedirectStandardError = true; + p.StartInfo.RedirectStandardOutput = true; p.Start(); + p.WaitForExit(); + + string error = p.StandardError.ReadToEnd(); + string output = p.StandardOutput.ReadToEnd(); + + if (!String.IsNullOrEmpty(error)) + { + throw new Exception(error); + } + } + + protected override void LoadFromMarkupInternal(MarkupTagElement tag) + { + MarkupTagElement tagCommandLine = (tag.Elements["CommandLine"] as MarkupTagElement); + if (tagCommandLine != null) + { + mvarCommandLine = ExpandedString.FromMarkup(tagCommandLine); + } } } } diff --git a/CSharp/Plugins/UniversalEditor.Essential/ProjectTaskEvent.cs b/CSharp/Plugins/UniversalEditor.Essential/ProjectTaskEvent.cs new file mode 100644 index 00000000..48ee8b66 --- /dev/null +++ b/CSharp/Plugins/UniversalEditor.Essential/ProjectTaskEvent.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace UniversalEditor +{ + public delegate void ProjectTaskEventHandler(object sender, ProjectTaskEventArgs e); + public class ProjectTaskEventArgs : EventArgs + { + private string mvarMessage = String.Empty; + public string Message { get { return mvarMessage; } set { mvarMessage = value; } } + + public ProjectTaskEventArgs(string message) + { + mvarMessage = message; + } + } +} diff --git a/CSharp/Plugins/UniversalEditor.Essential/UniversalEditor.Essential.csproj b/CSharp/Plugins/UniversalEditor.Essential/UniversalEditor.Essential.csproj index b862bc71..6549eecd 100644 --- a/CSharp/Plugins/UniversalEditor.Essential/UniversalEditor.Essential.csproj +++ b/CSharp/Plugins/UniversalEditor.Essential/UniversalEditor.Essential.csproj @@ -111,6 +111,7 @@ +