Mono.CSharp.MemberCore.IsAccessibleAs C# (CSharp) Method

IsAccessibleAs() public method

public IsAccessibleAs ( System.TypeSpec p ) : bool
p System.TypeSpec
return bool
		public bool IsAccessibleAs (TypeSpec p)
		{
			//
			// if M is private, its accessibility is the same as this declspace.
			// we already know that P is accessible to T before this method, so we
			// may return true.
			//
			if ((mod_flags & Modifiers.PRIVATE) != 0)
				return true;

			while (TypeManager.HasElementType (p))
				p = TypeManager.GetElementType (p);

			if (p.IsGenericParameter)
				return true;

			for (TypeSpec p_parent; p != null; p = p_parent) {
				p_parent = p.DeclaringType;

				if (p.IsGeneric) {
					foreach (TypeSpec t in p.TypeArguments) {
						if (!IsAccessibleAs (t))
							return false;
					}
				}

				var pAccess = p.Modifiers & Modifiers.AccessibilityMask;
				if (pAccess == Modifiers.PUBLIC)
					continue;

				bool same_access_restrictions = false;
				for (MemberCore mc = this; !same_access_restrictions && mc != null && mc.Parent != null; mc = mc.Parent) {
					var al = mc.ModFlags & Modifiers.AccessibilityMask;
					switch (pAccess) {
					case Modifiers.INTERNAL:
						if (al == Modifiers.PRIVATE || al == Modifiers.INTERNAL)
							same_access_restrictions = p.MemberDefinition.IsInternalAsPublic (mc.Module.DeclaringAssembly);
						
						break;

					case Modifiers.PROTECTED:
						if (al == Modifiers.PROTECTED) {
							same_access_restrictions = mc.Parent.IsBaseTypeDefinition (p_parent);
							break;
						}

						if (al == Modifiers.PRIVATE) {
							//
							// When type is private and any of its parents derives from
							// protected type then the type is accessible
							//
							while (mc.Parent != null) {
								if (mc.Parent.IsBaseTypeDefinition (p_parent))
									same_access_restrictions = true;
								mc = mc.Parent; 
							}
						}
						
						break;

					case Modifiers.PROTECTED | Modifiers.INTERNAL:
						if (al == Modifiers.INTERNAL)
							same_access_restrictions = p.MemberDefinition.IsInternalAsPublic (mc.Module.DeclaringAssembly);
						else if (al == (Modifiers.PROTECTED | Modifiers.INTERNAL))
							same_access_restrictions = mc.Parent.IsBaseTypeDefinition (p_parent) && p.MemberDefinition.IsInternalAsPublic (mc.Module.DeclaringAssembly);
						else
							goto case Modifiers.PROTECTED;

						break;

					case Modifiers.PRIVATE:
						//
						// Both are private and share same parent
						//
						if (al == Modifiers.PRIVATE) {
							var decl = mc.Parent;
							do {
								same_access_restrictions = decl.CurrentType == p_parent;
							} while (!same_access_restrictions && !decl.IsTopLevel && (decl = decl.Parent) != null);
						}
						
						break;
						
					default:
						throw new InternalErrorException (al.ToString ());
					}
				}
				
				if (!same_access_restrictions)
					return false;
			}

			return true;
		}

Usage Example

