internal override AST PartiallyEvaluate(){
this.ctor = this.ctor.PartiallyEvaluateAsCallable();
//first weed out assignment expressions and use them as property initializers
ASTList positionalArgs = new ASTList(this.args.context);
ASTList namedArgs = new ASTList(this.args.context);
for (int i = 0, m = this.args.count; i < m; i++){
AST arg = this.args[i];
Assign assign = arg as Assign;
if (assign != null){
assign.rhside = assign.rhside.PartiallyEvaluate();
namedArgs.Append(assign);
}else
positionalArgs.Append(arg.PartiallyEvaluate());
}
int n = positionalArgs.count;
IReflect[] argIRs = new IReflect[n];
for (int i = 0; i < n; i++){
AST arg = positionalArgs[i];
// only accept ConstantWrappers
if (arg is ConstantWrapper){
Object argument = arg.Evaluate();
if ((argIRs[i] = CustomAttribute.TypeOfArgument(argument)) != null){
this.positionalArgValues.Add(argument);
continue;
}
}else if (arg is ArrayLiteral && ((ArrayLiteral)arg).IsOkToUseInCustomAttribute()){
argIRs[i] = Typeob.ArrayObject;
this.positionalArgValues.Add(arg.Evaluate());
continue;
}
arg.context.HandleError(JSError.InvalidCustomAttributeArgument);
return null; // the custom attribute is not good and it will be ignored
}
//Get the custom attribute and the appropriate constructor (under the covers)
this.type = this.ctor.ResolveCustomAttribute(positionalArgs, argIRs, this.target);
if (this.type == null) return null;
if (Convert.IsPromotableTo((IReflect)this.type, Typeob.CodeAccessSecurityAttribute)){
this.context.HandleError(JSError.CannotUseStaticSecurityAttribute);
return null;
}
//Coerce the positional arguments to the right type and supply default values for optional parameters
ConstructorInfo c = (ConstructorInfo)((Binding)this.ctor).member;
ParameterInfo[] parameters = c.GetParameters();
int j = 0;
int len = this.positionalArgValues.Count;
foreach (ParameterInfo p in parameters){
IReflect ir = p is ParameterDeclaration ? ((ParameterDeclaration)p).ParameterIReflect : p.ParameterType;
if (j < len ){
Object value = this.positionalArgValues[j];
this.positionalArgValues[j] = Convert.Coerce(value, ir, value is ArrayObject);
j++;
}else{
Object value;
if (TypeReferences.GetDefaultParameterValue(p) == System.Convert.DBNull){
value = Convert.Coerce(null, ir);
}else
value = TypeReferences.GetDefaultParameterValue(p);
this.positionalArgValues.Add(value);
}
}
//Check validity of property/field initializers
for (int i = 0, m = namedArgs.count; i < m; i++){
Assign assign = (Assign)namedArgs[i];
if (assign.lhside is Lookup &&
(assign.rhside is ConstantWrapper ||
(assign.rhside is ArrayLiteral && ((ArrayLiteral)assign.rhside).IsOkToUseInCustomAttribute()))){
Object value = assign.rhside.Evaluate();
IReflect argType = null;
if (value is ArrayObject || ((argType = CustomAttribute.TypeOfArgument(value)) != null && argType != Typeob.Object)){
String name = ((Lookup)assign.lhside).Name;
MemberInfo [] members = ((IReflect)this.type).GetMember(name, BindingFlags.Public|BindingFlags.Instance);
if (members == null || members.Length == 0){
assign.context.HandleError(JSError.NoSuchMember);
return null;
}
if (members.Length == 1){
MemberInfo member = members[0];
if (member is FieldInfo){
FieldInfo fieldInfo = (FieldInfo)member;
if (!fieldInfo.IsLiteral && !fieldInfo.IsInitOnly){
try{
IReflect ir = fieldInfo is JSVariableField ? ((JSVariableField)fieldInfo).GetInferredType(null) : fieldInfo.FieldType;
value = Convert.Coerce(value, ir, value is ArrayObject);
this.namedArgFields.Add(member);
this.namedArgFieldValues.Add(value);
continue;
}catch(JScriptException){
assign.rhside.context.HandleError(JSError.TypeMismatch);
return null; // the custom attribute is not good and it will be ignored
}
}
}else if (member is PropertyInfo){
PropertyInfo propertyInfo = (PropertyInfo)member;
MethodInfo setMethodInfo = JSProperty.GetSetMethod(propertyInfo, false);
if (setMethodInfo != null){
ParameterInfo [] paramInfo = setMethodInfo.GetParameters();
if (paramInfo != null && paramInfo.Length == 1){
try{
IReflect ir = paramInfo[0] is ParameterDeclaration ? ((ParameterDeclaration)paramInfo[0]).ParameterIReflect : paramInfo[0].ParameterType;
value = Convert.Coerce(value, ir, value is ArrayObject);
this.namedArgProperties.Add(member);
this.namedArgPropertyValues.Add(value);
}catch(JScriptException){
assign.rhside.context.HandleError(JSError.TypeMismatch);
return null; // the custom attribute is not good and it will be ignored
}
continue;
}
}
}
}
}
}
assign.context.HandleError(JSError.InvalidCustomAttributeArgument);
return null;
}
if (!this.CheckIfTargetOK(this.type))
return null; //Ignore attribute
//Consume and discard assembly name attributes
try{
Type ty = this.type as Type;
if (ty != null && this.target is AssemblyCustomAttributeList){
if (ty.FullName == "System.Reflection.AssemblyAlgorithmIdAttribute"){
if (this.positionalArgValues.Count > 0)
this.Engine.Globals.assemblyHashAlgorithm = (AssemblyHashAlgorithm)Convert.CoerceT(this.positionalArgValues[0], typeof(AssemblyHashAlgorithm));
return null;
}
if (ty.FullName == "System.Reflection.AssemblyCultureAttribute"){
if (this.positionalArgValues.Count > 0){
String cultureId = Convert.ToString(this.positionalArgValues[0]);
if (this.Engine.PEFileKind != PEFileKinds.Dll && cultureId.Length > 0){
this.context.HandleError(JSError.ExecutablesCannotBeLocalized);
return null;
}
this.Engine.Globals.assemblyCulture = new CultureInfo(cultureId);
}
return null;
}
if (ty.FullName == "System.Reflection.AssemblyDelaySignAttribute"){
if (this.positionalArgValues.Count > 0)
this.Engine.Globals.assemblyDelaySign = Convert.ToBoolean(this.positionalArgValues[0], false);
return null;
}
if (ty.FullName == "System.Reflection.AssemblyFlagsAttribute"){
if (this.positionalArgValues.Count > 0)
this.Engine.Globals.assemblyFlags = (AssemblyFlags)(uint)Convert.CoerceT(this.positionalArgValues[0], typeof(uint));
return null;
}
if (ty.FullName == "System.Reflection.AssemblyKeyFileAttribute"){
if (this.positionalArgValues.Count > 0){
this.Engine.Globals.assemblyKeyFileName = Convert.ToString(this.positionalArgValues[0]);
this.Engine.Globals.assemblyKeyFileNameContext = this.context;
if (this.Engine.Globals.assemblyKeyFileName != null && this.Engine.Globals.assemblyKeyFileName.Length == 0)
{
this.Engine.Globals.assemblyKeyFileName = null;
this.Engine.Globals.assemblyKeyFileNameContext = null;
}
}
return null;
}
if (ty.FullName == "System.Reflection.AssemblyKeyNameAttribute"){
if (this.positionalArgValues.Count > 0){
this.Engine.Globals.assemblyKeyName = Convert.ToString(this.positionalArgValues[0]);
this.Engine.Globals.assemblyKeyNameContext = this.context;
if (this.Engine.Globals.assemblyKeyName != null && this.Engine.Globals.assemblyKeyName.Length == 0) {
this.Engine.Globals.assemblyKeyName = null;
this.Engine.Globals.assemblyKeyNameContext = null;
}
}
return null;
}
if (ty.FullName == "System.Reflection.AssemblyVersionAttribute"){
if (this.positionalArgValues.Count > 0)
this.Engine.Globals.assemblyVersion = this.ParseVersion(Convert.ToString(this.positionalArgValues[0]));
return null;
}
if (ty.FullName == "System.CLSCompliantAttribute"){
this.Engine.isCLSCompliant = this.args == null || this.args.count == 0 || Convert.ToBoolean(this.positionalArgValues[0], false);
return this;
}
}
}catch(ArgumentException){
this.context.HandleError(JSError.InvalidCall);
}
return this;
}