2 // complete.cs: Expression that are used for completion suggestions.
5 // Miguel de Icaza (miguel@ximian.com)
6 // Marek Safar (marek.safar@gmail.com)
8 // Copyright 2001, 2002, 2003 Ximian, Inc.
9 // Copyright 2003-2009 Novell, Inc.
10 // Copyright 2011 Xamarin Inc
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
17 using System
.Collections
.Generic
;
20 namespace Mono
.CSharp
{
23 // A common base class for Completing expressions, it
24 // is just a very simple ExpressionStatement
26 public abstract class CompletingExpression
: ExpressionStatement
28 public static void AppendResults (List
<string> results
, string prefix
, IEnumerable
<string> names
)
30 foreach (string name
in names
) {
34 if (prefix
!= null && !name
.StartsWith (prefix
))
37 if (results
.Contains (name
))
41 results
.Add (name
.Substring (prefix
.Length
));
47 public override bool ContainsEmitWithAwait ()
52 public override Expression
CreateExpressionTree (ResolveContext ec
)
57 public override void EmitStatement (EmitContext ec
)
62 public override void Emit (EmitContext ec
)
68 public class CompletionSimpleName
: CompletingExpression
{
71 public CompletionSimpleName (string prefix
, Location l
)
77 protected override Expression
DoResolve (ResolveContext ec
)
79 var results
= new List
<string> ();
81 ec
.CurrentMemberDefinition
.GetCompletionStartingWith (Prefix
, results
);
83 throw new CompletionResult (Prefix
, results
.Distinct ().Select (l
=> l
.Substring (Prefix
.Length
)).ToArray ());
86 protected override void CloneTo (CloneContext clonectx
, Expression t
)
92 public class CompletionMemberAccess
: CompletingExpression
{
97 public CompletionMemberAccess (Expression e
, string partial_name
, Location l
)
101 this.partial_name
= partial_name
;
104 public CompletionMemberAccess (Expression e
, string partial_name
, TypeArguments targs
, Location l
)
108 this.partial_name
= partial_name
;
112 protected override Expression
DoResolve (ResolveContext rc
)
114 var sn
= expr
as SimpleName
;
115 const ResolveFlags flags
= ResolveFlags
.VariableOrValue
| ResolveFlags
.Type
;
118 var errors_printer
= new SessionReportPrinter ();
119 var old
= rc
.Report
.SetPrinter (errors_printer
);
121 expr
= sn
.LookupNameExpression (rc
, MemberLookupRestrictions
.ReadAccess
| MemberLookupRestrictions
.ExactArity
);
123 rc
.Report
.SetPrinter (old
);
126 if (errors_printer
.ErrorsCount
!= 0)
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
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
);
141 expr
= expr
.Resolve (rc
, flags
);
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
);
154 if (!targs
.Resolve (rc
, true))
158 var results
= new List
<string> ();
159 var nexpr
= expr
as NamespaceExpression
;
161 string namespaced_partial
;
163 if (partial_name
== null)
164 namespaced_partial
= nexpr
.Namespace
.Name
;
166 namespaced_partial
= nexpr
.Namespace
.Name
+ "." + partial_name
;
168 rc
.CurrentMemberDefinition
.GetCompletionStartingWith (namespaced_partial
, results
);
169 if (partial_name
!= null)
170 results
= results
.Select (l
=> l
.Substring (partial_name
.Length
)).ToList ();
172 var r
= MemberCache
.GetCompletitionMembers (rc
, expr_type
, partial_name
).Select (l
=> l
.Name
);
173 AppendResults (results
, partial_name
, r
);
176 throw new CompletionResult (partial_name
== null ? "" : partial_name
, results
.Distinct ().ToArray ());
179 protected override void CloneTo (CloneContext clonectx
, Expression t
)
181 CompletionMemberAccess target
= (CompletionMemberAccess
) t
;
184 target
.targs
= targs
.Clone ();
186 target
.expr
= expr
.Clone (clonectx
);
190 public class CompletionElementInitializer
: CompletingExpression
{
193 public CompletionElementInitializer (string partial_name
, Location l
)
195 this.partial_name
= partial_name
;
199 protected override Expression
DoResolve (ResolveContext ec
)
201 var members
= MemberCache
.GetCompletitionMembers (ec
, ec
.CurrentInitializerVariable
.Type
, partial_name
);
203 // TODO: Does this mean exact match only ?
204 // if (partial_name != null && results.Count > 0 && result [0] == "")
205 // throw new CompletionResult ("", new string [] { "=" });
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
);
214 throw new CompletionResult (partial_name
== null ? "" : partial_name
, results
.Distinct ().ToArray ());
217 protected override void CloneTo (CloneContext clonectx
, Expression t
)
223 public class EmptyCompletion
: CompletingExpression
225 protected override void CloneTo (CloneContext clonectx
, Expression target
)
229 protected override Expression
DoResolve (ResolveContext rc
)
231 throw new CompletionResult ("", new string [0]);