e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
733 lines
32 KiB
C#
733 lines
32 KiB
C#
//-----------------------------------------------------------------------------
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
namespace Microsoft.VisualBasic.Activities
|
|
{
|
|
using System;
|
|
using System.Activities;
|
|
using System.Activities.ExpressionParser;
|
|
using System.Activities.Expressions;
|
|
using System.Activities.Validation;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Linq.Expressions;
|
|
using System.Reflection;
|
|
using System.Runtime;
|
|
|
|
public static class VisualBasicDesignerHelper
|
|
{
|
|
static Type VisualBasicExpressionFactoryType = typeof(VisualBasicExpressionFactory<>);
|
|
static VisualBasicNameShadowingConstraint nameShadowingConstraint = new VisualBasicNameShadowingConstraint();
|
|
|
|
// Returns the additional constraint for visual basic which enforces variable name shadowing for
|
|
// projects targeting 4.0 for backward compatibility.
|
|
public static Constraint NameShadowingConstraint
|
|
{
|
|
get
|
|
{
|
|
return nameShadowingConstraint;
|
|
}
|
|
}
|
|
|
|
// Recompile the VBValue passed in, with its current LocationReferenceEnvironment context
|
|
// in a weakly-typed manner (the argument VBValue's type argument is ignored)
|
|
[SuppressMessage(FxCop.Category.Design, FxCop.Rule.AvoidOutParameters,
|
|
Justification = "Design has been approved")]
|
|
public static Activity RecompileVisualBasicValue(ActivityWithResult visualBasicValue,
|
|
out Type returnType,
|
|
out SourceExpressionException compileError,
|
|
out VisualBasicSettings vbSettings)
|
|
{
|
|
ITextExpression textExpression = visualBasicValue as ITextExpression;
|
|
if (textExpression == null || textExpression.Language != VisualBasicHelper.Language)
|
|
{
|
|
// the argument must be of type VisualBasicValue<>
|
|
throw FxTrace.Exception.AsError(new ArgumentException());
|
|
}
|
|
string expressionText = textExpression.ExpressionText;
|
|
LocationReferenceEnvironment environment = visualBasicValue.GetParentEnvironment();
|
|
|
|
IList<string> namespaces;
|
|
IList<string> referencedAssemblies;
|
|
GetAllImportReferences(visualBasicValue, out namespaces, out referencedAssemblies);
|
|
|
|
return CreatePrecompiledVisualBasicValue(
|
|
null,
|
|
expressionText,
|
|
namespaces,
|
|
referencedAssemblies,
|
|
environment,
|
|
out returnType,
|
|
out compileError,
|
|
out vbSettings);
|
|
}
|
|
|
|
// Recompile the VBReference passed in, with its current LocationReferenceEnvironment context
|
|
// in a weakly-typed manner (the argument VBReference's type argument is ignored)
|
|
[SuppressMessage(FxCop.Category.Design, FxCop.Rule.AvoidOutParameters,
|
|
Justification = "Design has been approved")]
|
|
public static Activity RecompileVisualBasicReference(ActivityWithResult visualBasicReference,
|
|
out Type returnType,
|
|
out SourceExpressionException compileError,
|
|
out VisualBasicSettings vbSettings)
|
|
{
|
|
ITextExpression textExpression = visualBasicReference as ITextExpression;
|
|
if (textExpression == null || textExpression.Language != VisualBasicHelper.Language)
|
|
{
|
|
// the argument must be of type VisualBasicReference<>
|
|
throw FxTrace.Exception.AsError(new ArgumentException());
|
|
}
|
|
string expressionText = textExpression.ExpressionText;
|
|
LocationReferenceEnvironment environment = visualBasicReference.GetParentEnvironment();
|
|
|
|
IList<string> namespaces;
|
|
IList<string> referencedAssemblies;
|
|
GetAllImportReferences(visualBasicReference, out namespaces, out referencedAssemblies);
|
|
|
|
return CreatePrecompiledVisualBasicReference(
|
|
null,
|
|
expressionText,
|
|
namespaces,
|
|
referencedAssemblies,
|
|
environment,
|
|
out returnType,
|
|
out compileError,
|
|
out vbSettings);
|
|
}
|
|
|
|
// create a pre-compiled VBValueExpression, and also provides expressin type back to the caller.
|
|
[SuppressMessage(FxCop.Category.Design, FxCop.Rule.AvoidOutParameters,
|
|
Justification = "Design has been approved")]
|
|
public static Activity CreatePrecompiledVisualBasicValue(Type targetType, string expressionText, IEnumerable<string> namespaces, IEnumerable<string> referencedAssemblies,
|
|
LocationReferenceEnvironment environment,
|
|
out Type returnType,
|
|
out SourceExpressionException compileError,
|
|
out VisualBasicSettings vbSettings)
|
|
{
|
|
LambdaExpression lambda = null;
|
|
HashSet<string> namespacesSet = new HashSet<string>();
|
|
HashSet<AssemblyName> assembliesSet = new HashSet<AssemblyName>();
|
|
compileError = null;
|
|
returnType = null;
|
|
|
|
if (namespaces != null)
|
|
{
|
|
foreach (string ns in namespaces)
|
|
{
|
|
if (ns != null)
|
|
{
|
|
namespacesSet.Add(ns);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (referencedAssemblies != null)
|
|
{
|
|
foreach (string assm in referencedAssemblies)
|
|
{
|
|
if (assm != null)
|
|
{
|
|
assembliesSet.Add(new AssemblyName(assm));
|
|
}
|
|
}
|
|
}
|
|
|
|
VisualBasicHelper vbhelper = new VisualBasicHelper(expressionText, assembliesSet, namespacesSet);
|
|
if (targetType == null)
|
|
{
|
|
try
|
|
{
|
|
lambda = vbhelper.CompileNonGeneric(environment);
|
|
if (lambda != null)
|
|
{
|
|
returnType = lambda.ReturnType;
|
|
}
|
|
}
|
|
catch (SourceExpressionException e)
|
|
{
|
|
compileError = e;
|
|
returnType = typeof(object);
|
|
}
|
|
targetType = returnType;
|
|
}
|
|
else
|
|
{
|
|
MethodInfo genericCompileMethod = typeof(VisualBasicHelper).GetMethod("Compile", new Type[] { typeof(LocationReferenceEnvironment) });
|
|
genericCompileMethod = genericCompileMethod.MakeGenericMethod(new Type[] { targetType });
|
|
try
|
|
{
|
|
lambda = (LambdaExpression)genericCompileMethod.Invoke(vbhelper, new object[] { environment });
|
|
returnType = targetType;
|
|
}
|
|
catch (TargetInvocationException e)
|
|
{
|
|
SourceExpressionException se = e.InnerException as SourceExpressionException;
|
|
if (se != null)
|
|
{
|
|
compileError = se;
|
|
returnType = typeof(object);
|
|
}
|
|
else
|
|
{
|
|
throw FxTrace.Exception.AsError(e.InnerException);
|
|
}
|
|
}
|
|
}
|
|
|
|
vbSettings = new VisualBasicSettings();
|
|
if (lambda != null)
|
|
{
|
|
HashSet<Type> typeReferences = new HashSet<Type>();
|
|
FindTypeReferences(lambda.Body, typeReferences);
|
|
foreach (Type type in typeReferences)
|
|
{
|
|
Assembly tassembly = type.Assembly;
|
|
if (tassembly.IsDynamic)
|
|
{
|
|
continue;
|
|
}
|
|
string assemblyName = VisualBasicHelper.GetFastAssemblyName(tassembly).Name;
|
|
VisualBasicImportReference importReference = new VisualBasicImportReference { Assembly = assemblyName, Import = type.Namespace };
|
|
vbSettings.ImportReferences.Add(importReference);
|
|
}
|
|
}
|
|
|
|
Type concreteHelperType = VisualBasicExpressionFactoryType.MakeGenericType(targetType);
|
|
VisualBasicExpressionFactory expressionFactory = (VisualBasicExpressionFactory)Activator.CreateInstance(concreteHelperType);
|
|
|
|
return expressionFactory.CreateVisualBasicValue(expressionText);
|
|
}
|
|
|
|
// create a pre-compiled VBValueExpression, and also provides expressin type back to the caller.
|
|
[SuppressMessage(FxCop.Category.Design, FxCop.Rule.AvoidOutParameters,
|
|
Justification = "Design has been approved")]
|
|
public static Activity CreatePrecompiledVisualBasicReference(Type targetType, string expressionText, IEnumerable<string> namespaces, IEnumerable<string> referencedAssemblies,
|
|
LocationReferenceEnvironment environment,
|
|
out Type returnType,
|
|
out SourceExpressionException compileError,
|
|
out VisualBasicSettings vbSettings)
|
|
{
|
|
LambdaExpression lambda = null;
|
|
HashSet<string> namespacesSet = new HashSet<string>();
|
|
HashSet<AssemblyName> assembliesSet = new HashSet<AssemblyName>();
|
|
compileError = null;
|
|
returnType = null;
|
|
|
|
if (namespaces != null)
|
|
{
|
|
foreach (string ns in namespaces)
|
|
{
|
|
if (ns != null)
|
|
{
|
|
namespacesSet.Add(ns);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (referencedAssemblies != null)
|
|
{
|
|
foreach (string assm in referencedAssemblies)
|
|
{
|
|
if (assm != null)
|
|
{
|
|
assembliesSet.Add(new AssemblyName(assm));
|
|
}
|
|
}
|
|
}
|
|
|
|
VisualBasicHelper vbhelper = new VisualBasicHelper(expressionText, assembliesSet, namespacesSet);
|
|
if (targetType == null)
|
|
{
|
|
try
|
|
{
|
|
lambda = vbhelper.CompileNonGeneric(environment);
|
|
if (lambda != null)
|
|
{
|
|
// inspect the expressionTree to see if it is a valid location expression(L-value)
|
|
string extraErrorMessage;
|
|
if (!ExpressionUtilities.IsLocation(lambda, targetType, out extraErrorMessage))
|
|
{
|
|
string errorMessage = SR.InvalidLValueExpression;
|
|
if (extraErrorMessage != null)
|
|
{
|
|
errorMessage += ":" + extraErrorMessage;
|
|
}
|
|
throw FxTrace.Exception.AsError(
|
|
new SourceExpressionException(SR.CompilerErrorSpecificExpression(expressionText, errorMessage)));
|
|
}
|
|
returnType = lambda.ReturnType;
|
|
}
|
|
}
|
|
catch (SourceExpressionException e)
|
|
{
|
|
compileError = e;
|
|
returnType = typeof(object);
|
|
}
|
|
targetType = returnType;
|
|
}
|
|
else
|
|
{
|
|
MethodInfo genericCompileMethod = typeof(VisualBasicHelper).GetMethod("Compile", new Type[] { typeof(LocationReferenceEnvironment) });
|
|
genericCompileMethod = genericCompileMethod.MakeGenericMethod(new Type[] { targetType });
|
|
try
|
|
{
|
|
lambda = (LambdaExpression)genericCompileMethod.Invoke(vbhelper, new object[] { environment });
|
|
// inspect the expressionTree to see if it is a valid location expression(L-value)
|
|
string extraErrorMessage = null;
|
|
if (!ExpressionUtilities.IsLocation(lambda, targetType, out extraErrorMessage))
|
|
{
|
|
string errorMessage = SR.InvalidLValueExpression;
|
|
if (extraErrorMessage != null)
|
|
{
|
|
errorMessage += ":" + extraErrorMessage;
|
|
}
|
|
throw FxTrace.Exception.AsError(
|
|
new SourceExpressionException(SR.CompilerErrorSpecificExpression(expressionText, errorMessage)));
|
|
}
|
|
returnType = targetType;
|
|
}
|
|
catch (SourceExpressionException e)
|
|
{
|
|
compileError = e;
|
|
returnType = typeof(object);
|
|
}
|
|
catch (TargetInvocationException e)
|
|
{
|
|
SourceExpressionException se = e.InnerException as SourceExpressionException;
|
|
if (se != null)
|
|
{
|
|
compileError = se;
|
|
returnType = typeof(object);
|
|
}
|
|
else
|
|
{
|
|
throw FxTrace.Exception.AsError(e.InnerException);
|
|
}
|
|
}
|
|
}
|
|
|
|
vbSettings = new VisualBasicSettings();
|
|
if (lambda != null)
|
|
{
|
|
HashSet<Type> typeReferences = new HashSet<Type>();
|
|
FindTypeReferences(lambda.Body, typeReferences);
|
|
foreach (Type type in typeReferences)
|
|
{
|
|
Assembly tassembly = type.Assembly;
|
|
if (tassembly.IsDynamic)
|
|
{
|
|
continue;
|
|
}
|
|
string assemblyName = VisualBasicHelper.GetFastAssemblyName(tassembly).Name;
|
|
VisualBasicImportReference importReference = new VisualBasicImportReference { Assembly = assemblyName, Import = type.Namespace };
|
|
vbSettings.ImportReferences.Add(importReference);
|
|
}
|
|
}
|
|
|
|
Type concreteHelperType = VisualBasicExpressionFactoryType.MakeGenericType(targetType);
|
|
VisualBasicExpressionFactory expressionFactory = (VisualBasicExpressionFactory)Activator.CreateInstance(concreteHelperType);
|
|
|
|
return expressionFactory.CreateVisualBasicReference(expressionText);
|
|
}
|
|
|
|
|
|
static void EnsureTypeReferenced(Type type, bool isDirectReference, HashSet<Type> typeReferences)
|
|
{
|
|
if (type == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (type.HasElementType)
|
|
{
|
|
EnsureTypeReferenced(type.GetElementType(), isDirectReference, typeReferences);
|
|
}
|
|
else
|
|
{
|
|
EnsureTypeReferencedRecurse(type, isDirectReference, typeReferences);
|
|
if (type.IsGenericType)
|
|
{
|
|
Type[] typeArgs = type.GetGenericArguments();
|
|
for (int i = 1; i < typeArgs.Length; ++i)
|
|
{
|
|
EnsureTypeReferencedRecurse(typeArgs[i], isDirectReference, typeReferences);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void EnsureTypeReferencedRecurse(Type type, bool isDirectReference, HashSet<Type> typeReferences)
|
|
{
|
|
if (typeReferences.Contains(type))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// don't add base types/interfaces if they're in the default set (or we'll get superfluous xmlns references)
|
|
if (isDirectReference || !VisualBasicHelper.DefaultReferencedAssemblies.Contains(type.Assembly))
|
|
{
|
|
typeReferences.Add(type);
|
|
}
|
|
|
|
// make sure any interfaces needed by this type are referenced
|
|
Type[] interfaces = type.GetInterfaces();
|
|
for (int i = 0; i < interfaces.Length; ++i)
|
|
{
|
|
EnsureTypeReferencedRecurse(interfaces[i], false, typeReferences);
|
|
}
|
|
|
|
// same for base types
|
|
Type baseType = type.BaseType;
|
|
while ((baseType != null) && (baseType != TypeHelper.ObjectType))
|
|
{
|
|
EnsureTypeReferencedRecurse(baseType, false, typeReferences);
|
|
baseType = baseType.BaseType;
|
|
}
|
|
}
|
|
|
|
static void FindTypeReferences(Expression expression, HashSet<Type> typeReferences)
|
|
{
|
|
if (expression == null)
|
|
{
|
|
return;
|
|
}
|
|
switch (expression.NodeType)
|
|
{
|
|
case ExpressionType.Add:
|
|
case ExpressionType.AddChecked:
|
|
case ExpressionType.And:
|
|
case ExpressionType.AndAlso:
|
|
case ExpressionType.Coalesce:
|
|
case ExpressionType.Divide:
|
|
case ExpressionType.Equal:
|
|
case ExpressionType.ExclusiveOr:
|
|
case ExpressionType.GreaterThan:
|
|
case ExpressionType.GreaterThanOrEqual:
|
|
case ExpressionType.LeftShift:
|
|
case ExpressionType.LessThan:
|
|
case ExpressionType.LessThanOrEqual:
|
|
case ExpressionType.Modulo:
|
|
case ExpressionType.Multiply:
|
|
case ExpressionType.MultiplyChecked:
|
|
case ExpressionType.NotEqual:
|
|
case ExpressionType.Or:
|
|
case ExpressionType.OrElse:
|
|
case ExpressionType.Power:
|
|
case ExpressionType.RightShift:
|
|
case ExpressionType.Subtract:
|
|
case ExpressionType.SubtractChecked:
|
|
BinaryExpression binaryExpression = (BinaryExpression)expression;
|
|
FindTypeReferences(binaryExpression.Left, typeReferences);
|
|
FindTypeReferences(binaryExpression.Right, typeReferences);
|
|
return;
|
|
|
|
case ExpressionType.Conditional:
|
|
ConditionalExpression conditional = (ConditionalExpression)expression;
|
|
FindTypeReferences(conditional.Test, typeReferences);
|
|
FindTypeReferences(conditional.IfTrue, typeReferences);
|
|
FindTypeReferences(conditional.IfFalse, typeReferences);
|
|
return;
|
|
|
|
case ExpressionType.Constant:
|
|
ConstantExpression constantExpr = (ConstantExpression)expression;
|
|
if (constantExpr.Value is Type)
|
|
{
|
|
EnsureTypeReferenced((Type)constantExpr.Value, true, typeReferences);
|
|
}
|
|
else if (constantExpr.Value != null)
|
|
{
|
|
EnsureTypeReferenced(constantExpr.Value.GetType(), true, typeReferences);
|
|
}
|
|
return;
|
|
|
|
case ExpressionType.Invoke:
|
|
InvocationExpression invocation = (InvocationExpression)expression;
|
|
FindTypeReferences(invocation.Expression, typeReferences);
|
|
for (int i = 0; i < invocation.Arguments.Count; i++)
|
|
{
|
|
FindTypeReferences(invocation.Arguments[i], typeReferences);
|
|
}
|
|
return;
|
|
|
|
case ExpressionType.Lambda:
|
|
LambdaExpression lambda = (LambdaExpression)expression;
|
|
FindTypeReferences(lambda.Body, typeReferences);
|
|
for (int i = 0; i < lambda.Parameters.Count; i++)
|
|
{
|
|
FindTypeReferences(lambda.Parameters[i], typeReferences);
|
|
}
|
|
return;
|
|
|
|
case ExpressionType.ListInit:
|
|
ListInitExpression listInit = (ListInitExpression)expression;
|
|
FindTypeReferences(listInit.NewExpression, typeReferences);
|
|
for (int i = 0; i < listInit.Initializers.Count; i++)
|
|
{
|
|
ReadOnlyCollection<Expression> arguments = listInit.Initializers[i].Arguments;
|
|
for (int argumentIndex = 0; argumentIndex < arguments.Count; argumentIndex++)
|
|
{
|
|
FindTypeReferences(arguments[argumentIndex], typeReferences);
|
|
}
|
|
}
|
|
return;
|
|
|
|
case ExpressionType.Parameter:
|
|
ParameterExpression paramExpr = (ParameterExpression)expression;
|
|
EnsureTypeReferenced(paramExpr.Type, false, typeReferences);
|
|
return;
|
|
|
|
case ExpressionType.MemberAccess:
|
|
MemberExpression memberExpression = (MemberExpression)expression;
|
|
if (memberExpression.Expression == null)
|
|
{
|
|
EnsureTypeReferenced(memberExpression.Member.DeclaringType, true, typeReferences);
|
|
}
|
|
else
|
|
{
|
|
FindTypeReferences(memberExpression.Expression, typeReferences);
|
|
}
|
|
EnsureTypeReferenced(memberExpression.Type, false, typeReferences);
|
|
return;
|
|
|
|
case ExpressionType.MemberInit:
|
|
MemberInitExpression memberInit = (MemberInitExpression)expression;
|
|
FindTypeReferences(memberInit.NewExpression, typeReferences);
|
|
ReadOnlyCollection<MemberBinding> bindings = memberInit.Bindings;
|
|
for (int i = 0; i < bindings.Count; i++)
|
|
{
|
|
FindTypeReferences(bindings[i], typeReferences);
|
|
}
|
|
return;
|
|
|
|
case ExpressionType.ArrayIndex:
|
|
// ArrayIndex can be a MethodCallExpression or a BinaryExpression
|
|
MethodCallExpression arrayIndex = expression as MethodCallExpression;
|
|
if (arrayIndex != null)
|
|
{
|
|
FindTypeReferences(arrayIndex.Object, typeReferences);
|
|
ReadOnlyCollection<Expression> arguments = arrayIndex.Arguments;
|
|
for (int i = 0; i < arguments.Count; i++)
|
|
{
|
|
FindTypeReferences(arguments[i], typeReferences);
|
|
}
|
|
return;
|
|
}
|
|
BinaryExpression alternateIndex = (BinaryExpression)expression;
|
|
FindTypeReferences(alternateIndex.Left, typeReferences);
|
|
FindTypeReferences(alternateIndex.Right, typeReferences);
|
|
return;
|
|
|
|
case ExpressionType.Call:
|
|
MethodCallExpression methodCall = (MethodCallExpression)expression;
|
|
MethodInfo method = methodCall.Method;
|
|
EnsureTypeReferenced(methodCall.Type, false, typeReferences);
|
|
if (methodCall.Object != null)
|
|
{
|
|
FindTypeReferences(methodCall.Object, typeReferences);
|
|
}
|
|
else
|
|
{
|
|
EnsureTypeReferenced(method.DeclaringType, true, typeReferences);
|
|
}
|
|
|
|
if (method.IsGenericMethod && !method.IsGenericMethodDefinition && !method.ContainsGenericParameters)
|
|
{
|
|
// closed generic method
|
|
Type[] typeArgs = method.GetGenericArguments();
|
|
for (int i = 1; i < typeArgs.Length; ++i)
|
|
{
|
|
EnsureTypeReferenced(typeArgs[i], true, typeReferences);
|
|
}
|
|
}
|
|
|
|
ParameterInfo[] parameters = method.GetParameters();
|
|
if (parameters != null)
|
|
{
|
|
foreach (ParameterInfo parameter in parameters)
|
|
{
|
|
EnsureTypeReferenced(parameter.ParameterType, false, typeReferences);
|
|
}
|
|
}
|
|
|
|
ReadOnlyCollection<Expression> callArguments = methodCall.Arguments;
|
|
for (int i = 0; i < callArguments.Count; i++)
|
|
{
|
|
FindTypeReferences(callArguments[i], typeReferences);
|
|
}
|
|
return;
|
|
|
|
case ExpressionType.NewArrayInit:
|
|
NewArrayExpression newArray = (NewArrayExpression)expression;
|
|
EnsureTypeReferenced(newArray.Type.GetElementType(), true, typeReferences);
|
|
ReadOnlyCollection<Expression> expressions = newArray.Expressions;
|
|
for (int i = 0; i < expressions.Count; i++)
|
|
{
|
|
FindTypeReferences(expressions[i], typeReferences);
|
|
}
|
|
return;
|
|
|
|
case ExpressionType.NewArrayBounds:
|
|
NewArrayExpression newArrayBounds = (NewArrayExpression)expression;
|
|
EnsureTypeReferenced(newArrayBounds.Type.GetElementType(), true, typeReferences);
|
|
ReadOnlyCollection<Expression> boundExpressions = newArrayBounds.Expressions;
|
|
for (int i = 0; i < boundExpressions.Count; i++)
|
|
{
|
|
FindTypeReferences(boundExpressions[i], typeReferences);
|
|
}
|
|
return;
|
|
|
|
case ExpressionType.New:
|
|
NewExpression newExpression = (NewExpression)expression;
|
|
if (newExpression.Constructor != null)
|
|
{
|
|
EnsureTypeReferenced(newExpression.Constructor.DeclaringType, true, typeReferences);
|
|
}
|
|
else
|
|
{
|
|
// if no constructors defined (e.g. structs), the simply use the type
|
|
EnsureTypeReferenced(newExpression.Type, true, typeReferences);
|
|
}
|
|
ReadOnlyCollection<Expression> ctorArguments = newExpression.Arguments;
|
|
for (int i = 0; i < ctorArguments.Count; i++)
|
|
{
|
|
FindTypeReferences(ctorArguments[i], typeReferences);
|
|
}
|
|
return;
|
|
|
|
case ExpressionType.TypeIs:
|
|
TypeBinaryExpression typeBinary = (TypeBinaryExpression)expression;
|
|
FindTypeReferences(typeBinary.Expression, typeReferences);
|
|
EnsureTypeReferenced(typeBinary.TypeOperand, true, typeReferences);
|
|
return;
|
|
|
|
case ExpressionType.TypeAs:
|
|
case ExpressionType.Convert:
|
|
case ExpressionType.ConvertChecked:
|
|
UnaryExpression unary = (UnaryExpression)expression;
|
|
FindTypeReferences(unary.Operand, typeReferences);
|
|
EnsureTypeReferenced(unary.Type, true, typeReferences);
|
|
return;
|
|
|
|
case ExpressionType.ArrayLength:
|
|
case ExpressionType.Negate:
|
|
case ExpressionType.NegateChecked:
|
|
case ExpressionType.Not:
|
|
case ExpressionType.Quote:
|
|
case ExpressionType.UnaryPlus:
|
|
UnaryExpression unaryExpression = (UnaryExpression)expression;
|
|
FindTypeReferences(unaryExpression.Operand, typeReferences);
|
|
return;
|
|
|
|
// Expression Tree V2.0 types. This is due to the hosted VB compiler generating ET V2.0 nodes
|
|
|
|
case ExpressionType.Block:
|
|
BlockExpression block = (BlockExpression)expression;
|
|
ReadOnlyCollection<ParameterExpression> variables = block.Variables;
|
|
for (int i = 0; i < variables.Count; i++)
|
|
{
|
|
FindTypeReferences(variables[i], typeReferences);
|
|
}
|
|
ReadOnlyCollection<Expression> blockExpressions = block.Expressions;
|
|
for (int i = 0; i < blockExpressions.Count; i++)
|
|
{
|
|
FindTypeReferences(blockExpressions[i], typeReferences);
|
|
}
|
|
return;
|
|
|
|
case ExpressionType.Assign:
|
|
BinaryExpression assign = (BinaryExpression)expression;
|
|
FindTypeReferences(assign.Left, typeReferences);
|
|
FindTypeReferences(assign.Right, typeReferences);
|
|
return;
|
|
}
|
|
|
|
Fx.Assert("Don't understand expression type " + expression.NodeType);
|
|
return;
|
|
}
|
|
|
|
static void FindTypeReferences(MemberBinding binding, HashSet<Type> typeReferences)
|
|
{
|
|
switch (binding.BindingType)
|
|
{
|
|
case MemberBindingType.Assignment:
|
|
MemberAssignment assignment = (MemberAssignment)binding;
|
|
FindTypeReferences(assignment.Expression, typeReferences);
|
|
return;
|
|
|
|
case MemberBindingType.ListBinding:
|
|
MemberListBinding list = (MemberListBinding)binding;
|
|
ReadOnlyCollection<ElementInit> initializers = list.Initializers;
|
|
for (int i = 0; i < initializers.Count; i++)
|
|
{
|
|
ReadOnlyCollection<Expression> arguments = initializers[i].Arguments;
|
|
for (int j = 0; j < arguments.Count; j++)
|
|
{
|
|
FindTypeReferences(arguments[j], typeReferences);
|
|
}
|
|
}
|
|
return;
|
|
|
|
case MemberBindingType.MemberBinding:
|
|
MemberMemberBinding member = (MemberMemberBinding)binding;
|
|
ReadOnlyCollection<MemberBinding> bindings = member.Bindings;
|
|
for (int i = 0; i < bindings.Count; i++)
|
|
{
|
|
FindTypeReferences(bindings[i], typeReferences);
|
|
}
|
|
return;
|
|
|
|
default:
|
|
Fx.Assert("MemberBinding type '" + binding.BindingType + "' is not supported.");
|
|
return;
|
|
}
|
|
}
|
|
|
|
static void GetAllImportReferences(Activity activity, out IList<string> namespaces, out IList<string> assemblies)
|
|
{
|
|
IList<AssemblyReference> referencedAssemblies;
|
|
VisualBasicHelper.GetAllImportReferences(activity, true, out namespaces, out referencedAssemblies);
|
|
|
|
assemblies = new List<string>();
|
|
foreach (AssemblyReference reference in referencedAssemblies)
|
|
{
|
|
if (reference.AssemblyName != null)
|
|
{
|
|
assemblies.Add(reference.AssemblyName.FullName);
|
|
}
|
|
else if (reference.Assembly != null)
|
|
{
|
|
assemblies.Add(reference.Assembly.FullName);
|
|
}
|
|
}
|
|
}
|
|
|
|
// to perform the generics dance around VisualBasicValue/Reference we need these helpers
|
|
abstract class VisualBasicExpressionFactory
|
|
{
|
|
public abstract Activity CreateVisualBasicValue(string expressionText);
|
|
public abstract Activity CreateVisualBasicReference(string expressionText);
|
|
}
|
|
|
|
class VisualBasicExpressionFactory<T> : VisualBasicExpressionFactory
|
|
{
|
|
public override Activity CreateVisualBasicReference(string expressionText)
|
|
{
|
|
return new VisualBasicReference<T>()
|
|
{
|
|
ExpressionText = expressionText
|
|
};
|
|
}
|
|
|
|
public override Activity CreateVisualBasicValue(string expressionText)
|
|
{
|
|
return new VisualBasicValue<T>()
|
|
{
|
|
ExpressionText = expressionText
|
|
};
|
|
}
|
|
}
|
|
}
|
|
}
|