internal void PartiallyEvaluate(){
if (this.partiallyEvaluated)
return;
// 49885 - Putting class definitions in a package makes class order dependent
// For methods, the logic in FunctionObject.PartiallyEvaluate must be called by
// Class.PartiallyEvaluate in order to ensure that the scope chain is set up correctly.
ClassScope classScope = this.enclosing_scope as ClassScope;
if (null != classScope)
classScope.owner.PartiallyEvaluate();
// In the case where the the caller is Class.PartiallyEvaluate, the call returns
// immediately since Class.partiallyEvaluated wil be set and this.partiallEvaluated
// will still be false to allow the partial evaluation to be computed. In the case where
// the caller isn't Class.PartiallyEvaluate, the call to Class.PartiallyEvaluate results
// in a call back to FunctionObject.PartiallyEvaluate. This call will set this.partiallyEvaluated
// and thus, we will not need to evaluate again.
if (this.partiallyEvaluated)
return;
this.partiallyEvaluated = true;
// deal with custom attributes
this.clsCompliance = CLSComplianceSpec.NotAttributed;
if (this.customAttributes != null){
this.customAttributes.PartiallyEvaluate();
CustomAttribute clsAttr = this.customAttributes.GetAttribute(Typeob.CLSCompliantAttribute);
if (clsAttr != null){
this.clsCompliance = clsAttr.GetCLSComplianceValue();
this.customAttributes.Remove(clsAttr);
}
clsAttr = this.customAttributes.GetAttribute(Typeob.Override);
if (clsAttr != null){
if (this.isStatic)
clsAttr.context.HandleError(JSError.StaticMethodsCannotOverride);
else
this.attributes &= ~MethodAttributes.NewSlot;
this.noVersionSafeAttributeSpecified = false;
this.customAttributes.Remove(clsAttr);
}
clsAttr = this.customAttributes.GetAttribute(Typeob.Hide);
if (clsAttr != null){
if (!this.noVersionSafeAttributeSpecified){
clsAttr.context.HandleError(JSError.OverrideAndHideUsedTogether);
this.attributes |= MethodAttributes.NewSlot;
this.noVersionSafeAttributeSpecified = true;
}else{
if (this.isStatic)
clsAttr.context.HandleError(JSError.StaticMethodsCannotHide);
this.noVersionSafeAttributeSpecified = false;
}
this.customAttributes.Remove(clsAttr);
}
CustomAttribute expAttr = this.customAttributes.GetAttribute(Typeob.Expando);
if (expAttr != null){
if (!this.noVersionSafeAttributeSpecified && (this.attributes & MethodAttributes.NewSlot) == 0){
expAttr.context.HandleError(JSError.ExpandoPrecludesOverride);
this.attributes |= MethodAttributes.NewSlot;
this.noVersionSafeAttributeSpecified = true;
}
if (this.isConstructor)
expAttr.context.HandleError(JSError.NotValidForConstructor);
else if ((this.attributes & MethodAttributes.Abstract) != 0)
expAttr.context.HandleError(JSError.ExpandoPrecludesAbstract);
else if ((this.attributes & MethodAttributes.Static) != 0)
expAttr.context.HandleError(JSError.ExpandoPrecludesStatic);
else if ((this.attributes & MethodAttributes.MemberAccessMask) != MethodAttributes.Public)
expAttr.context.HandleError(JSError.ExpandoMustBePublic);
else{
this.own_scope.isMethod = false;
this.isMethod = false;
this.isExpandoMethod = true;
this.isStatic = true;
this.attributes &= ~MethodAttributes.Virtual;
this.attributes &= ~MethodAttributes.NewSlot;
this.attributes |= MethodAttributes.Static;
}
}
}
for (int i = 0, n = this.parameter_declarations.Length; i < n; i++){
this.parameter_declarations[i].PartiallyEvaluate();
JSLocalField pfield = (JSLocalField)this.own_scope.name_table[this.formal_parameters[i]];
pfield.type = this.parameter_declarations[i].type;
if (pfield.type == null)
pfield.type = new TypeExpression(new ConstantWrapper(Typeob.Object, this.parameter_declarations[i].context));
pfield.isDefined = true;
}
if (this.return_type_expr != null){
this.return_type_expr.PartiallyEvaluate();
this.own_scope.returnVar.type = this.return_type_expr;
if (this.own_scope.returnVar.type.ToIReflect() == Typeob.Void){
this.own_scope.returnVar.type = null;
this.own_scope.returnVar = null; //This does not completely get rid of the returnVar value, but acts as flag, hence the above.
}
}
globals.ScopeStack.Push(this.own_scope);
if (!this.own_scope.isKnownAtCompileTime) //Function contains an eval. Type inference is impossible for local vars
for (int i = 0, n = this.fields.Length; i < n; i++)
this.fields[i].SetInferredType(Typeob.Object, null);
if (!this.isConstructor)
this.body.PartiallyEvaluate();
else{
this.body.MarkSuperOKIfIsFirstStatement();
this.body.PartiallyEvaluate(); //super constructor calls that have not been marked OK will generate errors
ClassScope cscope = (ClassScope)this.enclosing_scope;
int n = this.superConstructorCall == null ? 0 : this.superConstructorCall.arguments.count;
Type[] argTypes = n == 0 ? Type.EmptyTypes : new Type[n];
IReflect[] argIRs = new IReflect[n];
for (int i = 0; i < n; i++)
argIRs[i] = this.superConstructorCall.arguments[i].InferType(null);
Context errorContext = this.superConstructorCall == null ? this.funcContext : this.superConstructorCall.context;
try{
if (this.superConstructorCall != null && !this.superConstructorCall.isSuperConstructorCall)
this.superConstructor = JSBinder.SelectConstructor(cscope.constructors, argIRs);
else
this.superConstructor = cscope.owner.GetSuperConstructor(argIRs);
if (this.superConstructor == null)
errorContext.HandleError(JSError.SuperClassConstructorNotAccessible);
else{
ConstructorInfo cons = (ConstructorInfo)this.superConstructor;
if (!cons.IsPublic && !cons.IsFamily && !cons.IsFamilyOrAssembly &&
!(this.superConstructor is JSConstructor && ((JSConstructor)this.superConstructor).IsAccessibleFrom(this.enclosing_scope))){
errorContext.HandleError(JSError.SuperClassConstructorNotAccessible);
this.superConstructor = null;
}else if (n > 0)
if (!Binding.CheckParameters(cons.GetParameters(), argIRs, this.superConstructorCall.arguments, this.superConstructorCall.context))
this.superConstructor = null;
}
}catch(AmbiguousMatchException){
errorContext.HandleError(JSError.AmbiguousConstructorCall);
}
}
this.own_scope.HandleUnitializedVariables();
globals.ScopeStack.Pop();
this.must_save_stack_locals = this.own_scope.mustSaveStackLocals;
this.fields = this.own_scope.GetLocalFields();
}