9ee16f9fd0da1afeb71f900d36594fd0f1e3c271
[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 namespace Mono.CSharp {
17         using System;
18         using System.Collections;
19         using System.Reflection;
20         using System.Reflection.Emit;
21         using System.Text;
22
23         //
24         // A common base class for Completing expressions, it
25         // is just a very simple ExpressionStatement
26         //
27         public abstract class CompletingExpression : ExpressionStatement {
28                 public override void EmitStatement (EmitContext ec)
29                 {
30                         // Do nothing
31                 }
32
33                 public override void Emit (EmitContext ec)
34                 {
35                         // Do nothing
36                 }
37
38                 public override Expression CreateExpressionTree (EmitContext ec)
39                 {
40                         return null;
41                 }
42         }
43         
44         public class CompletionSimpleName : CompletingExpression {
45                 string prefix;
46                 
47                 public CompletionSimpleName (string prefix, Location l)
48                 {
49                         this.loc = l;
50                         this.prefix = prefix;
51                 }
52
53                 void AppendResults (ArrayList results, string prefix, IEnumerable names)
54                 {
55                         foreach (string name in names){
56                                 if (!name.StartsWith (prefix))
57                                         continue;
58
59                                 if (results.Contains (name))
60                                         continue;
61
62                                 if (prefix != null)
63                                         results.Add (name.Substring (prefix.Length));
64                                 else
65                                         results.Add (name);
66                         }
67
68                 }
69                 
70                 public override Expression DoResolve (EmitContext ec)
71                 {
72                         ArrayList results = new ArrayList ();
73
74                         AppendResults (results, prefix, Evaluator.GetVarNames ());
75                         AppendResults (results, prefix, ec.TypeContainer.NamespaceEntry.CompletionGetTypesStartingWith (ec.TypeContainer, prefix));
76                         AppendResults (results, prefix, Evaluator.GetUsingList ());
77                         
78                         throw new CompletionResult (prefix, (string []) results.ToArray (typeof (string)));
79                 }
80
81                 protected override void CloneTo (CloneContext clonectx, Expression t)
82                 {
83                         // Nothing
84                 }
85         }
86         
87         public class CompletionMemberAccess : CompletingExpression {
88                 Expression expr;
89                 string partial_name;
90                 TypeArguments targs;
91
92                 static MemberFilter CollectingFilter = new MemberFilter (Match);
93
94                 static bool Match (MemberInfo m, object filter_criteria)
95                 {
96                         if (m is FieldInfo){
97                                 if (((FieldInfo) m).IsSpecialName)
98                                         return false;
99                                 
100                         }
101                         if (m is MethodInfo){
102                                 if (((MethodInfo) m).IsSpecialName)
103                                         return false;
104                         }
105
106                         if (filter_criteria == null)
107                                 return true;
108                         
109                         string n = (string) filter_criteria;
110                         if (m.Name.StartsWith (n))
111                                 return true;
112                         
113                         return false;
114                 }
115                 
116                 public CompletionMemberAccess (Expression e, string partial_name, Location l)
117                 {
118                         this.expr = e;
119                         this.loc = l;
120                         this.partial_name = partial_name;
121                 }
122
123                 public CompletionMemberAccess (Expression e, string partial_name, TypeArguments targs, Location l)
124                 {
125                         this.expr = e;
126                         this.loc = l;
127                         this.partial_name = partial_name;
128                         this.targs = targs;
129                 }
130                 
131                 public override Expression DoResolve (EmitContext ec)
132                 {
133                         SimpleName original = expr as SimpleName;
134                         Expression expr_resolved = expr.Resolve (ec,
135                                 ResolveFlags.VariableOrValue | ResolveFlags.Type |
136                                 ResolveFlags.Intermediate | ResolveFlags.DisableStructFlowAnalysis);
137
138                         if (expr_resolved == null)
139                                 return null;
140
141                         Type expr_type = expr_resolved.Type;
142                         if (expr_type.IsPointer || expr_type == TypeManager.void_type || expr_type == TypeManager.null_type || expr_type == TypeManager.anonymous_method_type) {
143                                 Unary.Error_OperatorCannotBeApplied (loc, ".", expr_type);
144                                 return null;
145                         }
146
147                         if (targs != null) {
148                                 if (!targs.Resolve (ec))
149                                         return null;
150                         }
151
152                         ArrayList results = new ArrayList ();
153                         MemberInfo [] result = expr_type.FindMembers (MemberTypes.All, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public, CollectingFilter, partial_name);
154                         foreach (MemberInfo r in result){
155                                 string name;
156
157                                 MethodBase rasb = r as MethodBase;
158                                 if (rasb != null && rasb.IsSpecialName)
159                                         continue;
160                                 
161                                 if (partial_name == null)
162                                         name = r.Name;
163                                 else {
164                                         name = r.Name.Substring (partial_name.Length);
165                                 }
166                                 
167                                 if (results.Contains (name))
168                                         continue;
169                                 results.Add (name);
170                         }
171
172                         throw new CompletionResult (partial_name == null ? "" : partial_name, (string []) results.ToArray (typeof (string)));
173                 }
174
175                 protected override void CloneTo (CloneContext clonectx, Expression t)
176                 {
177                         CompletionMemberAccess target = (CompletionMemberAccess) t;
178
179                         if (targs != null)
180                                 target.targs = targs.Clone ();
181
182                         target.expr = expr.Clone (clonectx);
183                 }
184         }
185 }