2010-06-21 Atsushi Enomoto <atsushi@ximian.com>
[mcs.git] / mcs / complete.cs
blobec3663ef2a6133361a445fa7691c06af3b439e6c
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;
22 using System.Linq;
24 namespace Mono.CSharp {
27 // A common base class for Completing expressions, it
28 // is just a very simple ExpressionStatement
30 public abstract class CompletingExpression : ExpressionStatement
32 public static void AppendResults (List<string> results, string prefix, IEnumerable<string> names)
34 foreach (string name in names) {
35 if (name == null || prefix == null)
36 continue;
38 if (!name.StartsWith (prefix))
39 continue;
41 if (results.Contains (name))
42 continue;
44 if (prefix != null)
45 results.Add (name.Substring (prefix.Length));
46 else
47 results.Add (name);
51 public override void EmitStatement (EmitContext ec)
53 // Do nothing
56 public override void Emit (EmitContext ec)
58 // Do nothing
61 public override Expression CreateExpressionTree (ResolveContext ec)
63 return null;
67 public class CompletionSimpleName : CompletingExpression {
68 public string Prefix;
70 public CompletionSimpleName (string prefix, Location l)
72 this.loc = l;
73 this.Prefix = prefix;
76 protected override Expression DoResolve (ResolveContext ec)
78 var results = new List<string> ();
80 AppendResults (results, Prefix, Evaluator.GetVarNames ());
81 AppendResults (results, Prefix, ec.CurrentMemberDefinition.Parent.NamespaceEntry.CompletionGetTypesStartingWith (Prefix));
82 AppendResults (results, Prefix, Evaluator.GetUsingList ());
84 throw new CompletionResult (Prefix, results.ToArray ());
87 protected override void CloneTo (CloneContext clonectx, Expression t)
89 // Nothing
93 public class CompletionMemberAccess : CompletingExpression {
94 Expression expr;
95 string partial_name;
96 TypeArguments targs;
98 public CompletionMemberAccess (Expression e, string partial_name, Location l)
100 this.expr = e;
101 this.loc = l;
102 this.partial_name = partial_name;
105 public CompletionMemberAccess (Expression e, string partial_name, TypeArguments targs, Location l)
107 this.expr = e;
108 this.loc = l;
109 this.partial_name = partial_name;
110 this.targs = targs;
113 protected override Expression DoResolve (ResolveContext ec)
115 Expression expr_resolved = expr.Resolve (ec,
116 ResolveFlags.VariableOrValue | ResolveFlags.Type);
118 if (expr_resolved == null)
119 return null;
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;
127 if (targs != null) {
128 if (!targs.Resolve (ec))
129 return null;
132 var results = new List<string> ();
133 if (expr_resolved is Namespace){
134 Namespace nexpr = expr_resolved as Namespace;
135 string namespaced_partial;
137 if (partial_name == null)
138 namespaced_partial = nexpr.Name;
139 else
140 namespaced_partial = nexpr.Name + "." + partial_name;
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);
147 #endif
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);
158 throw new CompletionResult (partial_name == null ? "" : partial_name, results.Distinct ().ToArray ());
161 protected override void CloneTo (CloneContext clonectx, Expression t)
163 CompletionMemberAccess target = (CompletionMemberAccess) t;
165 if (targs != null)
166 target.targs = targs.Clone ();
168 target.expr = expr.Clone (clonectx);
172 public class CompletionElementInitializer : CompletingExpression {
173 string partial_name;
175 public CompletionElementInitializer (string partial_name, Location l)
177 this.partial_name = partial_name;
178 this.loc = l;
181 protected override Expression DoResolve (ResolveContext ec)
183 var members = MemberCache.GetCompletitionMembers (ec.CurrentInitializerVariable.Type, partial_name);
185 // TODO: Does this mean exact match only ?
186 // if (partial_name != null && results.Count > 0 && result [0] == "")
187 // throw new CompletionResult ("", new string [] { "=" });
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;
196 throw new CompletionResult (partial_name == null ? "" : partial_name, results.Distinct ().ToArray ());
199 protected override void CloneTo (CloneContext clonectx, Expression t)
201 // Nothing