[runtime] Avoid indirection when building MonoContext on darwin
[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 // Copyright 2011 Xamarin Inc
11 //
12 // Completion* classes derive from ExpressionStatement as this allows
13 // them to pass through the parser in many conditions that require
14 // statements even when the expression is incomplete (for example
15 // completing inside a lambda
16 //
17 using System.Collections.Generic;
18 using System.Linq;
19
20 namespace Mono.CSharp {
21
22         //
23         // A common base class for Completing expressions, it
24         // is just a very simple ExpressionStatement
25         //
26         public abstract class CompletingExpression : ExpressionStatement
27         {
28                 public static void AppendResults (List<string> results, string prefix, IEnumerable<string> names)
29                 {
30                         foreach (string name in names) {
31                                 if (name == null)
32                                         continue;
33
34                                 if (prefix != null && !name.StartsWith (prefix))
35                                         continue;
36
37                                 if (results.Contains (name))
38                                         continue;
39
40                                 if (prefix != null)
41                                         results.Add (name.Substring (prefix.Length));
42                                 else
43                                         results.Add (name);
44                         }
45                 }
46
47                 public override bool ContainsEmitWithAwait ()
48                 {
49                         return false;
50                 }
51
52                 public override Expression CreateExpressionTree (ResolveContext ec)
53                 {
54                         return null;
55                 }
56
57                 public override void EmitStatement (EmitContext ec)
58                 {
59                         // Do nothing
60                 }
61
62                 public override void Emit (EmitContext ec)
63                 {
64                         // Do nothing
65                 }
66         }
67         
68         public class CompletionSimpleName : CompletingExpression {
69                 public string Prefix;
70                 
71                 public CompletionSimpleName (string prefix, Location l)
72                 {
73                         this.loc = l;
74                         this.Prefix = prefix;
75                 }
76                 
77                 protected override Expression DoResolve (ResolveContext ec)
78                 {
79                         var results = new List<string> ();
80
81                         ec.CurrentMemberDefinition.GetCompletionStartingWith (Prefix, results);
82
83                         throw new CompletionResult (Prefix, results.Distinct ().Select (l => l.Substring (Prefix.Length)).ToArray ());
84                 }
85
86                 protected override void CloneTo (CloneContext clonectx, Expression t)
87                 {
88                         // Nothing
89                 }
90         }
91         
92         public class CompletionMemberAccess : CompletingExpression {
93                 Expression expr;
94                 string partial_name;
95                 TypeArguments targs;
96                 
97                 public CompletionMemberAccess (Expression e, string partial_name, Location l)
98                 {
99                         this.expr = e;
100                         this.loc = l;
101                         this.partial_name = partial_name;
102                 }
103
104                 public CompletionMemberAccess (Expression e, string partial_name, TypeArguments targs, Location l)
105                 {
106                         this.expr = e;
107                         this.loc = l;
108                         this.partial_name = partial_name;
109                         this.targs = targs;
110                 }
111                 
112                 protected override Expression DoResolve (ResolveContext rc)
113                 {
114                         var sn = expr as SimpleName;
115                         const ResolveFlags flags = ResolveFlags.VariableOrValue | ResolveFlags.Type;
116
117                         if (sn != null) {
118                                 var errors_printer = new SessionReportPrinter ();
119                                 var old = rc.Report.SetPrinter (errors_printer);
120                                 try {
121                                         expr = sn.LookupNameExpression (rc, MemberLookupRestrictions.ReadAccess | MemberLookupRestrictions.ExactArity);
122                                 } finally {
123                                         rc.Report.SetPrinter (old);
124                                 }
125
126                                 if (errors_printer.ErrorsCount != 0)
127                                         return null;
128
129                                 //
130                                 // Resolve expression which does have type set as we need expression type
131                                 // with disable flow analysis as we don't know whether left side expression
132                                 // is used as variable or type
133                                 //
134                                 if (expr is VariableReference || expr is ConstantExpr || expr is Linq.TransparentMemberAccess) {
135                                         expr = expr.Resolve (rc);
136                                 } else if (expr is TypeParameterExpr) {
137                                         expr.Error_UnexpectedKind (rc, flags, sn.Location);
138                                         expr = null;
139                                 }
140                         } else {
141                                 expr = expr.Resolve (rc, flags);
142                         }
143
144                         if (expr == null)
145                                 return null;
146
147                         TypeSpec expr_type = expr.Type;
148                         if (expr_type.IsPointer || expr_type.Kind == MemberKind.Void || expr_type == InternalType.NullLiteral || expr_type == InternalType.AnonymousMethod) {
149                                 expr.Error_OperatorCannotBeApplied (rc, loc, ".", expr_type);
150                                 return null;
151                         }
152
153                         if (targs != null) {
154                                 if (!targs.Resolve (rc, true))
155                                         return null;
156                         }
157
158                         var results = new List<string> ();
159                         var nexpr = expr as NamespaceExpression;
160                         if (nexpr != null) {
161                                 string namespaced_partial;
162
163                                 if (partial_name == null)
164                                         namespaced_partial = nexpr.Namespace.Name;
165                                 else
166                                         namespaced_partial = nexpr.Namespace.Name + "." + partial_name;
167
168                                 rc.CurrentMemberDefinition.GetCompletionStartingWith (namespaced_partial, results);
169                                 if (partial_name != null)
170                                         results = results.Select (l => l.Substring (partial_name.Length)).ToList ();
171                         } else {
172                                 var r = MemberCache.GetCompletitionMembers (rc, expr_type, partial_name).Select (l => l.Name);
173                                 AppendResults (results, partial_name, r);
174                         }
175
176                         throw new CompletionResult (partial_name == null ? "" : partial_name, results.Distinct ().ToArray ());
177                 }
178
179                 protected override void CloneTo (CloneContext clonectx, Expression t)
180                 {
181                         CompletionMemberAccess target = (CompletionMemberAccess) t;
182
183                         if (targs != null)
184                                 target.targs = targs.Clone ();
185
186                         target.expr = expr.Clone (clonectx);
187                 }
188         }
189
190         public class CompletionElementInitializer : CompletingExpression {
191                 string partial_name;
192                 
193                 public CompletionElementInitializer (string partial_name, Location l)
194                 {
195                         this.partial_name = partial_name;
196                         this.loc = l;
197                 }
198                 
199                 protected override Expression DoResolve (ResolveContext ec)
200                 {
201                         var members = MemberCache.GetCompletitionMembers (ec, ec.CurrentInitializerVariable.Type, partial_name);
202
203 // TODO: Does this mean exact match only ?
204 //                      if (partial_name != null && results.Count > 0 && result [0] == "")
205 //                              throw new CompletionResult ("", new string [] { "=" });
206
207                         var results = members.Where (l => (l.Kind & (MemberKind.Field | MemberKind.Property)) != 0).Select (l => l.Name).ToList ();
208                         if (partial_name != null) {
209                                 var temp = new List<string> ();
210                                 AppendResults (temp, partial_name, results);
211                                 results = temp;
212                         }
213
214                         throw new CompletionResult (partial_name == null ? "" : partial_name, results.Distinct ().ToArray ());
215                 }
216
217                 protected override void CloneTo (CloneContext clonectx, Expression t)
218                 {
219                         // Nothing
220                 }
221         }
222
223         public class EmptyCompletion : CompletingExpression
224         {
225                 protected override void CloneTo (CloneContext clonectx, Expression target)
226                 {
227                 }
228
229                 protected override Expression DoResolve (ResolveContext rc)
230                 {
231                         throw new CompletionResult ("", new string [0]);
232                 }
233         }
234         
235 }