Correctly handle precedence of ToolsVersion value coming
[mono.git] / mcs / mcs / complete.cs
1 //
2 // complete.cs: Expression that are used for completion suggestions.
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //   Marek Safar (marek.safar@gmail.com)
7 //
8 // Copyright 2001, 2002, 2003 Ximian, Inc.
9 // Copyright 2003-2009 Novell, Inc.
10 //
11 // Completion* classes derive from ExpressionStatement as this allows
12 // them to pass through the parser in many conditions that require
13 // statements even when the expression is incomplete (for example
14 // completing inside a lambda
15 //
16 using System;
17 using System.Collections.Generic;
18 using System.Reflection;
19 using System.Reflection.Emit;
20 using System.Text;
21 using Mono.CSharp.Linq;
22 using System.Linq;
23
24 namespace Mono.CSharp {
25
26         //
27         // A common base class for Completing expressions, it
28         // is just a very simple ExpressionStatement
29         //
30         public abstract class CompletingExpression : ExpressionStatement
31         {
32                 public static void AppendResults (List<string> results, string prefix, IEnumerable<string> names)
33                 {
34                         foreach (string name in names) {
35                                 if (name == null || prefix == null)
36                                         continue;
37
38                                 if (!name.StartsWith (prefix))
39                                         continue;
40
41                                 if (results.Contains (name))
42                                         continue;
43
44                                 if (prefix != null)
45                                         results.Add (name.Substring (prefix.Length));
46                                 else
47                                         results.Add (name);
48                         }
49                 }
50
51                 public override void EmitStatement (EmitContext ec)
52                 {
53                         // Do nothing
54                 }
55
56                 public override void Emit (EmitContext ec)
57                 {
58                         // Do nothing
59                 }
60
61                 public override Expression CreateExpressionTree (ResolveContext ec)
62                 {
63                         return null;
64                 }
65         }
66         
67         public class CompletionSimpleName : CompletingExpression {
68                 public string Prefix;
69                 
70                 public CompletionSimpleName (string prefix, Location l)
71                 {
72                         this.loc = l;
73                         this.Prefix = prefix;
74                 }
75                 
76                 protected override Expression DoResolve (ResolveContext ec)
77                 {
78                         var results = new List<string> ();
79
80                         AppendResults (results, Prefix, Evaluator.GetVarNames ());
81                         AppendResults (results, Prefix, ec.CurrentMemberDefinition.Parent.NamespaceEntry.CompletionGetTypesStartingWith (Prefix));
82                         AppendResults (results, Prefix, Evaluator.GetUsingList ());
83                         
84                         throw new CompletionResult (Prefix, results.ToArray ());
85                 }
86
87                 protected override void CloneTo (CloneContext clonectx, Expression t)
88                 {
89                         // Nothing
90                 }
91         }
92         
93         public class CompletionMemberAccess : CompletingExpression {
94                 Expression expr;
95                 string partial_name;
96                 TypeArguments targs;
97                 
98                 public CompletionMemberAccess (Expression e, string partial_name, Location l)
99                 {
100                         this.expr = e;
101                         this.loc = l;
102                         this.partial_name = partial_name;
103                 }
104
105                 public CompletionMemberAccess (Expression e, string partial_name, TypeArguments targs, Location l)
106                 {
107                         this.expr = e;
108                         this.loc = l;
109                         this.partial_name = partial_name;
110                         this.targs = targs;
111                 }
112                 
113                 protected override Expression DoResolve (ResolveContext ec)
114                 {
115                         Expression expr_resolved = expr.Resolve (ec,
116                                 ResolveFlags.VariableOrValue | ResolveFlags.Type);
117
118                         if (expr_resolved == null)
119                                 return null;
120
121                         TypeSpec expr_type = expr_resolved.Type;
122                         if (expr_type.IsPointer || expr_type == TypeManager.void_type || expr_type == TypeManager.null_type || expr_type == InternalType.AnonymousMethod) {
123                                 Unary.Error_OperatorCannotBeApplied (ec, loc, ".", expr_type);
124                                 return null;
125                         }
126
127                         if (targs != null) {
128                                 if (!targs.Resolve (ec))
129                                         return null;
130                         }
131
132                         var results = new List<string> ();
133                         if (expr_resolved is Namespace){
134                                 Namespace nexpr = expr_resolved as Namespace;
135                                 string namespaced_partial;
136
137                                 if (partial_name == null)
138                                         namespaced_partial = nexpr.Name;
139                                 else
140                                         namespaced_partial = nexpr.Name + "." + partial_name;
141
142 #if false
143                                 Console.WriteLine ("Workign with: namespaced partial {0}", namespaced_partial);
144                                 foreach (var x in ec.TypeContainer.NamespaceEntry.CompletionGetTypesStartingWith (ec.TypeContainer, namespaced_partial)){
145                                         Console.WriteLine ("    {0}", x);
146                                 }
147 #endif
148
149                                 CompletionSimpleName.AppendResults (
150                                         results,
151                                         partial_name, 
152                                         ec.CurrentMemberDefinition.Parent.NamespaceEntry.CompletionGetTypesStartingWith (namespaced_partial));
153                         } else {
154                                 var r = MemberCache.GetCompletitionMembers (expr_type, partial_name).Select (l => l.Name);
155                                 AppendResults (results, partial_name, r);
156                         }
157
158                         throw new CompletionResult (partial_name == null ? "" : partial_name, results.Distinct ().ToArray ());
159                 }
160
161                 protected override void CloneTo (CloneContext clonectx, Expression t)
162                 {
163                         CompletionMemberAccess target = (CompletionMemberAccess) t;
164
165                         if (targs != null)
166                                 target.targs = targs.Clone ();
167
168                         target.expr = expr.Clone (clonectx);
169                 }
170         }
171
172         public class CompletionElementInitializer : CompletingExpression {
173                 string partial_name;
174                 
175                 public CompletionElementInitializer (string partial_name, Location l)
176                 {
177                         this.partial_name = partial_name;
178                         this.loc = l;
179                 }
180                 
181                 protected override Expression DoResolve (ResolveContext ec)
182                 {
183                         var members = MemberCache.GetCompletitionMembers (ec.CurrentInitializerVariable.Type, partial_name);
184
185 // TODO: Does this mean exact match only ?
186 //                      if (partial_name != null && results.Count > 0 && result [0] == "")
187 //                              throw new CompletionResult ("", new string [] { "=" });
188
189                         var results = members.Where (l => (l.Kind & (MemberKind.Field | MemberKind.Property)) != 0).Select (l => l.Name).ToList ();
190                         if (partial_name != null) {
191                                 var temp = new List<string> ();
192                                 AppendResults (temp, partial_name, results);
193                                 results = temp;
194                         }
195
196                         throw new CompletionResult (partial_name == null ? "" : partial_name, results.Distinct ().ToArray ());
197                 }
198
199                 protected override void CloneTo (CloneContext clonectx, Expression t)
200                 {
201                         // Nothing
202                 }
203         }
204         
205 }