Exemple #1
0
        public static string GetNamespace(TypeReference type)
        {
            if (type.GetElementType().IsNested)
            {
                type = type.GetElementType();
            }
            while (type != null && type.IsNested)
            {
                type = type.DeclaringType;
            }
            if (type == null)
            {
                return(string.Empty);
            }

            string typeNS = type.Namespace;

            // first, make sure this isn't a type reference to another assembly/module

            bool isInAssembly = MDocUpdater.IsInAssemblies(type.Module.Name);

            if (isInAssembly && !typeNS.StartsWith("System") && MDocUpdater.HasDroppedNamespace(type))
            {
                typeNS = string.Format("{0}.{1}", MDocUpdater.droppedNamespace, typeNS);
            }
            return(typeNS);
        }
Exemple #2
0
        public static string GetTranslatedName(TypeReference t)
        {
            string typename = t.FullName;

            bool isInAssembly = MDocUpdater.IsInAssemblies(t.Module.Name);

            if (isInAssembly && !typename.StartsWith("System") && MDocUpdater.HasDroppedNamespace(t))
            {
                string nameWithDropped = string.Format("{0}.{1}", MDocUpdater.droppedNamespace, typename);
                return(nameWithDropped);
            }
            return(typename);
        }
Exemple #3
0
        public static string GetNamespace(TypeReference type, string delimeter = null)
        {
            if (type == null)
            {
                return(string.Empty);
            }

            if (type.GetElementType().IsNested)
            {
                type = type.GetElementType();
            }
            while (type != null && type.IsNested && !type.IsGenericParameter)
            {
                type = type.DeclaringType;
            }
            if (type == null)
            {
                return(string.Empty);
            }

            string typeNS = type.Namespace;

            if (!string.IsNullOrEmpty(delimeter))
            {
                typeNS = typeNS.Replace(".", delimeter);
            }

            // first, make sure this isn't a type reference to another assembly/module

            bool isInAssembly = MDocUpdater.IsInAssemblies(type.Module.Name);

            if (isInAssembly && !typeNS.StartsWith("System") && MDocUpdater.HasDroppedNamespace(type))
            {
                typeNS = string.Format("{0}{1}{2}", MDocUpdater.droppedNamespace, delimeter ?? ".", typeNS);
            }
            return(typeNS);
        }
        public static MemberReference GetMember(TypeDefinition type, DocumentationMember member)
        {
            string membertype = member.MemberType;

            string returntype = member.ReturnType;

            string docName = member.MemberName;

            string[] docTypeParams = GetTypeParameters(docName, member.TypeParameters);

            // If we're using 'magic types', then we might get false positives ... in those cases, we keep searching
            MemberReference likelyCandidate = null;

            // Loop through all members in this type with the same name
            var reflectedMembers = GetReflectionMembers(type, docName, membertype).ToArray();

            foreach (MemberReference mi in reflectedMembers)
            {
                bool matchedMagicType = false;
                if (mi is TypeDefinition)
                {
                    continue;
                }
                if (MDocUpdater.GetMemberType(mi) != membertype)
                {
                    continue;
                }

                if (MDocUpdater.IsPrivate(mi))
                {
                    continue;
                }

                IList <ParameterDefinition> pis = null;
                string[] typeParams             = null;
                if (mi is MethodDefinition)
                {
                    MethodDefinition mb = (MethodDefinition)mi;
                    pis = mb.Parameters;
                    if (mb.IsGenericMethod())
                    {
                        IList <GenericParameter> args = mb.GenericParameters;
                        typeParams = args.Select(p => p.Name).ToArray();
                    }
                }
                else if (mi is PropertyDefinition)
                {
                    pis = ((PropertyDefinition)mi).Parameters;
                }

                // check type parameters
                int methodTcount     = member.TypeParameters == null ? 0 : member.TypeParameters.Count;
                int reflectionTcount = typeParams == null ? 0 : typeParams.Length;
                if (methodTcount != reflectionTcount)
                {
                    continue;
                }

                // check member parameters
                int mcount = member.Parameters == null ? 0 : member.Parameters.Count;
                int pcount = pis == null ? 0 : pis.Count;
                if (mcount != pcount)
                {
                    continue;
                }

                MethodDefinition mDef = mi as MethodDefinition;
                if (mDef != null && !mDef.IsConstructor && (mDef.Name.StartsWith("op_Explicit", StringComparison.Ordinal) || mDef.Name.StartsWith("op_Implicit", StringComparison.Ordinal)))
                {
                    // Casting operators can overload based on return type.
                    string rtype = GetReplacedString(
                        MDocUpdater.GetDocTypeFullName(((MethodDefinition)mi).ReturnType),
                        typeParams, docTypeParams);
                    string originalRType = rtype;
                    if (MDocUpdater.SwitchingToMagicTypes)
                    {
                        rtype = NativeTypeManager.ConvertFromNativeType(rtype);
                    }
                    if ((returntype != rtype && originalRType == rtype) ||
                        (MDocUpdater.SwitchingToMagicTypes && returntype != originalRType && returntype != rtype && originalRType != rtype))
                    {
                        continue;
                    }

                    if (originalRType != rtype)
                    {
                        matchedMagicType = true;
                    }
                }

                if (pcount == 0)
                {
                    return(mi);
                }
                bool isExtensionMethod = DocUtils.IsExtensionMethod(mDef);
                bool good = true;
                for (int i = 0; i < pis.Count; i++)
                {
                    bool isRefType = pis[i].ParameterType is ByReferenceType;

                    if (i == 0 && !isRefType && isExtensionMethod)
                    {
                        isRefType = true; // this will be the case for generic parameter types
                    }
                    string paramType = GetReplacedString(
                        MDocUpdater.GetDocParameterType(pis[i].ParameterType),
                        typeParams, docTypeParams);

                    // if magictypes, replace paramType to "classic value" ... so the comparison works
                    string originalParamType = paramType;
                    if (MDocUpdater.SwitchingToMagicTypes)
                    {
                        paramType = NativeTypeManager.ConvertFromNativeType(paramType);
                    }

                    string xmlMemberType = member.Parameters[i];

                    // TODO: take into account extension method reftype
                    bool xmlIsRefType  = xmlMemberType.Contains('&');
                    bool refTypesMatch = isRefType == xmlIsRefType;

                    if (!refTypesMatch)
                    {
                        good = false;
                        break;
                    }

                    xmlMemberType = xmlIsRefType ? xmlMemberType.Substring(0, xmlMemberType.Length - 1) : xmlMemberType;

                    if ((!paramType.Equals(xmlMemberType) && paramType.Equals(originalParamType)) ||
                        (MDocUpdater.SwitchingToMagicTypes && !originalParamType.Equals(xmlMemberType) && !paramType.Equals(xmlMemberType) && !paramType.Equals(originalParamType)))
                    {
                        // did not match ... if we're dropping the namespace, and the paramType has the dropped
                        // namespace, we should see if it matches when added
                        bool stillDoesntMatch = true;
                        if (MDocUpdater.HasDroppedNamespace(type) && paramType.StartsWith(MDocUpdater.droppedNamespace))
                        {
                            string withDroppedNs = string.Format("{0}.{1}", MDocUpdater.droppedNamespace, xmlMemberType);

                            stillDoesntMatch = withDroppedNs != paramType;
                        }

                        if (stillDoesntMatch)
                        {
                            good = false;
                            break;
                        }
                    }

                    if (originalParamType != paramType)
                    {
                        matchedMagicType = true;
                    }
                }
                if (!good)
                {
                    continue;
                }

                if (MDocUpdater.SwitchingToMagicTypes && likelyCandidate == null && matchedMagicType)
                {
                    // we matched this on a magic type conversion ... let's keep going to see if there's another one we should look at that matches more closely
                    likelyCandidate = mi;
                    continue;
                }

                return(mi);
            }

            return(likelyCandidate);
        }
        private static IEnumerable <MemberReference> GetReflectionMembersCore(TypeDefinition type, string docName, string memberType)
        {
            // In case of dropping the namespace, we have to remove the dropped NS
            // so that docName will match what's in the assembly/type
            if (MDocUpdater.HasDroppedNamespace(type) && docName.StartsWith(MDocUpdater.droppedNamespace + "."))
            {
                int droppedNsLength = MDocUpdater.droppedNamespace.Length;
                docName = docName.Substring(droppedNsLength + 1, docName.Length - droppedNsLength - 1);
            }



            // need to worry about 4 forms of //@MemberName values:
            //  1. "Normal" (non-generic) member names: GetEnumerator
            //    - Lookup as-is.
            //  2. Explicitly-implemented interface member names: System.Collections.IEnumerable.Current
            //    - try as-is, and try type.member (due to "kludge" for property
            //      support.
            //  3. "Normal" Generic member names: Sort<T> (CSC)
            //    - need to remove generic parameters --> "Sort"
            //  4. Explicitly-implemented interface members for generic interfaces:
            //    -- System.Collections.Generic.IEnumerable<T>.Current
            //    - Try as-is, and try type.member, *keeping* the generic parameters.
            //     --> System.Collections.Generic.IEnumerable<T>.Current, IEnumerable<T>.Current
            //  5. As of 2008-01-02, gmcs will do e.g. 'IFoo`1[A].Method' instead of
            //    'IFoo<A>.Method' for explicitly implemented methods; don't interpret
            //    this as (1) or (2).
            if (docName.IndexOf('<') == -1 && docName.IndexOf('[') == -1)
            {
                int memberCount = 0;

                // Cases 1 & 2
                foreach (MemberReference mi in type.GetMembers(docName))
                {
                    memberCount++;
                    yield return(mi);
                }

                if (memberCount == 0 && CountChars(docName, '.') > 0)
                {
                    Func <MemberReference, bool> verifyInterface = (member) =>
                    {
                        var meth = member as MethodDefinition;

                        if (meth == null && member is PropertyReference)
                        {
                            var propertyDefinition = ((PropertyReference)member).Resolve();
                            meth = propertyDefinition.GetMethod ?? propertyDefinition.SetMethod;
                        }
                        return(meth != null && (member.Name.Equals(".ctor") || DocUtils.IsExplicitlyImplemented(meth)));
                    };


                    // might be a property; try only type.member instead of
                    // namespace.type.member.
                    var typeMember = DocUtils.GetTypeDotMember(docName);
                    var memberName = DocUtils.GetMember(docName);
                    foreach (MemberReference mi in
                             type.GetMembers(typeMember).Where(verifyInterface))
                    {
                        memberCount++;
                        yield return(mi);
                    }

                    // some VB libraries use just the member name
                    foreach (MemberReference mi in
                             type.GetMembers(memberName).Where(verifyInterface))
                    {
                        memberCount++;
                        yield return(mi);
                    }

                    // some VB libraries use a `typemember` naming convention
                    foreach (MemberReference mi in
                             type.GetMembers(typeMember.Replace(".", "")).Where(verifyInterface))
                    {
                        memberCount++;
                        yield return(mi);
                    }

                    // if we still haven't found the member, there are some VB libraries
                    // that use a different interface name for implementation.
                    if (memberCount == 0)
                    {
                        foreach (MemberReference mi in
                                 type
                                 .GetMembers()
                                 .Where(m => m.Name.StartsWith("I", StringComparison.InvariantCultureIgnoreCase) &&
                                        m.Name.EndsWith(memberName, StringComparison.InvariantCultureIgnoreCase))
                                 .Where(verifyInterface))
                        {
                            memberCount++;
                            yield return(mi);
                        }
                    }

                    if (memberCount == 0 && memberType == "Property")
                    {
                        foreach (MemberReference mr in type.GetMembers().Where(x => x is PropertyDefinition))
                        {
                            var method = ((PropertyDefinition)mr).GetMethod ?? ((PropertyDefinition)mr).SetMethod;
                            if (method?.Overrides != null && method.Overrides.Any())
                            {
                                DocUtils.GetInfoForExplicitlyImplementedMethod(method, out TypeReference iface, out MethodReference ifaceMethod);
                                var newName = DocUtils.GetMemberForProperty(ifaceMethod.Name);
                                if (newName == memberName && verifyInterface(mr) && docName.Contains(iface.Name))
                                {
                                    yield return(mr);
                                }
                            }
                        }
                    }
                }
                yield break;
            }
            // cases 3 & 4
            int numLt = 0;
            int numDot = 0;
            int startLt, startType, startMethod;

            startLt = startType = startMethod = -1;
            for (int i = 0; i < docName.Length; ++i)
            {
                switch (docName[i])
                {
                case '<':
                    if (numLt == 0)
                    {
                        startLt = i;
                    }
                    ++numLt;
                    break;

                case '>':
                    --numLt;
                    if (numLt == 0 && (i + 1) < docName.Length)
                    {
                        // there's another character in docName, so this <...> sequence is
                        // probably part of a generic type -- case 4.
                        startLt = -1;
                    }
                    break;

                case '.':
                    startType   = startMethod;
                    startMethod = i;
                    ++numDot;
                    break;
                }
            }
            string refName = startLt == -1 ? docName : docName.Substring(0, startLt);

            // case 3
            foreach (MemberReference mi in type.GetMembers(refName))
            {
                yield return(mi);
            }

            // case 4
            foreach (MemberReference mi in type.GetMembers(refName.Substring(startType + 1)))
            {
                yield return(mi);
            }

            // If we _still_ haven't found it, we've hit another generic naming issue:
            // post Mono 1.1.18, gmcs generates [[FQTN]] instead of <TypeName> for
            // explicitly-implemented METHOD names (not properties), e.g.
            // "System.Collections.Generic.IEnumerable`1[[Foo, test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]].GetEnumerator"
            // instead of "System.Collections.Generic.IEnumerable<Foo>.GetEnumerator",
            // which the XML docs will contain.
            //
            // Alas, we can't derive the Mono name from docName, so we need to iterate
            // over all member names, convert them into CSC format, and compare... :-(
            if (numDot == 0)
            {
                yield break;
            }
            foreach (MemberReference mi in type.GetMembers())
            {
                if (MDocUpdater.GetMemberName(mi) == docName)
                {
                    yield return(mi);
                }
            }
        }