OLD | NEW |
(Empty) | |
| 1 using System; |
| 2 using System.Collections.Generic; |
| 3 using System.Linq; |
| 4 using System.Text; |
| 5 |
| 6 using Microsoft.Build.Framework; |
| 7 using System.Xaml; |
| 8 using Microsoft.Build.Framework.XamlTypes; |
| 9 using Microsoft.Build.Utilities; |
| 10 |
| 11 namespace NaCl.Build.CPPTasks |
| 12 { |
| 13 class XamlParser |
| 14 { |
| 15 public XamlParser(string path) |
| 16 { |
| 17 // load and store properties from xaml file |
| 18 m_parsedBuildRule = (Rule)XamlServices.Load(path); |
| 19 |
| 20 // NOTE: |
| 21 // There are MSBuild classes which support command line building, |
| 22 // argument switch encapsulation and more. Code within VCToolTask, |
| 23 // a hidden interface, uses some these classes to generate command l
ine |
| 24 // switches given project settings. As the VCToolTask class is a hid
den |
| 25 // class and the MSBuild documentation is very sparse, we are going |
| 26 // with a small custom solution. For reference see the |
| 27 // Microsoft.Build.Tasks.Xaml, Microsoft.Build.Framework.XamlTypes n
amespaces. |
| 28 |
| 29 // move the properties to a property name keyed dictionary for faste
r lookup |
| 30 ToolProperties = new Dictionary<string, PropertyWrapper>(); |
| 31 ToolProperties = m_parsedBuildRule.Properties.ToDictionary(x => x.Na
me, x => (new PropertyWrapper(x.GetType(), x))); |
| 32 |
| 33 InitFunctionMap(); |
| 34 } |
| 35 |
| 36 private void InitFunctionMap() |
| 37 { |
| 38 m_typeFunctionMap = new Dictionary<Type, Action<CommandLineBuilder,
BaseProperty, string>> |
| 39 { |
| 40 { typeof(StringListProperty), GenerateArgumentStringList }, |
| 41 { typeof(StringProperty), GenerateArgumentString }, |
| 42 { typeof(IntProperty), GenerateArgumentString }, |
| 43 { typeof(BoolProperty), GenerateArgumentBool }, |
| 44 { typeof(EnumProperty), GenerateArgumentEnum } |
| 45 }; |
| 46 } |
| 47 |
| 48 public string Parse(ITaskItem taskItem) |
| 49 { |
| 50 CommandLineBuilder builder = new CommandLineBuilder(); |
| 51 |
| 52 foreach (string name in taskItem.MetadataNames) |
| 53 { |
| 54 string value = taskItem.GetMetadata(name); |
| 55 AppendArgumentForProperty(builder, name, value); |
| 56 } |
| 57 |
| 58 string result = builder.ToString(); |
| 59 result = result.Replace('\\', '/'); // posix paths |
| 60 return result; |
| 61 } |
| 62 |
| 63 private string AppendArgumentForProperty(CommandLineBuilder builder, str
ing name, string value) |
| 64 { |
| 65 PropertyWrapper current; |
| 66 ToolProperties.TryGetValue(name, out current); |
| 67 if (current != null && value.Length > 0) |
| 68 { |
| 69 // call appropriate function for type |
| 70 m_typeFunctionMap[current.PropertyType](builder, current.Propert
y, value); |
| 71 } |
| 72 return string.Empty; |
| 73 } |
| 74 |
| 75 private void GenerateArgumentEnum(CommandLineBuilder builder, BaseProper
ty property, string value) |
| 76 { |
| 77 var result = ((EnumProperty)property).AdmissibleValues.Find(x => (x.
Name == value)); |
| 78 if (result != null) |
| 79 { |
| 80 builder.AppendSwitchUnquotedIfNotNull(m_parsedBuildRule.SwitchPr
efix, result.Switch); |
| 81 } |
| 82 } |
| 83 |
| 84 // helper for string-based properties |
| 85 private void AppendStringValue(CommandLineBuilder builder, BaseProperty
property, string subtype, string value) |
| 86 { |
| 87 value = value.Trim(); |
| 88 |
| 89 // could cache this SubType test off in property wrapper or somewher
e if performance were an issue |
| 90 if (subtype == "file" || subtype == "folder") |
| 91 { |
| 92 builder.AppendSwitchIfNotNull(m_parsedBuildRule.SwitchPrefix + p
roperty.Switch + property.Separator, value); |
| 93 } |
| 94 else |
| 95 { |
| 96 builder.AppendSwitchUnquotedIfNotNull(m_parsedBuildRule.SwitchPr
efix + property.Switch + property.Separator, value); |
| 97 } |
| 98 } |
| 99 |
| 100 private void GenerateArgumentStringList(CommandLineBuilder builder, Base
Property property, string value) |
| 101 { |
| 102 string [] arguments = value.Split(';'); |
| 103 |
| 104 foreach (string argument in arguments) |
| 105 { |
| 106 if (argument.Length > 0) |
| 107 { |
| 108 StringListProperty casted = (StringListProperty)property; |
| 109 AppendStringValue(builder, property, casted.Subtype, argumen
t); |
| 110 } |
| 111 } |
| 112 } |
| 113 |
| 114 private void GenerateArgumentString(CommandLineBuilder builder, BaseProp
erty property, string value) |
| 115 { |
| 116 // could cache this SubType test off in property wrapper or somewher
e if performance were an issue |
| 117 StringProperty casted = (StringProperty)property; |
| 118 AppendStringValue(builder, property, casted.Subtype, value); |
| 119 } |
| 120 |
| 121 private void GenerateArgumentBool(CommandLineBuilder builder, BaseProper
ty property, string value) |
| 122 { |
| 123 if (value == "true") |
| 124 { |
| 125 builder.AppendSwitchUnquotedIfNotNull(m_parsedBuildRule.SwitchPr
efix, property.Switch); |
| 126 } |
| 127 else if (value == "false" && ((BoolProperty)property).ReverseSwitch
!= null) |
| 128 { |
| 129 builder.AppendSwitchUnquotedIfNotNull(m_parsedBuildRule.SwitchPr
efix, ((BoolProperty)property).ReverseSwitch); |
| 130 } |
| 131 } |
| 132 |
| 133 // to store off MSBuild property type and allow faster searching on them |
| 134 private class PropertyWrapper |
| 135 { |
| 136 public PropertyWrapper(Type newType, BaseProperty newProperty) |
| 137 { |
| 138 PropertyType = newType; |
| 139 Property = newProperty; |
| 140 } |
| 141 public Type PropertyType { get; set; } |
| 142 public BaseProperty Property { get; set; } |
| 143 } // class |
| 144 |
| 145 private Rule m_parsedBuildRule; |
| 146 private Dictionary<string, PropertyWrapper> ToolProperties { get; set; } |
| 147 |
| 148 // function mapping for easy property function calling |
| 149 private Dictionary<Type, Action<CommandLineBuilder, BaseProperty, string
>> m_typeFunctionMap; |
| 150 } // XamlParser |
| 151 } // namespace NaCl.Build.CPPTasks |
| 152 |
OLD | NEW |