2009-07-17 Zoltan Varga <vargaz@gmail.com>
[mcs.git] / mcs / complete.cs
blob9ff1d96690d07eb73a845ff1da331111abb318f7
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.
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
16 namespace Mono.CSharp {
17 using System;
18 using System.Collections;
19 using System.Reflection;
20 using System.Reflection.Emit;
21 using System.Text;
24 // A common base class for Completing expressions, it
25 // is just a very simple ExpressionStatement
27 public abstract class CompletingExpression : ExpressionStatement {
28 public override void EmitStatement (EmitContext ec)
30 // Do nothing
33 public override void Emit (EmitContext ec)
35 // Do nothing
38 public override Expression CreateExpressionTree (EmitContext ec)
40 return null;
44 public class CompletionSimpleName : CompletingExpression {
45 public string Prefix;
47 public CompletionSimpleName (string prefix, Location l)
49 this.loc = l;
50 this.Prefix = prefix;
53 public static void AppendResults (ArrayList results, string prefix, IEnumerable names)
55 foreach (string name in names){
56 if (name == null)
57 continue;
59 if (!name.StartsWith (prefix))
60 continue;
62 if (results.Contains (name))
63 continue;
65 if (prefix != null)
66 results.Add (name.Substring (prefix.Length));
67 else
68 results.Add (name);
73 public override Expression DoResolve (EmitContext ec)
75 ArrayList results = new ArrayList ();
77 AppendResults (results, Prefix, Evaluator.GetVarNames ());
78 AppendResults (results, Prefix, ec.TypeContainer.NamespaceEntry.CompletionGetTypesStartingWith (ec.TypeContainer, Prefix));
79 AppendResults (results, Prefix, Evaluator.GetUsingList ());
81 throw new CompletionResult (Prefix, (string []) results.ToArray (typeof (string)));
84 protected override void CloneTo (CloneContext clonectx, Expression t)
86 // Nothing
90 public class CompletionMemberAccess : CompletingExpression {
91 Expression expr;
92 string partial_name;
93 TypeArguments targs;
95 internal static MemberFilter CollectingFilter = new MemberFilter (Match);
97 static bool Match (MemberInfo m, object filter_criteria)
99 if (m is FieldInfo){
100 if (((FieldInfo) m).IsSpecialName)
101 return false;
104 if (m is MethodInfo){
105 if (((MethodInfo) m).IsSpecialName)
106 return false;
109 if (filter_criteria == null)
110 return true;
112 string n = (string) filter_criteria;
113 if (m.Name.StartsWith (n))
114 return true;
116 return false;
119 public CompletionMemberAccess (Expression e, string partial_name, Location l)
121 this.expr = e;
122 this.loc = l;
123 this.partial_name = partial_name;
126 public CompletionMemberAccess (Expression e, string partial_name, TypeArguments targs, Location l)
128 this.expr = e;
129 this.loc = l;
130 this.partial_name = partial_name;
131 this.targs = targs;
134 public override Expression DoResolve (EmitContext ec)
136 SimpleName original = expr as SimpleName;
137 Expression expr_resolved = expr.Resolve (ec,
138 ResolveFlags.VariableOrValue | ResolveFlags.Type |
139 ResolveFlags.Intermediate | ResolveFlags.DisableStructFlowAnalysis);
141 if (expr_resolved == null)
142 return null;
144 Type expr_type = expr_resolved.Type;
145 if (expr_type.IsPointer || expr_type == TypeManager.void_type || expr_type == TypeManager.null_type || expr_type == InternalType.AnonymousMethod) {
146 Unary.Error_OperatorCannotBeApplied (loc, ".", expr_type);
147 return null;
150 if (targs != null) {
151 if (!targs.Resolve (ec))
152 return null;
155 ArrayList results = new ArrayList ();
156 if (expr_resolved is Namespace){
157 Namespace nexpr = expr_resolved as Namespace;
158 string namespaced_partial;
160 if (partial_name == null)
161 namespaced_partial = nexpr.Name;
162 else
163 namespaced_partial = nexpr.Name + "." + partial_name;
165 #if false
166 Console.WriteLine ("Workign with: namespaced partial {0}", namespaced_partial);
167 foreach (var x in ec.TypeContainer.NamespaceEntry.CompletionGetTypesStartingWith (ec.TypeContainer, namespaced_partial)){
168 Console.WriteLine (" {0}", x);
170 #endif
172 CompletionSimpleName.AppendResults (
173 results,
174 partial_name,
175 ec.TypeContainer.NamespaceEntry.CompletionGetTypesStartingWith (ec.TypeContainer, namespaced_partial));
176 } else {
177 MemberInfo [] result = expr_type.FindMembers (
178 MemberTypes.All, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public,
179 CollectingFilter, partial_name);
181 foreach (MemberInfo r in result){
182 string name;
184 MethodBase rasb = r as MethodBase;
185 if (rasb != null && rasb.IsSpecialName)
186 continue;
188 if (partial_name == null)
189 name = r.Name;
190 else
191 name = r.Name.Substring (partial_name.Length);
193 if (results.Contains (name))
194 continue;
195 results.Add (name);
199 throw new CompletionResult (partial_name == null ? "" : partial_name, (string []) results.ToArray (typeof (string)));
202 protected override void CloneTo (CloneContext clonectx, Expression t)
204 CompletionMemberAccess target = (CompletionMemberAccess) t;
206 if (targs != null)
207 target.targs = targs.Clone ();
209 target.expr = expr.Clone (clonectx);
213 public class CompletionElementInitializer : CompletingExpression {
214 string partial_name;
216 public CompletionElementInitializer (string partial_name, Location l)
218 this.partial_name = partial_name;
219 this.loc = l;
222 public override Expression DoResolve (EmitContext ec)
224 MemberList members = TypeManager.FindMembers (
225 ec.CurrentInitializerVariable.Type,
226 MemberTypes.Field | MemberTypes.Property,
227 BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public,
228 CompletionMemberAccess.CollectingFilter, partial_name);
230 string [] result = new string [members.Count];
231 int i = 0;
232 foreach (MemberInfo mi in members){
233 string name;
235 if (partial_name == null)
236 name = mi.Name;
237 else
238 name = mi.Name.Substring (partial_name.Length);
240 result [i++] = name;
243 if (partial_name != null && i > 0 && result [0] == "")
244 throw new CompletionResult ("", new string [] { "=" });
246 throw new CompletionResult (partial_name == null ? "" : partial_name, result);
249 protected override void CloneTo (CloneContext clonectx, Expression t)
251 // Nothing