Better error reporting for async delegates
[mono.git] / mcs / mcs / namespace.cs
index 8fa20c329ccc841e786386531423100670b1060d..bd55dce6c2bf3c9b00b200c600f6eb9cb884001d 100644 (file)
@@ -63,13 +63,6 @@ namespace Mono.CSharp {
                        : base ("global")
                {
                }
-
-               public override void Error_NamespaceDoesNotExist (Location loc, string name, int arity, IMemberContext ctx)
-               {
-                       ctx.Module.Compiler.Report.Error (400, loc,
-                               "The type or namespace name `{0}' could not be found in the global namespace (are you missing an assembly reference?)",
-                               name);
-               }
        }
 
        //
@@ -159,9 +152,16 @@ namespace Mono.CSharp {
                        return this;
                }
 
-               public virtual void Error_NamespaceDoesNotExist (Location loc, string name, int arity, IMemberContext ctx)
+               public void Error_NamespaceDoesNotExist (IMemberContext ctx, string name, int arity, Location loc)
                {
-                       var retval = LookupType (ctx, name, -System.Math.Max (1, arity), loc);
+                       var retval = LookupType (ctx, name, arity, LookupMode.IgnoreAccessibility, loc);
+                       if (retval != null) {
+                               ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (retval.Type);
+                               ErrorIsInaccesible (ctx, retval.GetSignatureForError (), loc);
+                               return;
+                       }
+
+                       retval = LookupType (ctx, name, -System.Math.Max (1, arity), LookupMode.Probing, loc);
                        if (retval != null) {
                                Error_TypeArgumentsCannotBeUsed (ctx, retval.Type, arity, loc);
                                return;
@@ -173,9 +173,15 @@ namespace Mono.CSharp {
                                return;
                        }
 
-                       ctx.Module.Compiler.Report.Error (234, loc,
-                               "The type or namespace name `{0}' does not exist in the namespace `{1}'. Are you missing an assembly reference?",
-                               name, GetSignatureForError ());
+                       if (this is GlobalRootNamespace) {
+                               ctx.Module.Compiler.Report.Error (400, loc,
+                                       "The type or namespace name `{0}' could not be found in the global namespace (are you missing an assembly reference?)",
+                                       name);
+                       } else {
+                               ctx.Module.Compiler.Report.Error (234, loc,
+                                       "The type or namespace name `{0}' does not exist in the namespace `{1}'. Are you missing an assembly reference?",
+                                       name, GetSignatureForError ());
+                       }
                }
 
                public override string GetSignatureForError ()
@@ -217,7 +223,7 @@ namespace Mono.CSharp {
                        return found;
                }
 
-               public TypeExpr LookupType (IMemberContext ctx, string name, int arity, Location loc)
+               public TypeExpr LookupType (IMemberContext ctx, string name, int arity, LookupMode mode, Location loc)
                {
                        if (types == null)
                                return null;
@@ -234,14 +240,19 @@ namespace Mono.CSharp {
                        foreach (var ts in found) {
                                if (ts.Arity == arity) {
                                        if (best == null) {
+                                               if ((ts.Modifiers & Modifiers.INTERNAL) != 0 && !ts.MemberDefinition.IsInternalAsPublic (ctx.Module.DeclaringAssembly) && mode != LookupMode.IgnoreAccessibility)
+                                                       continue;
+
                                                best = ts;
                                                continue;
                                        }
 
                                        if (best.MemberDefinition.IsImported && ts.MemberDefinition.IsImported) {
-                                               ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (best);
-                                               ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ts);
-                                               ctx.Module.Compiler.Report.Error (433, loc, "The imported type `{0}' is defined multiple times", ts.GetSignatureForError ());
+                                               if (mode == LookupMode.Normal) {
+                                                       ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (best);
+                                                       ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ts);
+                                                       ctx.Module.Compiler.Report.Error (433, loc, "The imported type `{0}' is defined multiple times", ts.GetSignatureForError ());
+                                               }
                                                break;
                                        }
 
@@ -251,6 +262,9 @@ namespace Mono.CSharp {
                                        if ((best.Modifiers & Modifiers.INTERNAL) != 0 && !best.MemberDefinition.IsInternalAsPublic (ctx.Module.DeclaringAssembly))
                                                continue;
 
+                                       if (mode != LookupMode.Normal)
+                                               continue;
+
                                        if (ts.MemberDefinition.IsImported)
                                                ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ts);
 
@@ -260,7 +274,7 @@ namespace Mono.CSharp {
                                }
 
                                //
-                               // Lookup for the best candidate with closest arity match
+                               // Lookup for the best candidate with the closest arity match
                                //
                                if (arity < 0) {
                                        if (best == null) {
@@ -274,13 +288,10 @@ namespace Mono.CSharp {
                        if (best == null)
                                return null;
 
-                       if ((best.Modifiers & Modifiers.INTERNAL) != 0 && !best.MemberDefinition.IsInternalAsPublic (ctx.Module.DeclaringAssembly))
-                               return null;
-
                        te = new TypeExpression (best, Location.Null);
 
                        // TODO MemberCache: Cache more
-                       if (arity == 0)
+                       if (arity == 0 && mode == LookupMode.Normal)
                                cached_types.Add (name, te);
 
                        return te;
@@ -317,20 +328,22 @@ namespace Mono.CSharp {
                        return null;
                }
 
-               public FullNamedExpression LookupTypeOrNamespace (IMemberContext ctx, string name, int arity, Location loc)
+               public FullNamedExpression LookupTypeOrNamespace (IMemberContext ctx, string name, int arity, LookupMode mode, Location loc)
                {
-                       var texpr = LookupType (ctx, name, arity, loc);
+                       var texpr = LookupType (ctx, name, arity, mode, loc);
 
                        Namespace ns;
                        if (arity == 0 && namespaces.TryGetValue (name, out ns)) {
                                if (texpr == null)
                                        return ns;
 
-                               ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (texpr.Type);
-                               // ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ns.loc, "");
-                               ctx.Module.Compiler.Report.Warning (437, 2, loc,
-                                       "The type `{0}' conflicts with the imported namespace `{1}'. Using the definition found in the source file",
-                                       texpr.GetSignatureForError (), ns.GetSignatureForError ());
+                               if (mode != LookupMode.Probing) {
+                                       ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (texpr.Type);
+                                       // ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ns.loc, "");
+                                       ctx.Module.Compiler.Report.Warning (437, 2, loc,
+                                               "The type `{0}' conflicts with the imported namespace `{1}'. Using the definition found in the source file",
+                                               texpr.GetSignatureForError (), ns.GetSignatureForError ());
+                               }
 
                                if (texpr.Type.MemberDefinition.IsImported)
                                        return ns;
@@ -357,9 +370,9 @@ namespace Mono.CSharp {
                        return res;
                }
 
-               /// 
-               /// Looks for extension method in this namespace
-               //
+               // 
+               // Looks for extension method in this namespace
+               //
                public List<MethodSpec> LookupExtensionMethod (IMemberContext invocationContext, TypeSpec extensionType, string name, int arity)
                {
                        if (types == null)
@@ -389,6 +402,26 @@ namespace Mono.CSharp {
                        return found;
                }
 
+               //
+               // Extension methods look up for dotted namespace names
+               //
+               public IList<MethodSpec> LookupExtensionMethod (IMemberContext invocationContext, TypeSpec extensionType, string name, int arity, out Namespace scope)
+               {
+                       //
+                       // Inspect parent namespaces in namespace expression
+                       //
+                       scope = this;
+                       do {
+                               var candidates = scope.LookupExtensionMethod (invocationContext, extensionType, name, arity);
+                               if (candidates != null)
+                                       return candidates;
+
+                               scope = scope.Parent;
+                       } while (scope != null);
+
+                       return null;
+               }
+
                public void AddType (ModuleContainer module, TypeSpec ts)
                {
                        if (types == null) {
@@ -784,7 +817,7 @@ namespace Mono.CSharp {
                // Does extension methods look up to find a method which matches name and extensionType.
                // Search starts from this namespace and continues hierarchically up to top level.
                //
-               public IList<MethodSpec> LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceContainer scope)
+               public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
                {
                        List<MethodSpec> candidates = null;
                        foreach (Namespace n in GetUsingTable ()) {
@@ -798,37 +831,29 @@ namespace Mono.CSharp {
                                        candidates.AddRange (a);
                        }
 
-                       scope = parent;
                        if (candidates != null)
-                               return candidates;
+                               return new ExtensionMethodCandidates (candidates, this);
 
                        if (parent == null)
                                return null;
 
-                       //
-                       // Inspect parent namespaces in namespace expression
-                       //
-                       Namespace parent_ns = ns.Parent;
-                       do {
-                               candidates = parent_ns.LookupExtensionMethod (this, extensionType, name, arity);
-                               if (candidates != null)
-                                       return candidates;
-
-                               parent_ns = parent_ns.Parent;
-                       } while (parent_ns != null);
+                       Namespace ns_scope;
+                       var ns_candidates = ns.Parent.LookupExtensionMethod (this, extensionType, name, arity, out ns_scope);
+                       if (ns_candidates != null)
+                               return new ExtensionMethodCandidates (ns_candidates, this, ns_scope);
 
                        //
-                       // Continue in parent scope
+                       // Continue in parent container
                        //
-                       return parent.LookupExtensionMethod (extensionType, name, arity, ref scope);
+                       return parent.LookupExtensionMethod (extensionType, name, arity);
                }
 
-               public FullNamedExpression LookupNamespaceOrType (string name, int arity, Location loc, bool ignore_cs0104)
+               public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
                {
                        // Precondition: Only simple names (no dots) will be looked up with this function.
                        FullNamedExpression resolved = null;
                        for (NamespaceContainer curr_ns = this; curr_ns != null; curr_ns = curr_ns.ImplicitParent) {
-                               if ((resolved = curr_ns.Lookup (name, arity, loc, ignore_cs0104)) != null)
+                               if ((resolved = curr_ns.Lookup (name, arity, mode, loc)) != null)
                                        break;
                        }
 
@@ -872,12 +897,12 @@ namespace Mono.CSharp {
                        return null;
                }
 
-               private FullNamedExpression Lookup (string name, int arity, Location loc, bool ignore_cs0104)
+               FullNamedExpression Lookup (string name, int arity, LookupMode mode, Location loc)
                {
                        //
                        // Check whether it's in the namespace.
                        //
-                       FullNamedExpression fne = ns.LookupTypeOrNamespace (this, name, arity, loc);
+                       FullNamedExpression fne = ns.LookupTypeOrNamespace (this, name, arity, mode, loc);
 
                        //
                        // Check aliases. 
@@ -887,12 +912,14 @@ namespace Mono.CSharp {
                                        if (ue.Alias == name) {
                                                if (fne != null) {
                                                        if (Doppelganger != null) {
-                                                               // TODO: Namespace has broken location
-                                                               //Report.SymbolRelatedToPreviousError (fne.Location, null);
-                                                               Compiler.Report.SymbolRelatedToPreviousError (ue.Location, null);
-                                                               Compiler.Report.Error (576, loc,
-                                                                       "Namespace `{0}' contains a definition with same name as alias `{1}'",
-                                                                       GetSignatureForError (), name);
+                                                               if (mode == LookupMode.Normal) {
+                                                                       // TODO: Namespace has broken location
+                                                                       //Report.SymbolRelatedToPreviousError (fne.Location, null);
+                                                                       Compiler.Report.SymbolRelatedToPreviousError (ue.Location, null);
+                                                                       Compiler.Report.Error (576, loc,
+                                                                               "Namespace `{0}' contains a definition with same name as alias `{1}'",
+                                                                               GetSignatureForError (), name);
+                                                               }
                                                        } else {
                                                                return fne;
                                                        }
@@ -903,10 +930,8 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       if (fne != null) {
-                               if (!((fne.Type.Modifiers & Modifiers.INTERNAL) != 0 && !fne.Type.MemberDefinition.IsInternalAsPublic (module.DeclaringAssembly)))
-                                       return fne;
-                       }
+                       if (fne != null)
+                               return fne;
 
                        if (IsImplicit)
                                return null;
@@ -918,7 +943,7 @@ namespace Mono.CSharp {
                        foreach (Namespace using_ns in GetUsingTable ()) {
                                // A using directive imports only types contained in the namespace, it
                                // does not import any nested namespaces
-                               fne = using_ns.LookupType (this, name, arity, loc);
+                               fne = using_ns.LookupType (this, name, arity, mode, loc);
                                if (fne == null)
                                        continue;
 
@@ -937,16 +962,16 @@ namespace Mono.CSharp {
                                        continue;
                                }
 
-                               if (ignore_cs0104)
-                                       return match;
-
                                // It can be top level accessibility only
                                var better = Namespace.IsImportedTypeOverride (module, texpr_match.Type, texpr_fne.Type);
                                if (better == null) {
-                                       Compiler.Report.SymbolRelatedToPreviousError (texpr_match.Type);
-                                       Compiler.Report.SymbolRelatedToPreviousError (texpr_fne.Type);
-                                       Compiler.Report.Error (104, loc, "`{0}' is an ambiguous reference between `{1}' and `{2}'",
-                                               name, texpr_match.GetSignatureForError (), texpr_fne.GetSignatureForError ());
+                                       if (mode == LookupMode.Normal) {
+                                               Compiler.Report.SymbolRelatedToPreviousError (texpr_match.Type);
+                                               Compiler.Report.SymbolRelatedToPreviousError (texpr_fne.Type);
+                                               Compiler.Report.Error (104, loc, "`{0}' is an ambiguous reference between `{1}' and `{2}'",
+                                                       name, texpr_match.GetSignatureForError (), texpr_fne.GetSignatureForError ());
+                                       }
+
                                        return match;
                                }
 
@@ -1090,11 +1115,6 @@ namespace Mono.CSharp {
                        get { return SlaveDeclSpace.CurrentTypeParameters; }
                }
 
-               // FIXME: It's false for expression types
-               public bool HasUnresolvedConstraints {
-                       get { return true; }
-               }
-
                public bool IsObsolete {
                        get { return SlaveDeclSpace.IsObsolete; }
                }