public void TestLoadXml() { TaskParser tp = new TaskParser(); string s = @"<ProjectSchemaDefinitions xmlns=`clr-namespace:Microsoft.Build.Framework.XamlTypes;assembly=Microsoft.Build.Framework` xmlns:x=`http://schemas.microsoft.com/winfx/2006/xaml` xmlns:sys=`clr-namespace:System;assembly=mscorlib` xmlns:impl=`clr-namespace:Microsoft.VisualStudio.Project.Contracts.Implementation;assembly=Microsoft.VisualStudio.Project.Contracts.Implementation`> <Rule Name=`TaskGeneratorLoadTest`> <BoolProperty Name=`TestProperty1` Switch=`tp` /> </Rule> </ProjectSchemaDefinitions>"; Assert.True(tp.Parse(s.Replace("`", "\""), "TaskGeneratorLoadTest")); // "File failed to load correctly." }
public TaskGenerator() { this.propertiesTypesToIgnore = new string[] { "AdditionalOptions" }; this.platform = string.Empty; this.dependencyList = new Dictionary<string, Property>(StringComparer.OrdinalIgnoreCase); this.errorLog = new LinkedList<string>(); this.taskParser = new TaskParser(); this.relationsParser = new RelationsParser(); }
public CommandLineGenerator(Rule rule, Dictionary <string, Object> parameterValues) { ErrorUtilities.VerifyThrowArgumentNull(rule, nameof(rule)); ErrorUtilities.VerifyThrowArgumentNull(parameterValues, nameof(parameterValues)); // Parse the Xaml file var parser = new TaskParser(); bool success = parser.ParseXamlDocument(rule); ErrorUtilities.VerifyThrow(success, "Unable to parse specified file or contents."); // Generate the switch order list _switchOrderList = parser.SwitchOrderList; foreach (Property property in parser.Properties) { if (parameterValues.TryGetValue(property.Name, out object value)) { var switchToAdd = new CommandLineToolSwitch(); if (!String.IsNullOrEmpty(property.Reversible) && String.Equals(property.Reversible, "true", StringComparison.OrdinalIgnoreCase)) { switchToAdd.Reversible = true; } switchToAdd.IncludeInCommandLine = property.IncludeInCommandLine; switchToAdd.Separator = property.Separator; switchToAdd.DisplayName = property.DisplayName; switchToAdd.Description = property.Description; if (!String.IsNullOrEmpty(property.Required) && String.Equals(property.Required, "true", StringComparison.OrdinalIgnoreCase)) { switchToAdd.Required = true; } switchToAdd.FallbackArgumentParameter = property.Fallback; switchToAdd.FalseSuffix = property.FalseSuffix; switchToAdd.TrueSuffix = property.TrueSuffix; if (!String.IsNullOrEmpty(property.SwitchName)) { switchToAdd.SwitchValue = property.Prefix + property.SwitchName; } switchToAdd.IsValid = true; // Based on the switch type, cast the value and set as appropriate switch (property.Type) { case PropertyType.Boolean: switchToAdd.Type = CommandLineToolSwitchType.Boolean; switchToAdd.BooleanValue = (bool)value; if (!String.IsNullOrEmpty(property.ReverseSwitchName)) { switchToAdd.ReverseSwitchValue = property.Prefix + property.ReverseSwitchName; } break; case PropertyType.Integer: switchToAdd.Type = CommandLineToolSwitchType.Integer; switchToAdd.Number = (int)value; if (!String.IsNullOrEmpty(property.Min)) { if (switchToAdd.Number < Convert.ToInt32(property.Min, System.Threading.Thread.CurrentThread.CurrentCulture)) { switchToAdd.IsValid = false; } } if (!String.IsNullOrEmpty(property.Max)) { if (switchToAdd.Number > Convert.ToInt32(property.Max, System.Threading.Thread.CurrentThread.CurrentCulture)) { switchToAdd.IsValid = false; } } break; case PropertyType.ItemArray: switchToAdd.Type = CommandLineToolSwitchType.ITaskItemArray; switchToAdd.TaskItemArray = (ITaskItem[])value; break; case PropertyType.None: break; case PropertyType.String: switchToAdd.Type = CommandLineToolSwitchType.String; switchToAdd.ReverseSwitchValue = property.Prefix + property.ReverseSwitchName; if (property.Values.Count > 0) { string enumValueToSelect = (string)value; switchToAdd.Value = (string)value; switchToAdd.AllowMultipleValues = true; // Find the matching value in the enum foreach (Value enumValue in property.Values) { if (String.Equals(enumValue.Name, enumValueToSelect, StringComparison.OrdinalIgnoreCase)) { if (!String.IsNullOrEmpty(enumValue.SwitchName)) { switchToAdd.SwitchValue = enumValue.Prefix + enumValue.SwitchName; } else { switchToAdd = null; break; } } } } else { switchToAdd.Value = (string)value; } break; case PropertyType.StringArray: switchToAdd.Type = CommandLineToolSwitchType.StringArray; switchToAdd.StringList = (string[])value; break; } if (switchToAdd != null) { _activeCommandLineToolSwitches[property.Name] = switchToAdd; } } } }
public CommandLineGenerator(Rule rule, Dictionary <string, object> parameterValues) { this.activeCommandLineToolSwitches = new Dictionary <string, CommandLineToolSwitch>(StringComparer.OrdinalIgnoreCase); this.additionalOptions = string.Empty; Microsoft.Build.Shared.ErrorUtilities.VerifyThrowArgumentNull(rule, "rule"); Microsoft.Build.Shared.ErrorUtilities.VerifyThrowArgumentNull(parameterValues, "parameterValues"); TaskParser parser = new TaskParser(); Microsoft.Build.Shared.ErrorUtilities.VerifyThrow(parser.ParseXamlDocument(rule), "Unable to parse specified file or contents."); this.switchOrderList = parser.SwitchOrderList; this.activeCommandLineToolSwitches = new Dictionary <string, CommandLineToolSwitch>(StringComparer.OrdinalIgnoreCase); foreach (Property property in parser.Properties) { object obj2 = null; if (parameterValues.TryGetValue(property.Name, out obj2)) { CommandLineToolSwitch switch2 = new CommandLineToolSwitch(); if (!string.IsNullOrEmpty(property.Reversible) && string.Equals(property.Reversible, "true", StringComparison.OrdinalIgnoreCase)) { switch2.Reversible = true; } switch2.Separator = property.Separator; switch2.DisplayName = property.DisplayName; switch2.Description = property.Description; if (!string.IsNullOrEmpty(property.Required) && string.Equals(property.Required, "true", StringComparison.OrdinalIgnoreCase)) { switch2.Required = true; } switch2.FallbackArgumentParameter = property.Fallback; switch2.FalseSuffix = property.FalseSuffix; switch2.TrueSuffix = property.TrueSuffix; if (!string.IsNullOrEmpty(property.SwitchName)) { switch2.SwitchValue = property.Prefix + property.SwitchName; } switch2.IsValid = true; switch (property.Type) { case PropertyType.Boolean: switch2.Type = CommandLineToolSwitchType.Boolean; switch2.BooleanValue = (bool)obj2; if (!string.IsNullOrEmpty(property.ReverseSwitchName)) { switch2.ReverseSwitchValue = property.Prefix + property.ReverseSwitchName; } break; case PropertyType.String: switch2.Type = CommandLineToolSwitchType.String; switch2.ReverseSwitchValue = property.Prefix + property.ReverseSwitchName; if (property.Values.Count > 0) { string b = (string)obj2; switch2.Value = (string)obj2; switch2.AllowMultipleValues = true; foreach (Value value2 in property.Values) { if (string.Equals(value2.Name, b, StringComparison.OrdinalIgnoreCase)) { if (!string.IsNullOrEmpty(value2.SwitchName)) { switch2.SwitchValue = value2.Prefix + value2.SwitchName; } else { switch2 = null; break; } } } } else { switch2.Value = (string)obj2; } break; case PropertyType.Integer: switch2.Type = CommandLineToolSwitchType.Integer; switch2.Number = (int)obj2; if (!string.IsNullOrEmpty(property.Min) && (switch2.Number < Convert.ToInt32(property.Min, Thread.CurrentThread.CurrentCulture))) { switch2.IsValid = false; } if (!string.IsNullOrEmpty(property.Max) && (switch2.Number > Convert.ToInt32(property.Max, Thread.CurrentThread.CurrentCulture))) { switch2.IsValid = false; } break; case PropertyType.StringArray: switch2.Type = CommandLineToolSwitchType.StringArray; switch2.StringList = (string[])obj2; break; case PropertyType.ItemArray: switch2.Type = CommandLineToolSwitchType.ITaskItemArray; switch2.TaskItemArray = (ITaskItem[])obj2; break; } if (switch2 != null) { this.activeCommandLineToolSwitches[property.Name] = switch2; } } } }
public bool Initialize(string taskName, IDictionary<string, TaskPropertyInfo> taskParameters, string taskElementContents, IBuildEngine taskFactoryLoggingHost) { CompilerResults results; Microsoft.Build.Shared.ErrorUtilities.VerifyThrowArgumentNull(taskName, "taskName"); Microsoft.Build.Shared.ErrorUtilities.VerifyThrowArgumentNull(taskParameters, "taskParameters"); TaskLoggingHelper helper = new TaskLoggingHelper(taskFactoryLoggingHost, taskName) { TaskResources = Microsoft.Build.Shared.AssemblyResources.PrimaryResources, HelpKeywordPrefix = "MSBuild." }; if (taskElementContents == null) { helper.LogErrorWithCodeFromResources("Xaml.MissingTaskBody", new object[0]); return false; } this.TaskElementContents = taskElementContents.Trim(); TaskParser parser = new TaskParser(); parser.Parse(this.TaskElementContents, taskName); this.TaskName = parser.GeneratedTaskName; this.TaskNamespace = parser.Namespace; CodeCompileUnit compileUnit = new TaskGenerator(parser).GenerateCode(); Assembly assembly = Assembly.LoadWithPartialName("System"); Assembly assembly2 = Assembly.LoadWithPartialName("Microsoft.Build.Framework"); Assembly assembly3 = Assembly.LoadWithPartialName("Microsoft.Build.Utilities.V4.0"); Assembly assembly4 = Assembly.LoadWithPartialName("Microsoft.Build.Tasks.V4.0"); CompilerParameters parameters = new CompilerParameters(new string[] { assembly.Location, assembly2.Location, assembly3.Location, assembly4.Location }) { GenerateInMemory = true, TreatWarningsAsErrors = false }; CodeDomProvider provider = CodeDomProvider.CreateProvider("cs"); bool flag = Environment.GetEnvironmentVariable("MSBUILDWRITEXAMLTASK") == "1"; if (flag) { using (StreamWriter writer = new StreamWriter(taskName + "_XamlTask.cs")) { CodeGeneratorOptions options = new CodeGeneratorOptions { BlankLinesBetweenMembers = true, BracingStyle = "C" }; provider.GenerateCodeFromCompileUnit(compileUnit, writer, options); } results = provider.CompileAssemblyFromFile(parameters, new string[] { taskName + "_XamlTask.cs" }); } else { results = provider.CompileAssemblyFromDom(parameters, new CodeCompileUnit[] { compileUnit }); } try { this.taskAssembly = results.CompiledAssembly; } catch (FileNotFoundException) { } if (this.taskAssembly == null) { StringBuilder builder = new StringBuilder(); builder.AppendLine(); foreach (CompilerError error in results.Errors) { if (!error.IsWarning) { if (flag) { builder.AppendLine(string.Format(Thread.CurrentThread.CurrentUICulture, "({0},{1}) {2}", new object[] { error.Line, error.Column, error.ErrorText })); } else { builder.AppendLine(error.ErrorText); } } } helper.LogErrorWithCodeFromResources("Xaml.TaskCreationFailed", new object[] { builder.ToString() }); } return !helper.HasLoggedErrors; }
/// <summary> /// MSBuild engine will call this to initialize the factory. This should initialize the factory enough so that the factory can be asked /// whether or not task names can be created by the factory. /// </summary> public bool Initialize(string taskName, IDictionary<string, TaskPropertyInfo> taskParameters, string taskElementContents, IBuildEngine taskFactoryLoggingHost) { ErrorUtilities.VerifyThrowArgumentNull(taskName, "taskName"); ErrorUtilities.VerifyThrowArgumentNull(taskParameters, "taskParameters"); TaskLoggingHelper log = new TaskLoggingHelper(taskFactoryLoggingHost, taskName); log.TaskResources = AssemblyResources.PrimaryResources; log.HelpKeywordPrefix = "MSBuild."; if (taskElementContents == null) { log.LogErrorWithCodeFromResources("Xaml.MissingTaskBody"); return false; } TaskElementContents = taskElementContents.Trim(); // Attempt to load the task TaskParser parser = new TaskParser(); bool parseSuccessful = parser.Parse(TaskElementContents, taskName); TaskName = parser.GeneratedTaskName; TaskNamespace = parser.Namespace; TaskGenerator generator = new TaskGenerator(parser); CodeCompileUnit dom = generator.GenerateCode(); string pathToMSBuildBinaries = ToolLocationHelper.GetPathToBuildTools(ToolLocationHelper.CurrentToolsVersion); // create the code generator options // Since we are running msbuild 12.0 these had better load. CompilerParameters compilerParameters = new CompilerParameters ( new string[] { "System.dll", Path.Combine(pathToMSBuildBinaries, "Microsoft.Build.Framework.dll"), Path.Combine(pathToMSBuildBinaries, "Microsoft.Build.Utilities.Core.dll"), Path.Combine(pathToMSBuildBinaries, "Microsoft.Build.Tasks.Core.dll") } ); compilerParameters.GenerateInMemory = true; compilerParameters.TreatWarningsAsErrors = false; // create the code provider CodeDomProvider codegenerator = CodeDomProvider.CreateProvider("cs"); CompilerResults results; bool debugXamlTask = Environment.GetEnvironmentVariable("MSBUILDWRITEXAMLTASK") == "1"; if (debugXamlTask) { using (StreamWriter outputWriter = new StreamWriter(taskName + "_XamlTask.cs")) { CodeGeneratorOptions options = new CodeGeneratorOptions(); options.BlankLinesBetweenMembers = true; options.BracingStyle = "C"; codegenerator.GenerateCodeFromCompileUnit(dom, outputWriter, options); } results = codegenerator.CompileAssemblyFromFile(compilerParameters, taskName + "_XamlTask.cs"); } else { results = codegenerator.CompileAssemblyFromDom(compilerParameters, new[] { dom }); } try { _taskAssembly = results.CompiledAssembly; } catch (FileNotFoundException) { // This occurs if there is a failure to compile the assembly. We just pass through because we will take care of the failure below. } if (_taskAssembly == null) { StringBuilder errorList = new StringBuilder(); errorList.AppendLine(); foreach (CompilerError error in results.Errors) { if (error.IsWarning) { continue; } if (debugXamlTask) { errorList.AppendLine(String.Format(Thread.CurrentThread.CurrentUICulture, "({0},{1}) {2}", error.Line, error.Column, error.ErrorText)); } else { errorList.AppendLine(error.ErrorText); } } log.LogErrorWithCodeFromResources("Xaml.TaskCreationFailed", errorList.ToString()); } return !log.HasLoggedErrors; }
/// <summary> /// Creates a generator that generates a command-line based on the specified Xaml file and parameters. /// </summary> public CommandLineGenerator(Rule rule, Dictionary<string, Object> parameterValues) { ErrorUtilities.VerifyThrowArgumentNull(rule, "rule"); ErrorUtilities.VerifyThrowArgumentNull(parameterValues, "parameterValues"); // Parse the Xaml file TaskParser parser = new TaskParser(); bool success = parser.ParseXamlDocument(rule); ErrorUtilities.VerifyThrow(success, "Unable to parse specified file or contents."); // Generate the switch order list _switchOrderList = parser.SwitchOrderList; _activeCommandLineToolSwitches = new Dictionary<string, CommandLineToolSwitch>(StringComparer.OrdinalIgnoreCase); foreach (Property property in parser.Properties) { Object value = null; if (parameterValues.TryGetValue(property.Name, out value)) { CommandLineToolSwitch switchToAdd = new CommandLineToolSwitch(); if (!String.IsNullOrEmpty(property.Reversible) && String.Equals(property.Reversible, "true", StringComparison.OrdinalIgnoreCase)) { switchToAdd.Reversible = true; } switchToAdd.IncludeInCommandLine = property.IncludeInCommandLine; switchToAdd.Separator = property.Separator; switchToAdd.DisplayName = property.DisplayName; switchToAdd.Description = property.Description; if (!String.IsNullOrEmpty(property.Required) && String.Equals(property.Required, "true", StringComparison.OrdinalIgnoreCase)) { switchToAdd.Required = true; } switchToAdd.FallbackArgumentParameter = property.Fallback; switchToAdd.FalseSuffix = property.FalseSuffix; switchToAdd.TrueSuffix = property.TrueSuffix; if (!String.IsNullOrEmpty(property.SwitchName)) { switchToAdd.SwitchValue = property.Prefix + property.SwitchName; } switchToAdd.IsValid = true; // Based on the switch type, cast the value and set as appropriate switch (property.Type) { case PropertyType.Boolean: switchToAdd.Type = CommandLineToolSwitchType.Boolean; switchToAdd.BooleanValue = (bool)value; if (!String.IsNullOrEmpty(property.ReverseSwitchName)) { switchToAdd.ReverseSwitchValue = property.Prefix + property.ReverseSwitchName; } break; case PropertyType.Integer: switchToAdd.Type = CommandLineToolSwitchType.Integer; switchToAdd.Number = (int)value; if (!String.IsNullOrEmpty(property.Min)) { if (switchToAdd.Number < Convert.ToInt32(property.Min, System.Threading.Thread.CurrentThread.CurrentCulture)) { switchToAdd.IsValid = false; } } if (!String.IsNullOrEmpty(property.Max)) { if (switchToAdd.Number > Convert.ToInt32(property.Max, System.Threading.Thread.CurrentThread.CurrentCulture)) { switchToAdd.IsValid = false; } } break; case PropertyType.ItemArray: switchToAdd.Type = CommandLineToolSwitchType.ITaskItemArray; switchToAdd.TaskItemArray = (ITaskItem[])value; break; case PropertyType.None: break; case PropertyType.String: switchToAdd.Type = CommandLineToolSwitchType.String; switchToAdd.ReverseSwitchValue = property.Prefix + property.ReverseSwitchName; if (property.Values.Count > 0) { string enumValueToSelect = (string)value; switchToAdd.Value = (string)value; switchToAdd.AllowMultipleValues = true; // Find the matching value in the enum foreach (Value enumValue in property.Values) { if (String.Equals(enumValue.Name, enumValueToSelect, StringComparison.OrdinalIgnoreCase)) { if (!String.IsNullOrEmpty(enumValue.SwitchName)) { switchToAdd.SwitchValue = enumValue.Prefix + enumValue.SwitchName; } else { switchToAdd = null; break; } } } } else { switchToAdd.Value = (string)value; } break; case PropertyType.StringArray: switchToAdd.Type = CommandLineToolSwitchType.StringArray; switchToAdd.StringList = (string[])value; break; } if (switchToAdd != null) { _activeCommandLineToolSwitches[property.Name] = switchToAdd; } } } }
/// <summary> /// used for testing. Will load snippets of xml into the task generator /// </summary> /// <param name="s"></param> /// <returns></returns> public static TaskParser LoadAndParse(string s, string desiredRule) { TaskParser tp = new TaskParser(); tp.Parse(s.Replace("`", "\""), desiredRule); return tp; }
/// <summary> /// Constructor that takes a parser /// </summary> internal TaskGenerator(TaskParser parser) { _taskParser = parser; }