Better check for instance equality of generic types. Fixes #15100
[mono.git] / mcs / mcs / complete.cs
index 81be26ab8f3b8e86036912ae5e04d501788495cd..6eb42cddada0a51de2f96f54fe9c35b0b6cd294e 100644 (file)
@@ -7,67 +7,80 @@
 //
 // Copyright 2001, 2002, 2003 Ximian, Inc.
 // Copyright 2003-2009 Novell, Inc.
+// Copyright 2011 Xamarin Inc
 //
 // Completion* classes derive from ExpressionStatement as this allows
 // them to pass through the parser in many conditions that require
 // statements even when the expression is incomplete (for example
 // completing inside a lambda
 //
+using System.Collections.Generic;
+using System.Linq;
+
 namespace Mono.CSharp {
-       using System;
-       using System.Collections;
-       using System.Reflection;
-       using System.Reflection.Emit;
-       using System.Text;
 
        //
        // A common base class for Completing expressions, it
        // is just a very simple ExpressionStatement
        //
-       public abstract class CompletingExpression : ExpressionStatement {
-               public override void EmitStatement (EmitContext ec)
+       public abstract class CompletingExpression : ExpressionStatement
+       {
+               public static void AppendResults (List<string> results, string prefix, IEnumerable<string> names)
                {
-                       // Do nothing
+                       foreach (string name in names) {
+                               if (name == null)
+                                       continue;
+
+                               if (prefix != null && !name.StartsWith (prefix))
+                                       continue;
+
+                               if (results.Contains (name))
+                                       continue;
+
+                               if (prefix != null)
+                                       results.Add (name.Substring (prefix.Length));
+                               else
+                                       results.Add (name);
+                       }
                }
 
-               public override void Emit (EmitContext ec)
+               public override bool ContainsEmitWithAwait ()
                {
-                       // Do nothing
+                       return false;
                }
 
-               public override Expression CreateExpressionTree (EmitContext ec)
+               public override Expression CreateExpressionTree (ResolveContext ec)
                {
                        return null;
                }
+
+               public override void EmitStatement (EmitContext ec)
+               {
+                       // Do nothing
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       // Do nothing
+               }
        }
        
        public class CompletionSimpleName : CompletingExpression {
-               string prefix;
+               public string Prefix;
                
                public CompletionSimpleName (string prefix, Location l)
                {
                        this.loc = l;
-                       this.prefix = prefix;
+                       this.Prefix = prefix;
                }
-
-               public override Expression DoResolve (EmitContext ec)
+               
+               protected override Expression DoResolve (ResolveContext ec)
                {
-                       string [] names = Evaluator.GetVarNames ();
-
-                       ArrayList results = new ArrayList ();
-                       foreach (string name in names){
-                               if (!name.StartsWith (prefix))
-                                       continue;
+                       var results = new List<string> ();
 
-                               if (results.Contains (name))
-                                       continue;
+                       ec.CurrentMemberDefinition.GetCompletionStartingWith (Prefix, results);
 
-                               if (prefix != null)
-                                       results.Add (name.Substring (prefix.Length));
-                               else
-                                       results.Add (name);
-                       }
-                       throw new CompletionResult (prefix, (string []) results.ToArray (typeof (string)));
+                       throw new CompletionResult (Prefix, results.Distinct ().Select (l => l.Substring (Prefix.Length)).ToArray ());
                }
 
                protected override void CloneTo (CloneContext clonectx, Expression t)
@@ -80,30 +93,6 @@ namespace Mono.CSharp {
                Expression expr;
                string partial_name;
                TypeArguments targs;
-
-               static MemberFilter CollectingFilter = new MemberFilter (Match);
-
-               static bool Match (MemberInfo m, object filter_criteria)
-               {
-                       if (m is FieldInfo){
-                               if (((FieldInfo) m).IsSpecialName)
-                                       return false;
-                               
-                       }
-                       if (m is MethodInfo){
-                               if (((MethodInfo) m).IsSpecialName)
-                                       return false;
-                       }
-
-                       if (filter_criteria == null)
-                               return true;
-                       
-                       string n = (string) filter_criteria;
-                       if (m.Name.StartsWith (n))
-                               return true;
-                       
-                       return false;
-               }
                
                public CompletionMemberAccess (Expression e, string partial_name, Location l)
                {
@@ -120,48 +109,72 @@ namespace Mono.CSharp {
                        this.targs = targs;
                }
                
-               public override Expression DoResolve (EmitContext ec)
+               protected override Expression DoResolve (ResolveContext rc)
                {
-                       SimpleName original = expr as SimpleName;
-                       Expression expr_resolved = expr.Resolve (ec,
-                               ResolveFlags.VariableOrValue | ResolveFlags.Type |
-                               ResolveFlags.Intermediate | ResolveFlags.DisableStructFlowAnalysis);
+                       var sn = expr as SimpleName;
+                       const ResolveFlags flags = ResolveFlags.VariableOrValue | ResolveFlags.Type;
+
+                       //
+                       // Resolve the expression with flow analysis turned off, we'll do the definite
+                       // assignment checks later.  This is because we don't know yet what the expression
+                       // will resolve to - it may resolve to a FieldExpr and in this case we must do the
+                       // definite assignment check on the actual field and not on the whole struct.
+                       //
+                       using (rc.Set (ResolveContext.Options.OmitStructFlowAnalysis)) {
+                               if (sn != null) {
+                                       expr = sn.LookupNameExpression (rc, MemberLookupRestrictions.ReadAccess | MemberLookupRestrictions.ExactArity);
+
+                                       //
+                                       // Resolve expression which does have type set as we need expression type
+                                       // with disable flow analysis as we don't know whether left side expression
+                                       // is used as variable or type
+                                       //
+                                       if (expr is VariableReference || expr is ConstantExpr || expr is Linq.TransparentMemberAccess) {
+                                               using (rc.With (ResolveContext.Options.DoFlowAnalysis, false)) {
+                                                       expr = expr.Resolve (rc);
+                                               }
+                                       } else if (expr is TypeParameterExpr) {
+                                               expr.Error_UnexpectedKind (rc, flags, sn.Location);
+                                               expr = null;
+                                       }
+                               } else {
+                                       expr = expr.Resolve (rc, flags);
+                               }
+                       }
 
-                       if (expr_resolved == null)
+                       if (expr == null)
                                return null;
 
-                       Type expr_type = expr_resolved.Type;
-                       if (expr_type.IsPointer || expr_type == TypeManager.void_type || expr_type == TypeManager.null_type || expr_type == TypeManager.anonymous_method_type) {
-                               Unary.Error_OperatorCannotBeApplied (loc, ".", expr_type);
+                       TypeSpec expr_type = expr.Type;
+                       if (expr_type.IsPointer || expr_type.Kind == MemberKind.Void || expr_type == InternalType.NullLiteral || expr_type == InternalType.AnonymousMethod) {
+                               expr.Error_OperatorCannotBeApplied (rc, loc, ".", expr_type);
                                return null;
                        }
 
                        if (targs != null) {
-                               if (!targs.Resolve (ec))
+                               if (!targs.Resolve (rc))
                                        return null;
                        }
 
-                       ArrayList results = new ArrayList ();
-                       MemberInfo [] result = expr_type.FindMembers (MemberTypes.All, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public, CollectingFilter, partial_name);
-                       foreach (MemberInfo r in result){
-                               string name;
+                       var results = new List<string> ();
+                       if (expr is Namespace) {
+                               Namespace nexpr = expr as Namespace;
+                               string namespaced_partial;
 
-                               MethodBase rasb = r as MethodBase;
-                               if (rasb != null && rasb.IsSpecialName)
-                                       continue;
-                               
                                if (partial_name == null)
-                                       name = r.Name;
-                               else {
-                                       name = r.Name.Substring (partial_name.Length);
-                               }
-                               
-                               if (results.Contains (name))
-                                       continue;
-                               results.Add (name);
+                                       namespaced_partial = nexpr.Name;
+                               else
+                                       namespaced_partial = nexpr.Name + "." + partial_name;
+
+                               rc.CurrentMemberDefinition.GetCompletionStartingWith (namespaced_partial, results);
+                               if (partial_name != null)
+                                       results = results.Select (l => l.Substring (partial_name.Length)).ToList ();
+                       } else {
+                               var r = MemberCache.GetCompletitionMembers (rc, expr_type, partial_name).Select (l => l.Name);
+                               AppendResults (results, partial_name, r);
                        }
 
-                       throw new CompletionResult (partial_name == null ? "" : partial_name, (string []) results.ToArray (typeof (string)));
+                       throw new CompletionResult (partial_name == null ? "" : partial_name, results.Distinct ().ToArray ());
                }
 
                protected override void CloneTo (CloneContext clonectx, Expression t)
@@ -174,4 +187,38 @@ namespace Mono.CSharp {
                        target.expr = expr.Clone (clonectx);
                }
        }
-}
\ No newline at end of file
+
+       public class CompletionElementInitializer : CompletingExpression {
+               string partial_name;
+               
+               public CompletionElementInitializer (string partial_name, Location l)
+               {
+                       this.partial_name = partial_name;
+                       this.loc = l;
+               }
+               
+               protected override Expression DoResolve (ResolveContext ec)
+               {
+                       var members = MemberCache.GetCompletitionMembers (ec, ec.CurrentInitializerVariable.Type, partial_name);
+
+// TODO: Does this mean exact match only ?
+//                     if (partial_name != null && results.Count > 0 && result [0] == "")
+//                             throw new CompletionResult ("", new string [] { "=" });
+
+                       var results = members.Where (l => (l.Kind & (MemberKind.Field | MemberKind.Property)) != 0).Select (l => l.Name).ToList ();
+                       if (partial_name != null) {
+                               var temp = new List<string> ();
+                               AppendResults (temp, partial_name, results);
+                               results = temp;
+                       }
+
+                       throw new CompletionResult (partial_name == null ? "" : partial_name, results.Distinct ().ToArray ());
+               }
+
+               protected override void CloneTo (CloneContext clonectx, Expression t)
+               {
+                       // Nothing
+               }
+       }
+       
+}