Esempio n. 1
0
		/// <summary>
		///   Resolve the constraints - but only resolve things into Expression's, not
		///   into actual types.
		/// </summary>
		public bool Resolve (MemberCore ec, TypeParameter tp, Report Report)
		{
			if (resolved)
				return true;

			if (ec == null)
				return false;

			iface_constraints = new ArrayList (2);	// TODO: Too expensive allocation
			type_param_constraints = new ArrayList ();

			foreach (object obj in constraints) {
				if (HasConstructorConstraint) {
					Report.Error (401, loc,
						      "The new() constraint must be the last constraint specified");
					return false;
				}

				if (obj is SpecialConstraint) {
					SpecialConstraint sc = (SpecialConstraint) obj;

					if (sc == SpecialConstraint.Constructor) {
						if (!HasValueTypeConstraint) {
							attrs |= GenericParameterAttributes.DefaultConstructorConstraint;
							continue;
						}

						Report.Error (451, loc, "The `new()' constraint " +
							"cannot be used with the `struct' constraint");
						return false;
					}

					if ((num_constraints > 0) || HasReferenceTypeConstraint || HasValueTypeConstraint) {
						Report.Error (449, loc, "The `class' or `struct' " +
							      "constraint must be the first constraint specified");
						return false;
					}

					if (sc == SpecialConstraint.ReferenceType)
						attrs |= GenericParameterAttributes.ReferenceTypeConstraint;
					else
						attrs |= GenericParameterAttributes.NotNullableValueTypeConstraint;
					continue;
				}

				int errors = Report.Errors;
				FullNamedExpression fn = ((Expression) obj).ResolveAsTypeStep (ec, false);

				if (fn == null) {
					if (errors != Report.Errors)
						return false;

					NamespaceEntry.Error_NamespaceNotFound (loc, ((Expression)obj).GetSignatureForError (), Report);
					return false;
				}

				TypeExpr expr;
				GenericTypeExpr cexpr = fn as GenericTypeExpr;
				if (cexpr != null) {
					expr = cexpr.ResolveAsBaseTerminal (ec, false);
				} else
					expr = ((Expression) obj).ResolveAsTypeTerminal (ec, false);

				if ((expr == null) || (expr.Type == null))
					return false;

				if (!ec.IsAccessibleAs (fn.Type)) {
					Report.SymbolRelatedToPreviousError (fn.Type);
					Report.Error (703, loc,
						"Inconsistent accessibility: constraint type `{0}' is less accessible than `{1}'",
						fn.GetSignatureForError (), ec.GetSignatureForError ());
					return false;
				}

				if (TypeManager.IsGenericParameter (expr.Type))
					type_param_constraints.Add (expr);
				else if (expr.IsInterface)
					iface_constraints.Add (expr);
				else if (class_constraint != null || iface_constraints.Count != 0) {
					Report.Error (406, loc,
						"The class type constraint `{0}' must be listed before any other constraints. Consider moving type constraint to the beginning of the constraint list",
						expr.GetSignatureForError ());
					return false;
				} else if (HasReferenceTypeConstraint || HasValueTypeConstraint) {
					Report.Error (450, loc, "`{0}': cannot specify both " +
						      "a constraint class and the `class' " +
						      "or `struct' constraint", expr.GetSignatureForError ());
					return false;
				} else
					class_constraint = expr;


				//
				// Checks whether each generic method parameter constraint type
				// is valid with respect to T
				//
				if (tp != null && tp.Type.DeclaringMethod != null) {
					TypeManager.CheckTypeVariance (expr.Type, Variance.Contravariant, ec as MemberCore);
				}

				num_constraints++;
			}

			ArrayList list = new ArrayList ();
			foreach (TypeExpr iface_constraint in iface_constraints) {
				foreach (Type type in list) {
					if (!type.Equals (iface_constraint.Type))
						continue;

					Report.Error (405, loc,
						      "Duplicate constraint `{0}' for type " +
						      "parameter `{1}'.", iface_constraint.GetSignatureForError (),
						      name);
					return false;
				}

				list.Add (iface_constraint.Type);
			}

			foreach (TypeExpr expr in type_param_constraints) {
				foreach (Type type in list) {
					if (!type.Equals (expr.Type))
						continue;

					Report.Error (405, loc,
						      "Duplicate constraint `{0}' for type " +
						      "parameter `{1}'.", expr.GetSignatureForError (), name);
					return false;
				}

				list.Add (expr.Type);
			}

			iface_constraint_types = new Type [list.Count];
			list.CopyTo (iface_constraint_types, 0);

			if (class_constraint != null) {
				class_constraint_type = class_constraint.Type;
				if (class_constraint_type == null)
					return false;

				if (class_constraint_type.IsSealed) {
					if (class_constraint_type.IsAbstract)
					{
						Report.Error (717, loc, "`{0}' is not a valid constraint. Static classes cannot be used as constraints",
							TypeManager.CSharpName (class_constraint_type));
					}
					else
					{
						Report.Error (701, loc, "`{0}' is not a valid constraint. A constraint must be an interface, " +
							"a non-sealed class or a type parameter", TypeManager.CSharpName(class_constraint_type));
					}
					return false;
				}

				if ((class_constraint_type == TypeManager.array_type) ||
				    (class_constraint_type == TypeManager.delegate_type) ||
				    (class_constraint_type == TypeManager.enum_type) ||
				    (class_constraint_type == TypeManager.value_type) ||
				    (class_constraint_type == TypeManager.object_type) ||
					class_constraint_type == TypeManager.multicast_delegate_type) {
					Report.Error (702, loc,
							  "A constraint cannot be special class `{0}'",
						      TypeManager.CSharpName (class_constraint_type));
					return false;
				}

				if (TypeManager.IsDynamicType (class_constraint_type)) {
					Report.Error (1967, loc, "A constraint cannot be the dynamic type");
					return false;
				}
			}

			if (class_constraint_type != null)
				effective_base_type = class_constraint_type;
			else if (HasValueTypeConstraint)
				effective_base_type = TypeManager.value_type;
			else
				effective_base_type = TypeManager.object_type;

			if ((attrs & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0)
				attrs |= GenericParameterAttributes.DefaultConstructorConstraint;

			resolved = true;
			return true;
		}