/* * Get the immediate child namespaces for a 'using' declaration */ protected List <LookupListItem> GetChildNamespaceList( LookupTarget target, string text) { string[] split = text.Split(';'); text = split[split.Length - 1]; // Is it a using declaration... Regex re1 = new Regex(@"using\s+"); MatchCollection mc = re1.Matches(text); if (mc.Count == 0) { return(null); } // ...but not a using statement. Regex re2 = new Regex(@"using\s*\("); Match m = re2.Match(text); if (m.Success) { return(null); } // Get the namespaces return(GetImmediateChildNamespaces(target.Entity)); }
/* * Use the namespace list to create each possible fully * qualified name for the target and test each one by * seeing if the type really exists. We have to do this * because C# allows unqualified type names which are * inferred from the 'using' declarations in the source. */ protected void GetFullyQualifiedTarget( LookupTarget target, List <string> namespaceList) { foreach (string ns in namespaceList) { string fullEntity = ns; if (ns != String.Empty) { fullEntity += "."; } fullEntity += target.Entity; string[] split = fullEntity.Split('.'); string type = String.Empty; for (int i = 0; i < split.Length; i++) { if (i > 0) { type += "."; } type += split[i]; /* * Try a lookahead for nested types. This is a hack * and only works for one level (i.e. just one '+'). */ if (i < split.Length - 1) { string nestedName = type + "+" + split[i + 1]; target.Type = SearchAssemblyList(nestedName); if (target.Type != null) { target.FullEntity = fullEntity; return; } } /* * Get back to looking for 'normal' types. */ target.Type = SearchAssemblyList(type); if (target.Type != null) { target.FullEntity = fullEntity; return; } } } }
public LookupContext(string fullSource, string preSource, string line, int lineStartPos, int currentPos, bool insideClass) { _fullSource = fullSource; _preSource = preSource; _line = line; _lineStartPos = lineStartPos; _currentPos = currentPos; _beforeClass = insideClass; /* * Cleanup the source code. */ _preSource = CSharpFormattingTools.RemoveUnwantedText(_preSource); _preSource = CSharpFormattingTools.RemoveUnwantedBracketText(_preSource); _line = CSharpFormattingTools.RemoveUnwantedText(_line); _line = CSharpFormattingTools.RemoveUnwantedBracketText(_line); /* * Get rid of 'global::' - we don't do anything with them * so we might as well not have them. */ _line = _line.Replace("global::", String.Empty); /* * We remove the content of any balanced brackets to * allow indexed variables to identified and classified. */ _line = CSharpFormattingTools.RemoveUnwantedParentheses(Line); /* * Create the target. */ _target = new LookupTarget(_line); /* * Find the visible methods and properties. */ _localMethods = new LocalMethods(_fullSource); _localProperties = new LocalProperties(_fullSource); }
protected override List <LookupListItem> GetChildNamespaces( LookupTarget target, string text) { return(GetChildNamespaceList(target, text)); }
protected List <LookupListItem> GetVisibleTypes( LookupContext context, bool includeLocals, bool includeNamespaces, bool includeVariables) { /* * Get the names of the base types of the current class. * This includes and ancestor class and any interfaces * implemented by the class. */ List <String> baseTypes = GetBaseTypes(context.PreSource); List <String> namespaceList = GetNamespaceList(context.PreSource); namespaceList.Insert(0, String.Empty); /* * We want to find the members inherited from the base * class not the interfaces. If there is no base type * System.Object is assumed. */ List <LookupListItem> list = new List <LookupListItem>(); foreach (string baseType in baseTypes) { LookupTarget target = new LookupTarget(baseType, String.Empty); List <LookupListItem> typeList = GetTypeMembers( context, target, context.DeclarationContext, namespaceList, true, true); if (typeList != null && !target.Type.IsInterface) { list.AddRange(typeList); } } if (list.Count == 0) { LookupTarget target = new LookupTarget("System.Object", String.Empty); List <LookupListItem> typeList = GetTypeMembers( context, target, context.DeclarationContext, namespaceList, true, true); if (typeList != null) { list.AddRange(typeList); } } if (includeNamespaces) { /* * Add all members of declared namespaces. */ List <LookupListItem> itemList = FindNamespaceTypeLookupItems(namespaceList); if (itemList != null) { list.AddRange(itemList); } } /* * Add declared (local) variables. */ if (includeVariables) { list.AddRange(context.DeclaredVariables. GetList(context.LineStartPos)); } /* * Add local methods and properties. */ if (includeLocals) { list.AddRange(context.Methods.GetList( context.DeclarationContext)); list.AddRange(context.Properties.GetList( context.DeclarationContext)); } return(list); }
protected abstract List <LookupListItem> GetChildNamespaces( LookupTarget target, string text);
protected List <LookupListItem> GetTypeMembers( LookupContext context, LookupTarget target, DeclarationContext declarationContext, List <String> namespaceList, bool allowNonPublic, bool isInherited) { #region Part 1: Find the type /* * To avoid multiple calls to GetNamespaceList in any * single lookup we can preload this list or create it here. */ if (namespaceList == null) { namespaceList = GetNamespaceList(context.PreSource); namespaceList.Insert(0, String.Empty); } /* * First we need to fully qualify the target type if it's * not already fully qualified. We assume it isn't and * test each possible namespace prefix until we find a * valid type. We add a blank namespace to the list to allow * for types that are already fully qualified. */ GetFullyQualifiedTarget(target, namespaceList); if (target.Type == null) { return(null); } if (target.Type.FullName == "System.Void") { return(new List <LookupListItem>()); } /* * We now need to separate the type from its sub-members * and work down the chain getting the type of * each sub-member until we either get a void return type or * reach the end of the list. The last type we get that's * not void is the type we want. */ string members = target.FullEntity.Substring( target.Type.FullName.Length).TrimStart('.'); Type type = target.Type; List <Type> allTypes = null; if (members != String.Empty) { string[] split = members.Split('.'); if (split.Length == 0) { return(null); } foreach (string member in split) { MemberInfo[] mi = type.GetMember(member); if (mi.Length == 0) { /* * Member not found; could be an * extension method... */ allTypes = FindNamespaceTypes(namespaceList); bool foundMember = false; foreach (Type t in allTypes) { if (!TypeHasExtensionMethods(t)) { continue; } MethodInfo[] mia = t.GetMethods(); if (ExtensionMethodFoundInTypeMembers( mia, member)) { mi = mia; foundMember = true; } } if (!foundMember) { return(null); } } /* * We are past the first level members which can * belong to a static or instance item; from here * all sub-members will be in instance contexts. */ declarationContext = DeclarationContext.Instance; string typeName = GetMemberTypeName(mi[0]); if (typeName == null) { return(null); } if (typeName == "System.Void") { return(null); } type = SearchAssemblyList(typeName); /* * If not found try a nested type. */ if (type == null) { typeName = target.Type.FullName + "+" + typeName; type = SearchAssemblyList(typeName); } /* * Exit if no return type found. */ if (type == null) { return(null); } } } #endregion #region Part 2: Get the type members /* * Now we can get the members of the type we've found. */ Dictionary <String, LookupListItem> foundItems = new Dictionary <String, LookupListItem>(); BindingFlags bindingAttr = BindingFlags.Public | BindingFlags.FlattenHierarchy; /* * Use static or instance lookup? */ if (declarationContext == DeclarationContext.Static || type.IsEnum) { bindingAttr |= BindingFlags.Static; } else { bindingAttr |= BindingFlags.Instance; if (isInherited) { bindingAttr |= BindingFlags.Static; } } /* * Include non-public? */ if (allowNonPublic) { bindingAttr |= BindingFlags.NonPublic; } MemberInfo[] items = type.GetMembers(bindingAttr); foreach (MemberInfo item in items) { if (item.MemberType == MemberTypes.Property) { AddProperty(foundItems, item); } else if (item.MemberType == MemberTypes.Method) { /* * Hide methods for Enums. */ if (type.IsEnum) { continue; } AddMethod(foundItems, item); } else if (item.MemberType == MemberTypes.Field) { AddField(foundItems, item); } else if (item.MemberType == MemberTypes.Event) { AddEvent(foundItems, item, target.Name, context.LineStartPos); } } #endregion #region Part 3: Find any extension methods for the type if (allTypes == null) { allTypes = FindNamespaceTypes(namespaceList); } foreach (Type t in allTypes) { if (!TypeHasExtensionMethods(t)) { continue; } MethodInfo[] mia = t.GetMethods(); foreach (MethodInfo mi in mia) { if (!mi.IsStatic) { continue; } if (mi.GetCustomAttributes( typeof(ExtensionAttribute), false).Length > 0) { ParameterInfo[] pia = mi.GetParameters(); if (pia.Length == 0) { break; } /* * Is the extension applicable to the current type? * We're assuming that the extension type is the * type of the 0-index parameter. */ /* * This doesn't appear to be 100% accurate * but it's OK for simple (i.e. non-generic) * extensions. (Might have something to do with * the above assumption?) */ if (pia[0].ParameterType.IsAssignableFrom(type)) { AddExtensionMethod(foundItems, mi); } } } } #endregion #region Part 4: Update overload information List <LookupListItem> lookupList = foundItems.Values.ToList <LookupListItem>(); foreach (LookupListItem li in lookupList) { /* * Update the tooltips to include overload count * or remove overload marker. */ string overloads = String.Empty; if (li.MenuItems.Count > 1) { overloads = String.Format(" (+{0} {1})", li.MenuItems.Count - 1, li.MenuItems.Count > 2 ? "overloads" : "overload"); } li.ToolTipText = li.ToolTipText.Replace("_OVR_", overloads); } #endregion return(lookupList); }