Xamarin Public Jenkins (auto-signing) e79aa3c0ed Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
2016-08-03 10:59:49 +00:00

236 lines
6.3 KiB
C#

//
// complete.cs: Expression that are used for completion suggestions.
//
// Author:
// Miguel de Icaza (miguel@ximian.com)
// Marek Safar (marek.safar@gmail.com)
//
// Copyright 2001, 2002, 2003 Ximian, Inc.
// Copyright 2003-2009 Novell, Inc.
// Copyright 2011 Xamarin Inc
//
// Completion* classes derive from ExpressionStatement as this allows
// them to pass through the parser in many conditions that require
// statements even when the expression is incomplete (for example
// completing inside a lambda
//
using System.Collections.Generic;
using System.Linq;
namespace Mono.CSharp {
//
// A common base class for Completing expressions, it
// is just a very simple ExpressionStatement
//
public abstract class CompletingExpression : ExpressionStatement
{
public static void AppendResults (List<string> results, string prefix, IEnumerable<string> names)
{
foreach (string name in names) {
if (name == null)
continue;
if (prefix != null && !name.StartsWith (prefix))
continue;
if (results.Contains (name))
continue;
if (prefix != null)
results.Add (name.Substring (prefix.Length));
else
results.Add (name);
}
}
public override bool ContainsEmitWithAwait ()
{
return false;
}
public override Expression CreateExpressionTree (ResolveContext ec)
{
return null;
}
public override void EmitStatement (EmitContext ec)
{
// Do nothing
}
public override void Emit (EmitContext ec)
{
// Do nothing
}
}
public class CompletionSimpleName : CompletingExpression {
public string Prefix;
public CompletionSimpleName (string prefix, Location l)
{
this.loc = l;
this.Prefix = prefix;
}
protected override Expression DoResolve (ResolveContext ec)
{
var results = new List<string> ();
ec.CurrentMemberDefinition.GetCompletionStartingWith (Prefix, results);
throw new CompletionResult (Prefix, results.Distinct ().Select (l => l.Substring (Prefix.Length)).ToArray ());
}
protected override void CloneTo (CloneContext clonectx, Expression t)
{
// Nothing
}
}
public class CompletionMemberAccess : CompletingExpression {
Expression expr;
string partial_name;
TypeArguments targs;
public CompletionMemberAccess (Expression e, string partial_name, Location l)
{
this.expr = e;
this.loc = l;
this.partial_name = partial_name;
}
public CompletionMemberAccess (Expression e, string partial_name, TypeArguments targs, Location l)
{
this.expr = e;
this.loc = l;
this.partial_name = partial_name;
this.targs = targs;
}
protected override Expression DoResolve (ResolveContext rc)
{
var sn = expr as SimpleName;
const ResolveFlags flags = ResolveFlags.VariableOrValue | ResolveFlags.Type;
if (sn != null) {
var errors_printer = new SessionReportPrinter ();
var old = rc.Report.SetPrinter (errors_printer);
try {
expr = sn.LookupNameExpression (rc, MemberLookupRestrictions.ReadAccess | MemberLookupRestrictions.ExactArity);
} finally {
rc.Report.SetPrinter (old);
}
if (errors_printer.ErrorsCount != 0)
return null;
//
// Resolve expression which does have type set as we need expression type
// with disable flow analysis as we don't know whether left side expression
// is used as variable or type
//
if (expr is VariableReference || expr is ConstantExpr || expr is Linq.TransparentMemberAccess) {
expr = expr.Resolve (rc);
} else if (expr is TypeParameterExpr) {
expr.Error_UnexpectedKind (rc, flags, sn.Location);
expr = null;
}
} else {
expr = expr.Resolve (rc, flags);
}
if (expr == null)
return null;
TypeSpec expr_type = expr.Type;
if (expr_type.IsPointer || expr_type.Kind == MemberKind.Void || expr_type == InternalType.NullLiteral || expr_type == InternalType.AnonymousMethod) {
expr.Error_OperatorCannotBeApplied (rc, loc, ".", expr_type);
return null;
}
if (targs != null) {
if (!targs.Resolve (rc, true))
return null;
}
var results = new List<string> ();
var nexpr = expr as NamespaceExpression;
if (nexpr != null) {
string namespaced_partial;
if (partial_name == null)
namespaced_partial = nexpr.Namespace.Name;
else
namespaced_partial = nexpr.Namespace.Name + "." + partial_name;
rc.CurrentMemberDefinition.GetCompletionStartingWith (namespaced_partial, results);
if (partial_name != null)
results = results.Select (l => l.Substring (partial_name.Length)).ToList ();
} else {
var r = MemberCache.GetCompletitionMembers (rc, expr_type, partial_name).Select (l => l.Name);
AppendResults (results, partial_name, r);
}
throw new CompletionResult (partial_name == null ? "" : partial_name, results.Distinct ().ToArray ());
}
protected override void CloneTo (CloneContext clonectx, Expression t)
{
CompletionMemberAccess target = (CompletionMemberAccess) t;
if (targs != null)
target.targs = targs.Clone ();
target.expr = expr.Clone (clonectx);
}
}
public class CompletionElementInitializer : CompletingExpression {
string partial_name;
public CompletionElementInitializer (string partial_name, Location l)
{
this.partial_name = partial_name;
this.loc = l;
}
protected override Expression DoResolve (ResolveContext ec)
{
var members = MemberCache.GetCompletitionMembers (ec, ec.CurrentInitializerVariable.Type, partial_name);
// TODO: Does this mean exact match only ?
// if (partial_name != null && results.Count > 0 && result [0] == "")
// throw new CompletionResult ("", new string [] { "=" });
var results = members.Where (l => (l.Kind & (MemberKind.Field | MemberKind.Property)) != 0).Select (l => l.Name).ToList ();
if (partial_name != null) {
var temp = new List<string> ();
AppendResults (temp, partial_name, results);
results = temp;
}
throw new CompletionResult (partial_name == null ? "" : partial_name, results.Distinct ().ToArray ());
}
protected override void CloneTo (CloneContext clonectx, Expression t)
{
// Nothing
}
}
public class EmptyCompletion : CompletingExpression
{
protected override void CloneTo (CloneContext clonectx, Expression target)
{
}
protected override Expression DoResolve (ResolveContext rc)
{
throw new CompletionResult ("", new string [0]);
}
}
}