internal Parser(RuleValidation validation) { this.validation = validation; Type[] allTypes = null; ITypeProvider provider = validation.GetTypeProvider(); if (provider == null) { // No type provider. The only type we know about is "This". //allTypes = new Type[] { validation.ThisType }; try { allTypes = validation.ThisType.Assembly.GetTypes(); } catch (ReflectionTypeLoadException e) { // problems loading all the types, take what we can get allTypes = e.Types; } } else { allTypes = provider.GetTypes(); } // Go through all the known types and gather namespace information. // Also note which types are uniquely named; these can be looked up without // qualification. Dictionary<string, NamespaceSymbol> rootNamespaces = new Dictionary<string, NamespaceSymbol>(); Dictionary<string, object> duplicateNames = new Dictionary<string, object>(); NamespaceSymbol nsSym = null; Symbol existingSymbol = null; NamespaceSymbol globalNS = null; // In case we encounter a type without a namespace for (int i = 0; i < allTypes.Length; ++i) { Type type = allTypes[i]; // If we got a ReflectionTypeLoadException, some types may be null, so skip them if (type == null) continue; // Skip types that are not visible. // (If type.Assembly == null, we assume it's a design-time type, and let it through.) if (type.IsNotPublic && (type.Assembly != null && type.Assembly != validation.ThisType.Assembly)) continue; // Skip nested types. if (type.IsNested) continue; // Add the namespaces. string typeNamespace = type.Namespace; if (string.IsNullOrEmpty(typeNamespace)) { if (globalNS == null) { globalNS = new NamespaceSymbol(); rootNamespaces.Add("", globalNS); } nsSym = globalNS; } else { string[] namespaces = typeNamespace.Split('.'); System.Diagnostics.Debug.Assert(namespaces.Length > 0); if (!rootNamespaces.TryGetValue(namespaces[0], out nsSym)) { nsSym = new NamespaceSymbol(namespaces[0], null); rootNamespaces.Add(namespaces[0], nsSym); // Also add the root namespace to the global unique symbol dictionary. // Replace anything that was there. I.e., we had MS.Test.Foo, // and this current one is Test.Bar. It wins. globalUniqueSymbols[namespaces[0]] = nsSym; } if (namespaces.Length > 1) { for (int j = 1; j < namespaces.Length; ++j) { nsSym = nsSym.AddNamespace(namespaces[j]); if (globalUniqueSymbols.TryGetValue(namespaces[j], out existingSymbol)) { // This sub-namespace is already in global unique symbols. // If it's the same one as what's there, no problem. NamespaceSymbol existingNS = existingSymbol as NamespaceSymbol; if (existingNS != null && existingNS.Parent != nsSym.Parent) { // It was different. If the levels are the same, it's a duplicate name. if (existingNS.Level == nsSym.Level) { duplicateNames[namespaces[j]] = null; } else { // If the new one is at a lower level than the existing one, // replace it. Otherwise, leave the existing one there. if (nsSym.Level < existingNS.Level) globalUniqueSymbols[namespaces[j]] = nsSym; } } } else { globalUniqueSymbols.Add(namespaces[j], nsSym); } } } } // Add the type to its namespace. nsSym.AddType(type); } // Remove non-unique namespaces. foreach (string name in duplicateNames.Keys) globalUniqueSymbols.Remove(name); Queue<NamespaceSymbol> nsQueue = new Queue<NamespaceSymbol>(); foreach (NamespaceSymbol rootNS in rootNamespaces.Values) nsQueue.Enqueue(rootNS); // Add the unique types as well. duplicateNames.Clear(); while (nsQueue.Count > 0) { nsSym = nsQueue.Dequeue(); foreach (Symbol nestedSym in nsSym.NestedSymbols.Values) { NamespaceSymbol nestedNS = nestedSym as NamespaceSymbol; if (nestedNS != null) { nsQueue.Enqueue(nestedNS); } else { string name = nestedSym.Name; if (globalUniqueSymbols.TryGetValue(name, out existingSymbol)) { // Found an existing one with the same name. if (existingSymbol is NamespaceSymbol) { // A type name matches a namespace name... namespace wins. continue; } else { TypeSymbolBase existingTypeSymBase = (TypeSymbolBase)existingSymbol; TypeSymbolBase typeSymBase = (TypeSymbolBase)nestedSym; OverloadedTypeSymbol overloadSym = existingTypeSymBase.OverloadType(typeSymBase); if (overloadSym == null) duplicateNames[name] = null; // Couldn't overload it. else globalUniqueSymbols[name] = overloadSym; } } else { globalUniqueSymbols.Add(name, nestedSym); } } } } // Remove non-unique types. foreach (string name in duplicateNames.Keys) globalUniqueSymbols.Remove(name); // Finally, deal with the members of "this". // // Nested types override/hide items in the global unique symbols list. // // All other members get added to the local unique symbols list. In most // contexts, these will override (replace, hide) any global symbols with the same name. // In contexts where the parser is only looking for types and/or namespaces, local // symbols do NOT hide global ones. Type thisType = validation.ThisType; MemberInfo[] members = thisType.GetMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.FlattenHierarchy); foreach (MemberInfo mi in members) { switch (mi.MemberType) { case MemberTypes.Field: if (mi.DeclaringType == thisType || ParserContext.IsNonPrivate((FieldInfo)mi, thisType)) localUniqueSymbols[mi.Name] = new MemberSymbol(mi); break; case MemberTypes.Property: PropertyInfo prop = (PropertyInfo)mi; ParameterInfo[] propParams = prop.GetIndexParameters(); if (propParams != null && propParams.Length > 0) { // If the property has arguments, it can only be accessed by directly calling // its accessor methods. MethodInfo[] accessors = prop.GetAccessors(true); foreach (MethodInfo accessor in accessors) { if (accessor.DeclaringType == thisType || ParserContext.IsNonPrivate(accessor, thisType)) localUniqueSymbols[mi.Name] = new MemberSymbol(accessor); } } else { if (mi.DeclaringType == thisType) { // It's a property on "this", so add it even if it's private. localUniqueSymbols[mi.Name] = new MemberSymbol(mi); } else { // Add the property if at least one of its accessors is non-private. MethodInfo[] accessors = prop.GetAccessors(true); foreach (MethodInfo accessor in accessors) { if (ParserContext.IsNonPrivate(accessor, thisType)) { localUniqueSymbols[mi.Name] = new MemberSymbol(mi); break; } } } } break; case MemberTypes.Method: MethodInfo method = (MethodInfo)mi; if (!method.IsSpecialName && !method.IsGenericMethod) { if (mi.DeclaringType == thisType || ParserContext.IsNonPrivate(method, thisType)) { // These simply hide anything else of the same name. localUniqueSymbols[mi.Name] = new MemberSymbol(mi); } } break; case MemberTypes.NestedType: case MemberTypes.TypeInfo: // Same thing but only happens with DesignTimeTypes // These can overload or hide global unique symbols. Type miType = (Type)mi; TypeSymbol memberSym = new TypeSymbol(miType); if (globalUniqueSymbols.TryGetValue(memberSym.Name, out existingSymbol)) { TypeSymbolBase existingTypeSymBase = existingSymbol as TypeSymbolBase; if (existingTypeSymBase != null) { // Try to overload. OverloadedTypeSymbol overloadSym = existingTypeSymBase.OverloadType(memberSym); if (overloadSym == null) { if (mi.DeclaringType == thisType || ParserContext.IsNonPrivate(miType, thisType)) { // We couldn't overload it, so hide it. globalUniqueSymbols[memberSym.Name] = memberSym; } } else if (mi.DeclaringType == thisType || ParserContext.IsNonPrivate(miType, thisType)) { globalUniqueSymbols[memberSym.Name] = overloadSym; } } else { // The name clashed with something that wasn't a type name. // Hide the outer one. if (mi.DeclaringType == thisType || ParserContext.IsNonPrivate((Type)mi, thisType)) globalUniqueSymbols[memberSym.Name] = memberSym; } } else { if (mi.DeclaringType == thisType || ParserContext.IsNonPrivate(miType, thisType)) { globalUniqueSymbols[memberSym.Name] = memberSym; } } break; default: break; } } }
internal Parser(RuleValidation validation) { this.validation = validation; Type[] types = null; ITypeProvider typeProvider = validation.GetTypeProvider(); if (typeProvider == null) { try { types = validation.ThisType.Assembly.GetTypes(); } catch (ReflectionTypeLoadException exception) { types = exception.Types; } } else { types = typeProvider.GetTypes(); } Dictionary<string, NamespaceSymbol> dictionary = new Dictionary<string, NamespaceSymbol>(); Dictionary<string, object> dictionary2 = new Dictionary<string, object>(); NamespaceSymbol symbol = null; Symbol symbol2 = null; NamespaceSymbol symbol3 = null; for (int i = 0; i < types.Length; i++) { Type type = types[i]; if (((type != null) && ((!type.IsNotPublic || (type.Assembly == null)) || (type.Assembly == validation.ThisType.Assembly))) && !type.IsNested) { string str = type.Namespace; if (string.IsNullOrEmpty(str)) { if (symbol3 == null) { symbol3 = new NamespaceSymbol(); dictionary.Add("", symbol3); } symbol = symbol3; } else { string[] strArray = str.Split(new char[] { '.' }); if (!dictionary.TryGetValue(strArray[0], out symbol)) { symbol = new NamespaceSymbol(strArray[0], null); dictionary.Add(strArray[0], symbol); this.globalUniqueSymbols[strArray[0]] = symbol; } if (strArray.Length > 1) { for (int j = 1; j < strArray.Length; j++) { symbol = symbol.AddNamespace(strArray[j]); if (this.globalUniqueSymbols.TryGetValue(strArray[j], out symbol2)) { NamespaceSymbol symbol4 = symbol2 as NamespaceSymbol; if ((symbol4 != null) && (symbol4.Parent != symbol.Parent)) { if (symbol4.Level == symbol.Level) { dictionary2[strArray[j]] = null; } else if (symbol.Level < symbol4.Level) { this.globalUniqueSymbols[strArray[j]] = symbol; } } } else { this.globalUniqueSymbols.Add(strArray[j], symbol); } } } } symbol.AddType(type); } } foreach (string str2 in dictionary2.Keys) { this.globalUniqueSymbols.Remove(str2); } Queue<NamespaceSymbol> queue = new Queue<NamespaceSymbol>(); foreach (NamespaceSymbol symbol5 in dictionary.Values) { queue.Enqueue(symbol5); } dictionary2.Clear(); while (queue.Count > 0) { foreach (Symbol symbol6 in queue.Dequeue().NestedSymbols.Values) { NamespaceSymbol item = symbol6 as NamespaceSymbol; if (item != null) { queue.Enqueue(item); } else { string name = symbol6.Name; if (this.globalUniqueSymbols.TryGetValue(name, out symbol2)) { if (!(symbol2 is NamespaceSymbol)) { TypeSymbolBase base2 = (TypeSymbolBase) symbol2; TypeSymbolBase typeSymBase = (TypeSymbolBase) symbol6; OverloadedTypeSymbol symbol8 = base2.OverloadType(typeSymBase); if (symbol8 == null) { dictionary2[name] = null; } else { this.globalUniqueSymbols[name] = symbol8; } } } else { this.globalUniqueSymbols.Add(name, symbol6); } } } } foreach (string str4 in dictionary2.Keys) { this.globalUniqueSymbols.Remove(str4); } Type thisType = validation.ThisType; foreach (MemberInfo info in thisType.GetMembers(BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance)) { PropertyInfo info2; Type type3; TypeSymbol symbol9; OverloadedTypeSymbol symbol10; switch (info.MemberType) { case MemberTypes.Property: { info2 = (PropertyInfo) info; ParameterInfo[] indexParameters = info2.GetIndexParameters(); if ((indexParameters == null) || (indexParameters.Length <= 0)) { break; } foreach (MethodInfo info3 in info2.GetAccessors(true)) { if ((info3.DeclaringType == thisType) || ParserContext.IsNonPrivate(info3, thisType)) { this.localUniqueSymbols[info.Name] = new MemberSymbol(info3); } } continue; } case MemberTypes.TypeInfo: case MemberTypes.NestedType: { type3 = (Type) info; symbol9 = new TypeSymbol(type3); if (!this.globalUniqueSymbols.TryGetValue(symbol9.Name, out symbol2)) { goto Label_06AA; } TypeSymbolBase base4 = symbol2 as TypeSymbolBase; if (base4 == null) { goto Label_0674; } symbol10 = base4.OverloadType(symbol9); if (symbol10 != null) { goto Label_0643; } if ((info.DeclaringType == thisType) || ParserContext.IsNonPrivate(type3, thisType)) { this.globalUniqueSymbols[symbol9.Name] = symbol9; } continue; } case MemberTypes.Field: { if ((info.DeclaringType == thisType) || ParserContext.IsNonPrivate((FieldInfo) info, thisType)) { this.localUniqueSymbols[info.Name] = new MemberSymbol(info); } continue; } case MemberTypes.Method: { MethodInfo methodInfo = (MethodInfo) info; if ((!methodInfo.IsSpecialName && !methodInfo.IsGenericMethod) && ((info.DeclaringType == thisType) || ParserContext.IsNonPrivate(methodInfo, thisType))) { this.localUniqueSymbols[info.Name] = new MemberSymbol(info); } continue; } default: { continue; } } if (info.DeclaringType == thisType) { this.localUniqueSymbols[info.Name] = new MemberSymbol(info); } else { foreach (MethodInfo info4 in info2.GetAccessors(true)) { if (ParserContext.IsNonPrivate(info4, thisType)) { this.localUniqueSymbols[info.Name] = new MemberSymbol(info); break; } } } continue; Label_0643: if ((info.DeclaringType == thisType) || ParserContext.IsNonPrivate(type3, thisType)) { this.globalUniqueSymbols[symbol9.Name] = symbol10; } continue; Label_0674: if ((info.DeclaringType == thisType) || ParserContext.IsNonPrivate((Type) info, thisType)) { this.globalUniqueSymbols[symbol9.Name] = symbol9; } continue; Label_06AA: if ((info.DeclaringType == thisType) || ParserContext.IsNonPrivate(type3, thisType)) { this.globalUniqueSymbols[symbol9.Name] = symbol9; } } }