/// <summary>
        /// C# compiler uses complecated logic to generate docIds for Eii properties. Need to have special logic here.
        /// </summary>
        /// <param name="property">Value to process</param>
        /// <returns>DocId for property member wchich needs to be equal to docId generated by compiler's /doc flag </returns>
        protected override string EiiPropertyProcessing(PropertyReference property)
        {
            string name;

            PropertyDefinition propertyDef = property as PropertyDefinition;
            MethodDefinition   method      = null;

            if (propertyDef != null)
            {
                method = propertyDef.GetMethod ?? propertyDef.SetMethod;
            }
            if (method != null && !DocUtils.IsExplicitlyImplemented(method))
            {
                name = property.Name;
            }
            else
            {
                DocUtils.GetInfoForExplicitlyImplementedMethod(method, out var iface, out var ifaceMethod);
                AddTypeCount = false;
                name         = string.Join("#", new string[] {
                    GetTypeName(iface).Replace(".", "#"),
                    DocUtils.GetMember(property.Name)
                });
                AddTypeCount = true;
            }

            return(name);
        }
Exemplo n.º 2
0
        protected override string GetPropertyName(PropertyReference property)
        {
            string name = null;

            PropertyDefinition propertyDef = property as PropertyDefinition;
            MethodDefinition   method      = null;

            if (propertyDef != null)
            {
                method = propertyDef.GetMethod ?? propertyDef.SetMethod;
            }
            if (method != null && !DocUtils.IsExplicitlyImplemented(method))
            {
                name = property.Name;
            }
            else
            {
                TypeReference   iface;
                MethodReference ifaceMethod;
                DocUtils.GetInfoForExplicitlyImplementedMethod(method, out iface, out ifaceMethod);
                AddTypeCount = false;
                name         = string.Join("#", new string[] {
                    GetTypeName(iface).Replace(".", "#"),
                    DocUtils.GetMember(property.Name)
                });
                AddTypeCount = true;
            }

            StringBuilder buf = new StringBuilder();

            buf.Append(GetName(property.DeclaringType));
            buf.Append('.');
            buf.Append(name);
            IList <ParameterDefinition> parameters = property.Parameters;

            if (parameters.Count > 0)
            {
                genDeclType = property.DeclaringType;
                buf.Append('(');
                IList <GenericParameter> genArgs = property.DeclaringType.GenericParameters;
                AppendParameter(buf, genArgs, parameters[0]);
                for (int i = 1; i < parameters.Count; ++i)
                {
                    buf.Append(',');
                    AppendParameter(buf, genArgs, parameters[i]);
                }
                buf.Append(')');
                genDeclType = null;
            }
            return(buf.ToString());
        }
        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);
                }
            }
        }