public static Member GetMemberForOperation(TypeNode typeNode, string operationName) { return typeNode.GetMembersNamed(Identifier.For(operationName))[0]; }
private static Method GetUniqueMethod(TypeNode type, string name) { var ms = type.GetMembersNamed(Identifier.For(name)); if (ms == null || ms.Count == 0) throw new InvalidOperationException("No such method"); if (ms.Count != 1) throw new InvalidOperationException("No unique method"); var res = ms[0] as Method; if (res == null) throw new InvalidOperationException("Member is not a method"); return res; }
/// <summary> /// Get the template type for the given type /// </summary> /// <param name="type">The type for which to get the template type</param> /// <returns>The type itself if it is not generic or the template type if it is</returns> public static TypeNode GetTemplateType(this TypeNode type) { if (type == null) { throw new ArgumentNullException(nameof(type)); } // Only generic types have templates if (!type.IsGeneric) { return(type); } // If the type is not nested, life is simpler. if (type.DeclaringType == null) { // If the type is not specified, the type is the template if (type.TemplateArguments == null) { return(type); } // Otherwise, construct the template type identifier and use it to fetch the template type Identifier name = new Identifier(String.Format(CultureInfo.InvariantCulture, "{0}`{1}", type.GetUnmangledNameWithoutTypeParameters(), type.TemplateArguments.Count)); TypeNode template = type.DeclaringModule.GetType(type.Namespace, name); // !EFW - Added by ComponentOne if (template == null) { template = type; } return(template); } // If the type is nested, life is harder. We have to walk up the chain, constructing unspecialized // identifiers as we go, then walk back down the chain, fetching template types as we go. // Create a stack to keep track of identifiers Stack <Identifier> identifiers = new Stack <Identifier>(); // Populate the stack with the identifiers of all the types up to the outermost type TypeNode current = type; while (true) { int count = 0; if (current.TemplateArguments != null && current.TemplateArguments.Count > count) { count = current.TemplateArguments.Count; } if (current.TemplateParameters != null && current.TemplateParameters.Count > count) { count = current.TemplateParameters.Count; } if (count == 0) { identifiers.Push(new Identifier(current.GetUnmangledNameWithoutTypeParameters())); } else { identifiers.Push(new Identifier(String.Format(CultureInfo.InvariantCulture, "{0}`{1}", current.GetUnmangledNameWithoutTypeParameters(), count))); } if (current.DeclaringType == null) { break; } current = current.DeclaringType; } // Fetch a TypeNode representing the outermost type current = current.DeclaringModule.GetType(current.Namespace, identifiers.Pop()); // Move down the stack to the inner type we want while (identifiers.Count > 0 && current != null) { current = (TypeNode)current.GetMembersNamed(identifiers.Pop()).FirstOrDefault(); } // !EFW - Added by ComponentOne if (current == null) { return(type); } // Whew, finally we've got it return(current); }
public static Member GetMemberForOperation(TypeNode typeNode, string operationName) { return(typeNode.GetMembersNamed(Identifier.For(operationName))[0]); }
/// <summary> /// Get the template member for the given member /// </summary> /// <param name="member">The member for which to get the template member</param> /// <returns>The template member for the given member. This will be the member itself if it is not /// generic or it is not specialized.</returns> public static Member GetTemplateMember(this Member member) { if (member == null) { throw new ArgumentNullException(nameof(member)); } // If the containing type isn't generic, the member is the template member TypeNode type = member.DeclaringType; if (!type.IsGeneric) { return(member); } // If the containing type isn't specialized, the member is the template member if (!type.IsSpecialized()) { return(member); } // Get the template type and look for members with the same name TypeNode template = member.DeclaringType.GetTemplateType(); MemberList candidates = template.GetMembersNamed(member.Name); // If no candidates, say so (this shouldn't happen) if (candidates.Count == 0) { throw new InvalidOperationException("No members in the template had the name found in the " + "specialization. This is not possible but apparently it happened."); } // If only one candidate, return it if (candidates.Count == 1) { return(candidates[0]); } // Multiple candidates, so now we need to compare parameters ParameterList parameters = member.GetParameters(); // !EFW - If there are no generic parameters in this method, check for an exact match // first ignoring all methods with generic parameters. This prevents it matching a // generic overload of the method prematurely and returning the wrong one as the match. bool hasNoGenericParams = true; foreach (var p in parameters) { if (p.Type.IsTemplateParameter) { hasNoGenericParams = false; break; } } if (hasNoGenericParams) { for (int i = 0; i < candidates.Count; i++) { Member candidate = candidates[i]; // Candidate must be same kind of node if (candidate.NodeType != member.NodeType) { continue; } // Match exactly, failing if compared to a version with generic parameters if (ParametersMatch(parameters, candidate.GetParameters(), true, false)) { return(candidate); } } } for (int i = 0; i < candidates.Count; i++) { Member candidate = candidates[i]; // Candidate must be same kind of node if (candidate.NodeType != member.NodeType) { continue; } // Allow matches to versions with generic parameters if (ParametersMatch(parameters, candidate.GetParameters(), false, false)) { return(candidate); } } // !EFW - If we get here, it's probably some really complicated signature involving multiple // generic types and/or mixes of intrinsic array types and generic template parameter array types. // So, give it one final last ditch attempt allowing intrinsic array types to match template // parameter array types. If that fails, we will give up. If there's a better way to do this, I'm // not aware of it. https://github.com/EWSoftware/SHFB/issues/302 for (int i = 0; i < candidates.Count; i++) { Member candidate = candidates[i]; // Candidate must be same kind of node if (candidate.NodeType != member.NodeType) { continue; } // Allow matches to versions with generic parameters if (ParametersMatch(parameters, candidate.GetParameters(), false, true)) { return(candidate); } } // !EFW - Due to yet another case related to generics used with array types, if we get here with no // matches, give up and just compare by literal type name. If we get a match great. If not, who // knows? We'll handle any such cases as they occur. They're very uncommon at this point anyway. for (int i = 0; i < candidates.Count; i++) { Member candidate = candidates[i]; if (candidate.NodeType != member.NodeType) { continue; } var cp = candidate.GetParameters(); if (parameters.Count != cp.Count) { continue; } int pi = 0; while (pi < parameters.Count) { if (parameters[pi].Type.FullName != cp[pi].Type.FullName) { break; } pi++; } if (pi == parameters.Count) { return(candidate); } } throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "{0}\r\n{1}\r\n" + "No members in the template matched the parameters of the specialization. This is not " + "possible but apparently it happened.", member.DeclaringType.FullName, member.FullName)); }