Microsoft.JScript.FunctionObject.GetMethodBase C# (CSharp) Method

GetMethodBase() private method

private GetMethodBase ( CompilerGlobals compilerGlobals ) : MethodBase
compilerGlobals CompilerGlobals
return System.Reflection.MethodBase
      internal MethodBase GetMethodBase(CompilerGlobals compilerGlobals){
        if (this.mb != null)
          return this.mb;
        if (this.cb != null)
          return this.cb;  
        JSFunctionAttributeEnum jsFunctionAttributes = 0;
        int extras = 3;
        if (this.isMethod){
          if (this.isConstructor && ((ClassScope)this.enclosing_scope).outerClassField != null){
            extras = 1;
            jsFunctionAttributes |= JSFunctionAttributeEnum.IsInstanceNestedClassConstructor;
          }else
            extras = 0;
        }else if (!this.hasArgumentsObject)
          extras = 2;
        int np = this.formal_parameters.Length+extras;
        Type[] ptypes = new Type[np];
        Type rtype = Convert.ToType(this.ReturnType(null));
        if (extras > 0){
          if (this.isConstructor)
            ptypes[np-1] = ((ClassScope)this.enclosing_scope).outerClassField.FieldType;
          else
            ptypes[0] = Typeob.Object;
          jsFunctionAttributes |= JSFunctionAttributeEnum.HasThisObject;
        }
        if (extras > 1){
          ptypes[1] = Typeob.VsaEngine;
          jsFunctionAttributes |= JSFunctionAttributeEnum.HasEngine;
        }
        if (extras > 2){
          ptypes[2] = Typeob.Object;
          jsFunctionAttributes |= JSFunctionAttributeEnum.HasArguments;
        }
        if (this.must_save_stack_locals)
          jsFunctionAttributes |= JSFunctionAttributeEnum.HasStackFrame;
        if (this.isExpandoMethod)
          jsFunctionAttributes |= JSFunctionAttributeEnum.IsExpandoMethod;
        if (this.isConstructor){
          for (int i = 0; i < np-extras; i++)
            ptypes[i] = this.parameter_declarations[i].ParameterType;
        }else{
          for (int i = extras; i < np; i++)
            ptypes[i] = this.parameter_declarations[i-extras].ParameterType;
        }
        if (this.enclosing_scope is ClassScope)
          if (this.isConstructor){
            this.cb = ((ClassScope)(this.enclosing_scope)).GetTypeBuilder().DefineConstructor(this.attributes&MethodAttributes.MemberAccessMask, 
              CallingConventions.Standard, ptypes);
          }else{
            String name = this.name;
            if (this.implementedIfaceMethod != null){
              JSMethod jsm = this.implementedIfaceMethod as JSMethod;
              if (jsm != null) this.implementedIfaceMethod = jsm.GetMethodInfo(compilerGlobals);
              name = this.implementedIfaceMethod.DeclaringType.FullName + "." + name;
            }
            TypeBuilder tb = ((ClassScope)(this.enclosing_scope)).GetTypeBuilder();
            if (this.mb != null) return this.mb; //Might have been defined as a result of the above call
            this.mb = tb.DefineMethod(name, this.attributes, rtype, ptypes);
            if (this.implementedIfaceMethod != null)
              ((ClassScope)(this.enclosing_scope)).GetTypeBuilder().DefineMethodOverride(this.mb, this.implementedIfaceMethod);
          }
        else{
          if (enclosing_scope is FunctionScope){ //dealing with a nested function/function expression. Mangle the name.
            if (((FunctionScope)enclosing_scope).owner != null){
              this.name = ((FunctionScope)enclosing_scope).owner.name+ "." + this.name;
              jsFunctionAttributes |= JSFunctionAttributeEnum.IsNested;
            }else{ //dealing with the dummy outer scope of a function expression
              ScriptObject escope = enclosing_scope;
              while (escope != null){
                if (escope is FunctionScope && ((FunctionScope)escope).owner != null){
                  this.name = ((FunctionScope)escope).owner.name+ "." + this.name;
                  jsFunctionAttributes |= JSFunctionAttributeEnum.IsNested;
                  break;
                }
                escope = escope.GetParent();
              }
            }
          }
          //The name could still be a duplicate, so check against a table of names already used.
          if (compilerGlobals.usedNames[this.name] != null)
            this.name = this.name + ":" + (compilerGlobals.usedNames.count).ToString(CultureInfo.InvariantCulture);
          compilerGlobals.usedNames[this.name] = this;
          
          // Use the class writer associated with the global scope if the function is a global
          // function or a nested function inside a global function. In these cases, 
          // compilerGlobals.classwriter will be setup incorrectly if the function is called
          // from a code inside a class before it is declared.
          ScriptObject classScope = this.enclosing_scope;
          while (classScope != null && !(classScope is ClassScope))
            classScope = classScope.GetParent();
          this.classwriter = (classScope == null ? compilerGlobals.globalScopeClassWriter : compilerGlobals.classwriter);
          
          this.mb = this.classwriter.DefineMethod(this.name, this.attributes, rtype, ptypes);
        }
        // the method is defined, we can now put debug info about the parameters
        if (extras > 0){
          if (this.mb != null)
            this.mb.DefineParameter(1, (ParameterAttributes)0, "this");
          else{
            ParameterBuilder pb = this.cb.DefineParameter(np, (ParameterAttributes)0, "this");
            pb.SetConstant(null);
            extras = 0;
            np--;
          }
        }
        if (extras > 1)
          this.mb.DefineParameter(2, (ParameterAttributes)0, "vsa Engine");
        if (extras > 2)
          this.mb.DefineParameter(3, (ParameterAttributes)0, "arguments");
        for (int i = extras; i < np; i++){
          ParameterBuilder pb = this.mb != null ? 
            this.mb.DefineParameter(i + 1, (ParameterAttributes)0, this.parameter_declarations[i-extras].identifier) :
            this.cb.DefineParameter(i + 1, (ParameterAttributes)0, this.parameter_declarations[i-extras].identifier);
          CustomAttributeList paramCustAttList = this.parameter_declarations[i-extras].customAttributes;
          if (paramCustAttList != null){
            CustomAttributeBuilder[] paramCustomAttributes = paramCustAttList.GetCustomAttributeBuilders(false);
            for (int attIndex = 0; attIndex < paramCustomAttributes.Length; attIndex++)
              pb.SetCustomAttribute(paramCustomAttributes[attIndex]);
          }
        }
        if (jsFunctionAttributes > 0){
          CustomAttributeBuilder cab = new CustomAttributeBuilder(CompilerGlobals.jsFunctionAttributeConstructor, new Object[1] {jsFunctionAttributes});
          if (this.mb != null)
            this.mb.SetCustomAttribute(cab);
          else
            this.cb.SetCustomAttribute(cab);
        }
        // deal with custom attributes
        if (this.customAttributes != null){
          CustomAttributeBuilder[] custAtt = this.customAttributes.GetCustomAttributeBuilders(false);
          for (int j = 0; j < custAtt.Length; j++){
            if (this.mb != null)
              this.mb.SetCustomAttribute(custAtt[j]);
            else
              this.cb.SetCustomAttribute(custAtt[j]);
          }
        }
        if (this.clsCompliance == CLSComplianceSpec.CLSCompliant)
          if (this.mb != null)
            this.mb.SetCustomAttribute(new CustomAttributeBuilder(CompilerGlobals.clsCompliantAttributeCtor, new Object[]{true}));
          else
            this.cb.SetCustomAttribute(new CustomAttributeBuilder(CompilerGlobals.clsCompliantAttributeCtor, new Object[]{true}));
        else if (this.clsCompliance == CLSComplianceSpec.NonCLSCompliant)
          if (this.mb != null)
            this.mb.SetCustomAttribute(new CustomAttributeBuilder(CompilerGlobals.clsCompliantAttributeCtor, new Object[]{false}));
          else
            this.cb.SetCustomAttribute(new CustomAttributeBuilder(CompilerGlobals.clsCompliantAttributeCtor, new Object[]{false}));
        if (this.mb != null){
          this.mb.InitLocals = true;
          return this.mb;
        }else{
          this.cb.InitLocals = true;
          return this.cb;
        }
      }