Microsoft.JScript.Class.CheckMatchingMethodForConsistency C# (CSharp) Method

CheckMatchingMethodForConsistency() private method

private CheckMatchingMethodForConsistency ( MethodInfo matchingMethod, FunctionObject func, int i, int n ) : void
matchingMethod System.Reflection.MethodInfo
func FunctionObject
i int
n int
return void
      private void CheckMatchingMethodForConsistency(MethodInfo matchingMethod, FunctionObject func, int i, int n){
        // return-type consistency - the return-type has to be the same
        IReflect rir = func.ReturnType(null);
        IReflect mrir = matchingMethod is JSFieldMethod ? ((JSFieldMethod)matchingMethod).func.ReturnType(null) : matchingMethod.ReturnType;
        if (!rir.Equals(mrir)){
          func.funcContext.HandleError(JSError.DifferentReturnTypeFromBase, func.name, true);
          return;
        }
        
        //Special treatment for methods that implement interface methods    
        if (func.implementedIface != null){
          func.implementedIfaceMethod = matchingMethod;
          this.superMembers[i] = func.name; //obliterate it so that it does not show up as unimplemented
          return;
        }

        // visibility consistency - the visibility specification has to be the same
        MethodAttributes visibility = func.attributes & MethodAttributes.MemberAccessMask;
        if ((matchingMethod.Attributes & MethodAttributes.MemberAccessMask) != visibility)
          //Allow Family to match FamORAssem
          if ((matchingMethod.Attributes & MethodAttributes.MemberAccessMask) != MethodAttributes.FamORAssem || visibility != MethodAttributes.Family)
            func.funcContext.HandleError(JSError.CannotChangeVisibility);

        // hiding, overriding and layout consistency
        // if i >= 0 after this, the base method is an overridden abstract method and steps should be taken to prevent a not implemented error
        if (func.noVersionSafeAttributeSpecified){ // current method does not specify any attribute (i.e. hide or override)
          if (this.Engine.versionSafe){
            //Give a message. The compiler option requires a method to say hide or override when there is a match.
            if ((matchingMethod.Attributes & MethodAttributes.Abstract) != 0){ // base is abstract
              func.funcContext.HandleError(JSError.HidesAbstractInBase, this.name + "." + func.name);
              func.attributes &= ~MethodAttributes.NewSlot;
              //Recover from error by overriding, it may be less bad than throwing a class load exception
            }else{ 
              func.funcContext.HandleError(JSError.NewNotSpecifiedInMethodDeclaration, this.IsInTheSameCompilationUnit(matchingMethod));
              i = -1;
            }
          }else{
            //No message, override if possible, otherwise hide
            if ((matchingMethod.Attributes & MethodAttributes.Virtual) == 0 || 
                (matchingMethod.Attributes & MethodAttributes.Final) != 0){ // base is non virtual or final, hide
              i = -1;
            }else{
              func.attributes &= ~MethodAttributes.NewSlot; //override
              if ((matchingMethod.Attributes & MethodAttributes.Abstract) == 0)
                i = -1;
            }
          }
        }else{ //Current method is marked override or hide
          if ((func.attributes & MethodAttributes.VtableLayoutMask) == MethodAttributes.ReuseSlot){ // current method specifies override
            if ((matchingMethod.Attributes & MethodAttributes.Virtual) == 0 || 
              (matchingMethod.Attributes & MethodAttributes.Final) != 0){ // base is non virtual or final, hide
              func.funcContext.HandleError(JSError.MethodInBaseIsNotVirtual);
              i = -1;
            }else{ 
              func.attributes &= ~MethodAttributes.NewSlot; //override
              if ((matchingMethod.Attributes & MethodAttributes.Abstract) == 0)
                i = -1;
            }
          }else{ // current method specifies hide
            Debug.Assert((func.attributes & MethodAttributes.VtableLayoutMask) == MethodAttributes.NewSlot);
            if ((matchingMethod.Attributes & MethodAttributes.Abstract) != 0){ // base is abstract
              func.funcContext.HandleError(JSError.HidesAbstractInBase, this.name + "." + func.name);
              func.attributes &= ~MethodAttributes.NewSlot;
              //Recover from error by overriding, it may be less bad than throwing a class load exception
            }else
              i = -1;
          }
        }

        if (i >= 0){
          //Overriding an abstract method. Take steps to prevent error messages.
          Debug.Assert((matchingMethod.Attributes & MethodAttributes.Abstract) != 0);
          this.superMembers[i] = func.name; //obliterate it so that it does not show up as unimplemented
          //Do likewise for any matching abstract members declared in less derived base classes
          for (int j = i+1; j < n; j++){ //Most derived class is always first
            MemberInfo mem = this.superMembers[j] as MemberInfo;
            if (mem == null) continue;
            if (mem.Name != matchingMethod.Name) break;
            MethodInfo meth2 = mem as MethodInfo;
            if (meth2 == null) continue;
            if (meth2.IsAbstract && Class.ParametersMatch(meth2.GetParameters(), matchingMethod.GetParameters())){
              IReflect rt = matchingMethod is JSFieldMethod ? ((JSFieldMethod)matchingMethod).ReturnIR() : matchingMethod.ReturnType;
              IReflect rt2 = meth2 is JSFieldMethod ? ((JSFieldMethod)meth2).ReturnIR() : meth2.ReturnType;
              if (rt == rt2) this.superMembers[j] = func.name;
            }
          }
        }
      }