2010-04-07 Jb Evain <jbevain@novell.com>
[mcs.git] / mcs / complete.cs
blob36de138c0a78371cb67f92c1908e6576b3bae976
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 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;
23 namespace Mono.CSharp {
26 // A common base class for Completing expressions, it
27 // is just a very simple ExpressionStatement
29 public abstract class CompletingExpression : ExpressionStatement {
30 public override void EmitStatement (EmitContext ec)
32 // Do nothing
35 public override void Emit (EmitContext ec)
37 // Do nothing
40 public override Expression CreateExpressionTree (ResolveContext ec)
42 return null;
46 public class CompletionSimpleName : CompletingExpression {
47 public string Prefix;
49 public CompletionSimpleName (string prefix, Location l)
51 this.loc = l;
52 this.Prefix = prefix;
55 public static void AppendResults (List<string> results, string prefix, IEnumerable<string> names)
57 foreach (string name in names){
58 if (name == null || prefix == null)
59 continue;
61 if (!name.StartsWith (prefix))
62 continue;
64 if (results.Contains (name))
65 continue;
67 if (prefix != null)
68 results.Add (name.Substring (prefix.Length));
69 else
70 results.Add (name);
75 protected override Expression DoResolve (ResolveContext ec)
77 var results = new List<string> ();
79 AppendResults (results, Prefix, Evaluator.GetVarNames ());
80 AppendResults (results, Prefix, ec.CurrentTypeDefinition.NamespaceEntry.CompletionGetTypesStartingWith (Prefix));
81 AppendResults (results, Prefix, Evaluator.GetUsingList ());
83 throw new CompletionResult (Prefix, results.ToArray ());
86 protected override void CloneTo (CloneContext clonectx, Expression t)
88 // Nothing
92 public class CompletionMemberAccess : CompletingExpression {
93 Expression expr;
94 string partial_name;
95 TypeArguments targs;
97 internal static MemberFilter CollectingFilter = new MemberFilter (Match);
99 static bool Match (MemberInfo m, object filter_criteria)
101 if (m is FieldInfo){
102 if (((FieldInfo) m).IsSpecialName)
103 return false;
106 if (m is MethodInfo){
107 if (((MethodInfo) m).IsSpecialName)
108 return false;
111 if (filter_criteria == null)
112 return true;
114 string n = (string) filter_criteria;
115 if (m.Name.StartsWith (n))
116 return true;
118 return false;
121 public CompletionMemberAccess (Expression e, string partial_name, Location l)
123 this.expr = e;
124 this.loc = l;
125 this.partial_name = partial_name;
128 public CompletionMemberAccess (Expression e, string partial_name, TypeArguments targs, Location l)
130 this.expr = e;
131 this.loc = l;
132 this.partial_name = partial_name;
133 this.targs = targs;
136 protected override Expression DoResolve (ResolveContext ec)
138 Expression expr_resolved = expr.Resolve (ec,
139 ResolveFlags.VariableOrValue | ResolveFlags.Type |
140 ResolveFlags.Intermediate);
142 if (expr_resolved == null)
143 return null;
145 Type expr_type = expr_resolved.Type;
146 if (expr_type.IsPointer || expr_type == TypeManager.void_type || expr_type == TypeManager.null_type || expr_type == InternalType.AnonymousMethod) {
147 Unary.Error_OperatorCannotBeApplied (ec, loc, ".", expr_type);
148 return null;
151 if (targs != null) {
152 if (!targs.Resolve (ec))
153 return null;
156 var results = new List<string> ();
157 if (expr_resolved is Namespace){
158 Namespace nexpr = expr_resolved as Namespace;
159 string namespaced_partial;
161 if (partial_name == null)
162 namespaced_partial = nexpr.Name;
163 else
164 namespaced_partial = nexpr.Name + "." + partial_name;
166 #if false
167 Console.WriteLine ("Workign with: namespaced partial {0}", namespaced_partial);
168 foreach (var x in ec.TypeContainer.NamespaceEntry.CompletionGetTypesStartingWith (ec.TypeContainer, namespaced_partial)){
169 Console.WriteLine (" {0}", x);
171 #endif
173 CompletionSimpleName.AppendResults (
174 results,
175 partial_name,
176 ec.CurrentTypeDefinition.NamespaceEntry.CompletionGetTypesStartingWith (namespaced_partial));
177 } else {
178 MemberInfo [] result = expr_type.FindMembers (
179 MemberTypes.All, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public,
180 CollectingFilter, partial_name);
182 foreach (MemberInfo r in result){
183 string name;
185 MethodBase rasb = r as MethodBase;
186 if (rasb != null && rasb.IsSpecialName)
187 continue;
189 if (partial_name == null)
190 name = r.Name;
191 else
192 name = r.Name.Substring (partial_name.Length);
194 if (results.Contains (name))
195 continue;
196 results.Add (name);
200 throw new CompletionResult (partial_name == null ? "" : partial_name, results.ToArray ());
203 protected override void CloneTo (CloneContext clonectx, Expression t)
205 CompletionMemberAccess target = (CompletionMemberAccess) t;
207 if (targs != null)
208 target.targs = targs.Clone ();
210 target.expr = expr.Clone (clonectx);
214 public class CompletionElementInitializer : CompletingExpression {
215 string partial_name;
217 public CompletionElementInitializer (string partial_name, Location l)
219 this.partial_name = partial_name;
220 this.loc = l;
223 protected override Expression DoResolve (ResolveContext ec)
225 MemberList members = TypeManager.FindMembers (
226 ec.CurrentInitializerVariable.Type,
227 MemberTypes.Field | MemberTypes.Property,
228 BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public,
229 CompletionMemberAccess.CollectingFilter, partial_name);
231 string [] result = new string [members.Count];
232 int i = 0;
233 foreach (MemberInfo mi in members){
234 string name;
236 if (partial_name == null)
237 name = mi.Name;
238 else
239 name = mi.Name.Substring (partial_name.Length);
241 result [i++] = name;
244 if (partial_name != null && i > 0 && result [0] == "")
245 throw new CompletionResult ("", new string [] { "=" });
247 throw new CompletionResult (partial_name == null ? "" : partial_name, result);
250 protected override void CloneTo (CloneContext clonectx, Expression t)
252 // Nothing