{
Report.Warning (
109, Location,
- "The member `" + parent.Name + "." + Name + "' does not hide an " +
+ "The member " + parent.MakeName (Name) + " does not hide an " +
"inherited member. The keyword new is not required");
}
- static string MethodBaseName (MethodBase mb)
- {
- return "`" + mb.ReflectedType.Name + "." + mb.Name + "'";
- }
-
- void Error_CannotChangeAccessModifiers (TypeContainer parent, MethodInfo parent_method)
+ void Error_CannotChangeAccessModifiers (TypeContainer parent, MethodInfo parent_method,
+ string name)
{
//
// FIXME: report the old/new permissions?
//
Report.Error (
- 507, "`" + parent_method + "." + Name +
- ": can't change the access modifiers from `" +
- parent_method.DeclaringType.Name + "." + parent_method.Name + "'");
+ 507, Location, parent.MakeName (Name) +
+ ": can't change the access modifiers when overriding inherited " +
+ "member `" + name + "'");
}
//
// `name' is the user visible name for reporting errors (this is used to
// provide the right name regarding method names and properties)
//
- protected bool CheckMethodAgainstBase (TypeContainer parent,
- MethodAttributes my_attrs, MethodInfo mb)
+ protected bool CheckMethodAgainstBase (TypeContainer parent, MethodAttributes my_attrs,
+ MethodInfo mb, string name)
{
bool ok = true;
if (!(mb.IsAbstract || mb.IsVirtual)){
Report.Error (
506, Location, parent.MakeName (Name) +
- ": cannot override inherited member " +
- MethodBaseName (mb) + " because it is not " +
+ ": cannot override inherited member `" +
+ name + "' because it is not " +
"virtual, abstract or override");
ok = false;
}
if (mb.IsFinal) {
Report.Error (239, Location, parent.MakeName (Name) + " : cannot " +
- "override inherited member " + MethodBaseName (mb) +
- " because it is sealed.");
+ "override inherited member `" + name +
+ "' because it is sealed.");
ok = false;
}
MethodAttributes parentp = mb.Attributes & MethodAttributes.MemberAccessMask;
if (thisp != parentp){
- Error_CannotChangeAccessModifiers (parent, mb);
+ Error_CannotChangeAccessModifiers (parent, mb, name);
ok = false;
}
}
if (Name != "Finalize" && (RootContext.WarningLevel >= 2)){
Report.Warning (
114, Location, parent.MakeName (Name) +
- " hides inherited member " + MethodBaseName (mb) +
- ". To make the current member override that " +
+ " hides inherited member `" + name +
+ "'. To make the current member override that " +
"implementation, add the override keyword, " +
"otherwise use the new keyword");
}
}
+ } else {
+ if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
+ if (Name != "Finalize" && (RootContext.WarningLevel >= 1)){
+ Report.Warning (
+ 108, Location, "The keyword new is required on " +
+ parent.MakeName (Name) + " because it hides " +
+ "inherited member `" + name + "'");
+ }
+ }
}
return ok;
/// this points to the actual definition that is being
/// created with System.Reflection.Emit
/// </summary>
- TypeBuilder definition;
+ public TypeBuilder TypeBuilder;
/// <summary>
/// This variable tracks whether we have Closed the type
//
public Namespace Namespace;
+ public Hashtable Cache = new Hashtable ();
+
public string Basename;
/// <summary>
}
}
- public TypeBuilder TypeBuilder {
- get {
- return definition;
- }
-
- set {
- definition = value;
- }
- }
-
public TypeContainer Parent {
get {
return parent;
}
}
+ /// <summary>
+ /// Looks up the alias for the name
+ /// </summary>
+ public string LookupAlias (string name)
+ {
+ if (Namespace != null)
+ return Namespace.LookupAlias (name);
+ else
+ return null;
+ }
+
//
// root_types contains all the types. All TopLevel types
// hence have a parent that points to `root_types', that is
{
if (!Created){
try {
- definition.CreateType ();
+ TypeBuilder.CreateType ();
} catch {
//
// The try/catch is needed because
}
}
+ /// <remarks>
+ /// Should be overriten by the appropriate declaration space
+ /// <remarks>
+ public abstract TypeBuilder DefineType ();
+
//
// Whether this is an `unsafe context'
//
}
}
+ public static string MakeFQN (string nsn, string name)
+ {
+ string prefix = (nsn == "" ? "" : nsn + ".");
+
+ return prefix + name;
+ }
+
+ EmitContext type_resolve_ec;
+ EmitContext GetTypeResolveEmitContext (TypeContainer parent, Location loc)
+ {
+ type_resolve_ec = new EmitContext (parent, this, loc, null, null, ModFlags, false);
+ type_resolve_ec.ResolvingTypeTree = true;
+
+ return type_resolve_ec;
+ }
+
+ // <summary>
+ // Looks up the type, as parsed into the expression `e'
+ // </summary>
+ public Type ResolveType (Expression e, bool silent, Location loc)
+ {
+ if (type_resolve_ec == null)
+ type_resolve_ec = GetTypeResolveEmitContext (parent, loc);
+ type_resolve_ec.loc = loc;
+ Expression d = e.Resolve (type_resolve_ec, ResolveFlags.Type);
+ if (d == null || d.eclass != ExprClass.Type){
+ if (!silent){
+ Report.Error (246, loc, "Cannot find type `"+ e.ToString () +"'");
+ }
+ return null;
+ }
+
+ return d.Type;
+ }
+
+ // <summary>
+ // Resolves the expression `e' for a type, and will recursively define
+ // types.
+ // </summary>
+ public Expression ResolveTypeExpr (Expression e, bool silent, Location loc)
+ {
+ if (type_resolve_ec == null)
+ type_resolve_ec = GetTypeResolveEmitContext (parent, loc);
+
+ Expression d = e.Resolve (type_resolve_ec, ResolveFlags.Type);
+ if (d == null || d.eclass != ExprClass.Type){
+ if (!silent){
+ Report.Error (246, loc, "Cannot find type `"+ e +"'");
+ }
+ return null;
+ }
+
+ return d;
+ }
+
+ Type LookupInterfaceOrClass (string ns, string name, out bool error)
+ {
+ DeclSpace parent;
+ Type t;
+
+ error = false;
+ name = MakeFQN (ns, name);
+
+ t = TypeManager.LookupType (name);
+ if (t != null)
+ return t;
+
+ parent = (DeclSpace) RootContext.Tree.Decls [name];
+ if (parent == null)
+ return null;
+
+ t = parent.DefineType ();
+ if (t == null){
+ Report.Error (146, "Class definition is circular: `"+name+"'");
+ error = true;
+ return null;
+ }
+ return t;
+ }
+
+ /// <summary>
+ /// GetType is used to resolve type names at the DeclSpace level.
+ /// Use this to lookup class/struct bases, interface bases or
+ /// delegate type references
+ /// </summary>
+ ///
+ /// <remarks>
+ /// Contrast this to LookupType which is used inside method bodies to
+ /// lookup types that have already been defined. GetType is used
+ /// during the tree resolution process and potentially define
+ /// recursively the type
+ /// </remarks>
+ public Type FindType (string name)
+ {
+ Type t;
+ bool error;
+
+ //
+ // For the case the type we are looking for is nested within this one
+ // or is in any base class
+ //
+ DeclSpace containing_ds = this;
+
+ while (containing_ds != null){
+ Type current_type = containing_ds.TypeBuilder;
+
+ while (current_type != null) {
+ string pre = current_type.FullName;
+
+ t = LookupInterfaceOrClass (pre, name, out error);
+ if (error)
+ return null;
+
+ if (t != null)
+ return t;
+
+ current_type = current_type.BaseType;
+ }
+ containing_ds = containing_ds.Parent;
+ }
+
+ //
+ // Attempt to lookup the class on our namespace and all it's implicit parents
+ //
+ for (string ns = Namespace.Name; ns != null; ns = RootContext.ImplicitParent (ns)) {
+
+ t = LookupInterfaceOrClass (ns, name, out error);
+ if (error)
+ return null;
+
+ if (t != null)
+ return t;
+ }
+
+ //
+ // Attempt to do a direct unqualified lookup
+ //
+ t = LookupInterfaceOrClass ("", name, out error);
+ if (error)
+ return null;
+
+ if (t != null)
+ return t;
+
+ //
+ // Attempt to lookup the class on any of the `using'
+ // namespaces
+ //
+
+ for (Namespace ns = Namespace; ns != null; ns = ns.Parent){
+
+ t = LookupInterfaceOrClass (ns.Name, name, out error);
+ if (error)
+ return null;
+
+ if (t != null)
+ return t;
+
+ //
+ // Now check the using clause list
+ //
+ ArrayList using_list = ns.UsingTable;
+
+ if (using_list == null)
+ continue;
+
+ foreach (string n in using_list){
+ t = LookupInterfaceOrClass (n, name, out error);
+ if (error)
+ return null;
+
+ if (t != null)
+ return t;
+ }
+
+ }
+
+ //Report.Error (246, Location, "Can not find type `"+name+"'");
+ return null;
+ }
+
+ /// <remarks>
+ /// This function is broken and not what you're looking for. It should only
+ /// be used while the type is still being created since it doesn't use the cache
+ /// and relies on the filter doing the member name check.
+ /// </remarks>
+ internal abstract MemberList FindMembers (MemberTypes mt, BindingFlags bf,
+ MemberFilter filter, object criteria);
+
+ /// <remarks>
+ /// If we have a MemberCache, return it. This property may return null if the
+ /// class doesn't have a member cache or while it's still being created.
+ /// </remarks>
+ public abstract MemberCache MemberCache {
+ get;
+ }
}
}