Example #1
0
		public static Member GetMemberForOperation(TypeNode typeNode, string operationName)
		{
			return typeNode.GetMembersNamed(Identifier.For(operationName))[0];
		}
Example #2
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;
        }
Example #3
0
        /// <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);
        }
Example #4
0
 public static Member GetMemberForOperation(TypeNode typeNode, string operationName)
 {
     return(typeNode.GetMembersNamed(Identifier.For(operationName))[0]);
 }
Example #5
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));
        }