// Usually this will return zero or one name, but it can return more (eg for explicit interface // implementations). public Item[] Find(CsMember context, ResolvedTarget target, CsGlobalNamespace globals, string name, int arity) { Profile.Start("ResolveMembers::Find"); var items = new List<Item>(); var types = new List<CsType>(); var baseNames = new List<string>(); var interfaceNames = new List<string>(); string[] allNames = DoGetBases(globals, target.TypeName, types, baseNames, interfaceNames); bool includeProtected = context != null && allNames.Contains(context.DeclaringType.FullName); foreach (CsType type in types) { var candidates = new List<Item>(); bool includePrivate = context != null && type.FullName == context.DeclaringType.FullName; DoGetParsedMembers(type, target.IsInstance, target.IsStatic, candidates, includePrivate, includeProtected); items = (from m in candidates where DoMatch(m, name, arity) select m).ToList(); } // Note that we need to make two GetMembers queries to ensure that interface // methods are not used in place of base methods (this gives us better results // when the context menu is used to filter out methods associated with types). DoAddIfMissingRange("Fields:", items, m_database.GetFields(baseNames.ToArray(), target.IsInstance, target.IsStatic, name, includeProtected)); DoAddIfMissingRange("Base Members:", items, m_database.GetMembers(baseNames.ToArray(), target.IsInstance, target.IsStatic, name, arity, includeProtected)); DoAddIfMissingRange("Interface Members:", items, m_database.GetMembers(interfaceNames.ToArray(), target.IsInstance, target.IsStatic, name, arity, includeProtected)); if (target.IsInstance) { var namespaces = new List<string>(); for (int i = 0; i < globals.Namespaces.Length; ++i) namespaces.Add(globals.Namespaces[i].Name); for (int i = 0; i < globals.Uses.Length; ++i) namespaces.Add(globals.Uses[i].Namespace); DoAddIfMissingRange("extension methods:", items, m_database.GetExtensionMethods(allNames, namespaces.ToArray(), name, arity)); } Profile.Stop("ResolveMembers::Find"); return items.ToArray(); }
public ResolveName(CsMember context, ITargetDatabase database, ICsLocalsParser locals, string text, int offset, CsGlobalNamespace globals) { Profile.Start("ResolveName::ctor"); m_database = database; m_typeResolver = new ResolveType(database); m_globals = globals; m_offset = offset; m_context = context; Profile.Start("DoFindMember"); m_member = DoFindMember(m_globals); Profile.Stop("DoFindMember"); Profile.Start("DoGetVariables"); m_variables = DoGetVariables(text, locals); Profile.Stop("DoGetVariables"); Profile.Stop("ResolveName::ctor"); }
// Offset should point just after the expression to resolve. May return null. public ResolvedTarget Resolve(CsMember context, string text, int offset) { Contract.Requires(offset >= 0, "offset is negative"); Contract.Requires(offset <= text.Length, "offset is too large"); Profile.Start("ResolveExpr::Resolve"); ResolvedTarget result = null; Log.WriteLine(TraceLevel.Verbose, "AutoComplete", "---------------- resolving expression"); Log.WriteLine(TraceLevel.Verbose, "AutoComplete", "text: '{0}'", text.Substring(Math.Max(0, offset - 48), offset - Math.Max(0, offset - 48)).EscapeAll()); string expr = DoFindExpr(text, offset); Log.WriteLine("AutoComplete", "expression: '{0}'", expr); if (!string.IsNullOrEmpty(expr)) result = m_nameResolver.Resolve(expr); if (result == null) { string[] operands = DoGetOperands(expr); int first = 0; result = DoGetOperandType(context, operands, ref first); Log.WriteLine(TraceLevel.Verbose, "AutoComplete", "operand type: {0}", result); for (int i = first; i < operands.Length; ++i) { string operand = operands[i]; ResolvedTarget old = result; result = DoResolveOperand(context, result, operand); Log.WriteLine(TraceLevel.Verbose, "AutoComplete", "{0}::{1} resolved to {2}", old, operand, result); if (result == null) break; } } Log.WriteLine("AutoComplete", "---- expression {0} -> {1}", expr, result); Profile.Stop("ResolveExpr::Resolve"); return result; }
// : base(after ? member.Offset + member.Length + 1 : member.Offset, DoMungeLines(after, lines)) public AddRelativeMember(CsMember member, bool after, params string[] lines) { m_after = after; m_member = member; m_lines = DoMungeLines(lines); }
public void QueueChangeAccess(CsMember member, string access) { m_refactor.Queue(new ChangeAccess(member, access)); }
private string DoGetShortName(CsMember member) { string result; do { CsEvent v = member as CsEvent; if (v != null) { result = string.Format("event {0}", v.Name); break; } CsField f = member as CsField; if (f != null) { result = f.Name; break; } CsIndexer i = member as CsIndexer; if (i != null) { result = "this[...]"; break; } CsMethod m = member as CsMethod; if (m != null) { result = m.Name; break; } CsOperator o = member as CsOperator; if (o != null) { if (o.IsImplicit) result = string.Format("implicit operator {0}", o.ReturnType); else if (o.IsExplicit) result = string.Format("explicit operator {0}", o.ReturnType); else result = string.Format("operator {0}", o.Name); break; } CsProperty p = member as CsProperty; if (p != null) { result = string.Format("{0}", p.Name); break; } Contract.Assert(false, "Unexpected member type: " + member.GetType()); result = "?"; } while (false); return result; }
private object DoGetName(CsMember member) { return member.Name; }
private object DoGetIsVolatile(CsMember member) { return (member.Modifiers & MemberModifiers.Volatile) == MemberModifiers.Volatile; }
private object DoGetIsStatic(CsMember member) { return (member.Modifiers & MemberModifiers.Static) == MemberModifiers.Static; }
private object DoGetDeclaringType(CsMember member) { return member.DeclaringType; }
private object DoGetAttributes(CsMember member) { return member.Attributes; }
private object DoGetAccess(CsMember member) { return member.Access.ToString().ToLower(); }
private object DoChangeAccess(CsMember member, string access) { return new ChangeAccess(member, access); }
private object DoAddMethodBefore(CsMember member, string text) { return new AddRelativeMember(member, false, text.Split('\n')); }
private object DoAddMethodAfter(CsMember member, string text) { return new AddRelativeMember(member, true, text.Split('\n')); }
private object DoGetIsReadonly(CsMember member) { return (member.Modifiers & MemberModifiers.Readonly) == MemberModifiers.Readonly; }
private object DoGetIsSealed(CsMember member) { return (member.Modifiers & MemberModifiers.Sealed) == MemberModifiers.Sealed; }
private object DoGetFullName(CsMember member) { return member.FullName; }
private object DoGetIsVirtual(CsMember member) { return (member.Modifiers & MemberModifiers.Virtual) == MemberModifiers.Virtual; }
private object DoGetIsAbstract(CsMember member) { return (member.Modifiers & MemberModifiers.Abstract) == MemberModifiers.Abstract; }
private object DoGetModifiers(CsMember member) { return member.Modifiers.ToString().ToLower(); }
private object DoGetIsConst(CsMember member) { return (member.Modifiers & MemberModifiers.Const) == MemberModifiers.Const; }
private string DoGetFullName(CsMember member) { string result; do { CsIndexer i = member as CsIndexer; if (i != null) { result = string.Format("this[{0}]", DoGetParams(i.Parameters)); break; } CsMethod m = member as CsMethod; if (m != null) { if (m.GenericArguments != null) result = string.Format("{0}<{1}>({2})", m.Name, m.GenericArguments, DoGetParams(m.Parameters)); else result = string.Format("{0}({1})", m.Name, DoGetParams(m.Parameters)); break; } CsOperator o = member as CsOperator; if (o != null && !o.IsConversion) { result = string.Format("operator {0}({1})", o.Name, DoGetParams(o.Parameters)); break; } result = DoGetShortName(member); } while (false); return result; }
private object DoGetIsInternal(CsMember member) { return (member.Modifiers & MemberModifiers.Internal) == MemberModifiers.Internal; }
public void QueueAddRelativeMember(CsMember member, bool after, params string[] lines) { m_refactor.Queue(new AddRelativeMember(member, after, lines)); }
private object DoGetIsOverride(CsMember member) { return (member.Modifiers & MemberModifiers.Override) == MemberModifiers.Override; }
private object DoGetIsPrivate(CsMember member) { return (member.Modifiers & MemberModifiers.Private) == MemberModifiers.Private; }
private object DoGetIsProtected(CsMember member) { return (member.Modifiers & MemberModifiers.Protected) == MemberModifiers.Protected; }
public ChangeAccess(CsMember member, string access) { Contract.Requires(member != null, "member is null"); Contract.Requires(!string.IsNullOrEmpty(access), "access is null or empty"); m_access = access; m_member = member; }
private ResolvedTarget DoResolveOperand(CsMember context, ResolvedTarget target, string operand) { ResolvedTarget result = null; Log.WriteLine(TraceLevel.Verbose, "AutoComplete", " target: {0}, operand: '{1}'", target, operand); // Handle locals and args. if (target == null) { Log.WriteLine(TraceLevel.Verbose, "AutoComplete", "trying local operand"); result = m_nameResolver.Resolve(operand); } // Handle this calls (this will work for static calls too). if (target == null && result == null) { target = m_nameResolver.Resolve("this"); Log.WriteLine(TraceLevel.Verbose, "AutoComplete", "new target: {0}", target); } // Handle other calls. if (target != null && result == null) { int numArgs = DoGetNumArgs(operand); int i = operand.IndexOfAny(new char[]{'(', ' ', '\t', '\n', '\r'}); string name = i >= 0 ? operand.Substring(0, i) : operand; if (name != null) { Log.WriteLine(TraceLevel.Verbose, "AutoComplete", "trying {0}({1} args) item operand", name, numArgs); if (name == "typeof" && numArgs == 1) { Log.WriteLine(TraceLevel.Verbose, "AutoComplete", "resolved to System.Type"); result = new ResolvedTarget("System.Type", null, true, false); } else { Item[] candidates = m_memberResolver.Find(context, target, m_globals, name, numArgs); IEnumerable<Item> items = from c in candidates where c.Type != null select c; if (items.Any()) { if (items.All(m => m.Type == items.First().Type)) { Log.WriteLine(TraceLevel.Verbose, "AutoComplete", "{0}:{1} with {2} args resolved to {3}", target, name, numArgs, items.First().Type); result = m_typeResolver.Resolve(items.First().Type, context, m_globals, true, false); } else { Log.WriteLine("AutoComplete", "{0} has an ambiguous return type:", name); foreach (Item item in items) { Log.WriteLine("AutoComplete", " {0} {1}", item.Type, item); } } } } } } if (result == null) Log.WriteLine("AutoComplete", "failed to resolve {0}::{1}", target, operand); return result; }