You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@@ -0,0 +1,384 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Build.Tasks.Xaml
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Xaml;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Runtime;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
using System.Globalization;
|
||||
using XamlBuildTask;
|
||||
|
||||
public sealed class AttributeData
|
||||
{
|
||||
static CultureInfo invariantEnglishUS = CultureInfo.ReadOnly(new CultureInfo("en-us", false));
|
||||
List<AttributeParameterData> parameters;
|
||||
Dictionary<string, AttributeParameterData> properties;
|
||||
|
||||
public XamlType Type
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public IList<AttributeParameterData> Parameters
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.parameters == null)
|
||||
{
|
||||
this.parameters = new List<AttributeParameterData>();
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
}
|
||||
|
||||
public IDictionary<string, AttributeParameterData> Properties
|
||||
{
|
||||
get
|
||||
{
|
||||
if (properties == null)
|
||||
{
|
||||
properties = new Dictionary<string, AttributeParameterData>();
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
}
|
||||
|
||||
// We get here when we are inside x:ClassAttributes or x:Property.Attributes. We expect the first element to be the Attribute SO.
|
||||
internal static AttributeData LoadAttributeData(XamlReader reader, NamespaceTable namespaceTable, string rootNamespace)
|
||||
{
|
||||
AttributeData attributeData = null;
|
||||
reader.Read();
|
||||
if (reader.NodeType == XamlNodeType.StartObject)
|
||||
{
|
||||
attributeData = new AttributeData { Type = reader.Type };
|
||||
|
||||
bool readNext = false;
|
||||
while (readNext || reader.Read())
|
||||
{
|
||||
namespaceTable.ManageNamespace(reader);
|
||||
readNext = false;
|
||||
if (reader.NodeType == XamlNodeType.StartMember)
|
||||
{
|
||||
if (reader.Member == XamlLanguage.Arguments)
|
||||
{
|
||||
foreach (AttributeParameterData parameterData in ReadParameters(reader.ReadSubtree(), namespaceTable, rootNamespace))
|
||||
{
|
||||
attributeData.Parameters.Add(parameterData);
|
||||
}
|
||||
readNext = true;
|
||||
}
|
||||
else if (!reader.Member.IsDirective)
|
||||
{
|
||||
KeyValuePair<string, AttributeParameterData> propertyInfo = ReadAttributeProperty(reader.ReadSubtree(), namespaceTable, rootNamespace);
|
||||
attributeData.Properties.Add(propertyInfo.Key, propertyInfo.Value);
|
||||
readNext = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return attributeData;
|
||||
}
|
||||
|
||||
// Read the Property on the attribute.
|
||||
private static KeyValuePair<string, AttributeParameterData> ReadAttributeProperty(XamlReader reader, NamespaceTable namespaceTable, string rootNamespace)
|
||||
{
|
||||
reader.Read();
|
||||
Fx.Assert(reader.Member != null, "Member element should not be null");
|
||||
XamlMember member = reader.Member;
|
||||
|
||||
AttributeParameterData propertyInfo = new AttributeParameterData();
|
||||
|
||||
if (member.Type != null && !member.Type.IsUnknown)
|
||||
{
|
||||
propertyInfo.Type = member.Type;
|
||||
}
|
||||
|
||||
ReadParamInfo(reader, member.Type, namespaceTable, rootNamespace, propertyInfo);
|
||||
return new KeyValuePair<string, AttributeParameterData>(member.Name, propertyInfo);
|
||||
}
|
||||
|
||||
// Read the parameters on the Attribute. We expect the parameters to be in the order in which they are supposed to appear in the output code.
|
||||
// Here we are inside x:Arguments and we expect a list of parameters.
|
||||
private static IList<AttributeParameterData> ReadParameters(XamlReader reader, NamespaceTable namespaceTable, string rootNamespace)
|
||||
{
|
||||
IList<AttributeParameterData> parameters = new List<AttributeParameterData>();
|
||||
bool readNext = false;
|
||||
while (readNext || reader.Read())
|
||||
{
|
||||
readNext = false;
|
||||
if (reader.NodeType == XamlNodeType.StartObject)
|
||||
{
|
||||
AttributeParameterData paramInfo = new AttributeParameterData();
|
||||
ReadParamInfo(reader.ReadSubtree(), null, namespaceTable, rootNamespace, paramInfo);
|
||||
parameters.Add(paramInfo);
|
||||
readNext = true;
|
||||
}
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
|
||||
// Read the actual parameter info, i.e. the type of the paramter and its value.
|
||||
// The first element could be a V or an SO.
|
||||
private static void ReadParamInfo(XamlReader reader, XamlType type, NamespaceTable namespaceTable, string rootNamespace, AttributeParameterData paramInfo)
|
||||
{
|
||||
reader.Read();
|
||||
|
||||
bool readNext = false;
|
||||
do
|
||||
{
|
||||
readNext = false;
|
||||
if (reader.NodeType == XamlNodeType.StartObject && reader.Type == XamlLanguage.Array)
|
||||
{
|
||||
paramInfo.IsArray = true;
|
||||
XamlReader xamlArrayReader = reader.ReadSubtree();
|
||||
xamlArrayReader.Read();
|
||||
while (readNext || xamlArrayReader.Read())
|
||||
{
|
||||
readNext = false;
|
||||
if (xamlArrayReader.NodeType == XamlNodeType.StartMember && xamlArrayReader.Member.Name == "Type")
|
||||
{
|
||||
xamlArrayReader.Read();
|
||||
if (xamlArrayReader.NodeType == XamlNodeType.Value)
|
||||
{
|
||||
XamlType arrayType = XamlBuildTaskServices.GetXamlTypeFromString(xamlArrayReader.Value as string, namespaceTable, xamlArrayReader.SchemaContext);
|
||||
if (arrayType.UnderlyingType != null)
|
||||
{
|
||||
paramInfo.Type = xamlArrayReader.SchemaContext.GetXamlType(arrayType.UnderlyingType.MakeArrayType());
|
||||
}
|
||||
else
|
||||
{
|
||||
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.AttributeParameterTypeUnknown(arrayType)));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (xamlArrayReader.NodeType == XamlNodeType.StartObject)
|
||||
{
|
||||
AttributeParameterData arrayEntry = new AttributeParameterData();
|
||||
ReadParamInfo(xamlArrayReader.ReadSubtree(), null, namespaceTable, rootNamespace, arrayEntry);
|
||||
paramInfo.AddArrayContentsEntry(arrayEntry);
|
||||
readNext = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (reader.NodeType == XamlNodeType.StartObject || reader.NodeType == XamlNodeType.Value)
|
||||
{
|
||||
paramInfo.IsArray = false;
|
||||
string paramVal;
|
||||
object paramObj = null;
|
||||
XamlType paramType;
|
||||
GetParamValueType(reader.ReadSubtree(), type, namespaceTable, rootNamespace, out paramVal, out paramType, out paramObj);
|
||||
paramInfo.TextValue = paramVal;
|
||||
paramInfo.Type = paramType;
|
||||
paramInfo.Value = paramObj;
|
||||
}
|
||||
} while (readNext || reader.Read());
|
||||
}
|
||||
|
||||
// Get the paramter value. If the value is enclosed inside nodes of the type, then get the parameter type as well.
|
||||
// Else infer the type from the type of the property.
|
||||
private static void GetParamValueType(XamlReader reader, XamlType type, NamespaceTable namespaceTable, string rootNamespace, out string paramValue, out XamlType paramType, out Object paramObj)
|
||||
{
|
||||
paramValue = String.Empty;
|
||||
paramType = type;
|
||||
paramObj = null;
|
||||
while (reader.Read())
|
||||
{
|
||||
if (reader.NodeType == XamlNodeType.Value)
|
||||
{
|
||||
if (paramType != null && paramType.UnderlyingType != null)
|
||||
{
|
||||
if (!IsSupportedParameterType(paramType.UnderlyingType) || paramType.UnderlyingType.IsArray)
|
||||
{
|
||||
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.AttributeParamTypeNotSupported(paramType.UnderlyingType.FullName)));
|
||||
}
|
||||
|
||||
paramValue = reader.Value as string;
|
||||
if (typeof(Type).IsAssignableFrom(paramType.UnderlyingType))
|
||||
{
|
||||
Tuple<string, Type> result = ParseParameterValueTypeName(paramValue, rootNamespace, reader.SchemaContext, namespaceTable);
|
||||
paramValue = result.Item1;
|
||||
paramObj = result.Item2;
|
||||
}
|
||||
else
|
||||
{
|
||||
paramObj = ParseParameterValue(ref paramValue, paramType);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.AttributeParameterTypeUnknown(reader.Value as string)));
|
||||
}
|
||||
}
|
||||
else if (reader.NodeType == XamlNodeType.StartObject)
|
||||
{
|
||||
if (reader.Type == XamlLanguage.Null)
|
||||
{
|
||||
paramValue = null;
|
||||
paramType = null;
|
||||
}
|
||||
else if (reader.Type == XamlLanguage.Type)
|
||||
{
|
||||
paramType = reader.SchemaContext.GetXamlType(typeof(Type));
|
||||
}
|
||||
else
|
||||
{
|
||||
paramType = reader.Type;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool IsSupportedParameterType(Type type)
|
||||
{
|
||||
if (type.IsArray)
|
||||
{
|
||||
return IsSupportedParameterType(type.GetElementType());
|
||||
}
|
||||
return type.IsEnum ||
|
||||
type.IsPrimitive ||
|
||||
typeof(string) == type ||
|
||||
typeof(Type).IsAssignableFrom(type);
|
||||
}
|
||||
|
||||
// Given a live value for an attribute parameter, returns the text that needs to be
|
||||
// code-gened for the value.
|
||||
internal static string GetParameterText(object value, XamlType paramType)
|
||||
{
|
||||
Type type = paramType.UnderlyingType;
|
||||
if (type.IsEnum)
|
||||
{
|
||||
// Note: this doesn't support flags enums with multiple flags set, but neither
|
||||
// does the existing Dev10 code
|
||||
return type.FullName + "." + value.ToString();
|
||||
}
|
||||
else if (typeof(Type).IsAssignableFrom(type))
|
||||
{
|
||||
return ((Type)value).FullName;
|
||||
}
|
||||
else if (type == typeof(String))
|
||||
{
|
||||
return (string)value;
|
||||
}
|
||||
else if (type.IsPrimitive)
|
||||
{
|
||||
TypeConverter typeConverter = paramType.TypeConverter.ConverterInstance;
|
||||
Fx.Assert(typeConverter != null, "All primitives have TypeConverters");
|
||||
return (string)typeConverter.ConvertTo(null, invariantEnglishUS, value, typeof(string));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw Fx.AssertAndThrow("Unexpected attribute parameter type");
|
||||
}
|
||||
}
|
||||
|
||||
// Given the text for an attribute parameter, parses it to a live value (if possible).
|
||||
internal static object GetParameterValue(ref string paramValue, XamlType paramType)
|
||||
{
|
||||
if (typeof(Type).IsAssignableFrom(paramType.UnderlyingType))
|
||||
{
|
||||
// We can't convert a CLR type name to a Type because we don't know what assembly it's from
|
||||
return null;
|
||||
}
|
||||
return ParseParameterValue(ref paramValue, paramType);
|
||||
}
|
||||
|
||||
// Parses a XAML QName to a CLR Type Name (and the corresponding ROL type, if available)
|
||||
private static Tuple<string, Type> ParseParameterValueTypeName(string paramValue, string rootNamespace, XamlSchemaContext schemaContext, NamespaceTable namespaceTable)
|
||||
{
|
||||
XamlType xamlType = XamlBuildTaskServices.GetXamlTypeFromString(paramValue, namespaceTable, schemaContext);
|
||||
|
||||
string clrTypeName;
|
||||
if (!XamlBuildTaskServices.TryGetClrTypeName(xamlType, rootNamespace, out clrTypeName))
|
||||
{
|
||||
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.TypeNameUnknown(XamlBuildTaskServices.GetFullTypeName(xamlType))));
|
||||
}
|
||||
return Tuple.Create(clrTypeName, xamlType.UnderlyingType);
|
||||
}
|
||||
|
||||
// Given a text value for an attribute parameter, attempts to convert it to a live value.
|
||||
// Inverse of GetParameterText.
|
||||
private static object ParseParameterValue(ref string paramValue, XamlType paramType)
|
||||
{
|
||||
object valueObj = null;
|
||||
paramValue = NormalizeParameterText(paramValue, paramType);
|
||||
if (!paramType.UnderlyingType.Assembly.ReflectionOnly)
|
||||
{
|
||||
TypeConverter typeConverter = paramType.TypeConverter.ConverterInstance;
|
||||
if (typeConverter != null && typeConverter.CanConvertFrom(paramValue.GetType()))
|
||||
{
|
||||
try
|
||||
{
|
||||
valueObj = typeConverter.ConvertFrom(null, invariantEnglishUS, paramValue);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (Fx.IsFatal(e))
|
||||
{
|
||||
throw;
|
||||
}
|
||||
// ----ing exceptions here to avoid throwing on
|
||||
// a format that we don't recognize, but the compiler
|
||||
// might be able to interpret.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return valueObj;
|
||||
}
|
||||
|
||||
// Get the parameter value that is to be put in the generated code as is.
|
||||
private static string NormalizeParameterText(string value, XamlType xamlType)
|
||||
{
|
||||
string paramValue;
|
||||
Type type = xamlType.UnderlyingType;
|
||||
Fx.Assert(!typeof(Type).IsAssignableFrom(type), "This method should not be called for Types");
|
||||
|
||||
if (type.IsEnum)
|
||||
{
|
||||
paramValue = type.FullName + "." + value;
|
||||
}
|
||||
else if (type == typeof(String))
|
||||
{
|
||||
paramValue = value;
|
||||
}
|
||||
else if (type.IsPrimitive)
|
||||
{
|
||||
value = value.TrimStart('"');
|
||||
value = value.TrimEnd('"');
|
||||
|
||||
if (type == typeof(bool))
|
||||
{
|
||||
if (string.Compare(value, "true", StringComparison.OrdinalIgnoreCase) == 0)
|
||||
{
|
||||
paramValue = "true";
|
||||
}
|
||||
else if (string.Compare(value, "false", StringComparison.OrdinalIgnoreCase) == 0)
|
||||
{
|
||||
paramValue = "false";
|
||||
}
|
||||
else
|
||||
{
|
||||
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.UnknownBooleanValue(value)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
paramValue = value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw Fx.AssertAndThrow("Unexpected attribute parameter type");
|
||||
}
|
||||
return paramValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Build.Tasks.Xaml
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Runtime;
|
||||
using System.Xaml;
|
||||
using XamlBuildTask;
|
||||
|
||||
// This class is modal. The following properties are set in different modes:
|
||||
// Type TextValue Value ArrayContents
|
||||
// x:Null
|
||||
// x:Array x x
|
||||
// Known Value x x x
|
||||
// Unknown Value x x
|
||||
//
|
||||
// While this modality is not ideal, it's preferable to having multiple concrete classes
|
||||
// and requiring the user to down-cast.
|
||||
// However, we can't make the class mutable and expect users to maintain the modality.
|
||||
// So it's publicly immutable and has constructors for various modes (except for x:Null,
|
||||
// which the user can replicate by passing value == null and type == object).
|
||||
public sealed class AttributeParameterData
|
||||
{
|
||||
List<AttributeParameterData> arrayContents;
|
||||
|
||||
public AttributeParameterData(XamlType type, string textValue)
|
||||
{
|
||||
ValidateType(type);
|
||||
if (textValue == null && type.UnderlyingType.IsValueType)
|
||||
{
|
||||
throw FxTrace.Exception.Argument("value", SR.AttributeValueNotNullable(type.UnderlyingType));
|
||||
}
|
||||
|
||||
this.Type = type;
|
||||
if (textValue != null)
|
||||
{
|
||||
this.Value = AttributeData.GetParameterValue(ref textValue, type);
|
||||
this.TextValue = textValue;
|
||||
}
|
||||
}
|
||||
|
||||
public AttributeParameterData(XamlType type, object value)
|
||||
{
|
||||
ValidateType(type);
|
||||
if (value == null && type.UnderlyingType.IsValueType)
|
||||
{
|
||||
throw FxTrace.Exception.Argument("value", SR.AttributeValueNotNullable(type.UnderlyingType));
|
||||
}
|
||||
if (value != null && !type.UnderlyingType.IsAssignableFrom(value.GetType()))
|
||||
{
|
||||
throw FxTrace.Exception.Argument("value", SR.AttributeValueNotAssignableToType(value.GetType(), type.UnderlyingType));
|
||||
}
|
||||
|
||||
this.Type = type;
|
||||
if (value != null)
|
||||
{
|
||||
if (type.UnderlyingType.IsArray)
|
||||
{
|
||||
Array array = (Array)value;
|
||||
XamlType elementType = type.SchemaContext.GetXamlType(type.UnderlyingType.GetElementType());
|
||||
this.arrayContents = new List<AttributeParameterData>();
|
||||
foreach (object item in array)
|
||||
{
|
||||
this.arrayContents.Add(new AttributeParameterData(elementType, item));
|
||||
}
|
||||
this.IsArray = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Value = value;
|
||||
this.TextValue = AttributeData.GetParameterText(value, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AttributeParameterData(XamlType type, IEnumerable<AttributeParameterData> arrayContents)
|
||||
{
|
||||
ValidateType(type);
|
||||
if (!type.UnderlyingType.IsArray)
|
||||
{
|
||||
throw FxTrace.Exception.Argument("type", SR.AttributeTypeIsNotArray(type));
|
||||
}
|
||||
if (arrayContents == null)
|
||||
{
|
||||
throw FxTrace.Exception.ArgumentNull("arrayContents");
|
||||
}
|
||||
|
||||
this.Type = type;
|
||||
this.arrayContents = new List<AttributeParameterData>(arrayContents);
|
||||
this.IsArray = true;
|
||||
}
|
||||
|
||||
internal AttributeParameterData()
|
||||
{
|
||||
TextValue = String.Empty;
|
||||
IsArray = false;
|
||||
}
|
||||
|
||||
public string TextValue
|
||||
{
|
||||
get;
|
||||
internal set;
|
||||
}
|
||||
|
||||
public object Value
|
||||
{
|
||||
get;
|
||||
internal set;
|
||||
}
|
||||
|
||||
public XamlType Type
|
||||
{
|
||||
get;
|
||||
internal set;
|
||||
}
|
||||
|
||||
public ReadOnlyCollection<AttributeParameterData> ArrayContents
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.arrayContents == null ? null : this.arrayContents.AsReadOnly();
|
||||
}
|
||||
}
|
||||
|
||||
internal void AddArrayContentsEntry(AttributeParameterData arrayContentsEntry)
|
||||
{
|
||||
if (arrayContentsEntry != null)
|
||||
{
|
||||
if (this.arrayContents == null)
|
||||
{
|
||||
this.arrayContents = new List<AttributeParameterData>();
|
||||
}
|
||||
this.arrayContents.Add(arrayContentsEntry);
|
||||
}
|
||||
}
|
||||
|
||||
internal bool IsArray { get; set; }
|
||||
|
||||
private static void ValidateType(XamlType type)
|
||||
{
|
||||
if (type == null)
|
||||
{
|
||||
throw FxTrace.Exception.ArgumentNull("type");
|
||||
}
|
||||
if (type.IsUnknown)
|
||||
{
|
||||
throw FxTrace.Exception.Argument("type", SR.AttributeParameterTypeUnknownNoErrNum(type));
|
||||
}
|
||||
if (!AttributeData.IsSupportedParameterType(type.UnderlyingType))
|
||||
{
|
||||
throw FxTrace.Exception.Argument("type", SR.AttributeParamTypeNotSupportedNoErrNum(type));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
//----------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//----------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Build.Tasks.Xaml
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using Microsoft.Build.Utilities;
|
||||
|
||||
public class BuildExtensionContext
|
||||
{
|
||||
static readonly IList<string> emptyList = new List<string>(0);
|
||||
List<string> references;
|
||||
List<string> sourceCodeFiles;
|
||||
List<string> generatedFiles;
|
||||
List<string> generatedResourceFiles;
|
||||
|
||||
internal BuildExtensionContext()
|
||||
{
|
||||
}
|
||||
|
||||
public string AssemblyName
|
||||
{
|
||||
get;
|
||||
internal set;
|
||||
}
|
||||
|
||||
public bool IsInProcessXamlMarkupCompile
|
||||
{
|
||||
get;
|
||||
internal set;
|
||||
}
|
||||
|
||||
public string Language
|
||||
{
|
||||
get;
|
||||
internal set;
|
||||
}
|
||||
|
||||
public string OutputPath
|
||||
{
|
||||
get;
|
||||
internal set;
|
||||
}
|
||||
|
||||
public ReadOnlyCollection<string> References
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.references == null)
|
||||
{
|
||||
this.references = new List<string>();
|
||||
}
|
||||
return this.references.AsReadOnly();
|
||||
}
|
||||
}
|
||||
|
||||
public string RootNamespace
|
||||
{
|
||||
get;
|
||||
internal set;
|
||||
}
|
||||
|
||||
public ReadOnlyCollection<string> SourceCodeFiles
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.sourceCodeFiles == null)
|
||||
{
|
||||
this.sourceCodeFiles = new List<string>();
|
||||
}
|
||||
return this.sourceCodeFiles.AsReadOnly();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public string LocalAssembly
|
||||
{
|
||||
get;
|
||||
internal set;
|
||||
}
|
||||
|
||||
public TaskLoggingHelper XamlBuildLogger
|
||||
{
|
||||
get;
|
||||
internal set;
|
||||
}
|
||||
|
||||
public ReadOnlyCollection<string> GeneratedFiles
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.generatedFiles == null)
|
||||
{
|
||||
this.generatedFiles = new List<string>();
|
||||
}
|
||||
return this.generatedFiles.AsReadOnly();
|
||||
}
|
||||
}
|
||||
|
||||
public ReadOnlyCollection<string> GeneratedResourceFiles
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.generatedResourceFiles == null)
|
||||
{
|
||||
this.generatedResourceFiles = new List<string>();
|
||||
}
|
||||
return this.generatedResourceFiles.AsReadOnly();
|
||||
}
|
||||
}
|
||||
|
||||
public void AddGeneratedFile(string fileName)
|
||||
{
|
||||
if (this.generatedFiles == null)
|
||||
{
|
||||
this.generatedFiles = new List<string>();
|
||||
}
|
||||
this.generatedFiles.Add(fileName);
|
||||
}
|
||||
|
||||
public void AddGeneratedResourceFile(string fileName)
|
||||
{
|
||||
if (this.generatedResourceFiles == null)
|
||||
{
|
||||
this.generatedResourceFiles = new List<string>();
|
||||
}
|
||||
this.generatedResourceFiles.Add(fileName);
|
||||
}
|
||||
|
||||
internal void AddReferences(IList<string> references)
|
||||
{
|
||||
if (references != null)
|
||||
{
|
||||
if (this.references == null)
|
||||
{
|
||||
this.references = new List<string>();
|
||||
}
|
||||
this.references.AddRange(references);
|
||||
}
|
||||
}
|
||||
|
||||
internal void AddSourceCodeFiles(IList<string> sourceCodeFiles)
|
||||
{
|
||||
if (sourceCodeFiles != null)
|
||||
{
|
||||
if (this.sourceCodeFiles == null)
|
||||
{
|
||||
this.sourceCodeFiles = new List<string>();
|
||||
}
|
||||
this.sourceCodeFiles.AddRange(sourceCodeFiles);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Build.Tasks.Xaml
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using System.Xaml.Schema;
|
||||
using System.Xaml;
|
||||
using System.Windows.Markup;
|
||||
using System.Runtime;
|
||||
using System.Reflection;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections;
|
||||
|
||||
public class ClassData
|
||||
{
|
||||
[Fx.Tag.Queue(typeof(NamedObject), Scope = Fx.Tag.Strings.DeclaringInstance)]
|
||||
private List<NamedObject> namedObjects;
|
||||
[Fx.Tag.Queue(typeof(string), Scope = Fx.Tag.Strings.DeclaringInstance)]
|
||||
private List<string> codeSnippets;
|
||||
List<AttributeData> attributes;
|
||||
PropertyDataCollection properties;
|
||||
|
||||
public ClassData()
|
||||
{
|
||||
this.IsPublic = true;
|
||||
}
|
||||
|
||||
public XamlType BaseType
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public IList<String> CodeSnippets
|
||||
{
|
||||
get
|
||||
{
|
||||
if (codeSnippets == null)
|
||||
{
|
||||
codeSnippets = new List<String>();
|
||||
}
|
||||
return codeSnippets;
|
||||
}
|
||||
}
|
||||
|
||||
public string EmbeddedResourceFileName
|
||||
{
|
||||
get;
|
||||
internal set;
|
||||
}
|
||||
|
||||
public KeyedCollection<string, PropertyData> Properties
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.properties == null)
|
||||
{
|
||||
this.properties = new PropertyDataCollection();
|
||||
}
|
||||
return this.properties;
|
||||
}
|
||||
}
|
||||
|
||||
public IList<AttributeData> Attributes
|
||||
{
|
||||
get
|
||||
{
|
||||
if (attributes == null)
|
||||
{
|
||||
attributes = new List<AttributeData>();
|
||||
}
|
||||
return attributes;
|
||||
}
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get;
|
||||
internal set;
|
||||
}
|
||||
|
||||
public IList<NamedObject> NamedObjects
|
||||
{
|
||||
get
|
||||
{
|
||||
if (namedObjects == null)
|
||||
{
|
||||
namedObjects = new List<NamedObject>();
|
||||
}
|
||||
return namedObjects;
|
||||
}
|
||||
}
|
||||
|
||||
public String Namespace
|
||||
{
|
||||
get;
|
||||
internal set;
|
||||
}
|
||||
|
||||
public XamlNodeList EmbeddedResourceXaml
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public bool IsPublic
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string FileName
|
||||
{
|
||||
get;
|
||||
internal set;
|
||||
}
|
||||
|
||||
public string HelperClassFullName
|
||||
{
|
||||
get;
|
||||
internal set;
|
||||
}
|
||||
|
||||
internal String RootNamespace
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
internal bool SourceFileExists
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
internal bool RequiresCompilationPass2
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
class PropertyDataCollection : KeyedCollection<string, PropertyData>
|
||||
{
|
||||
protected override string GetKeyForItem(PropertyData item)
|
||||
{
|
||||
return item.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,79 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Build.Tasks.Xaml
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Xaml;
|
||||
using System.Runtime;
|
||||
using System.Reflection;
|
||||
using System;
|
||||
using System.Xaml.Schema;
|
||||
using Microsoft.Build.Utilities;
|
||||
using XamlBuildTask;
|
||||
|
||||
class ClassValidator
|
||||
{
|
||||
string xamlFileName;
|
||||
IList<LogData> eventArgs;
|
||||
Assembly localAssembly;
|
||||
string rootNamespace;
|
||||
|
||||
public ClassValidator(string xamlFileName, Assembly localAssembly, string rootNamespace)
|
||||
{
|
||||
this.xamlFileName = xamlFileName;
|
||||
this.localAssembly = localAssembly;
|
||||
this.eventArgs = null;
|
||||
this.rootNamespace = rootNamespace;
|
||||
}
|
||||
|
||||
public bool ValidateXaml(XamlReader xamlReader, bool failOnFirstError, string assemblyName, out IList<LogData> validationErrors)
|
||||
{
|
||||
if (xamlReader == null)
|
||||
{
|
||||
throw FxTrace.Exception.ArgumentNull("xamlReader");
|
||||
}
|
||||
validationErrors = null;
|
||||
|
||||
// We loop through the provided XAML using a XamlValidatingReader to ensure that:
|
||||
// 1. XAML is valid.
|
||||
// 2. All types referenced in XAML are validate-able. At this point, any types defined in the local
|
||||
// assembly should be referenced, so this should be possible.
|
||||
XamlValidatingReader reader = new XamlValidatingReader(xamlReader, this.localAssembly, rootNamespace, assemblyName);
|
||||
reader.OnValidationError += new EventHandler<ValidationEventArgs>(reader_OnValidationError);
|
||||
while (reader.Read())
|
||||
{
|
||||
if (this.eventArgs != null && failOnFirstError)
|
||||
{
|
||||
validationErrors = this.eventArgs;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
validationErrors = this.eventArgs;
|
||||
if (validationErrors != null && validationErrors.Count > 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void reader_OnValidationError(object sender, ValidationEventArgs e)
|
||||
{
|
||||
if (this.eventArgs == null)
|
||||
{
|
||||
this.eventArgs = new List<LogData>();
|
||||
}
|
||||
|
||||
this.eventArgs.Add(new LogData()
|
||||
{
|
||||
FileName = this.xamlFileName,
|
||||
LineNumber = e.LineNumber,
|
||||
LinePosition = e.LinePosition,
|
||||
Message = e.Message
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Build.Tasks.Xaml
|
||||
{
|
||||
using System;
|
||||
using System.CodeDom;
|
||||
|
||||
static class CodeDomExtensionMethods
|
||||
{
|
||||
internal static CodeVariableReferenceExpression DeclareVar(this CodeStatementCollection block, Type type,
|
||||
string name, CodeExpression initExpression)
|
||||
{
|
||||
block.Add(new CodeVariableDeclarationStatement()
|
||||
{
|
||||
Name = name,
|
||||
Type = new CodeTypeReference(type),
|
||||
InitExpression = initExpression
|
||||
});
|
||||
return new CodeVariableReferenceExpression(name);
|
||||
}
|
||||
|
||||
internal static CodeFieldReferenceExpression Field(this CodeExpression targetObject, string fieldName)
|
||||
{
|
||||
return new CodeFieldReferenceExpression(targetObject, fieldName);
|
||||
}
|
||||
|
||||
internal static CodeMethodInvokeExpression Invoke(this CodeExpression targetObject, string methodName,
|
||||
params CodeExpression[] parameters)
|
||||
{
|
||||
return new CodeMethodInvokeExpression(targetObject, methodName, parameters);
|
||||
}
|
||||
|
||||
internal static CodeObjectCreateExpression New(this Type type, params CodeExpression[] parameters)
|
||||
{
|
||||
return new CodeObjectCreateExpression(type, parameters);
|
||||
}
|
||||
|
||||
internal static CodePropertyReferenceExpression Property(this CodeExpression targetObject, string propertyName)
|
||||
{
|
||||
return new CodePropertyReferenceExpression(targetObject, propertyName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,315 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Build.Tasks.Xaml
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
using XamlBuildTask;
|
||||
|
||||
[Fx.Tag.XamlVisible(true)]
|
||||
public class CompilationPass2Task : Task
|
||||
{
|
||||
List<ITaskItem> generatedCodeFiles = new List<ITaskItem>();
|
||||
|
||||
// We will do Dev10 behavior if NONE of the new required properties are specified. This can happen
|
||||
// if a Dev10 version of the Microsoft.Xaml.Targets file is being used with Dev11 installed.
|
||||
// The new required properties for Dev11 are:
|
||||
// Language
|
||||
// OutputPath
|
||||
// MSBuildProjectDirectory
|
||||
// ApplicationMarkupWithTypeName
|
||||
//
|
||||
// If ANY of these are specified, then ALL must be specified.
|
||||
bool supportExtensions = false;
|
||||
string language;
|
||||
string outputPath;
|
||||
string msBuildProjectDirectory;
|
||||
ITaskItem[] applicationMarkupWithTypeName;
|
||||
|
||||
public CompilationPass2Task()
|
||||
{
|
||||
}
|
||||
|
||||
[Fx.Tag.KnownXamlExternal]
|
||||
public ITaskItem[] ApplicationMarkup { get; set; }
|
||||
|
||||
public string AssemblyName
|
||||
{ get; set; }
|
||||
|
||||
[Fx.Tag.KnownXamlExternal]
|
||||
public ITaskItem[] References { get; set; }
|
||||
|
||||
// Required in Dev11, but for backward compatibility with a Dev10 targets file, not marking as required.
|
||||
public string Language
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.language;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.language = value;
|
||||
this.supportExtensions = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Required in Dev11, but for backward compatibility with a Dev10 targets file, not marking as required.
|
||||
public string OutputPath
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.outputPath;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.outputPath = value;
|
||||
this.supportExtensions = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Required in Dev11, but for backward compatibility with a Dev10 targets file, not marking as required.
|
||||
public string MSBuildProjectDirectory
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.msBuildProjectDirectory;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.msBuildProjectDirectory = value;
|
||||
this.supportExtensions = true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsInProcessXamlMarkupCompile
|
||||
{ get; set; }
|
||||
|
||||
[Fx.Tag.KnownXamlExternal]
|
||||
public ITaskItem[] SourceCodeFiles
|
||||
{ get; set; }
|
||||
|
||||
public ITaskItem[] XamlBuildTypeInspectionExtensionNames
|
||||
{ get; set; }
|
||||
|
||||
// Required in Dev11, but for backward compatibility with a Dev10 targets file, not marking as required.
|
||||
public ITaskItem[] ApplicationMarkupWithTypeName
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.applicationMarkupWithTypeName;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.applicationMarkupWithTypeName = value;
|
||||
this.supportExtensions = true;
|
||||
}
|
||||
}
|
||||
|
||||
public string LocalAssemblyReference
|
||||
{ get; set; }
|
||||
|
||||
public string RootNamespace
|
||||
{ get; set; }
|
||||
|
||||
public string BuildTaskPath
|
||||
{ get; set; }
|
||||
|
||||
[Output]
|
||||
public ITaskItem[] ExtensionGeneratedCodeFiles
|
||||
{
|
||||
get
|
||||
{
|
||||
return generatedCodeFiles.ToArray();
|
||||
}
|
||||
set
|
||||
{
|
||||
generatedCodeFiles = new List<ITaskItem>(value);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
AppDomain appDomain = null;
|
||||
|
||||
try
|
||||
{
|
||||
ValidateRequiredDev11Properties();
|
||||
|
||||
appDomain = XamlBuildTaskServices.CreateAppDomain("CompilationPass2AppDomain_" + Guid.NewGuid(), BuildTaskPath);
|
||||
|
||||
CompilationPass2TaskInternal wrapper = (CompilationPass2TaskInternal)appDomain.CreateInstanceAndUnwrap(
|
||||
Assembly.GetExecutingAssembly().FullName,
|
||||
typeof(CompilationPass2TaskInternal).FullName);
|
||||
|
||||
PopulateBuildArtifacts(wrapper);
|
||||
|
||||
bool ret = wrapper.Execute();
|
||||
|
||||
ExtractBuiltArtifacts(wrapper);
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
foreach (LogData logData in wrapper.LogData)
|
||||
{
|
||||
XamlBuildTaskServices.LogException(
|
||||
this.Log,
|
||||
logData.Message,
|
||||
logData.FileName,
|
||||
logData.LineNumber,
|
||||
logData.LinePosition);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (Fx.IsFatal(e))
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
XamlBuildTaskServices.LogException(this.Log, e.Message);
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (appDomain != null)
|
||||
{
|
||||
AppDomain.Unload(appDomain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string SeparateWithComma(string originalString, string stringToAppend)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(originalString))
|
||||
{
|
||||
return String.Join(", ", originalString, stringToAppend);
|
||||
}
|
||||
else
|
||||
{
|
||||
return stringToAppend;
|
||||
}
|
||||
}
|
||||
|
||||
void ValidateRequiredDev11Properties()
|
||||
{
|
||||
if (this.supportExtensions)
|
||||
{
|
||||
string requiredPropertiesNotSpecified = "";
|
||||
if (this.language == null)
|
||||
{
|
||||
requiredPropertiesNotSpecified = SeparateWithComma(requiredPropertiesNotSpecified, "Language");
|
||||
}
|
||||
if (this.outputPath == null)
|
||||
{
|
||||
requiredPropertiesNotSpecified = SeparateWithComma(requiredPropertiesNotSpecified, "OutputPath");
|
||||
}
|
||||
if (this.msBuildProjectDirectory == null)
|
||||
{
|
||||
requiredPropertiesNotSpecified = SeparateWithComma(requiredPropertiesNotSpecified, "MSBuildProjectDirectory");
|
||||
}
|
||||
if (this.applicationMarkupWithTypeName == null)
|
||||
{
|
||||
requiredPropertiesNotSpecified = SeparateWithComma(requiredPropertiesNotSpecified, "ApplicationMarkupWithTypeName");
|
||||
}
|
||||
if (!String.IsNullOrEmpty(requiredPropertiesNotSpecified))
|
||||
{
|
||||
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.MissingRequiredParametersCompilationPass2Task(requiredPropertiesNotSpecified)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PopulateBuildArtifacts(CompilationPass2TaskInternal wrapper)
|
||||
{
|
||||
if (!this.supportExtensions)
|
||||
{
|
||||
IList<string> applicationMarkup = new List<string>(this.ApplicationMarkup.Length);
|
||||
foreach (ITaskItem taskItem in this.ApplicationMarkup)
|
||||
{
|
||||
applicationMarkup.Add(taskItem.ItemSpec);
|
||||
}
|
||||
wrapper.ApplicationMarkup = applicationMarkup;
|
||||
}
|
||||
|
||||
wrapper.SupportExtensions = this.supportExtensions;
|
||||
|
||||
wrapper.BuildLogger = this.Log;
|
||||
|
||||
wrapper.References = this.References
|
||||
.Select(i => new DelegatingTaskItem(i) as ITaskItem).ToList();
|
||||
|
||||
wrapper.LocalAssemblyReference = this.LocalAssemblyReference;
|
||||
|
||||
wrapper.AssemblyName = this.AssemblyName;
|
||||
|
||||
wrapper.RootNamespace = this.RootNamespace;
|
||||
|
||||
wrapper.Language = this.Language;
|
||||
|
||||
wrapper.OutputPath = this.OutputPath;
|
||||
|
||||
wrapper.IsInProcessXamlMarkupCompile = this.IsInProcessXamlMarkupCompile;
|
||||
|
||||
wrapper.MSBuildProjectDirectory = this.MSBuildProjectDirectory;
|
||||
|
||||
IList<string> sourceCodeFiles = null;
|
||||
if (this.SourceCodeFiles != null)
|
||||
{
|
||||
sourceCodeFiles = new List<string>(this.SourceCodeFiles.Length);
|
||||
foreach (ITaskItem taskItem in this.SourceCodeFiles)
|
||||
{
|
||||
sourceCodeFiles.Add(taskItem.ItemSpec);
|
||||
}
|
||||
}
|
||||
wrapper.SourceCodeFiles = sourceCodeFiles;
|
||||
|
||||
if (this.supportExtensions)
|
||||
{
|
||||
wrapper.XamlBuildTaskTypeInspectionExtensionNames = XamlBuildTaskServices.GetXamlBuildTaskExtensionNames(this.XamlBuildTypeInspectionExtensionNames);
|
||||
|
||||
// Here we create a Dictionary of Type Full Name and corresponding TaskItem
|
||||
// This is passed to the extensions which enables them to look up
|
||||
// metadata about a type like file name.
|
||||
IDictionary<string, ITaskItem> applicationMarkupWithTypeName = null;
|
||||
if (this.ApplicationMarkupWithTypeName != null)
|
||||
{
|
||||
applicationMarkupWithTypeName = new Dictionary<string, ITaskItem>();
|
||||
}
|
||||
foreach (ITaskItem taskItem in this.ApplicationMarkupWithTypeName)
|
||||
{
|
||||
string typeName = taskItem.GetMetadata("typeName");
|
||||
if (!String.IsNullOrWhiteSpace(typeName))
|
||||
{
|
||||
applicationMarkupWithTypeName.Add(typeName, new DelegatingTaskItem(taskItem));
|
||||
}
|
||||
}
|
||||
wrapper.ApplicationMarkupWithTypeName = applicationMarkupWithTypeName;
|
||||
}
|
||||
}
|
||||
|
||||
void ExtractBuiltArtifacts(CompilationPass2TaskInternal wrapper)
|
||||
{
|
||||
if (wrapper.GeneratedCodeFiles == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (string code in wrapper.GeneratedCodeFiles)
|
||||
{
|
||||
this.generatedCodeFiles.Add(new TaskItem(code));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,362 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Build.Tasks.Xaml
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Xaml;
|
||||
using System.Xaml.Schema;
|
||||
using System.Xml;
|
||||
using System.Reflection;
|
||||
using System.Runtime;
|
||||
using System.Runtime.Remoting.Lifetime;
|
||||
using System.Globalization;
|
||||
using Microsoft.Build.Utilities;
|
||||
using XamlBuildTask;
|
||||
using Microsoft.Build.Framework;
|
||||
|
||||
internal class CompilationPass2TaskInternal : MarshalByRefObject
|
||||
{
|
||||
IList<string> applicationMarkup;
|
||||
IList<ITaskItem> references;
|
||||
IList<LogData> logData;
|
||||
IList<string> sourceCodeFiles;
|
||||
IList<string> generatedCodeFiles;
|
||||
XamlBuildTypeInspectionExtensionContext buildContextForExtensions;
|
||||
IDictionary<string, ITaskItem> applicationMarkupWithTypeName;
|
||||
|
||||
// Set the lease lifetime according to the environment variable with the name defined by RemotingLeaseLifetimeInMinutesEnvironmentVariableName
|
||||
public override object InitializeLifetimeService()
|
||||
{
|
||||
ILease lease = (ILease)base.InitializeLifetimeService();
|
||||
XamlBuildTaskLeaseLifetimeHelper.SetLeaseLifetimeFromEnvironmentVariable(lease);
|
||||
return lease;
|
||||
}
|
||||
|
||||
public IList<string> ApplicationMarkup
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.applicationMarkup == null)
|
||||
{
|
||||
this.applicationMarkup = new List<string>();
|
||||
}
|
||||
return this.applicationMarkup;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.applicationMarkup = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string AssemblyName
|
||||
{ get; set; }
|
||||
|
||||
public TaskLoggingHelper BuildLogger
|
||||
{ get; set; }
|
||||
|
||||
public string LocalAssemblyReference
|
||||
{ get; set; }
|
||||
|
||||
public string RootNamespace
|
||||
{ get; set; }
|
||||
|
||||
public string MSBuildProjectDirectory
|
||||
{ get; set; }
|
||||
|
||||
public IList<LogData> LogData
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.logData == null)
|
||||
{
|
||||
this.logData = new List<LogData>();
|
||||
}
|
||||
return this.logData;
|
||||
}
|
||||
}
|
||||
|
||||
public IList<ITaskItem> References
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.references == null)
|
||||
{
|
||||
this.references = new List<ITaskItem>();
|
||||
}
|
||||
return this.references;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.references = value;
|
||||
}
|
||||
}
|
||||
|
||||
public IList<string> SourceCodeFiles
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.sourceCodeFiles == null)
|
||||
{
|
||||
this.sourceCodeFiles = new List<string>();
|
||||
}
|
||||
return this.sourceCodeFiles;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.sourceCodeFiles = value;
|
||||
}
|
||||
}
|
||||
|
||||
public IList<string> GeneratedCodeFiles
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.generatedCodeFiles == null)
|
||||
{
|
||||
this.generatedCodeFiles = new List<string>();
|
||||
}
|
||||
return generatedCodeFiles;
|
||||
}
|
||||
}
|
||||
|
||||
public IDictionary<string, ITaskItem> ApplicationMarkupWithTypeName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.applicationMarkupWithTypeName == null)
|
||||
{
|
||||
this.applicationMarkupWithTypeName = new Dictionary<string, ITaskItem>();
|
||||
}
|
||||
return applicationMarkupWithTypeName;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.applicationMarkupWithTypeName = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string OutputPath
|
||||
{ get; set; }
|
||||
|
||||
public string Language
|
||||
{ get; set; }
|
||||
|
||||
public bool IsInProcessXamlMarkupCompile
|
||||
{ get; set; }
|
||||
|
||||
public IList<Tuple<string, string, string>> XamlBuildTaskTypeInspectionExtensionNames
|
||||
{ get; set; }
|
||||
|
||||
public IList<Tuple<AssemblyName, Assembly>> ReferencedAssemblies
|
||||
{ get; set; }
|
||||
|
||||
public bool SupportExtensions
|
||||
{ get; set; }
|
||||
|
||||
public XamlBuildTypeInspectionExtensionContext BuildContextForExtensions
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.buildContextForExtensions == null)
|
||||
{
|
||||
XamlBuildTypeInspectionExtensionContext local = new XamlBuildTypeInspectionExtensionContext();
|
||||
local.AssemblyName = this.AssemblyName;
|
||||
local.IsInProcessXamlMarkupCompile = this.IsInProcessXamlMarkupCompile;
|
||||
local.Language = this.Language;
|
||||
local.OutputPath = this.OutputPath;
|
||||
local.RootNamespace = this.RootNamespace;
|
||||
local.AddSourceCodeFiles(this.SourceCodeFiles);
|
||||
local.LocalAssembly = this.LocalAssemblyReference;
|
||||
local.XamlBuildLogger = this.BuildLogger;
|
||||
local.AddReferences(XamlBuildTaskServices.GetReferences(this.references));
|
||||
local.AddApplicationMarkupWithTypeName(this.ApplicationMarkupWithTypeName);
|
||||
|
||||
this.buildContextForExtensions = local;
|
||||
}
|
||||
return this.buildContextForExtensions;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Execute()
|
||||
{
|
||||
try
|
||||
{
|
||||
if ((!this.SupportExtensions) && ((this.ApplicationMarkup == null) || this.ApplicationMarkup.Count == 0))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (this.ApplicationMarkupWithTypeName == null || this.ApplicationMarkupWithTypeName.Count == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
IList<Assembly> loadedAssemblyList = null;
|
||||
if (this.References != null)
|
||||
{
|
||||
loadedAssemblyList = XamlBuildTaskServices.Load(this.References, false);
|
||||
}
|
||||
|
||||
Assembly localAssembly = null;
|
||||
if (LocalAssemblyReference != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
localAssembly = XamlBuildTaskServices.Load(LocalAssemblyReference);
|
||||
loadedAssemblyList.Add(localAssembly);
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
XamlBuildTaskServices.LogException(this.BuildLogger, e.Message, e.FileName, 0, 0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += new ResolveEventHandler(XamlBuildTaskServices.ReflectionOnlyAssemblyResolve);
|
||||
XamlNsReplacingContext wxsc = new XamlNsReplacingContext(loadedAssemblyList, localAssembly.GetName().Name, this.AssemblyName);
|
||||
|
||||
bool foundValidationErrors = false;
|
||||
if (!this.SupportExtensions)
|
||||
{
|
||||
foreach (string app in ApplicationMarkup)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!ProcessMarkupItem(app, wxsc, localAssembly))
|
||||
{
|
||||
foundValidationErrors = true;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (Fx.IsFatal(e))
|
||||
{
|
||||
throw;
|
||||
}
|
||||
XamlBuildTaskServices.LogException(this.BuildLogger, e.Message, app, 0, 0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (ITaskItem app in this.ApplicationMarkupWithTypeName.Values)
|
||||
{
|
||||
string inputMarkupFile = app.ItemSpec;
|
||||
try
|
||||
{
|
||||
if (!ProcessMarkupItem(inputMarkupFile, wxsc, localAssembly))
|
||||
{
|
||||
foundValidationErrors = true;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (Fx.IsFatal(e))
|
||||
{
|
||||
throw;
|
||||
}
|
||||
XamlBuildTaskServices.LogException(this.BuildLogger, e.Message, inputMarkupFile, 0, 0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!foundValidationErrors)
|
||||
{
|
||||
foundValidationErrors = !ExecuteExtensions();
|
||||
if (!foundValidationErrors)
|
||||
{
|
||||
foundValidationErrors = this.BuildLogger.HasLoggedErrors;
|
||||
}
|
||||
}
|
||||
}
|
||||
return !foundValidationErrors;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (Fx.IsFatal(e))
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
// Log unknown errors that do not originate from the task.
|
||||
// Assumes that all known errors are logged when the exception is thrown.
|
||||
XamlBuildTaskServices.LogException(this.BuildLogger, e.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ProcessMarkupItem(string markupItem, XamlNsReplacingContext wxsc, Assembly localAssembly)
|
||||
{
|
||||
XamlXmlReaderSettings settings = new XamlXmlReaderSettings() { LocalAssembly = localAssembly, ProvideLineInfo = true, AllowProtectedMembersOnRoot = true };
|
||||
using (StreamReader streamReader = new StreamReader(markupItem))
|
||||
{
|
||||
var xamlReader = new XamlXmlReader(XmlReader.Create(streamReader), wxsc, settings);
|
||||
ClassValidator validator = new ClassValidator(markupItem, localAssembly, this.RootNamespace);
|
||||
IList<LogData> validationErrors = null;
|
||||
if (validator.ValidateXaml(xamlReader, false, this.AssemblyName, out validationErrors))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (LogData logData in validationErrors)
|
||||
{
|
||||
this.LogData.Add(logData);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ExecuteExtensions()
|
||||
{
|
||||
ResolveAssemblyHelper resolveAssemblyHelper = new ResolveAssemblyHelper(XamlBuildTaskServices.GetReferences(this.References));
|
||||
AppDomain.CurrentDomain.AssemblyResolve += resolveAssemblyHelper.ResolveLocalProjectReferences;
|
||||
|
||||
bool extensionExecutedSuccessfully = true;
|
||||
try
|
||||
{
|
||||
IEnumerable<IXamlBuildTypeInspectionExtension> extensions =
|
||||
XamlBuildTaskServices.GetXamlBuildTaskExtensions<IXamlBuildTypeInspectionExtension>(
|
||||
this.XamlBuildTaskTypeInspectionExtensionNames,
|
||||
this.BuildLogger,
|
||||
this.MSBuildProjectDirectory);
|
||||
|
||||
foreach (IXamlBuildTypeInspectionExtension extension in extensions)
|
||||
{
|
||||
try
|
||||
{
|
||||
extensionExecutedSuccessfully &= extension.Execute(this.BuildContextForExtensions);
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
throw FxTrace.Exception.AsError(new LoggableException(SR.ExceptionThrownInExtension(extension.ToString(), e.GetType().ToString(), SR.AssemblyNotFound(ResolveAssemblyHelper.FileNotFound))));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (Fx.IsFatal(e))
|
||||
{
|
||||
throw;
|
||||
}
|
||||
throw FxTrace.Exception.AsError(new LoggableException(SR.ExceptionThrownInExtension(extension.ToString(), e.GetType().ToString(), e.Message)));
|
||||
}
|
||||
}
|
||||
if (!this.BuildLogger.HasLoggedErrors && extensionExecutedSuccessfully)
|
||||
{
|
||||
foreach (string file in this.BuildContextForExtensions.GeneratedFiles)
|
||||
{
|
||||
this.GeneratedCodeFiles.Add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
AppDomain.CurrentDomain.AssemblyResolve -= resolveAssemblyHelper.ResolveLocalProjectReferences;
|
||||
}
|
||||
return extensionExecutedSuccessfully;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
// <copyright>
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace Microsoft.Build.Tasks.Xaml
|
||||
{
|
||||
using System;
|
||||
using System.Collections;
|
||||
using Microsoft.Build.Framework;
|
||||
|
||||
// In Dev10, we allowed use of non-remotable ITaskItems. While there's not really any good scenario
|
||||
// for those, we need to support that for back-compat. So we wrap each provided TaskItems in an MBRO.
|
||||
internal class DelegatingTaskItem : MarshalByRefObject, ITaskItem
|
||||
{
|
||||
private ITaskItem underlyingItem;
|
||||
|
||||
// This is different from TaskItem.ctor(ITaskItem): it's a wrapper, not a clone.
|
||||
// So any changes are propagated back to the original object.
|
||||
public DelegatingTaskItem(ITaskItem underlyingItem)
|
||||
{
|
||||
this.underlyingItem = underlyingItem;
|
||||
}
|
||||
|
||||
public string ItemSpec
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.underlyingItem.ItemSpec;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.underlyingItem.ItemSpec = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int MetadataCount
|
||||
{
|
||||
get { return this.underlyingItem.MetadataCount; }
|
||||
}
|
||||
|
||||
public ICollection MetadataNames
|
||||
{
|
||||
get { return this.underlyingItem.MetadataNames; }
|
||||
}
|
||||
|
||||
public IDictionary CloneCustomMetadata()
|
||||
{
|
||||
return this.underlyingItem.CloneCustomMetadata();
|
||||
}
|
||||
|
||||
public void CopyMetadataTo(ITaskItem destinationItem)
|
||||
{
|
||||
this.underlyingItem.CopyMetadataTo(destinationItem);
|
||||
}
|
||||
|
||||
public string GetMetadata(string metadataName)
|
||||
{
|
||||
return this.underlyingItem.GetMetadata(metadataName);
|
||||
}
|
||||
|
||||
public void RemoveMetadata(string metadataName)
|
||||
{
|
||||
this.underlyingItem.RemoveMetadata(metadataName);
|
||||
}
|
||||
|
||||
public void SetMetadata(string metadataName, string metadataValue)
|
||||
{
|
||||
this.underlyingItem.SetMetadata(metadataName, metadataValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Build.Tasks.Xaml
|
||||
{
|
||||
using System;
|
||||
using System.CodeDom;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Xaml;
|
||||
using System.Xaml.Schema;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
using System.Reflection;
|
||||
using System.Globalization;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime;
|
||||
using Microsoft.Build.BuildEngine;
|
||||
|
||||
[Fx.Tag.XamlVisible(true)]
|
||||
public class GenerateTemporaryAssemblyTask : Task
|
||||
{
|
||||
const string MSBuildNamespace = "http://schemas.microsoft.com/developer/msbuild/2003";
|
||||
|
||||
// We will do Dev10 behavior if the new required property GeneratedResourceFiles is NOT specified. This can happen
|
||||
// if a Dev10 version of the Microsoft.Xaml.Targets file is being used with Dev11 installed.
|
||||
bool supportExtensions = false;
|
||||
ITaskItem[] generatedResourceFiles;
|
||||
|
||||
public GenerateTemporaryAssemblyTask()
|
||||
{
|
||||
}
|
||||
|
||||
[Required]
|
||||
public string AssemblyName
|
||||
{ get; set; }
|
||||
|
||||
[Required]
|
||||
public string OutputPath
|
||||
{ get; set; }
|
||||
|
||||
[Required]
|
||||
public string CurrentProject
|
||||
{ get; set; }
|
||||
|
||||
[Fx.Tag.KnownXamlExternal]
|
||||
[Required]
|
||||
public ITaskItem[] SourceCodeFiles { get; set; }
|
||||
|
||||
[Required]
|
||||
public string CompileTargetName
|
||||
{ get; set; }
|
||||
|
||||
// Required in Dev11, but for backward compatibility with a Dev10 targets file, not marking as required.
|
||||
public ITaskItem[] GeneratedResourcesFiles
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.generatedResourceFiles;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.generatedResourceFiles = value;
|
||||
this.supportExtensions = true;
|
||||
}
|
||||
}
|
||||
|
||||
[Fx.Tag.KnownXamlExternal]
|
||||
public ITaskItem[] ReferencePaths
|
||||
{ get; set; }
|
||||
|
||||
[Required]
|
||||
public string ApplicationMarkupTypeName
|
||||
{ get; set; }
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
bool retVal;
|
||||
try
|
||||
{
|
||||
XDocument projectDocument = XDocument.Load(this.CurrentProject);
|
||||
if (projectDocument != null)
|
||||
{
|
||||
XElement projectElement = projectDocument.Element(XName.Get("Project", MSBuildNamespace));
|
||||
if (projectElement != null)
|
||||
{
|
||||
RemoveItemsByName(projectElement, this.ApplicationMarkupTypeName);
|
||||
RemoveItemsByName(projectElement, "Reference");
|
||||
RemoveItemsByName(projectElement, "ProjectReference");
|
||||
if (this.supportExtensions)
|
||||
{
|
||||
AddNewResourceItems(projectElement, this.GeneratedResourcesFiles);
|
||||
}
|
||||
AddNewItems(projectElement, "Compile", this.SourceCodeFiles);
|
||||
AddNewItems(projectElement, "ReferencePath", this.ReferencePaths);
|
||||
|
||||
RemovePropertyByName(projectElement, "OutputType");
|
||||
RemovePropertyByName(projectElement, "AssemblyName");
|
||||
AddNewProperties(projectElement,
|
||||
new ProjectProperty[] {
|
||||
new ProjectProperty() { Name = "OutputType", Value = "Library" },
|
||||
new ProjectProperty() { Name = "AssemblyName", Value = this.AssemblyName },
|
||||
new ProjectProperty() { Name = "Utf8Output", Value = "true", Condition = "'$(Utf8Output)' == ''" }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
string randomName = Path.GetRandomFileName();
|
||||
randomName = Path.ChangeExtension(randomName, "");
|
||||
string filename = Path.ChangeExtension(randomName, ".tmp_proj");
|
||||
projectDocument.Save(filename);
|
||||
Hashtable globalProperties = new Hashtable();
|
||||
globalProperties["IntermediateOutputPath"] = this.OutputPath;
|
||||
globalProperties["AssemblyName"] = this.AssemblyName;
|
||||
globalProperties["OutputType"] = "Library";
|
||||
retVal = base.BuildEngine.BuildProjectFile(filename, new string[] { this.CompileTargetName }, globalProperties, null);
|
||||
File.Delete(filename);
|
||||
return retVal;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (Fx.IsFatal(e))
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
// Log unknown errors that do not originate from the task.
|
||||
// Assumes that all known errors are logged when the exception is thrown.
|
||||
XamlBuildTaskServices.LogException(this.Log, e.Message);
|
||||
retVal = false;
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void RemoveItemsByName(XElement project, string itemName)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(itemName))
|
||||
{
|
||||
IEnumerable<XElement> itemGroups = project.Elements(XName.Get("ItemGroup", MSBuildNamespace));
|
||||
itemGroups.Elements(XName.Get(itemName, MSBuildNamespace)).Remove();
|
||||
}
|
||||
}
|
||||
|
||||
void AddNewItems(XElement project, string itemName, ITaskItem[] items)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(itemName) && items != null)
|
||||
{
|
||||
XElement newItemGroup = new XElement(XName.Get("ItemGroup", MSBuildNamespace));
|
||||
project.Add(newItemGroup);
|
||||
foreach (ITaskItem item in items)
|
||||
{
|
||||
XElement newElement = new XElement(XName.Get(itemName, MSBuildNamespace));
|
||||
XAttribute include = new XAttribute("Include", item.ItemSpec);
|
||||
newElement.Add(include);
|
||||
newItemGroup.Add(newElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//<ItemGroup>
|
||||
// <EmbeddedResource Include="@(XamlGeneratedResources)">
|
||||
// <Type>Non-Resx</Type>
|
||||
// <WithCulture>false</WithCulture>
|
||||
// </EmbeddedResource>
|
||||
//</ItemGroup>
|
||||
void AddNewResourceItems(XElement project, ITaskItem[] items)
|
||||
{
|
||||
if (items != null && items.Length > 0)
|
||||
{
|
||||
XElement newItemGroup = new XElement(XName.Get("ItemGroup", MSBuildNamespace));
|
||||
project.Add(newItemGroup);
|
||||
foreach (ITaskItem item in items)
|
||||
{
|
||||
XElement newResource = new XElement(XName.Get("EmbeddedResource", MSBuildNamespace));
|
||||
newResource.Add(new XAttribute("Include", item.ItemSpec));
|
||||
|
||||
XElement type = new XElement(XName.Get("Type", MSBuildNamespace), "Non-Resx");
|
||||
newResource.Add(type);
|
||||
|
||||
XElement withCulture = new XElement(XName.Get("WithCulture", MSBuildNamespace), "false");
|
||||
newResource.Add(withCulture);
|
||||
|
||||
newItemGroup.Add(newResource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RemovePropertyByName(XElement project, string propertyName)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(propertyName))
|
||||
{
|
||||
IEnumerable<XElement> itemGroups = project.Elements(XName.Get("PropertyGroup", MSBuildNamespace));
|
||||
itemGroups.Elements(XName.Get(propertyName, MSBuildNamespace)).Remove();
|
||||
}
|
||||
}
|
||||
|
||||
void AddNewProperties(XElement project, IEnumerable<ProjectProperty> properties)
|
||||
{
|
||||
if (properties != null)
|
||||
{
|
||||
XElement newPropertyGroup = new XElement(XName.Get("PropertyGroup", MSBuildNamespace));
|
||||
project.Add(newPropertyGroup);
|
||||
foreach (ProjectProperty prop in properties)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(prop.Name) && prop.Value != null)
|
||||
{
|
||||
XElement newElement = new XElement(XName.Get(prop.Name, MSBuildNamespace));
|
||||
newElement.Value = prop.Value;
|
||||
if (!string.IsNullOrEmpty(prop.Condition))
|
||||
{
|
||||
newElement.SetAttributeValue(XName.Get("Condition", string.Empty), prop.Condition);
|
||||
}
|
||||
newPropertyGroup.Add(newElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ProjectProperty
|
||||
{
|
||||
public string Name
|
||||
{ get; set; }
|
||||
public string Value
|
||||
{ get; set; }
|
||||
public string Condition
|
||||
{ get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
|
||||
namespace Microsoft.Build.Tasks.Xaml
|
||||
{
|
||||
using System.CodeDom;
|
||||
|
||||
public interface IXamlBuildTypeGenerationExtension
|
||||
{
|
||||
bool Execute(ClassData classData, XamlBuildTypeGenerationExtensionContext buildContext);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Build.Tasks.Xaml
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
|
||||
public interface IXamlBuildTypeInspectionExtension
|
||||
{
|
||||
bool Execute(XamlBuildTypeInspectionExtensionContext buildContext);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Build.Tasks.Xaml
|
||||
{
|
||||
using System;
|
||||
|
||||
[Serializable]
|
||||
internal struct LogData
|
||||
{
|
||||
public string Message
|
||||
{ get; set; }
|
||||
|
||||
public string FileName
|
||||
{ get; set; }
|
||||
|
||||
public int LineNumber
|
||||
{ get; set; }
|
||||
|
||||
public int LinePosition
|
||||
{ get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Build.Tasks.Xaml
|
||||
{
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
[Serializable]
|
||||
class LoggableException : Exception
|
||||
{
|
||||
int lineNumber;
|
||||
int linePosition;
|
||||
|
||||
public LoggableException()
|
||||
{
|
||||
}
|
||||
|
||||
public int LineNumber
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.lineNumber;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.lineNumber = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int LinePosition
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.linePosition;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.linePosition = value;
|
||||
}
|
||||
}
|
||||
|
||||
public LoggableException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public LoggableException(Exception innerException)
|
||||
: base(innerException.Message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
public override void GetObjectData(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
base.GetObjectData(info, context);
|
||||
|
||||
if (info != null)
|
||||
{
|
||||
info.AddValue("lineNumber", this.lineNumber);
|
||||
info.AddValue("columnNumber", this.linePosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Build.Tasks.Xaml
|
||||
{
|
||||
public enum MemberVisibility
|
||||
{
|
||||
Public,
|
||||
Private,
|
||||
Family,
|
||||
Assembly,
|
||||
FamilyOrAssembly,
|
||||
FamilyAndAssembly
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Build.Tasks.Xaml
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using System.Xaml;
|
||||
using System.Xaml.Schema;
|
||||
using XamlBuildTask;
|
||||
|
||||
public class NamedObject
|
||||
{
|
||||
MemberVisibility visibility;
|
||||
|
||||
public String Name
|
||||
{ get; set; }
|
||||
|
||||
public XamlType Type
|
||||
{ get; set; }
|
||||
|
||||
public MemberVisibility Visibility
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.visibility;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (!Enum.IsDefined(typeof(MemberVisibility), value))
|
||||
{
|
||||
throw FxTrace.Exception.AsError(new ArgumentOutOfRangeException("value"));
|
||||
}
|
||||
this.visibility = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xaml;
|
||||
|
||||
namespace Microsoft.Build.Tasks.Xaml
|
||||
{
|
||||
internal class NamespaceTable : IXamlNamespaceResolver
|
||||
{
|
||||
Dictionary<string, NamespaceDeclaration> tempNamespaceList = new Dictionary<string, NamespaceDeclaration>();
|
||||
Stack<Dictionary<string, NamespaceDeclaration>> namespaceStack = new Stack<Dictionary<string, NamespaceDeclaration>>();
|
||||
string localAssemblyName;
|
||||
|
||||
public NamespaceTable(string localAssemblyName)
|
||||
{
|
||||
this.localAssemblyName = localAssemblyName;
|
||||
}
|
||||
|
||||
public IEnumerable<NamespaceDeclaration> GetNamespacePrefixes()
|
||||
{
|
||||
List<NamespaceDeclaration> list = new List<NamespaceDeclaration>();
|
||||
HashSet<string> prefixSet = new HashSet<string>();
|
||||
if (tempNamespaceList != null && tempNamespaceList.Count > 0)
|
||||
{
|
||||
foreach (NamespaceDeclaration ns in tempNamespaceList.Values)
|
||||
{
|
||||
if (!prefixSet.Contains(ns.Prefix))
|
||||
{
|
||||
prefixSet.Add(ns.Prefix);
|
||||
list.Add(ns);
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (Dictionary<string, NamespaceDeclaration> currentNamespaces in this.namespaceStack)
|
||||
{
|
||||
foreach (NamespaceDeclaration ns in currentNamespaces.Values)
|
||||
{
|
||||
if (!prefixSet.Contains(ns.Prefix))
|
||||
{
|
||||
prefixSet.Add(ns.Prefix);
|
||||
list.Add(ns);
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public string GetNamespace(string prefix)
|
||||
{
|
||||
NamespaceDeclaration @namespace = null;
|
||||
foreach (Dictionary<string, NamespaceDeclaration> currentNamespaces in this.namespaceStack)
|
||||
{
|
||||
if (null != currentNamespaces && currentNamespaces.TryGetValue(prefix, out @namespace))
|
||||
{
|
||||
return @namespace.Namespace;
|
||||
}
|
||||
}
|
||||
|
||||
if (tempNamespaceList != null && tempNamespaceList.TryGetValue(prefix, out @namespace))
|
||||
{
|
||||
return @namespace.Namespace;
|
||||
}
|
||||
|
||||
return @namespace.Namespace;
|
||||
}
|
||||
|
||||
public void ManageNamespace(XamlReader reader)
|
||||
{
|
||||
switch (reader.NodeType)
|
||||
{
|
||||
case XamlNodeType.NamespaceDeclaration:
|
||||
tempNamespaceList.Add(reader.Namespace.Prefix,
|
||||
new NamespaceDeclaration(
|
||||
XamlBuildTaskServices.UpdateClrNamespaceUriWithLocalAssembly(reader.Namespace.Namespace, this.localAssemblyName),
|
||||
reader.Namespace.Prefix));
|
||||
break;
|
||||
case XamlNodeType.StartObject:
|
||||
case XamlNodeType.StartMember:
|
||||
case XamlNodeType.GetObject:
|
||||
if (tempNamespaceList != null)
|
||||
{
|
||||
namespaceStack.Push(tempNamespaceList);
|
||||
tempNamespaceList = new Dictionary<string, NamespaceDeclaration>();
|
||||
}
|
||||
break;
|
||||
case XamlNodeType.EndMember:
|
||||
case XamlNodeType.EndObject:
|
||||
namespaceStack.Pop();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,387 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Build.Tasks.Xaml
|
||||
{
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime;
|
||||
using System.Threading;
|
||||
using System.Xaml;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
using Microsoft.VisualStudio.Activities;
|
||||
|
||||
[Fx.Tag.XamlVisible(true)]
|
||||
public class PartialClassGenerationTask : Task
|
||||
{
|
||||
const string DefaultGeneratedSourceExtension = "g";
|
||||
List<ITaskItem> generatedResources = new List<ITaskItem>();
|
||||
List<ITaskItem> generatedCodeFiles = new List<ITaskItem>();
|
||||
|
||||
// We will do Dev10 behavior if the new required property MSBuildProjectDirectory is NOT specified. This can happen
|
||||
// if a Dev10 version of the Microsoft.Xaml.Targets file is being used with Dev11 installed.
|
||||
bool supportExtensions = false;
|
||||
string msBuildProjectDirectory;
|
||||
|
||||
public PartialClassGenerationTask()
|
||||
{
|
||||
this.GeneratedSourceExtension = DefaultGeneratedSourceExtension;
|
||||
}
|
||||
|
||||
[Fx.Tag.KnownXamlExternal]
|
||||
[Output]
|
||||
public ITaskItem[] ApplicationMarkup { get; set; }
|
||||
|
||||
public string AssemblyName
|
||||
{ get; set; }
|
||||
|
||||
public string[] KnownReferencePaths { get; set; }
|
||||
|
||||
[Fx.Tag.KnownXamlExternal]
|
||||
[Output]
|
||||
public ITaskItem[] GeneratedResources
|
||||
{
|
||||
get
|
||||
{
|
||||
return generatedResources.ToArray();
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
generatedResources = new List<ITaskItem>(value);
|
||||
}
|
||||
}
|
||||
|
||||
[Fx.Tag.KnownXamlExternal]
|
||||
[Output]
|
||||
public ITaskItem[] GeneratedCodeFiles
|
||||
{
|
||||
get
|
||||
{
|
||||
return generatedCodeFiles.ToArray();
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
generatedCodeFiles = new List<ITaskItem>(value);
|
||||
}
|
||||
}
|
||||
|
||||
public string GeneratedSourceExtension
|
||||
{ get; set; }
|
||||
|
||||
[Required]
|
||||
public string Language
|
||||
{ get; set; }
|
||||
|
||||
[Required]
|
||||
public string OutputPath
|
||||
{ get; set; }
|
||||
|
||||
// This is Required for Dev11, but to allow things to work with a Dev10 targets file, we are not marking it required.
|
||||
public string MSBuildProjectDirectory
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.msBuildProjectDirectory;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.msBuildProjectDirectory = value;
|
||||
// The fact that this property is being set indicates that a Dev11 version of the targets
|
||||
// file is being used, so we should not do Dev10 behavior.
|
||||
this.supportExtensions = true;
|
||||
}
|
||||
}
|
||||
|
||||
[Fx.Tag.KnownXamlExternal]
|
||||
public ITaskItem[] References
|
||||
{ get; set; }
|
||||
|
||||
public string RootNamespace
|
||||
{ get; set; }
|
||||
|
||||
[Fx.Tag.KnownXamlExternal]
|
||||
public ITaskItem[] SourceCodeFiles
|
||||
{ get; set; }
|
||||
|
||||
[Output]
|
||||
public bool RequiresCompilationPass2
|
||||
{ get; set; }
|
||||
|
||||
public string BuildTaskPath
|
||||
{ get; set; }
|
||||
|
||||
public bool IsInProcessXamlMarkupCompile
|
||||
{ get; set; }
|
||||
|
||||
public ITaskItem[] XamlBuildTypeGenerationExtensionNames
|
||||
{ get; set; }
|
||||
|
||||
public ITaskItem[] XamlBuildTypeInspectionExtensionNames
|
||||
{ get; set; }
|
||||
|
||||
private static AppDomain inProcessAppDomain;
|
||||
private static Dictionary<string, DateTime> referencesTimeStampCache;
|
||||
private Object referencesCacheLock = new Object();
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
VSDesignerPerfEventProvider perfEventProvider = new VSDesignerPerfEventProvider();
|
||||
perfEventProvider.WriteEvent(VSDesignerPerfEvents.XamlBuildTaskExecuteStart);
|
||||
|
||||
try
|
||||
{
|
||||
if (IsInProcessXamlMarkupCompile)
|
||||
{
|
||||
bool acquiredLock = false;
|
||||
try
|
||||
{
|
||||
Monitor.TryEnter(referencesCacheLock, ref acquiredLock);
|
||||
if (acquiredLock)
|
||||
{
|
||||
return ReuseAppDomainAndExecute();
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetAppDomainAndExecute();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (acquiredLock)
|
||||
{
|
||||
Monitor.Exit(referencesCacheLock);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetAppDomainAndExecute();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
perfEventProvider.WriteEvent(VSDesignerPerfEvents.XamlBuildTaskExecuteEnd);
|
||||
}
|
||||
}
|
||||
|
||||
bool ReuseAppDomainAndExecute()
|
||||
{
|
||||
AppDomain appDomain = null;
|
||||
bool createdNewAppDomain = false;
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
appDomain = GetInProcessAppDomain(out createdNewAppDomain);
|
||||
bool ret = ExecuteInternal(appDomain);
|
||||
return ret;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (Fx.IsFatal(e))
|
||||
{
|
||||
throw;
|
||||
}
|
||||
if (createdNewAppDomain)
|
||||
{
|
||||
XamlBuildTaskServices.LogException(this.Log, e.Message);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
AppDomain.Unload(inProcessAppDomain);
|
||||
inProcessAppDomain = null;
|
||||
return GetAppDomainAndExecute();
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (Log != null)
|
||||
{
|
||||
Log.MarkAsInactive();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GetAppDomainAndExecute()
|
||||
{
|
||||
AppDomain appDomain = null;
|
||||
try
|
||||
{
|
||||
appDomain = CreateNewAppDomain();
|
||||
bool ret = ExecuteInternal(appDomain);
|
||||
return ret;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (Fx.IsFatal(e))
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
XamlBuildTaskServices.LogException(this.Log, e.Message);
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (appDomain != null)
|
||||
{
|
||||
AppDomain.Unload(appDomain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ExecuteInternal(AppDomain appDomain)
|
||||
{
|
||||
PartialClassGenerationTaskInternal wrapper = (PartialClassGenerationTaskInternal)appDomain.CreateInstanceAndUnwrap(
|
||||
Assembly.GetExecutingAssembly().FullName,
|
||||
typeof(PartialClassGenerationTaskInternal).FullName);
|
||||
|
||||
PopulateBuildArtifacts(wrapper);
|
||||
|
||||
bool ret = wrapper.Execute();
|
||||
|
||||
if (ret)
|
||||
{
|
||||
ExtractBuiltArtifacts(wrapper);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
AppDomain CreateNewAppDomain()
|
||||
{
|
||||
return XamlBuildTaskServices.CreateAppDomain("PartialClassAppDomain_" + Guid.NewGuid(), BuildTaskPath);
|
||||
}
|
||||
|
||||
// For Intellisense builds, we re-use the AppDomain for successive builds instead of creating a new one every time,
|
||||
// if the references have not changed (there are no new references and they have not been updated since the last build)
|
||||
// This method accesses the static referencesTimeStampCache (indirectly).
|
||||
// To ensure thread safety, this method should be called inside a lock/monitor
|
||||
AppDomain GetInProcessAppDomain(out bool newAppDomain)
|
||||
{
|
||||
newAppDomain = false;
|
||||
if (inProcessAppDomain == null)
|
||||
{
|
||||
inProcessAppDomain = CreateNewAppDomain();
|
||||
newAppDomain = true;
|
||||
UpdateReferenceCache();
|
||||
}
|
||||
else if (AreReferencesChanged())
|
||||
{
|
||||
AppDomain.Unload(inProcessAppDomain);
|
||||
inProcessAppDomain = CreateNewAppDomain();
|
||||
newAppDomain = true;
|
||||
UpdateReferenceCache();
|
||||
}
|
||||
return inProcessAppDomain;
|
||||
}
|
||||
|
||||
// This method accesses the static referencesTimeStampCache.
|
||||
// To ensure thread safety, this method should be called inside a lock/monitor
|
||||
bool AreReferencesChanged()
|
||||
{
|
||||
bool refsChanged = false;
|
||||
if (referencesTimeStampCache == null || referencesTimeStampCache.Count != References.Length)
|
||||
{
|
||||
refsChanged = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var reference in References)
|
||||
{
|
||||
string fullPath = Path.GetFullPath(reference.ItemSpec);
|
||||
DateTime timeStamp = File.GetLastWriteTimeUtc(fullPath);
|
||||
if (!referencesTimeStampCache.ContainsKey(fullPath)
|
||||
|| timeStamp > referencesTimeStampCache[fullPath]
|
||||
|| timeStamp == DateTime.MinValue)
|
||||
{
|
||||
refsChanged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return refsChanged;
|
||||
}
|
||||
|
||||
// This method accesses the static referencesTimeStampCache.
|
||||
// To ensure thread safety, this method should be called inside a lock/monitor
|
||||
void UpdateReferenceCache()
|
||||
{
|
||||
referencesTimeStampCache = new Dictionary<string, DateTime>();
|
||||
foreach (var reference in References)
|
||||
{
|
||||
string fullPath = Path.GetFullPath(reference.ItemSpec);
|
||||
DateTime timeStamp = File.GetLastWriteTimeUtc(fullPath);
|
||||
referencesTimeStampCache.Add(fullPath, timeStamp);
|
||||
}
|
||||
}
|
||||
|
||||
void PopulateBuildArtifacts(PartialClassGenerationTaskInternal wrapper)
|
||||
{
|
||||
IList<ITaskItem> applicationMarkup = null;
|
||||
if (this.ApplicationMarkup != null)
|
||||
{
|
||||
applicationMarkup = this.ApplicationMarkup
|
||||
.Select(i => new DelegatingTaskItem(i) as ITaskItem).ToList();
|
||||
}
|
||||
wrapper.ApplicationMarkup = applicationMarkup;
|
||||
|
||||
wrapper.BuildLogger = this.Log;
|
||||
|
||||
wrapper.References = this.References
|
||||
.Select(i => new DelegatingTaskItem(i) as ITaskItem).ToList();
|
||||
|
||||
IList<string> sourceCodeFiles = null;
|
||||
if (this.SourceCodeFiles != null)
|
||||
{
|
||||
sourceCodeFiles = new List<string>(this.SourceCodeFiles.Length);
|
||||
foreach (ITaskItem taskItem in this.SourceCodeFiles)
|
||||
{
|
||||
sourceCodeFiles.Add(taskItem.ItemSpec);
|
||||
}
|
||||
}
|
||||
wrapper.SourceCodeFiles = sourceCodeFiles;
|
||||
|
||||
wrapper.Language = this.Language;
|
||||
wrapper.AssemblyName = this.AssemblyName;
|
||||
wrapper.OutputPath = this.OutputPath;
|
||||
wrapper.RootNamespace = this.RootNamespace;
|
||||
wrapper.GeneratedSourceExtension = this.GeneratedSourceExtension;
|
||||
wrapper.IsInProcessXamlMarkupCompile = this.IsInProcessXamlMarkupCompile;
|
||||
wrapper.MSBuildProjectDirectory = this.MSBuildProjectDirectory;
|
||||
wrapper.XamlBuildTaskTypeGenerationExtensionNames = XamlBuildTaskServices.GetXamlBuildTaskExtensionNames(this.XamlBuildTypeGenerationExtensionNames);
|
||||
if (this.XamlBuildTypeInspectionExtensionNames != null && this.XamlBuildTypeInspectionExtensionNames.Length > 0)
|
||||
{
|
||||
wrapper.MarkupCompilePass2ExtensionsPresent = true;
|
||||
}
|
||||
|
||||
wrapper.SupportExtensions = this.supportExtensions;
|
||||
}
|
||||
|
||||
void ExtractBuiltArtifacts(PartialClassGenerationTaskInternal wrapper)
|
||||
{
|
||||
foreach (string resource in wrapper.GeneratedResources)
|
||||
{
|
||||
this.generatedResources.Add(new TaskItem(resource));
|
||||
}
|
||||
|
||||
foreach (string code in wrapper.GeneratedCodeFiles)
|
||||
{
|
||||
this.generatedCodeFiles.Add(new TaskItem(code));
|
||||
}
|
||||
|
||||
this.RequiresCompilationPass2 = wrapper.RequiresCompilationPass2 ||
|
||||
(this.XamlBuildTypeInspectionExtensionNames != null && this.XamlBuildTypeInspectionExtensionNames.Length > 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user